Feature: implemented bru.interpolate (#4122)

* feat: enhance variable highlighting in CodeMirror and update interpolation method

* feat: add interpolate function to bru shim and corresponding tests

- Implemented the `interpolate` function in the bru shim to handle variable interpolation.
- Added a new test case for the `interpolate` function to verify its functionality with mock variables.

* feat: enhance interpolate function to support object interpolation

* feat: add translation support for pm.variables.replaceIn to bru.interpolate

* revert: eslint config changes

* revert: eslint config changes

* fix: update method call to use correct interpolation function in Bru class

* refactor: added jsdoc to codemirror highlighting code

* fix: higlighting for multiline editor
This commit is contained in:
sanish chirayath
2025-05-22 15:37:15 +05:30
committed by GitHub
parent 553f7675f2
commit 9a35302d4b
16 changed files with 161 additions and 41 deletions

View File

@ -38,4 +38,4 @@ module.exports = defineConfig([
"no-undef": "error", "no-undef": "error",
}, },
} }
]); ]);

View File

@ -71,4 +71,4 @@
} }
} }
} }
} }

View File

@ -87,7 +87,8 @@ if (!SERVER_RENDERED) {
'bru.runner', 'bru.runner',
'bru.runner.setNextRequest(requestName)', 'bru.runner.setNextRequest(requestName)',
'bru.runner.skipRequest()', 'bru.runner.skipRequest()',
'bru.runner.stopExecution()' 'bru.runner.stopExecution()',
'bru.interpolate(str)'
]; ];
CodeMirror.registerHelper('hint', 'brunoJS', (editor, options) => { CodeMirror.registerHelper('hint', 'brunoJS', (editor, options) => {
const cursor = editor.getCursor(); const cursor = editor.getCursor();
@ -365,7 +366,7 @@ export default class CodeEditor extends React.Component {
let variables = getAllVariables(this.props.collection, this.props.item); let variables = getAllVariables(this.props.collection, this.props.item);
this.variables = variables; this.variables = variables;
defineCodeMirrorBrunoVariablesMode(variables, mode); defineCodeMirrorBrunoVariablesMode(variables, mode, false, this.props.enableVariableHighlighting);
this.editor.setOption('mode', 'brunovariables'); this.editor.setOption('mode', 'brunovariables');
}; };

View File

@ -130,7 +130,7 @@ class MultiLineEditor extends Component {
addOverlay = (variables) => { addOverlay = (variables) => {
this.variables = variables; this.variables = variables;
defineCodeMirrorBrunoVariablesMode(variables, 'text/plain'); defineCodeMirrorBrunoVariablesMode(variables, 'text/plain', false, true);
this.editor.setOption('mode', 'brunovariables'); this.editor.setOption('mode', 'brunovariables');
}; };

View File

@ -67,6 +67,7 @@ const GraphQLVariables = ({ variables, item, collection }) => {
mode="javascript" mode="javascript"
onRun={onRun} onRun={onRun}
onSave={onSave} onSave={onSave}
enableVariableHighlighting={true}
/> />
</> </>
); );

View File

@ -49,7 +49,7 @@ const RequestBody = ({ item, collection }) => {
<StyledWrapper className="w-full"> <StyledWrapper className="w-full">
<CodeEditor <CodeEditor
collection={collection} collection={collection}
item={item} item={item}
theme={displayedTheme} theme={displayedTheme}
font={get(preferences, 'font.codeFont', 'default')} font={get(preferences, 'font.codeFont', 'default')}
fontSize={get(preferences, 'font.codeFontSize')} fontSize={get(preferences, 'font.codeFontSize')}
@ -58,13 +58,14 @@ const RequestBody = ({ item, collection }) => {
onRun={onRun} onRun={onRun}
onSave={onSave} onSave={onSave}
mode={codeMirrorMode[bodyMode]} mode={codeMirrorMode[bodyMode]}
enableVariableHighlighting={true}
/> />
</StyledWrapper> </StyledWrapper>
); );
} }
if (bodyMode === 'file') { if (bodyMode === 'file') {
return <FileBody item={item} collection={collection}/> return <FileBody item={item} collection={collection} />;
} }
if (bodyMode === 'formUrlEncoded') { if (bodyMode === 'formUrlEncoded') {
@ -77,4 +78,4 @@ const RequestBody = ({ item, collection }) => {
return <StyledWrapper className="w-full">No Body</StyledWrapper>; return <StyledWrapper className="w-full">No Body</StyledWrapper>;
}; };
export default RequestBody; export default RequestBody;

View File

@ -146,7 +146,7 @@ class SingleLineEditor extends Component {
addOverlay = (variables) => { addOverlay = (variables) => {
this.variables = variables; this.variables = variables;
defineCodeMirrorBrunoVariablesMode(variables, 'text/plain', this.props.highlightPathParams); defineCodeMirrorBrunoVariablesMode(variables, 'text/plain', this.props.highlightPathParams, true);
this.editor.setOption('mode', 'brunovariables'); this.editor.setOption('mode', 'brunovariables');
}; };

View File

@ -74,11 +74,11 @@ export class MaskedEditor {
} else { } else {
for (let line = 0; line < lineCount; line++) { for (let line = 0; line < lineCount; line++) {
const lineLength = this.editor.getLine(line).length; const lineLength = this.editor.getLine(line).length;
const maskedNode = document.createTextNode('*'.repeat(lineLength)); const maskedNode = document.createTextNode('*'.repeat(lineLength));
this.editor.markText( this.editor.markText(
{ line, ch: 0 }, { line, ch: 0 },
{ line, ch: lineLength }, { line, ch: lineLength },
{ replacedWith: maskedNode, handleMouseEvents: false } { replacedWith: maskedNode, handleMouseEvents: false }
); );
} }
} }
@ -86,7 +86,18 @@ export class MaskedEditor {
}; };
} }
export const defineCodeMirrorBrunoVariablesMode = (_variables, mode, highlightPathParams) => { /**
* Defines a custom CodeMirror mode for Bruno variables highlighting.
* This function creates a specialized mode that can highlight both Bruno template
* variables (in the format {{variable}}) and URL path parameters (in the format /:param).
*
* @param {Object} _variables - The variables object containing data to validate against
* @param {string} mode - The base CodeMirror mode to extend (e.g., 'javascript', 'application/json')
* @param {boolean} highlightPathParams - Whether to highlight URL path parameters
* @param {boolean} highlightVariables - Whether to highlight template variables
* @returns {void} - Registers the mode with CodeMirror for later use
*/
export const defineCodeMirrorBrunoVariablesMode = (_variables, mode, highlightPathParams, highlightVariables) => {
CodeMirror.defineMode('brunovariables', function (config, parserConfig) { CodeMirror.defineMode('brunovariables', function (config, parserConfig) {
const { pathParams = {}, ...variables } = _variables || {}; const { pathParams = {}, ...variables } = _variables || {};
const variablesOverlay = { const variablesOverlay = {
@ -139,13 +150,15 @@ export const defineCodeMirrorBrunoVariablesMode = (_variables, mode, highlightPa
} }
}; };
let baseMode = CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || mode), variablesOverlay); let baseMode = CodeMirror.getMode(config, parserConfig.backdrop || mode);
if (highlightPathParams) { if (highlightVariables) {
return CodeMirror.overlayMode(baseMode, urlPathParamsOverlay); baseMode = CodeMirror.overlayMode(baseMode, variablesOverlay);
} else {
return baseMode;
} }
if (highlightPathParams) {
baseMode = CodeMirror.overlayMode(baseMode, urlPathParamsOverlay);
}
return baseMode;
}); });
}; };

