diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js index 01a5f083..75f55643 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -183,7 +183,7 @@ export const collectionsSlice = createSlice({ } }, scriptEnvironmentUpdateEvent: (state, action) => { - const { collectionUid, environment, collectionVariables } = action.payload; + const { collectionUid, envVariables, collectionVariables } = action.payload; const collection = findCollectionByUid(state.collections, collectionUid); if (collection) { @@ -191,7 +191,7 @@ export const collectionsSlice = createSlice({ const activeEnvironment = findEnvironmentInCollection(collection, activeEnvironmentUid); if (activeEnvironment) { - forOwn(environment, (value, key) => { + forOwn(envVariables, (value, key) => { const variable = find(activeEnvironment.variables, (v) => v.name === key); if (variable) { @@ -201,7 +201,6 @@ export const collectionsSlice = createSlice({ } collection.collectionVariables = collectionVariables; - } }, requestCancelled: (state, action) => { diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index 9994ee14..bb426792 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -13,7 +13,7 @@ "pack-app": "electron-builder --dir" }, "dependencies": { - "@usebruno/js": "0.1.0", + "@usebruno/js": "0.2.0", "@usebruno/lang": "0.2.2", "@usebruno/schema": "0.3.1", "axios": "^0.26.0", diff --git a/packages/bruno-electron/src/app/watcher.js b/packages/bruno-electron/src/app/watcher.js index 4fdaad7b..988b00bf 100644 --- a/packages/bruno-electron/src/app/watcher.js +++ b/packages/bruno-electron/src/app/watcher.js @@ -42,6 +42,7 @@ const hydrateRequestWithUuid = (request, pathname) => { const headers = _.get(request, 'request.headers', []); const requestVars = _.get(request, 'request.vars.req', []); const responseVars = _.get(request, 'request.vars.res', []); + const assertions = _.get(request, 'request.assertions', []); const bodyFormUrlEncoded = _.get(request, 'request.body.formUrlEncoded', []); const bodyMultipartForm = _.get(request, 'request.body.multipartForm', []); @@ -49,6 +50,7 @@ const hydrateRequestWithUuid = (request, pathname) => { headers.forEach((header) => header.uid = uuid()); requestVars.forEach((variable) => variable.uid = uuid()); responseVars.forEach((variable) => variable.uid = uuid()); + assertions.forEach((assertion) => assertion.uid = uuid()); bodyFormUrlEncoded.forEach((param) => param.uid = uuid()); bodyMultipartForm.forEach((param) => param.uid = uuid()); diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js index 5a15f4d4..0e669fef 100644 --- a/packages/bruno-electron/src/ipc/network/index.js +++ b/packages/bruno-electron/src/ipc/network/index.js @@ -3,7 +3,7 @@ const Mustache = require('mustache'); const FormData = require('form-data'); const { ipcMain } = require('electron'); const { forOwn, extend, each, get } = require('lodash'); -const { ScriptRuntime, TestRuntime } = require('@usebruno/js'); +const { VarsRuntime, AssertRuntime, ScriptRuntime, TestRuntime } = require('@usebruno/js'); const prepareRequest = require('./prepare-request'); const prepareGqlIntrospectionRequest = require('./prepare-gql-introspection-request'); const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../../utils/cancel-token'); @@ -96,13 +96,27 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => { const envVars = getEnvVars(environment); + // run pre-request vars + const preRequestVars = get(request, 'vars.req', []); + if(preRequestVars && preRequestVars.length) { + const varsRuntime = new VarsRuntime(); + const result = varsRuntime.runPreRequestVars(preRequestVars, request, envVars, collectionVariables, collectionPath); + + mainWindow.webContents.send('main:script-environment-update', { + envVariables: result.envVariables, + collectionVariables: result.collectionVariables, + collectionUid + }); + } + + // run pre-request script const requestScript = get(request, 'script.req'); if(requestScript && requestScript.length) { const scriptRuntime = new ScriptRuntime(); const result = scriptRuntime.runRequestScript(requestScript, request, envVars, collectionVariables, collectionPath); mainWindow.webContents.send('main:script-environment-update', { - environment: result.environment, + envVariables: result.envVariables, collectionVariables: result.collectionVariables, collectionUid }); @@ -127,18 +141,33 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => { const response = await axios(request); + // run post-response vars + const postResponseVars = get(request, 'vars.res', []); + if(postResponseVars && postResponseVars.length) { + const varsRuntime = new VarsRuntime(); + const result = varsRuntime.runPostResponseVars(postResponseVars, request, response, envVars, collectionVariables, collectionPath); + + mainWindow.webContents.send('main:script-environment-update', { + envVariables: result.envVariables, + collectionVariables: result.collectionVariables, + collectionUid + }); + } + + // run post-response script const responseScript = get(request, 'script.res'); if(responseScript && responseScript.length) { const scriptRuntime = new ScriptRuntime(); const result = scriptRuntime.runResponseScript(responseScript, request, response, envVars, collectionVariables, collectionPath); mainWindow.webContents.send('main:script-environment-update', { - environment: result.environment, + envVariables: result.envVariables, collectionVariables: result.collectionVariables, collectionUid }); } + // run tests const testFile = get(item, 'request.tests'); if(testFile && testFile.length) { const testRuntime = new TestRuntime(); @@ -284,18 +313,27 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => { request.data = form; } + // run pre-request vars + const preRequestVars = get(request, 'vars.req', []); + if(preRequestVars && preRequestVars.length) { + const varsRuntime = new VarsRuntime(); + varsRuntime.runPreRequestVars(preRequestVars, request, envVars, collectionVariables, collectionPath); + } + + // run pre-request script const requestScript = get(request, 'script.req'); if(requestScript && requestScript.length) { const scriptRuntime = new ScriptRuntime(); const result = scriptRuntime.runRequestScript(requestScript, request, envVars, collectionVariables, collectionPath); mainWindow.webContents.send('main:script-environment-update', { - environment: result.environment, + envVariables: result.envVariables, collectionVariables: result.collectionVariables, collectionUid }); } + // interpolate variables inside request interpolateVars(request, envVars, collectionVariables); // todo: @@ -312,17 +350,26 @@ const registerNetworkIpc = (mainWindow, watcher, lastOpenedCollections) => { ...eventData }); + // send request timeStart = Date.now(); const response = await axios(request); timeEnd = Date.now(); + // run post-response vars + const postResponseVars = get(request, 'vars.res', []); + if(postResponseVars && postResponseVars.length) { + const varsRuntime = new VarsRuntime(); + varsRuntime.runPostResponseVars(postResponseVars, request, response, envVars, collectionVariables, collectionPath); + } + + // run response script const responseScript = get(request, 'script.res'); if(responseScript && responseScript.length) { const scriptRuntime = new ScriptRuntime(); const result = scriptRuntime.runResponseScript(responseScript, request, response, envVars, collectionVariables, collectionPath); mainWindow.webContents.send('main:script-environment-update', { - environment: result.environment, + envVariables: result.envVariables, collectionVariables: result.collectionVariables, collectionUid }); diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js index 48dd393f..ef2feb45 100644 --- a/packages/bruno-electron/src/ipc/network/prepare-request.js +++ b/packages/bruno-electron/src/ipc/network/prepare-request.js @@ -63,6 +63,9 @@ const prepareRequest = (request) => { axiosRequest.script = request.script; } + axiosRequest.vars = request.vars; + axiosRequest.assertions = request.assertions; + return axiosRequest; }; diff --git a/packages/bruno-js/src/runtime/script-runtime.js b/packages/bruno-js/src/runtime/script-runtime.js index 77a2b274..39ce6b1b 100644 --- a/packages/bruno-js/src/runtime/script-runtime.js +++ b/packages/bruno-js/src/runtime/script-runtime.js @@ -17,8 +17,8 @@ class ScriptRuntime { constructor() { } - runRequestScript(script, request, environment, collectionVariables, collectionPath) { - const bru = new Bru(environment, collectionVariables); + runRequestScript(script, request, envVariables, collectionVariables, collectionPath) { + const bru = new Bru(envVariables, collectionVariables); const req = new BrunoRequest(request); const context = { @@ -47,13 +47,13 @@ class ScriptRuntime { return { request, - environment, + envVariables, collectionVariables }; } - runResponseScript(script, request, response, environment, collectionVariables, collectionPath) { - const bru = new Bru(environment, collectionVariables); + runResponseScript(script, request, response, envVariables, collectionVariables, collectionPath) { + const bru = new Bru(envVariables, collectionVariables); const req = new BrunoRequest(request); const res = new BrunoResponse(response); @@ -84,7 +84,7 @@ class ScriptRuntime { return { response, - environment, + envVariables, collectionVariables }; } diff --git a/packages/bruno-js/src/runtime/test-runtime.js b/packages/bruno-js/src/runtime/test-runtime.js index cbb1050f..8ad12603 100644 --- a/packages/bruno-js/src/runtime/test-runtime.js +++ b/packages/bruno-js/src/runtime/test-runtime.js @@ -20,8 +20,8 @@ class TestRuntime { constructor() { } - runTests(testsFile, request, response, environment, collectionVariables, collectionPath) { - const bru = new Bru(environment, collectionVariables); + runTests(testsFile, request, response, envVariables, collectionVariables, collectionPath) { + const bru = new Bru(envVariables, collectionVariables); const req = new BrunoRequest(request); const res = new BrunoResponse(response); @@ -60,7 +60,7 @@ class TestRuntime { return { request, - environment, + envVariables, collectionVariables, results: __brunoTestResults.getResults() }; diff --git a/packages/bruno-js/src/runtime/vars-runtime.js b/packages/bruno-js/src/runtime/vars-runtime.js index fdc07d38..dd651d52 100644 --- a/packages/bruno-js/src/runtime/vars-runtime.js +++ b/packages/bruno-js/src/runtime/vars-runtime.js @@ -1,7 +1,7 @@ const _ = require('lodash'); const Bru = require('../bru'); const BrunoRequest = require('../bruno-request'); -const { evaluateJsExpression, createResponseParser } = require('../utils'); +const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils'); class VarsRuntime { runPreRequestVars(vars, request, envVariables, collectionVariables, collectionPath) { @@ -25,9 +25,13 @@ class VarsRuntime { } _.each(enabledVars, (v) => { - const value = evaluateJsExpression(v.value, context); + const value = evaluateJsTemplateLiteral(v.value, context); bru.setVar(v.name, value); }); + + return { + collectionVariables + }; } runPostResponseVars(vars, request, response, envVariables, collectionVariables, collectionPath) { @@ -56,6 +60,11 @@ class VarsRuntime { const value = evaluateJsExpression(v.value, context); bru.setVar(v.name, value); }); + + return { + envVariables, + collectionVariables + }; } } diff --git a/packages/bruno-js/src/utils.js b/packages/bruno-js/src/utils.js index 26292690..04fe7126 100644 --- a/packages/bruno-js/src/utils.js +++ b/packages/bruno-js/src/utils.js @@ -60,6 +60,46 @@ const evaluateJsExpression = (expression, context) => { return fn(context); }; +const evaluateJsTemplateLiteral = (templateLiteral, context) => { + if(!templateLiteral || !templateLiteral.length || typeof templateLiteral !== 'string') { + return templateLiteral; + } + + templateLiteral = templateLiteral.trim(); + + if(templateLiteral === 'true') { + return true; + } + + if(templateLiteral === 'false') { + return false; + } + + if(templateLiteral === 'null') { + return null; + } + + if(templateLiteral === 'undefined') { + return undefined; + } + + if(templateLiteral.startsWith('"') && templateLiteral.endsWith('"')) { + return templateLiteral.slice(1, -1); + } + + if(templateLiteral.startsWith("'") && templateLiteral.endsWith("'")) { + return templateLiteral.slice(1, -1); + } + + if(!isNaN(templateLiteral)) { + return Number(templateLiteral); + } + + templateLiteral = "`" + templateLiteral + "`"; + + return evaluateJsExpression(templateLiteral, context); +}; + const createResponseParser = (response = {}) => { const res = (expr, ...fns) => { return get(response.data, expr, ...fns); @@ -80,6 +120,7 @@ const createResponseParser = (response = {}) => { module.exports = { evaluateJsExpression, + evaluateJsTemplateLiteral, createResponseParser, internalExpressionCache }; \ No newline at end of file