mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-24 16:20:39 -04:00
feat(GUI): enable test results pane (#7737)
* feat: enable the test result pane * test: bring back tests and cleanups * chore: replace tabitem with tabpanel * chore: useMemo for test result counts * refactor: abstract RequestTestResultRows as a component
This commit is contained in:
@@ -12,6 +12,7 @@ export function test(
|
||||
testCase: msg,
|
||||
status: 'passed',
|
||||
executionTime,
|
||||
category: 'unknown',
|
||||
});
|
||||
} catch (e) {
|
||||
const executionTime = performance.now() - started;
|
||||
@@ -20,6 +21,7 @@ export function test(
|
||||
status: 'failed',
|
||||
executionTime,
|
||||
errorMessage: `${e}`,
|
||||
category: 'unknown',
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -33,15 +35,18 @@ export function skip(
|
||||
testCase: msg,
|
||||
status: 'skipped',
|
||||
executionTime: 0,
|
||||
category: 'unknown',
|
||||
});
|
||||
}
|
||||
|
||||
export type TestStatus = 'passed' | 'failed' | 'skipped';
|
||||
export type TestCategory = 'unknown' | 'pre-request' | 'after-response';
|
||||
export interface RequestTestResult {
|
||||
testCase: string;
|
||||
status: TestStatus;
|
||||
executionTime: number; // milliseconds
|
||||
errorMessage?: string;
|
||||
category: TestCategory;
|
||||
}
|
||||
|
||||
export interface TestHandler {
|
||||
|
||||
@@ -19,20 +19,20 @@ test.describe('after-response script features tests', async () => {
|
||||
await page.getByLabel('After-response Scripts').click();
|
||||
});
|
||||
|
||||
// test('insomnia.test and insomnia.expect can work together', async ({ page }) => {
|
||||
// const responsePane = page.getByTestId('response-pane');
|
||||
test('post: insomnia.test and insomnia.expect can work together', async ({ page }) => {
|
||||
await page.getByLabel('Request Collection').getByTestId('tests with expect and test').press('Enter');
|
||||
|
||||
// await page.getByLabel('Request Collection').getByTestId('tests with expect and test').press('Enter');
|
||||
// send
|
||||
await page.getByTestId('request-pane').getByRole('button', { name: 'Send' }).click();
|
||||
|
||||
// // send
|
||||
// await page.getByTestId('request-pane').getByRole('button', { name: 'Send' }).click();
|
||||
// verify
|
||||
await page.getByRole('tab', { name: 'Tests' }).click();
|
||||
|
||||
// // verify
|
||||
// await page.getByRole('tab', { name: 'Console' }).click();
|
||||
|
||||
// await expect(responsePane).toContainText('✓ happy tests');
|
||||
// await expect(responsePane).toContainText('✕ unhappy tests: AssertionError: expected 199 to deeply equal 200');
|
||||
// });
|
||||
const rows = page.getByTestId('test-result-row');
|
||||
await expect(rows.first()).toContainText('PASS');
|
||||
await expect(rows.nth(1)).toContainText('FAIL');
|
||||
await expect(rows.nth(1)).toContainText('AssertionError:');
|
||||
});
|
||||
|
||||
test('environment and baseEnvironment can be persisted', async ({ page }) => {
|
||||
const statusTag = page.locator('[data-testid="response-status-tag"]:visible');
|
||||
|
||||
@@ -399,20 +399,20 @@ test.describe('pre-request features tests', async () => {
|
||||
await expect(responsePane).toContainText('fixtures/certificates/fake.pfx'); // original proxy
|
||||
});
|
||||
|
||||
// test('insomnia.test and insomnia.expect can work together ', async ({ page }) => {
|
||||
// const responsePane = page.getByTestId('response-pane');
|
||||
test('pre: insomnia.test and insomnia.expect can work together', async ({ page }) => {
|
||||
await page.getByLabel('Request Collection').getByTestId('insomnia.test').press('Enter');
|
||||
|
||||
// await page.getByLabel('Request Collection').getByTestId('insomnia.test').press('Enter');
|
||||
// send
|
||||
await page.getByTestId('request-pane').getByRole('button', { name: 'Send' }).click();
|
||||
|
||||
// // send
|
||||
// await page.getByTestId('request-pane').getByRole('button', { name: 'Send' }).click();
|
||||
// verify
|
||||
await page.getByRole('tab', { name: 'Tests' }).click();
|
||||
|
||||
// // verify
|
||||
// await page.getByRole('tab', { name: 'Console' }).click();
|
||||
|
||||
// await expect(responsePane).toContainText('✓ happy tests');
|
||||
// await expect(responsePane).toContainText('✕ unhappy tests: AssertionError: expected 199 to deeply equal 200');
|
||||
// });
|
||||
const rows = page.getByTestId('test-result-row');
|
||||
await expect(rows.first()).toContainText('PASS');
|
||||
await expect(rows.nth(1)).toContainText('FAIL');
|
||||
await expect(rows.nth(1)).toContainText('AssertionError:');
|
||||
});
|
||||
|
||||
test('environment and baseEnvironment can be persisted', async ({ page }) => {
|
||||
const statusTag = page.locator('[data-testid="response-status-tag"]:visible');
|
||||
|
||||
@@ -56,6 +56,7 @@ test.describe('test hidden window handling', async () => {
|
||||
expect(await page.locator('.pane-two pre').innerText()).toEqual('Timeout: Running script took too long');
|
||||
await page.getByRole('tab', { name: 'Console' }).click();
|
||||
await page.getByRole('tab', { name: 'Preview' }).click();
|
||||
|
||||
const windows = await app.windows();
|
||||
const hiddenWindow = windows[1];
|
||||
hiddenWindow.close();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import fs from 'fs';
|
||||
import type { RequestTestResult } from 'insomnia-sdk';
|
||||
import { Readable } from 'stream';
|
||||
import zlib from 'zlib';
|
||||
|
||||
@@ -46,6 +47,7 @@ export interface BaseResponse {
|
||||
// Things from the request
|
||||
settingStoreCookies: boolean | null;
|
||||
settingSendCookies: boolean | null;
|
||||
requestTestResults: RequestTestResult[];
|
||||
}
|
||||
|
||||
export type Response = BaseModel & BaseResponse;
|
||||
@@ -80,6 +82,7 @@ export function init(): BaseResponse {
|
||||
// Responses sent before environment filtering will have a special value
|
||||
// so they don't show up at all when filtering is on.
|
||||
environmentId: '__LEGACY__',
|
||||
requestTestResults: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -177,6 +177,7 @@ export const tryToExecutePreRequestScript = async ({
|
||||
settings,
|
||||
cookieJar,
|
||||
globals: activeGlobalEnvironment,
|
||||
requestTestResults: new Array<RequestTestResult>(),
|
||||
};
|
||||
}
|
||||
const joinedScript = [...folderScripts].join('\n');
|
||||
@@ -207,6 +208,7 @@ export const tryToExecutePreRequestScript = async ({
|
||||
settings: mutatedContext.settings || settings,
|
||||
globals: mutatedContext.globals,
|
||||
cookieJar: mutatedContext.cookieJar,
|
||||
requestTestResults: mutatedContext.requestTestResults,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -411,7 +413,10 @@ export async function tryToExecuteAfterResponseScript(context: RequestAndContext
|
||||
await fn${i}();
|
||||
`);
|
||||
if (folderScripts.length === 0) {
|
||||
return context;
|
||||
return {
|
||||
...context,
|
||||
requestTestResults: new Array<RequestTestResult>(),
|
||||
};
|
||||
}
|
||||
const joinedScript = [...folderScripts].join('\n');
|
||||
|
||||
|
||||
@@ -37,11 +37,12 @@ export const MockResponseExtractor = () => {
|
||||
const mimeType = maybeMimeType && isInMockContentTypeList(maybeMimeType) ? maybeMimeType : 'text/plain';
|
||||
return (
|
||||
<div className="px-32 h-full flex flex-col justify-center">
|
||||
<div className="flex place-content-center text-9xl pb-2 text-[--hl-md]">
|
||||
<div className="flex place-content-center text-9xl pb-8 text-[--hl-md]">
|
||||
<Icon icon="cube" />
|
||||
</div>
|
||||
<div className="flex place-content-center pb-2">
|
||||
Transform this {getContentTypeName(activeResponse?.contentType) || ''} response to a new mock route or overwrite an existing one.
|
||||
Transform this
|
||||
{activeResponse?.contentType ? getContentTypeName(activeResponse?.contentType) === 'Other' ? '' : ` ${getContentTypeName(activeResponse?.contentType)}` : ''} response to a new mock route or overwrite an existing one.
|
||||
</div>
|
||||
<form
|
||||
onSubmit={async e => {
|
||||
@@ -151,7 +152,7 @@ export const MockResponseExtractor = () => {
|
||||
setSelectedMockRoute('');
|
||||
}}
|
||||
>
|
||||
<option value="">-- Create new... --</option>
|
||||
<option value="">-- Create new --</option>
|
||||
{mockServerAndRoutes
|
||||
.map(w => (
|
||||
<option key={w._id} value={w._id}>
|
||||
@@ -177,7 +178,7 @@ export const MockResponseExtractor = () => {
|
||||
setSelectedMockRoute(selected);
|
||||
}}
|
||||
>
|
||||
<option value="">-- Create new... --</option>
|
||||
<option value="">-- Create new --</option>
|
||||
{mockServerAndRoutes.find(s => s._id === selectedMockServer)?.routes
|
||||
.map(w => (
|
||||
<option key={w._id} value={w._id}>
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
import crypto from 'crypto';
|
||||
import type { RequestTestResult } from 'insomnia-sdk';
|
||||
import React, { type FC, useState } from 'react';
|
||||
import { Toolbar } from 'react-aria-components';
|
||||
|
||||
import { fuzzyMatch } from '../../../common/misc';
|
||||
|
||||
type TargetTestType = 'all' | 'passed' | 'failed' | 'skipped';
|
||||
|
||||
interface RequestTestResultRowsProps {
|
||||
requestTestResults: RequestTestResult[];
|
||||
resultFilter: string;
|
||||
targetTests: string;
|
||||
}
|
||||
|
||||
const RequestTestResultRows: FC<RequestTestResultRowsProps> = ({
|
||||
requestTestResults,
|
||||
resultFilter,
|
||||
targetTests,
|
||||
}: RequestTestResultRowsProps) => {
|
||||
const testResultRows = requestTestResults
|
||||
.filter(result => {
|
||||
switch (targetTests) {
|
||||
case 'all':
|
||||
return true;
|
||||
case 'passed':
|
||||
return result.status === 'passed';
|
||||
case 'failed':
|
||||
return result.status === 'failed';
|
||||
case 'skipped':
|
||||
return result.status === 'skipped';
|
||||
default:
|
||||
throw Error(`unexpected target test type ${targetTests}`);
|
||||
}
|
||||
})
|
||||
.filter(result => {
|
||||
if (resultFilter.trim() === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Boolean(fuzzyMatch(
|
||||
resultFilter,
|
||||
result.testCase,
|
||||
{ splitSpace: false, loose: true }
|
||||
)?.indexes);
|
||||
})
|
||||
.map((result, i: number) => {
|
||||
const key = crypto
|
||||
.createHash('sha1')
|
||||
.update(`${result.testCase}"-${i}`)
|
||||
.digest('hex');
|
||||
|
||||
const statusText = {
|
||||
passed: 'PASS',
|
||||
failed: 'FAIL',
|
||||
skipped: 'SKIP',
|
||||
}[result.status];
|
||||
const statusTagColor = {
|
||||
passed: 'bg-lime-600',
|
||||
failed: 'bg-red-600',
|
||||
skipped: 'bg-slate-600',
|
||||
}[result.status];
|
||||
|
||||
const executionTime = <span className={result.executionTime < 300 ? 'text-white-500' : 'text-red-500'} >
|
||||
{result.executionTime === 0 ? '< 0.1' : `${result.executionTime.toFixed(1)}`}
|
||||
</span>;
|
||||
const statusTag = <div className={`text-xs rounded p-[2px] inline-block w-16 text-center font-semibold ${statusTagColor}`}>
|
||||
{statusText}
|
||||
</div >;
|
||||
const message = <>
|
||||
<span className='capitalize'>{result.testCase}</span>
|
||||
<span className='text-neutral-400'>{result.errorMessage ? ' | ' + result.errorMessage : ''}</span>
|
||||
</>;
|
||||
const testCategory = result.category === 'pre-request' ? 'Pre-request Test' :
|
||||
result.category === 'after-response' ? 'After-response Test' : 'Unknown';
|
||||
|
||||
return (
|
||||
<div key={key} data-testid="test-result-row">
|
||||
<div className="flex w-full my-3 text-base">
|
||||
<div className="leading-4 m-auto mx-1">
|
||||
<span className="mr-2 ml-2" >{statusTag}</span>
|
||||
</div>
|
||||
<div className="leading-4 mr-2">
|
||||
<div className='mr-2 my-1 w-auto text-nowrap'>{message}</div>
|
||||
<div className='text-sm text-neutral-400 my-1'>{`${testCategory} (`}{executionTime}{' ms)'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
});
|
||||
|
||||
return <>{testResultRows}</>;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
requestTestResults: RequestTestResult[];
|
||||
}
|
||||
|
||||
export const RequestTestResultPane: FC<Props> = ({
|
||||
requestTestResults,
|
||||
}) => {
|
||||
const [targetTests, setTargetTests] = useState<TargetTestType>('all');
|
||||
const [resultFilter, setResultFilter] = useState('');
|
||||
|
||||
const noTestFoundPage = (
|
||||
<div className="text-center mt-5">
|
||||
<div className="">No test results found</div>
|
||||
<div className="text-sm text-neutral-400">
|
||||
<b>
|
||||
<a href="https://docs.insomnia.rest/insomnia/after-response-script">
|
||||
Add test cases
|
||||
</a>
|
||||
</b> using scripting and run the request.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
if (requestTestResults.length === 0) {
|
||||
return noTestFoundPage;
|
||||
}
|
||||
|
||||
const selectAllTests = () => setTargetTests('all');
|
||||
const selectPassedTests = () => setTargetTests('passed');
|
||||
const selectFailedTests = () => setTargetTests('failed');
|
||||
const selectSkippedTests = () => setTargetTests('skipped');
|
||||
|
||||
return <>
|
||||
<div className='h-full flex flex-col divide-y divide-solid divide-[--hl-md]'>
|
||||
<div className='h-[calc(100%-var(--line-height-sm))]'>
|
||||
<Toolbar className="flex items-center h-[--line-height-sm] flex-row text-[var(--font-size-sm)] box-border overflow-x-auto border-solid border-b border-b-[--hl-md]">
|
||||
<button className="rounded-3xl btn btn--clicky-small mx-1 my-auto" onClick={selectAllTests} >All</button>
|
||||
<button className="rounded-3xl btn btn--clicky-small mx-1 my-auto" onClick={selectPassedTests} >Passed</button>
|
||||
<button className="rounded-3xl btn btn--clicky-small mx-1 my-auto" onClick={selectFailedTests} >Failed</button>
|
||||
<button className="rounded-3xl btn btn--clicky-small mx-1 my-auto" onClick={selectSkippedTests} >Skipped</button>
|
||||
</Toolbar>
|
||||
<div className="overflow-y-auto w-auto overflow-x-auto h-[calc(100%-var(--line-height-sm))]">
|
||||
<RequestTestResultRows
|
||||
requestTestResults={requestTestResults}
|
||||
resultFilter={resultFilter}
|
||||
targetTests={targetTests}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Toolbar className="flex items-center h-[--line-height-sm] flex-shrink-0 flex-row text-[var(--font-size-sm)] box-border overflow-x-auto">
|
||||
<input
|
||||
key="test-results-filter"
|
||||
type="text"
|
||||
className='flex-1 pl-3'
|
||||
title="Filter test results"
|
||||
defaultValue={resultFilter || ''}
|
||||
placeholder='Filter test results with name'
|
||||
onChange={e => {
|
||||
setResultFilter(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Toolbar>
|
||||
</div>
|
||||
</>;
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import { extension as mimeExtension } from 'mime-types';
|
||||
import React, { type FC, useCallback } from 'react';
|
||||
import React, { type FC, useCallback, useMemo } from 'react';
|
||||
import { Tab, TabList, TabPanel, Tabs, Toolbar } from 'react-aria-components';
|
||||
import { useRouteLoaderData } from 'react-router-dom';
|
||||
|
||||
@@ -29,6 +29,7 @@ import { ResponseViewer } from '../viewers/response-viewer';
|
||||
import { BlankPane } from './blank-pane';
|
||||
import { Pane, PaneHeader } from './pane';
|
||||
import { PlaceholderResponsePane } from './placeholder-response-pane';
|
||||
import { RequestTestResultPane } from './request-test-result-pane';
|
||||
|
||||
interface Props {
|
||||
activeRequestId: string;
|
||||
@@ -124,6 +125,21 @@ export const ResponsePane: FC<Props> = ({
|
||||
}
|
||||
}, [activeRequest, activeResponse]);
|
||||
|
||||
const { passedTestCount, totalTestCount } = useMemo(() => {
|
||||
let passedTestCount = 0;
|
||||
let totalTestCount = 0;
|
||||
activeResponse?.requestTestResults.forEach(result => {
|
||||
if (result.status === 'passed') {
|
||||
passedTestCount++;
|
||||
}
|
||||
totalTestCount++;
|
||||
});
|
||||
return { passedTestCount, totalTestCount };
|
||||
}, [activeResponse]);
|
||||
const testResultCountTagColor = totalTestCount > 0 ?
|
||||
passedTestCount === totalTestCount ? 'bg-lime-600' : 'bg-red-600' :
|
||||
'bg-[var(--hl-sm)]';
|
||||
|
||||
if (!activeRequest) {
|
||||
return <BlankPane type="response" />;
|
||||
}
|
||||
@@ -143,6 +159,7 @@ export const ResponsePane: FC<Props> = ({
|
||||
|
||||
const timeline = models.response.getTimeline(activeResponse);
|
||||
const cookieHeaders = getSetCookieHeaders(activeResponse.headers);
|
||||
|
||||
return (
|
||||
<Pane type="response">
|
||||
{!activeResponse ? null : (
|
||||
@@ -183,6 +200,22 @@ export const ResponsePane: FC<Props> = ({
|
||||
<span className="p-2 aspect-square flex items-center justify-between border-solid border border-[--hl-md] overflow-hidden rounded-lg text-xs shadow-small">{cookieHeaders.length}</span>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab
|
||||
className='flex-shrink-0 h-full flex items-center justify-between cursor-pointer gap-2 outline-none select-none px-3 py-1 text-[--hl] aria-selected:text-[--color-font] hover:bg-[--hl-sm] hover:text-[--color-font] aria-selected:bg-[--hl-xs] aria-selected:focus:bg-[--hl-sm] aria-selected:hover:bg-[--hl-sm] focus:bg-[--hl-sm] transition-colors duration-300'
|
||||
id='test-results'
|
||||
>
|
||||
<div>
|
||||
<span>
|
||||
Tests
|
||||
</span>
|
||||
<span
|
||||
className={`rounded-sm ml-1 px-1 ${testResultCountTagColor}`}
|
||||
style={{ color: 'text-[--hl]' }}
|
||||
>
|
||||
{`${passedTestCount} / ${totalTestCount}`}
|
||||
</span>
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab
|
||||
className='flex-shrink-0 h-full flex items-center justify-between cursor-pointer gap-2 outline-none select-none px-3 py-1 text-[--hl] aria-selected:text-[--color-font] hover:bg-[--hl-sm] hover:text-[--color-font] aria-selected:bg-[--hl-xs] aria-selected:focus:bg-[--hl-sm] aria-selected:hover:bg-[--hl-sm] focus:bg-[--hl-sm] transition-colors duration-300'
|
||||
id='mock-response'
|
||||
@@ -235,14 +268,18 @@ export const ResponsePane: FC<Props> = ({
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel
|
||||
className='w-full flex-1 flex flex-col overflow-y-auto'
|
||||
id='test-results'
|
||||
>
|
||||
<RequestTestResultPane requestTestResults={activeResponse.requestTestResults} />
|
||||
</TabPanel>
|
||||
<TabPanel
|
||||
className='w-full flex-1 flex flex-col overflow-y-auto'
|
||||
id='mock-response'
|
||||
>
|
||||
<MockResponseExtractor />
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel className='w-full flex-1 flex flex-col overflow-y-auto' id='timeline'>
|
||||
<ErrorBoundary key={activeResponse._id} errorClassName="font-error pad text-center">
|
||||
<ResponseTimelineViewer
|
||||
|
||||
@@ -36,7 +36,7 @@ export const ResponseTimer: FunctionComponent<Props> = ({ handleCancel, activeRe
|
||||
key={`${activeRequestId}-${record.stepName}`}
|
||||
className='flex w-full leading-8'
|
||||
>
|
||||
<div className='w-3/4 text-left content-center leading-8'>
|
||||
<div className='w-3/4 ml-1 text-left content-center leading-8'>
|
||||
<span className="leading-8">
|
||||
{
|
||||
record.duration ?
|
||||
@@ -48,7 +48,9 @@ export const ResponseTimer: FunctionComponent<Props> = ({ handleCancel, activeRe
|
||||
{record.stepName}
|
||||
</span>
|
||||
</div>
|
||||
{record.duration ? `${((record.duration) / 1000).toFixed(1)} s` : (<MillisecondTimer />)}
|
||||
<div className='w-1/4 mr-1 text-right leading-8'>
|
||||
{record.duration ? `${((record.duration) / 1000).toFixed(1)} s` : (<MillisecondTimer />)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createWriteStream } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
import * as contentDisposition from 'content-disposition';
|
||||
import type { RequestTestResult } from 'insomnia-sdk';
|
||||
import { extension as mimeExtension } from 'mime-types';
|
||||
import { type ActionFunction, type LoaderFunction, redirect } from 'react-router-dom';
|
||||
|
||||
@@ -421,19 +422,35 @@ export const sendAction: ActionFunction = async ({ request, params }) => {
|
||||
|
||||
const requestMeta = await models.requestMeta.getByParentId(requestId);
|
||||
invariant(requestMeta, 'RequestMeta not found');
|
||||
const responsePatch = await responseTransform(response, requestData.activeEnvironmentId, renderedRequest, renderedResult.context);
|
||||
const is2XXWithBodyPath = responsePatch.statusCode && responsePatch.statusCode >= 200 && responsePatch.statusCode < 300 && responsePatch.bodyPath;
|
||||
const baseResponsePatch = await responseTransform(response, requestData.activeEnvironmentId, renderedRequest, renderedResult.context);
|
||||
|
||||
const is2XXWithBodyPath = baseResponsePatch.statusCode && baseResponsePatch.statusCode >= 200 && baseResponsePatch.statusCode < 300 && baseResponsePatch.bodyPath;
|
||||
const shouldWriteToFile = shouldPromptForPathAfterResponse && is2XXWithBodyPath;
|
||||
|
||||
mutatedContext.request.afterResponseScript = afterResponseScript;
|
||||
window.main.addExecutionStep({ requestId, stepName: 'Executing after-response script' });
|
||||
await tryToExecuteAfterResponseScript({
|
||||
const postMutatedContext = await tryToExecuteAfterResponseScript({
|
||||
...requestData,
|
||||
...mutatedContext,
|
||||
response,
|
||||
});
|
||||
window.main.completeExecutionStep({ requestId });
|
||||
|
||||
const responsePatch = postMutatedContext ?
|
||||
{
|
||||
...baseResponsePatch,
|
||||
// both pre-request and after-response test results are collected
|
||||
requestTestResults: [
|
||||
...mutatedContext.requestTestResults.map(
|
||||
(result: RequestTestResult): RequestTestResult => ({ ...result, category: 'pre-request' }),
|
||||
),
|
||||
...postMutatedContext.requestTestResults.map(
|
||||
(result: RequestTestResult): RequestTestResult => ({ ...result, category: 'after-response' }),
|
||||
),
|
||||
],
|
||||
}
|
||||
: baseResponsePatch;
|
||||
|
||||
if (!shouldWriteToFile) {
|
||||
const response = await models.response.create(responsePatch, requestData.settings.maxHistoryResponses);
|
||||
await models.requestMeta.update(requestMeta, { activeResponseId: response._id });
|
||||
|
||||
Reference in New Issue
Block a user