View File

@ -5,6 +5,7 @@ const replacements = {
'pm\\.environment\\.set\\(': 'bru.setEnvVar(', 'pm\\.environment\\.set\\(': 'bru.setEnvVar(',
'pm\\.variables\\.get\\(': 'bru.getVar(', 'pm\\.variables\\.get\\(': 'bru.getVar(',
'pm\\.variables\\.set\\(': 'bru.setVar(', 'pm\\.variables\\.set\\(': 'bru.setVar(',
'pm\\.variables\\.replaceIn\\(': 'bru.interpolate(',
'pm\\.collectionVariables\\.get\\(': 'bru.getVar(', 'pm\\.collectionVariables\\.get\\(': 'bru.getVar(',
'pm\\.collectionVariables\\.set\\(': 'bru.setVar(', 'pm\\.collectionVariables\\.set\\(': 'bru.setVar(',
'pm\\.collectionVariables\\.has\\(': 'bru.hasVar(', 'pm\\.collectionVariables\\.has\\(': 'bru.hasVar(',

View File

@ -52,7 +52,7 @@ const simpleTranslations = {
'pm.variables.get': 'bru.getVar', 'pm.variables.get': 'bru.getVar',
'pm.variables.set': 'bru.setVar', 'pm.variables.set': 'bru.setVar',
'pm.variables.has': 'bru.hasVar', 'pm.variables.has': 'bru.hasVar',
'pm.variables.replaceIn': 'bru.interpolate',
// Collection variables // Collection variables
'pm.collectionVariables.get': 'bru.getVar', 'pm.collectionVariables.get': 'bru.getVar',
'pm.collectionVariables.set': 'bru.setVar', 'pm.collectionVariables.set': 'bru.setVar',

View File

@ -16,8 +16,8 @@ describe('postmanTranslations - comment handling', () => {
}); });
test('should comment non-translated pm commands', () => { test('should comment non-translated pm commands', () => {
const inputScript = "pm.test('random test', () => postman.variables.replaceIn('{{$guid}}'));"; const inputScript = "pm.test('random test', () => pm.cookies.get('cookieName'));";
const expectedOutput = "// test('random test', () => pm.variables.replaceIn('{{$guid}}'));"; const expectedOutput = "// test('random test', () => pm.cookies.get('cookieName'));";
expect(postmanTranslation(inputScript)).toBe(expectedOutput); expect(postmanTranslation(inputScript)).toBe(expectedOutput);
}); });

