Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sdk): change insomnia.test mechanism to improve the nested test cases #8388

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions packages/insomnia-sdk/src/objects/insomnia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,22 @@ export class InsomniaObject {

this.requestTestResults = new Array<RequestTestResult>();
this.parentFolders = rawObj.parentFolders;

return new Proxy(this, {
get: (target, prop, receiver) => {
if (prop === 'test') {
const testHandler: TestHandler = async (msg: string, fn: () => Promise<void>) => {
await this._test(msg, fn, this.pushRequestTestResult);
};
testHandler.skip = async (msg: string, fn: () => Promise<void>) => {
await this._skip(msg, fn, this.pushRequestTestResult);
};

return testHandler;
}
return Reflect.get(target, prop, receiver);
},
});
}

sendRequest(
Expand All @@ -91,24 +107,17 @@ export class InsomniaObject {
return sendRequest(request, cb, this._settings);
}

get test() {
const testHandler: TestHandler = async (msg: string, fn: () => Promise<void>) => {
await this._test(msg, fn, this.pushRequestTestResult);
};
testHandler.skip = async (msg: string, fn: () => Promise<void>) => {
await this._skip(msg, fn, this.pushRequestTestResult);
};

return testHandler;
}
test = () => {
// this method is intercepted by the proxy above
};

private pushRequestTestResult = (testResult: RequestTestResult) => {
this.requestTestResults = [...this.requestTestResults, testResult];
};

expect(exp: boolean | number | string | object) {
expect = (exp: boolean | number | string | object) => {
return this._expect(exp);
}
};

get settings() {
return undefined;
Expand Down
56 changes: 36 additions & 20 deletions packages/insomnia-sdk/src/objects/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,43 @@ export async function test(
fn: () => Promise<void>,
log: (testResult: RequestTestResult) => void,
) {
const started = performance.now();
const wrapFn = async () => {
const started = performance.now();

try {
await fn();
const executionTime = performance.now() - started;
log({
testCase: msg,
status: 'passed',
executionTime,
category: 'unknown',
});
} catch (e) {
const executionTime = performance.now() - started;
log({
testCase: msg,
status: 'failed',
executionTime,
errorMessage: `error: ${e} | ACTUAL: ${e.actual} | EXPECTED: ${e.expected}`,
category: 'unknown',
});
}
try {
await fn();

const executionTime = performance.now() - started;
log({
testCase: msg,
status: 'passed',
executionTime,
category: 'unknown',
});
} catch (e) {
const executionTime = performance.now() - started;
log({
testCase: msg,
status: 'failed',
executionTime,
errorMessage: `error: ${e} | ACTUAL: ${e.actual} | EXPECTED: ${e.expected}`,
category: 'unknown',
});
}
};

const testPromise = wrapFn();
startTestObserver(testPromise);
return testPromise;
}

let testPromises = new Array<Promise<void>>();
export async function waitForAllTestsDone() {
await Promise.allSettled(testPromises);
testPromises = [];
}
function startTestObserver(promise: Promise<void>) {
testPromises.push(promise);
}

export async function skip(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@ collection:
insomnia.expect(199).to.eql(200);
insomnia.expect(199).to.be.oneOf([201,202]);
});

function happyTestInFunc() {
insomnia.test('happyTestInFunc', () => {
insomnia.expect(200).to.eql(200);
});
}
function sadTestInFunc() {
insomnia.test('sadTestInFunc', () => {
insomnia.expect(199).to.eql(200);
});
}
function asyncHappyTestInFunc() {
insomnia.test('asyncHappyTestInFunc', async () => {
insomnia.expect(200).to.eql(200);
});
}
function asyncSadTestInFunc() {
insomnia.test('asyncSadTestInFunc', async () => {
insomnia.expect(199).to.eql(200);
});
}
happyTestInFunc();
sadTestInFunc();
asyncHappyTestInFunc();
asyncSadTestInFunc();
settings:
renderRequestBody: true
encodeUrl: true
Expand Down
41 changes: 38 additions & 3 deletions packages/insomnia-smoke-test/fixtures/runner-collection.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ collection:
insomnia.test('req1-post-check', () => {
insomnia.expect(insomnia.response.code).to.eql(200);
});
insomnia.test('req1-post-check-failed', () => {
insomnia.test('req1-post-check-failed', async () => {
await new Promise(resolve => setTimeout(resolve, 50));
insomnia.expect(insomnia.response.code).to.eql(201);
});
settings:
Expand Down Expand Up @@ -94,6 +95,40 @@ collection:
send: true
store: true
rebuildPath: true
- url: http://127.0.0.1:4010/echo
name: await-test
meta:
id: req_823443a369a74ac48cb9baa27ed8245c
created: 1636141014550
modified: 1636707449230
isPrivate: false
sortKey: -1636141014552
method: POST
scripts:
afterResponse: |-
await insomnia.test('t1', async () => {
await new Promise((resolve) => setTimeout(resolve, 50));
insomnia.expect(201).to.eql(200);
});

async function myTest() {
await insomnia.test('t2', () => {
insomnia.expect(201).to.eql(200);
});
}
await myTest();

insomnia.test('t3', () => {
insomnia.expect(201).to.eql(200);
});
settings:
renderRequestBody: true
encodeUrl: true
followRedirects: global
cookies:
send: true
store: true
rebuildPath: true
- url: http://127.0.0.1:4010/echo
name: req01
meta:
Expand Down Expand Up @@ -231,11 +266,11 @@ collection:
scripts:
preRequest: |-
insomnia.test('req2-pre-check', () => {
insomnia.expect(200).to.eql(200);
insomnia.expect(200).to.eql(200);
});
afterResponse: |-
insomnia.test('req2-post-check', () => {
insomnia.expect(insomnia.response.code).to.eql(200);
insomnia.expect(insomnia.response.code).to.eql(200);
});
settings:
renderRequestBody: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ test.describe('after-response script features tests', async () => {
const responsePane = page.getByTestId('response-pane');
await expect(responsePane).toContainText('PASS');
await expect(responsePane).toContainText('FAILunhappy tests | error: AssertionError: expected 199 to deeply equal 200 | ACTUAL: 199 | EXPECTED: 200');
await expect(responsePane).toContainText('PASShappyTestInFunc');
await expect(responsePane).toContainText('FAILsadTestInFunc | error: AssertionError: expected 199 to deeply equal 200 | ACTUAL: 199 | EXPECTED: 200');
await expect(responsePane).toContainText('PASSasyncHappyTestInFunc');
await expect(responsePane).toContainText('FAILasyncSadTestInFunc | error: AssertionError: expected 199 to deeply equal 200 | ACTUAL: 199 | EXPECTED: 200');
});

test('environment and baseEnvironment can be persisted', async ({ page }) => {
Expand Down
29 changes: 25 additions & 4 deletions packages/insomnia-smoke-test/tests/smoke/runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ test.describe('runner features tests', async () => {

const expectedTestOrder = [
'folder-pre-check',
'req1-pre-check',
'req1-pre-check-skipped',
'req1-pre-check',
'folder-post-check',
'req1-post-check',
'expected 200 to deeply equal 201',
Expand Down Expand Up @@ -133,10 +133,11 @@ test.describe('runner features tests', async () => {
// req2 should be skipped from pre-request script
expect(iterationTestResultElement).not.toContainText('req2');
}

await verifyResultRows(page, 4, 1, 6, [
'folder-pre-check',
'req1-pre-check',
'req1-pre-check-skipped',
'req1-pre-check',
'folder-post-check',
'req1-post-check',
'expected 200 to deeply equal 201',
Expand Down Expand Up @@ -164,6 +165,26 @@ test.describe('runner features tests', async () => {
await verifyResultRows(page, 3, 0, 3, expectedTestOrder, 1);
});

test('await test works', async ({ page }) => {
await page.getByTestId('run-collection-btn-quick').click();

await page.locator('.runner-request-list-await-test').click();

// send
await page.getByRole('button', { name: 'Run', exact: true }).click();

// check result
await page.getByText('0 / 3').first().click();

const expectedTestOrder = [
't1',
't2',
't3',
];

await verifyResultRows(page, 0, 0, 3, expectedTestOrder, 1);
});

test('run req5 3 times with setNextRequest in the after-response script', async ({ page }) => {
await page.getByTestId('run-collection-btn-quick').click();

Expand Down Expand Up @@ -239,10 +260,10 @@ test.describe('runner features tests', async () => {
await page.getByText('0 / 4').first().click();

const expectedTestOrder = [
'async_pre_test',
'sync_pre_test',
'async_post_test',
'async_pre_test',
'sync_post_test',
'async_post_test',
];

await verifyResultRows(page, 0, 0, 4, expectedTestOrder, 1);
Expand Down
14 changes: 5 additions & 9 deletions packages/insomnia/src/hidden-window.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as Sentry from '@sentry/electron/renderer';
import { SENTRY_OPTIONS } from 'insomnia/src/common/sentry';
import { initInsomniaObject, InsomniaObject } from 'insomnia-sdk';
import { initInsomniaObject, InsomniaObject, waitForAllTestsDone } from 'insomnia-sdk';
import { getNewConsole, mergeClientCertificates, mergeCookieJar, mergeRequests, mergeSettings, type RequestContext } from 'insomnia-sdk';
import * as _ from 'lodash';

Expand Down Expand Up @@ -37,12 +37,6 @@ window.bridge.onmessage(async (data, callback) => {
}
});

// as insomnia.test accepts an async function, prepend await to it as user don't write it
function translateTestHandlers(script: string): string {
const replacedTests = script.replace(/insomnia\.test\(/g, 'await insomnia.test(');
return replacedTests.replace(/insomnia\.test\.skip\(/g, 'await insomnia.test.skip(');
}

// This function is duplicated in scriptExecutor.ts to run in nodejs
// TODO: consider removing this implementation and using only nodejs scripting
const runScript = async (
Expand All @@ -52,7 +46,6 @@ const runScript = async (

const executionContext = await initInsomniaObject(context, scriptConsole.log);

const translatedScript = translateTestHandlers(script);
const AsyncFunction = (async () => { }).constructor;
const executeScript = AsyncFunction(
'insomnia',
Expand All @@ -64,10 +57,12 @@ const runScript = async (
'setImmediate',
'queueMicrotask',
'process',
'waitForAllTestsDone',
`
const $ = insomnia;
window.bridge.resetAsyncTasks(); // exclude unnecessary ones
${translatedScript};
${script};
await waitForAllTestsDone();
window.bridge.stopMonitorAsyncTasks(); // the next one should not be monitored
await window.bridge.asyncTasksAllSettled();
return insomnia;`
Expand All @@ -82,6 +77,7 @@ const runScript = async (
undefined,
undefined,
undefined,
waitForAllTestsDone,
);
if (mutatedInsomniaObject == null || !(mutatedInsomniaObject instanceof InsomniaObject)) {
throw Error('insomnia object is invalid or script returns earlier than expected.');
Expand Down
Loading