fix: resolve global env variable becoming undefined on script execution (#5816)

* fix: resolve global env variable becoming undefined on script execution

Fixes an issue where global disabled environment variables were becoming undefined during request execution when the pre request script is non-empty.

The update ensures that global variables persist as expected and are correctly referenced throughout the request lifecycle.

Closes #5772.

* feat: added test for checking proper global env update through scripts

* refactor: updated comments for more readability and added a new data-testid in modal.
This commit is contained in:
Abhishek S Lal
2025-10-17 21:50:50 +05:30
committed by GitHub
parent a4b1941817
commit 636901c23d
10 changed files with 169 additions and 6 deletions

View File

@@ -136,7 +136,7 @@ const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentV
/>
</td>
<td>
<div className="flex items-center">
<div className="flex items-center" data-testid={`env-var-name-${index}`}>
<input
type="text"
autoComplete="off"
@@ -153,7 +153,7 @@ const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentV
</div>
</td>
<td className="flex flex-row flex-nowrap items-center">
<div className="overflow-hidden grow w-full relative">
<div className="overflow-hidden grow w-full relative" data-testid={`env-var-value-${index}`}>
<MultiLineEditor
theme={storedTheme}
collection={_collection}

View File

@@ -9,7 +9,8 @@ const ModalHeader = ({ title, handleCancel, customHeader, hideClose }) => (
<div className="bruno-modal-header">
{customHeader ? customHeader : <>{title ? <div className="bruno-modal-header-title">{title}</div> : null}</>}
{handleCancel && !hideClose ? (
<div className="close cursor-pointer" onClick={handleCancel ? () => handleCancel() : null} data-test-id="modal-close-button">
// TODO: Remove data-test-id and use data-testid instead across the codebase.
<div className="close cursor-pointer" onClick={handleCancel ? () => handleCancel() : null} data-test-id="modal-close-button" data-testid="modal-close-button">
×
</div>
) : null}

View File

@@ -1,7 +1,7 @@
import { createSlice } from '@reduxjs/toolkit';
import { uuid } from 'utils/common/index';
import { environmentSchema } from '@usebruno/schema';
import { cloneDeep } from 'lodash';
import { cloneDeep, has } from 'lodash';
const initialState = {
globalEnvironments: [],
@@ -195,11 +195,15 @@ export const globalEnvironmentsUpdateEvent = ({ globalEnvironmentVariables }) =>
}
let variables = cloneDeep(environment?.variables);
console.log('globalEnvironmentVariables', globalEnvironmentVariables);
// update existing values
// "globalEnvironmentVariables" will include only the enabled variables and newly added variables created using the script.
// Update the value of each variable if it's present in "globalEnvironmentVariables", otherwise keep the existing value.
variables = variables?.map?.(variable => ({
...variable,
value: globalEnvironmentVariables?.[variable?.name]
value: has(globalEnvironmentVariables, variable?.name)
? globalEnvironmentVariables[variable?.name]
: variable?.value
}));
// add new env values

View File

@@ -0,0 +1,9 @@
{
"version": "1",
"name": "Global Environment Update",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}

View File

@@ -0,0 +1,12 @@
meta {
name: Global Environment Update
}
auth {
mode: none
}
script:pre-request {
//create a new global env variable.
bru.setGlobalEnvVar('newEnv', "newEnvValue");
}

View File

@@ -0,0 +1,24 @@
meta {
name: Test Request
type: http
seq: 1
}
get {
url: {{baseUrl}}/users
body: json
auth: inherit
}
script:pre-request {
//update already existing enabled env variable
bru.setGlobalEnvVar("existingEnvEnabled", "newExistingEnvEnabledValue");
//update already existing disabled env variable
bru.setGlobalEnvVar("existingEnvDisabled", "newExistingEnvDisabledValue");
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,62 @@
import { test, expect } from '../../../playwright';
import { closeAllCollections } from '../../utils/page';
test.describe('Global Environment Variable Update via Script', () => {
test.afterEach(async ({ pageWithUserData: page }) => {
// cleanup: close all collections
await closeAllCollections(page);
});
test('should update global environment values via script and verify the changes', async ({
pageWithUserData: page
}) => {
await test.step('Open the collection from sidebar', async () => {
await page.locator('#sidebar-collection-name').filter({ hasText: 'Global Environment Update' }).click();
});
await test.step('Open the test request that has a pre-request script', async () => {
await page.locator('.collection-name', { hasText: 'Global Environment Update' }).click();
await page.locator('.collection-item-name', { hasText: 'Test Request' }).click();
});
await test.step('Run the request', async () => {
await page.getByTestId('send-arrow-icon').click();
});
await test.step('Open the Global Environment Config modal', async () => {
await page.getByTestId('environment-selector-trigger').click();
await page.getByTestId('env-tab-global').click();
await page.getByText('Configure', { exact: true }).click();
});
const globalEnvModal = page.locator('.bruno-modal').filter({ hasText: 'Global Environments' });
await test.step('Verify that the value of "existingEnvEnabled" is updated by the pre-request script', async () => {
const updatedExistingEnvEnabledInputDiv = await globalEnvModal.getByTestId('env-var-value-1');
const updatedExistingEnvEnabledValue = await updatedExistingEnvEnabledInputDiv.locator('.CodeMirror-line').textContent();
await expect(updatedExistingEnvEnabledValue).toContain('newExistingEnvEnabledValue');
});
await test.step('Verify that the value of "existingEnvDisabled" is updated by the pre-request script', async () => {
const updatedExistingEnvDisabledInputDiv = await globalEnvModal.getByTestId('env-var-value-2');
const updatedExistingEnvDisabledValue = await updatedExistingEnvDisabledInputDiv.locator('.CodeMirror-line').textContent();
await expect(updatedExistingEnvDisabledValue).toContain('newExistingEnvDisabledValue');
});
await test.step('Verify that a new env variable "newEnv" is added by the pre-request script to the global environment', async () => {
const newEnvInputDiv = await globalEnvModal.getByTestId('env-var-value-3');
const newEnvValue = await newEnvInputDiv.locator('.CodeMirror-line').textContent();
await expect(newEnvValue).toContain('newEnvValue');
});
await test.step('Verify that the value of "baseUrl" is unchanged.', async () => {
const currentBaseUrlInputDiv = await globalEnvModal.getByTestId('env-var-value-0');
const currentBaseUrlValue = await currentBaseUrlInputDiv.locator('.CodeMirror-line').textContent();
await expect(currentBaseUrlValue).toContain('https://echo.usebruno.com');
});
await test.step('Close the global environment config modal.', async () => {
await page.getByTestId('modal-close-button').click();
});
});
});

View File

@@ -0,0 +1,10 @@
{
"collections": [
{
"path": "{{projectRoot}}/tests/environments/update-global-environment-via-script/fixtures/collection",
"securityConfig": {
"jsSandboxMode": "safe"
}
}
]
}

View File

@@ -0,0 +1,35 @@
{
"environments": [
{
"uid": "RrPsTcwRnHMv3yljQO3ex",
"name": "global",
"variables": [
{
"uid": "VXKOZdkYw0DyI4mlhn6Wr",
"name": "baseUrl",
"value": "https://echo.usebruno.com",
"type": "text",
"secret": false,
"enabled": true
},
{
"uid": "NTwrSscXsaeh4uee6ocJN",
"name": "existingEnvEnabled",
"value": "existingEnvEnabledValue",
"type": "text",
"secret": false,
"enabled": true
},
{
"uid": "PCsUccFm4pktVowXEKRvw",
"name": "existingEnvDisabled",
"value": "existingEnvDisabledValue",
"type": "text",
"secret": false,
"enabled": false
}
]
}
],
"activeGlobalEnvironmentUid": "RrPsTcwRnHMv3yljQO3ex"
}

View File

@@ -0,0 +1,6 @@
{
"maximized": true,
"lastOpenedCollections": [
"{{projectRoot}}/tests/environments/update-global-environment-via-script/fixtures/collection"
]
}