View File

@ -5,55 +5,104 @@ describe('Variables Translation', () => {
it('should translate pm.variables.get', () => { it('should translate pm.variables.get', () => {
const code = 'pm.variables.get("test");'; const code = 'pm.variables.get("test");';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.getVar("test");'); expect(translatedCode).toBe('bru.getVar("test");');
}); });
it('should translate pm.variables.set', () => { it('should translate pm.variables.set', () => {
const code = 'pm.variables.set("test", "value");'; const code = 'pm.variables.set("test", "value");';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.setVar("test", "value");'); expect(translatedCode).toBe('bru.setVar("test", "value");');
}); });
it('should translate pm.variables.has', () => { it('should translate pm.variables.has', () => {
const code = 'pm.variables.has("userId");'; const code = 'pm.variables.has("userId");';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.hasVar("userId");'); expect(translatedCode).toBe('bru.hasVar("userId");');
}); });
it('should translate pm.variables.replaceIn', () => {
const code = 'pm.variables.replaceIn("Hello {{name}}");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.interpolate("Hello {{name}}");');
});
it('should translate pm.variables.replaceIn with variables and expressions', () => {
const code = 'const greeting = pm.variables.replaceIn("Hello {{name}}, your user id is {{userId}}");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('const greeting = bru.interpolate("Hello {{name}}, your user id is {{userId}}");');
});
it('should translate pm.variables.replaceIn within complex expressions', () => {
const code = 'const url = baseUrl + pm.variables.replaceIn("/users/{{userId}}/profile");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('const url = baseUrl + bru.interpolate("/users/{{userId}}/profile");');
});
it('should translate pm.variables.replaceIn with multiple nested variable references', () => {
const code = 'const template = pm.variables.replaceIn("{{prefix}}-{{env}}-{{suffix}}");';
const translatedCode = translateCode(code);
expect(translatedCode).toBe('const template = bru.interpolate("{{prefix}}-{{env}}-{{suffix}}");');
});
it('should translate aliased variables.replaceIn', () => {
const code = `
const variables = pm.variables;
const message = variables.replaceIn("Welcome, {{username}}!");
`;
const translatedCode = translateCode(code);
expect(translatedCode).toBe(`
const message = bru.interpolate("Welcome, {{username}}!");
`);
});
// Collection variables tests // Collection variables tests
it('should translate pm.collectionVariables.get', () => { it('should translate pm.collectionVariables.get', () => {
const code = 'pm.collectionVariables.get("apiUrl");'; const code = 'pm.collectionVariables.get("apiUrl");';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.getVar("apiUrl");'); expect(translatedCode).toBe('bru.getVar("apiUrl");');
}); });
it('should translate pm.collectionVariables.set', () => { it('should translate pm.collectionVariables.set', () => {
const code = 'pm.collectionVariables.set("token", jsonData.token);'; const code = 'pm.collectionVariables.set("token", jsonData.token);';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.setVar("token", jsonData.token);'); expect(translatedCode).toBe('bru.setVar("token", jsonData.token);');
}); });
it('should translate pm.collectionVariables.has', () => { it('should translate pm.collectionVariables.has', () => {
const code = 'pm.collectionVariables.has("authToken");'; const code = 'pm.collectionVariables.has("authToken");';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.hasVar("authToken");'); expect(translatedCode).toBe('bru.hasVar("authToken");');
}); });
it('should translate pm.collectionVariables.unset', () => { it('should translate pm.collectionVariables.unset', () => {
const code = 'pm.collectionVariables.unset("tempVar");'; const code = 'pm.collectionVariables.unset("tempVar");';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.deleteVar("tempVar");'); expect(translatedCode).toBe('bru.deleteVar("tempVar");');
}); });
it('should handle pm.globals.get', () => { it('should handle pm.globals.get', () => {
const code = 'pm.globals.get("test");'; const code = 'pm.globals.get("test");';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.getGlobalEnvVar("test");'); expect(translatedCode).toBe('bru.getGlobalEnvVar("test");');
}); });
it('should handle pm.globals.set', () => { it('should handle pm.globals.set', () => {
const code = 'pm.globals.set("test", "value");'; const code = 'pm.globals.set("test", "value");';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.setGlobalEnvVar("test", "value");'); expect(translatedCode).toBe('bru.setGlobalEnvVar("test", "value");');
}); });
@ -66,6 +115,7 @@ describe('Variables Translation', () => {
const get = vars.get("test"); const get = vars.get("test");
`; `;
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe(` expect(translatedCode).toBe(`
const has = bru.hasVar("test"); const has = bru.hasVar("test");
const set = bru.setVar("test", "value"); const set = bru.setVar("test", "value");
@ -83,6 +133,7 @@ describe('Variables Translation', () => {
const unset = collVars.unset("test"); const unset = collVars.unset("test");
`; `;
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe(` expect(translatedCode).toBe(`
const has = bru.hasVar("test"); const has = bru.hasVar("test");
const set = bru.setVar("test", "value"); const set = bru.setVar("test", "value");
@ -98,6 +149,7 @@ describe('Variables Translation', () => {
const set = globals.set("test", "value"); const set = globals.set("test", "value");
`; `;
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe(` expect(translatedCode).toBe(`
const get = bru.getGlobalEnvVar("test"); const get = bru.getGlobalEnvVar("test");
const set = bru.setGlobalEnvVar("test", "value"); const set = bru.setGlobalEnvVar("test", "value");
@ -108,6 +160,7 @@ describe('Variables Translation', () => {
it('should handle conditional expressions with variable calls', () => { it('should handle conditional expressions with variable calls', () => {
const code = 'const userStatus = pm.variables.has("userId") ? "logged-in" : "guest";'; const code = 'const userStatus = pm.variables.has("userId") ? "logged-in" : "guest";';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('const userStatus = bru.hasVar("userId") ? "logged-in" : "guest";'); expect(translatedCode).toBe('const userStatus = bru.hasVar("userId") ? "logged-in" : "guest";');
}); });
@ -148,6 +201,7 @@ describe('Variables Translation', () => {
it('should handle more complex nested expressions with variables', () => { it('should handle more complex nested expressions with variables', () => {
const code = 'pm.collectionVariables.set("fullPath", pm.environment.get("baseUrl") + pm.variables.get("endpoint"));'; const code = 'pm.collectionVariables.set("fullPath", pm.environment.get("baseUrl") + pm.variables.get("endpoint"));';
const translatedCode = translateCode(code); const translatedCode = translateCode(code);
expect(translatedCode).toBe('bru.setVar("fullPath", bru.getEnvVar("baseUrl") + bru.getVar("endpoint"));'); expect(translatedCode).toBe('bru.setVar("fullPath", bru.getEnvVar("baseUrl") + bru.getVar("endpoint"));');
}); });
}); });

View File

@ -1,5 +1,5 @@
const { cloneDeep } = require('lodash'); const { cloneDeep } = require('lodash');
const { interpolate } = require('@usebruno/common'); const { interpolate: _interpolate } = require('@usebruno/common');
const variableNameRegex = /^[\w-.]*$/; const variableNameRegex = /^[\w-.]*$/;
@ -28,10 +28,10 @@ class Bru {
}; };
} }
_interpolate = (str) => { interpolate = (strOrObj) => {
if (!str || !str.length || typeof str !== 'string') { if (!strOrObj) return strOrObj;
return str; const isObj = typeof strOrObj === 'object';
} const strToInterpolate = isObj ? JSON.stringify(strOrObj) : strOrObj;
const combinedVars = { const combinedVars = {
...this.globalEnvironmentVariables, ...this.globalEnvironmentVariables,
@ -48,7 +48,8 @@ class Bru {
} }
}; };
return interpolate(str, combinedVars); const interpolatedStr = _interpolate(strToInterpolate, combinedVars);
return isObj ? JSON.parse(interpolatedStr) : interpolatedStr;
}; };
cwd() { cwd() {
@ -68,7 +69,7 @@ class Bru {
} }
getEnvVar(key) { getEnvVar(key) {
return this._interpolate(this.envVariables[key]); return this.interpolate(this.envVariables[key]);
} }
setEnvVar(key, value) { setEnvVar(key, value) {
@ -84,7 +85,7 @@ class Bru {
} }
getGlobalEnvVar(key) { getGlobalEnvVar(key) {
return this._interpolate(this.globalEnvironmentVariables[key]); return this.interpolate(this.globalEnvironmentVariables[key]);
} }
setGlobalEnvVar(key, value) { setGlobalEnvVar(key, value) {
@ -96,7 +97,7 @@ class Bru {
} }
getOauth2CredentialVar(key) { getOauth2CredentialVar(key) {
return this._interpolate(this.oauth2CredentialVariables[key]); return this.interpolate(this.oauth2CredentialVariables[key]);
} }
hasVar(key) { hasVar(key) {
@ -111,7 +112,7 @@ class Bru {
if (variableNameRegex.test(key) === false) { if (variableNameRegex.test(key) === false) {
throw new Error( throw new Error(
`Variable name: "${key}" contains invalid characters!` + `Variable name: "${key}" contains invalid characters!` +
' Names must only contain alpha-numeric characters, "-", "_", "."' ' Names must only contain alpha-numeric characters, "-", "_", "."'
); );
} }
@ -122,11 +123,11 @@ class Bru {
if (variableNameRegex.test(key) === false) { if (variableNameRegex.test(key) === false) {
throw new Error( throw new Error(
`Variable name: "${key}" contains invalid characters!` + `Variable name: "${key}" contains invalid characters!` +
' Names must only contain alpha-numeric characters, "-", "_", "."' ' Names must only contain alpha-numeric characters, "-", "_", "."'
); );
} }
return this._interpolate(this.runtimeVariables[key]); return this.interpolate(this.runtimeVariables[key]);
} }
deleteVar(key) { deleteVar(key) {
@ -142,15 +143,15 @@ class Bru {
} }
getCollectionVar(key) { getCollectionVar(key) {
return this._interpolate(this.collectionVariables[key]); return this.interpolate(this.collectionVariables[key]);
} }
getFolderVar(key) { getFolderVar(key) {
return this._interpolate(this.folderVariables[key]); return this.interpolate(this.folderVariables[key]);
} }
getRequestVar(key) { getRequestVar(key) {
return this._interpolate(this.requestVariables[key]); return this.interpolate(this.requestVariables[key]);
} }
setNextRequest(nextRequest) { setNextRequest(nextRequest) {

View File

@ -98,7 +98,7 @@ class ScriptRuntime {
}; };
} }
if(runRequestByItemPathname) { if (runRequestByItemPathname) {
context.bru.runRequest = runRequestByItemPathname; context.bru.runRequest = runRequestByItemPathname;
} }
@ -151,7 +151,7 @@ class ScriptRuntime {
chai, chai,
'node-fetch': fetch, 'node-fetch': fetch,
'crypto-js': CryptoJS, 'crypto-js': CryptoJS,
'xml2js': xml2js, xml2js: xml2js,
cheerio, cheerio,
tv4, tv4,
...whitelistedModules, ...whitelistedModules,
@ -235,7 +235,7 @@ class ScriptRuntime {
}; };
} }
if(runRequestByItemPathname) { if (runRequestByItemPathname) {
context.bru.runRequest = runRequestByItemPathname; context.bru.runRequest = runRequestByItemPathname;
} }

View File

@ -29,6 +29,12 @@ const addBruShimToContext = (vm, bru) => {
vm.setProp(bruObject, 'getProcessEnv', getProcessEnv); vm.setProp(bruObject, 'getProcessEnv', getProcessEnv);
getProcessEnv.dispose(); getProcessEnv.dispose();
let interpolate = vm.newFunction('interpolate', function (str) {
return marshallToVm(bru.interpolate(vm.dump(str)), vm);
});
vm.setProp(bruObject, 'interpolate', interpolate);
interpolate.dispose();
let hasEnvVar = vm.newFunction('hasEnvVar', function (key) { let hasEnvVar = vm.newFunction('hasEnvVar', function (key) {
return marshallToVm(bru.hasEnvVar(vm.dump(key)), vm); return marshallToVm(bru.hasEnvVar(vm.dump(key)), vm);
}); });
@ -157,7 +163,8 @@ const addBruShimToContext = (vm, bru) => {
let getTestResults = vm.newFunction('getTestResults', () => { let getTestResults = vm.newFunction('getTestResults', () => {
const promise = vm.newPromise(); const promise = vm.newPromise();
bru.getTestResults() bru
.getTestResults()
.then((results) => { .then((results) => {
promise.resolve(marshallToVm(cleanJson(results), vm)); promise.resolve(marshallToVm(cleanJson(results), vm));
}) })
@ -178,7 +185,8 @@ const addBruShimToContext = (vm, bru) => {
let getAssertionResults = vm.newFunction('getAssertionResults', () => { let getAssertionResults = vm.newFunction('getAssertionResults', () => {
const promise = vm.newPromise(); const promise = vm.newPromise();
bru.getAssertionResults() bru
.getAssertionResults()
.then((results) => { .then((results) => {
promise.resolve(marshallToVm(cleanJson(results), vm)); promise.resolve(marshallToVm(cleanJson(results), vm));
}) })
@ -199,7 +207,8 @@ const addBruShimToContext = (vm, bru) => {
let runRequestHandle = vm.newFunction('runRequest', (args) => { let runRequestHandle = vm.newFunction('runRequest', (args) => {
const promise = vm.newPromise(); const promise = vm.newPromise();
bru.runRequest(vm.dump(args)) bru
.runRequest(vm.dump(args))
.then((response) => { .then((response) => {
const { status, headers, data, dataBuffer, size, statusText } = response || {}; const { status, headers, data, dataBuffer, size, statusText } = response || {};
promise.resolve(marshallToVm(cleanJson({ status, statusText, headers, data, dataBuffer, size }), vm)); promise.resolve(marshallToVm(cleanJson({ status, statusText, headers, data, dataBuffer, size }), vm));

View File

@ -0,0 +1,39 @@
meta {
name: interpolate
type: http
seq: 13
}
get {
url: {{host}}/ping
body: none
auth: none
}
tests {
test("should interpolate envs", function() {
const interpolated = bru.interpolate("url: {{host}}")
expect(interpolated).to.equal("url: https://testbench-sanity.usebruno.com");
});
test("should interpolate random variables", function() {
const a = bru.interpolate("{{$randomInt}}")
const b = bru.interpolate("{{$randomInt}}")
expect(a).to.not.equal(b)
});
const randomObj = {
host: "{{host}}",
int: "{{$randomInt}}",
timestamp: "{{$timestamp}}"
}
test("should interpolate objects with vars, random vars", function() {
const objA = bru.interpolate(randomObj)
const objB = bru.interpolate(randomObj)
expect(objA).to.be.an("object")
expect(objB).to.be.an("object")
expect(objA).to.not.deep.eql(objB)
});
}