diff --git a/packages/insomnia-smoke-test/fixtures/pre-request-collection.yaml b/packages/insomnia-smoke-test/fixtures/pre-request-collection.yaml index 097025945..8248a0fe0 100644 --- a/packages/insomnia-smoke-test/fixtures/pre-request-collection.yaml +++ b/packages/insomnia-smoke-test/fixtures/pre-request-collection.yaml @@ -205,6 +205,10 @@ resources: environmentPropertyOrder: null metaSortKey: -1668533312225 _type: request_group + preRequestScript: |- + insomnia.environment.set('onlySetByFolderPreScript', 888); + afterResponseScript: |- + insomnia.environment.unset('onlySetByFolderPreScript'); - _id: req_89dade2ee9ee42fbb22d588783a9df3c parentId: fld_01de564274824ecaad272330339ea6b2 modified: 1636707449231 @@ -1194,3 +1198,32 @@ resources: "setByScript": "{{ setByScript }}" } _type: request + - _id: req_89dade2ee9ee42fbb22d588783a9df20 + parentId: fld_01de564274824ecaad272330339ea6b2 + modified: 1636707449231 + created: 1636141014552 + url: http://127.0.0.1:4010/echo + name: run parent scripts only + description: "" + method: POST + parameters: [] + headers: + - name: 'Content-Type' + value: 'application/json' + authentication: {} + metaSortKey: -1636141014553 + isPrivate: false + settingStoreCookies: true + settingSendCookies: true + settingDisableRenderRequestBody: false + settingEncodeUrl: true + settingRebuildPath: true + settingFollowRedirects: global + preRequestScript: '' + body: + mimeType: "application/json" + text: |- + { + "onlySetByFolderPreScript": {{ onlySetByFolderPreScript }} + } + _type: request diff --git a/packages/insomnia-smoke-test/tests/smoke/pre-request-script-features.test.ts b/packages/insomnia-smoke-test/tests/smoke/pre-request-script-features.test.ts index 8d742a46f..6e445ba5b 100644 --- a/packages/insomnia-smoke-test/tests/smoke/pre-request-script-features.test.ts +++ b/packages/insomnia-smoke-test/tests/smoke/pre-request-script-features.test.ts @@ -174,12 +174,12 @@ test.describe('pre-request features tests', async () => { asyncTaskDone: true, }, }, - // { - // name: 'can manipulate global envs', - // expectedBody: { - // setByScript: 'setByScript', - // }, - // }, + { + name: 'run parent scripts only', + expectedBody: { + 'onlySetByFolderPreScript': 888, + }, + }, ]; for (let i = 0; i < testCases.length; i++) { diff --git a/packages/insomnia/src/network/network.ts b/packages/insomnia/src/network/network.ts index af8e8a798..62f3b4c24 100644 --- a/packages/insomnia/src/network/network.ts +++ b/packages/insomnia/src/network/network.ts @@ -105,7 +105,8 @@ export const fetchRequestData = async (requestId: string) => { const timelinePath = pathJoin(responsesDir, responseId + '.timeline'); return { request, environment, settings, clientCertificates, caCert, activeEnvironmentId, timelinePath, responseId }; }; -export const getPreRequestScriptOutput = async ({ + +export const tryToExecutePreRequestScript = async ({ request, environment, settings, @@ -122,16 +123,32 @@ export const getPreRequestScriptOutput = async ({ activeGlobalEnvironment = await models.environment.getById(workspaceMeta.activeGlobalEnvironmentId) || undefined; } - if (!request.preRequestScript) { + const requestGroups = await db.withAncestors(request, [ + models.requestGroup.type, + ]) as (Request | RequestGroup)[]; + + const folderScripts = requestGroups.reverse() + .filter(group => group?.preRequestScript) + .map((group, i) => `const fn${i} = async ()=>{ + ${group.preRequestScript} + } + await fn${i}(); + `); + if (folderScripts.length === 0) { return { request, environment, baseEnvironment, clientCertificates, settings, + cookieJar, + globals: activeGlobalEnvironment, }; } - const mutatedContext = await tryToExecutePreRequestScript({ + const joinedScript = [...folderScripts].join('\n'); + + const mutatedContext = await tryToExecuteScript({ + script: joinedScript, request, environment, timelinePath, @@ -155,6 +172,7 @@ export const getPreRequestScriptOutput = async ({ clientCertificates: mutatedContext.clientCertificates || clientCertificates, settings: mutatedContext.settings || settings, globals: mutatedContext.globals, + cookieJar: mutatedContext.cookieJar, }; }; @@ -163,7 +181,7 @@ export const getPreRequestScriptOutput = async ({ // - If no global environment is seleted, no operation // - If one global environment is selected, it persists content to the selected global environment (base or sub). export async function savePatchesMadeByScript( - mutatedContext: Awaited>, + mutatedContext: Awaited>, environment: Environment, baseEnvironment: Environment, activeGlobalEnvironment: Environment | undefined, @@ -334,29 +352,15 @@ interface RequestContextForScript { cookieJar: CookieJar; globals?: Environment; // there could be no global environment } + type RequestAndContextAndResponse = RequestContextForScript & { response: sendCurlAndWriteTimelineError | sendCurlAndWriteTimelineResponse; }; + type RequestAndContextAndOptionalResponse = RequestContextForScript & { script: string; response?: sendCurlAndWriteTimelineError | sendCurlAndWriteTimelineResponse; }; -export async function tryToExecutePreRequestScript(context: RequestContextForScript) { - const requestGroups = await db.withAncestors(context.request, [ - models.requestGroup.type, - ]) as (Request | RequestGroup)[]; - - const folderScripts = requestGroups.reverse() - .filter(group => group?.preRequestScript) - .map((group, i) => `const fn${i} = async ()=>{ - ${group.preRequestScript} - } - await fn${i}(); - `); - const joinedScript = [...folderScripts].join('\n'); - - return tryToExecuteScript({ script: joinedScript, ...context }); -}; export async function tryToExecuteAfterResponseScript(context: RequestAndContextAndResponse) { const requestGroups = await db.withAncestors(context.request, [ @@ -370,9 +374,18 @@ export async function tryToExecuteAfterResponseScript(context: RequestAndContext } await fn${i}(); `); + if (folderScripts.length === 0) { + return context; + } const joinedScript = [...folderScripts].join('\n'); - return tryToExecuteScript({ script: joinedScript, ...context }); + const postMutatedContext = await tryToExecuteScript({ script: joinedScript, ...context }); + if (!postMutatedContext?.request) { + return null; + } + await savePatchesMadeByScript(postMutatedContext, context.environment, context.baseEnvironment, context.globals); + + return postMutatedContext; } export const tryToInterpolateRequest = async ( diff --git a/packages/insomnia/src/ui/routes/request.tsx b/packages/insomnia/src/ui/routes/request.tsx index eee3d3c4e..6f2172860 100644 --- a/packages/insomnia/src/ui/routes/request.tsx +++ b/packages/insomnia/src/ui/routes/request.tsx @@ -26,7 +26,7 @@ import { Response } from '../../models/response'; import { isWebSocketRequest, isWebSocketRequestId, WebSocketRequest } from '../../models/websocket-request'; import { WebSocketResponse } from '../../models/websocket-response'; import { getAuthHeader } from '../../network/authentication'; -import { fetchRequestData, getPreRequestScriptOutput, responseTransform, savePatchesMadeByScript, sendCurlAndWriteTimeline, tryToExecuteAfterResponseScript, tryToInterpolateRequest, tryToTransformRequestWithPlugins } from '../../network/network'; +import { fetchRequestData, responseTransform, sendCurlAndWriteTimeline, tryToExecuteAfterResponseScript, tryToExecutePreRequestScript, tryToInterpolateRequest, tryToTransformRequestWithPlugins } from '../../network/network'; import { RenderErrorSubType } from '../../templating'; import { invariant } from '../../utils/invariant'; import { SegmentEvent } from '../analytics'; @@ -367,8 +367,9 @@ export const sendAction: ActionFunction = async ({ request, params }) => { try { window.main.startExecution({ requestId }); const requestData = await fetchRequestData(requestId); + window.main.addExecutionStep({ requestId, stepName: 'Executing pre-request script' }); - const mutatedContext = await getPreRequestScriptOutput(requestData, workspaceId); + const mutatedContext = await tryToExecutePreRequestScript(requestData, workspaceId); window.main.completeExecutionStep({ requestId }); if (mutatedContext === null) { return null; @@ -421,29 +422,14 @@ export const sendAction: ActionFunction = async ({ request, params }) => { const shouldWriteToFile = shouldPromptForPathAfterResponse && is2XXWithBodyPath; mutatedContext.request.afterResponseScript = afterResponseScript; - if (requestData.request.afterResponseScript) { - const baseEnvironment = await models.environment.getOrCreateForParentId(workspaceId); - const cookieJar = await models.cookieJar.getOrCreateForParentId(workspaceId); - const globals = mutatedContext.globals; + window.main.addExecutionStep({ requestId, stepName: 'Executing after-response script' }); + await tryToExecuteAfterResponseScript({ + ...requestData, + ...mutatedContext, + response, + }); + window.main.completeExecutionStep({ requestId }); - window.main.addExecutionStep({ requestId, stepName: 'Executing after-response script' }); - - const postMutatedContext = await tryToExecuteAfterResponseScript({ - ...requestData, - ...mutatedContext, - baseEnvironment, - cookieJar, - response, - globals, - }); - window.main.completeExecutionStep({ requestId }); - if (!postMutatedContext?.request) { - // exiy early if there was a problem with the pre-request script - // TODO: improve error message? - return null; - } - await savePatchesMadeByScript(postMutatedContext, requestData.environment, baseEnvironment, globals); - } if (!shouldWriteToFile) { const response = await models.response.create(responsePatch, requestData.settings.maxHistoryResponses); await models.requestMeta.update(requestMeta, { activeResponseId: response._id });