Skip to content

Commit

Permalink
chore(runner): cleaning up runner-pr1 and resolve conflicts (#7878)
Browse files Browse the repository at this point in the history
* feat: log request testing results and return them to the main renderer

* fix: lint error

* fix: install chai with unified version across packages

* chore: restore package-lock

* chore: restore package-lock

* 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

* chore: cleanup package lock

* chore: restore package lock

* feat: enable collection runner

* fix: cli test failed

* fix: lint error

* fix: race condition in canceling runner

* fix: runner is not canceled when there's an exception

* fix: lint error

* 1.fix after response iteration and eventname issue

* chore: disable the flaky test

---------

Co-authored-by: Kent Wang <kent.wang@konghq.com>
  • Loading branch information
ihexxa and cwangsmv authored Aug 28, 2024
1 parent 2743c87 commit 02027fe
Show file tree
Hide file tree
Showing 54 changed files with 3,035 additions and 553 deletions.
193 changes: 71 additions & 122 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/insomnia-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@types/tv4": "^1.2.33",
"@types/xml2js": "^0.4.14",
"ajv": "^8.12.0",
"chai": "^5.1.0",
"chai": "^4.3.4",
"cheerio": "^1.0.0-rc.12",
"crypto-js": "^4.2.0",
"csv-parse": "^5.5.5",
Expand Down
27 changes: 26 additions & 1 deletion packages/insomnia-sdk/src/objects/__tests__/environments.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { validate } from 'uuid';
import { describe, expect, it } from 'vitest';

import { Environment, Variables } from '../environments';

Expand All @@ -21,4 +21,29 @@ describe('test Variables object', () => {
const uuidAndBrackets2 = variables.replaceIn('}}{{ $randomUUID }}');
expect(validate(uuidAndBrackets2.replace('}}', ''))).toBeTruthy();
});

it('test environment override', () => {
const globalOnlyVariables = new Variables({
globalVars: new Environment('globals', { scope: 'global', value: 'global-value' }),
environmentVars: new Environment('environments', {}),
collectionVars: new Environment('baseEnvironment', {}),
iterationDataVars: new Environment('iterationData', {}),
});
const normalVariables = new Variables({
globalVars: new Environment('globals', { scope: 'global', value: 'global-value' }),
environmentVars: new Environment('environments', { scope: 'subEnv', value: 'subEnv-value' }),
collectionVars: new Environment('baseEnvironment', { scope: 'baseEnv', value: 'baseEnv-value' }),
iterationDataVars: new Environment('iterationData', {}),
});
const variablesWithIterationData = new Variables({
globalVars: new Environment('globals', { scope: 'global', value: 'global-value' }),
environmentVars: new Environment('environments', { scope: 'subEnv', value: 'subEnv-value' }),
collectionVars: new Environment('baseEnvironment', { scope: 'baseEnv', value: 'baseEnv-value' }),
iterationDataVars: new Environment('iterationData', { scope: 'iterationData', value: 'iterationData-value' }),
});

expect(globalOnlyVariables.get('value')).toEqual('global-value');
expect(normalVariables.get('value')).toEqual('subEnv-value');
expect(variablesWithIterationData.get('value')).toEqual('iterationData-value');
});
});
37 changes: 37 additions & 0 deletions packages/insomnia-sdk/src/objects/__tests__/execution.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { describe, expect, it } from 'vitest';

import { Execution } from '../execution';

describe('test execution object', () => {
it('test location property', () => {
const location = ['project', 'workspace', 'file', 'requestname'];
const executionInstance = new Execution({ location });

expect(executionInstance.location).toStrictEqual(['project', 'workspace', 'file', 'requestname']);
// @ts-expect-error location should have current property by design
expect(executionInstance.location.current).toEqual(location[location.length - 1]);
expect(executionInstance.toObject()).toEqual({
location: ['project', 'workspace', 'file', 'requestname'],
skipRequest: false,
nextRequestIdOrName: '',
});
});

it('test skipRequest and set nextRequest', () => {
const location = ['project', 'workspace', 'file', 'requestname'];
const executionInstance = new Execution({ location });
executionInstance.skipRequest();
executionInstance.setNextRequest('nextRequestNameOrId');

expect(executionInstance.toObject()).toEqual({
location: ['project', 'workspace', 'file', 'requestname'],
skipRequest: true,
nextRequestIdOrName: 'nextRequestNameOrId',
});
});

it('set invalid location', () => {
// @ts-expect-error test invalid input
expect(() => new Execution({ location: 'invalid' })).toThrowError();
});
});
37 changes: 37 additions & 0 deletions packages/insomnia-sdk/src/objects/__tests__/request-info.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { describe, expect, it } from 'vitest';

import { RequestInfo } from '../request-info';

describe('test request info', () => {
it('test normal request info', () => {
const requestInfo = new RequestInfo({
eventName: 'prerequest',
requestName: 'request_name',
requestId: 'req_bd8b1eb53418482585b70d0a9616a8cc',
});
expect(requestInfo.toObject()).toEqual({
eventName: 'prerequest',
requestName: 'request_name',
requestId: 'req_bd8b1eb53418482585b70d0a9616a8cc',
iteration: 1,
iterationCount: 1,
});
});

it('test runner request info', () => {
const runnerRequestInfo = new RequestInfo({
eventName: 'prerequest',
requestName: 'request_name',
requestId: 'req_bd8b1eb53418482585b70d0a9616a8cc',
iteration: 3,
iterationCount: 5,
});
expect(runnerRequestInfo.toObject()).toEqual({
eventName: 'prerequest',
requestName: 'request_name',
requestId: 'req_bd8b1eb53418482585b70d0a9616a8cc',
iteration: 3,
iterationCount: 5,
});
});
});
46 changes: 46 additions & 0 deletions packages/insomnia-sdk/src/objects/execution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
export interface ExecutionOption {
location: string[];
skipRequest?: boolean;
nextRequestIdOrName?: string;
}

export class Execution {
private _skipRequest: boolean;
private _nextRequestIdOrName: string;
public location: string[];

constructor(options: ExecutionOption) {
const { location, skipRequest = false, nextRequestIdOrName = '' } = options;
if (Array.isArray(location)) {
// mapping postman usage of location refer: https://learning.postman.com/docs/tests-and-scripts/write-scripts/postman-sandbox-api-reference/#using-variables-in-scripts
this.location = new Proxy([...location], {
get: (target, prop, receiver) => {
if (prop === 'current') {
return target.length > 0 ? target[target.length - 1] : '';
};
return Reflect.get(target, prop, receiver);
},
});
this._skipRequest = skipRequest;
this._nextRequestIdOrName = nextRequestIdOrName;
} else {
throw new Error('Location input must be array of string');
}
};

skipRequest = () => {
this._skipRequest = true;
};

setNextRequest = (requestIdOrName: string) => {
this._nextRequestIdOrName = requestIdOrName;
};

toObject = () => {
return {
location: Array.from(this.location),
skipRequest: this._skipRequest,
nextRequestIdOrName: this._nextRequestIdOrName,
};
};
};
2 changes: 2 additions & 0 deletions packages/insomnia-sdk/src/objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export * from './cookies';
export * from './console';
export * from './request-info';
export * from './async_objects';
export * from './test';
export * from './execution';
84 changes: 48 additions & 36 deletions packages/insomnia-sdk/src/objects/insomnia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import type { Settings } from 'insomnia/src/models/settings';
import { toPreRequestAuth } from './auth';
import { CookieObject } from './cookies';
import { Environment, Variables } from './environments';
import { Execution } from './execution';
import type { RequestContext } from './interfaces';
import { unsupportedError } from './properties';
import { Request as ScriptRequest, type RequestOptions, toScriptRequestBody } from './request';
import { RequestInfo } from './request-info';
import { Response as ScriptResponse } from './response';
import { readBodyFromPath, toScriptResponse } from './response';
import { sendRequest } from './send-request';
import { test } from './test';
import { type RequestTestResult, skip, test, type TestHandler } from './test';
import { toUrlObject } from './urls';

export class InsomniaObject {
Expand All @@ -25,17 +25,19 @@ export class InsomniaObject {
public cookies: CookieObject;
public info: RequestInfo;
public response?: ScriptResponse;
public execution: Execution;

private clientCertificates: ClientCertificate[];
private _expect = expect;
private _test = test;
private _skip = skip;

private iterationData: Environment;
// TODO: follows will be enabled after Insomnia supports them
private globals: Environment;
private _iterationData: Environment;
private _settings: Settings;

private _log: (...msgs: any[]) => void;
private requestTestResults: RequestTestResult[];

constructor(
rawObj: {
Expand All @@ -49,25 +51,26 @@ export class InsomniaObject {
clientCertificates: ClientCertificate[];
cookies: CookieObject;
requestInfo: RequestInfo;
execution: Execution;
response?: ScriptResponse;
},
log: (...msgs: any[]) => void,
) {
this.globals = rawObj.globals;
this.environment = rawObj.environment;
this.baseEnvironment = rawObj.baseEnvironment;
this.collectionVariables = this.baseEnvironment; // collectionVariables is mapped to baseEnvironment
this._iterationData = rawObj.iterationData;
this.iterationData = rawObj.iterationData;
this.variables = rawObj.variables;
this.cookies = rawObj.cookies;
this.response = rawObj.response;
this.execution = rawObj.execution;

this.info = rawObj.requestInfo;
this.request = rawObj.request;
this._settings = rawObj.settings;
this.clientCertificates = rawObj.clientCertificates;

this._log = log;
this.requestTestResults = new Array<RequestTestResult>();
}

sendRequest(
Expand All @@ -77,19 +80,25 @@ export class InsomniaObject {
return sendRequest(request, cb, this._settings);
}

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

return testHandler;
}

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

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

// TODO: remove this after enabled iterationData
get iterationData() {
throw unsupportedError('iterationData', 'environment');
}

// TODO: remove this after enabled iterationData
get settings() {
return undefined;
Expand All @@ -100,14 +109,16 @@ export class InsomniaObject {
globals: this.globals.toObject(),
environment: this.environment.toObject(),
baseEnvironment: this.baseEnvironment.toObject(),
iterationData: this._iterationData.toObject(),
iterationData: this.iterationData.toObject(),
variables: this.variables.toObject(),
request: this.request,
settings: this.settings,
clientCertificates: this.clientCertificates,
cookieJar: this.cookies.jar().toInsomniaCookieJar(),
info: this.info.toObject(),
response: this.response ? this.response.toObject() : undefined,
requestTestResults: this.requestTestResults,
execution: this.execution.toObject(),
};
};
}
Expand All @@ -132,14 +143,15 @@ export async function initInsomniaObject(
if (rawObj.baseEnvironment.id === rawObj.environment.id) {
log('warning: No environment is selected, modification of insomnia.environment will be applied to the base environment.');
}
// TODO: update "iterationData" name when it is supported
const iterationData = new Environment('iterationData', rawObj.iterationData);
// Mapping rule for the environment user uploaded in collection runner
const iterationData = rawObj.iterationData ?
new Environment(rawObj.iterationData.name, rawObj.iterationData.data) : new Environment('iterationData', {});
const cookies = new CookieObject(rawObj.cookieJar);
// TODO: update follows when post-request script and iterationData are introduced
const requestInfo = new RequestInfo({
eventName: 'prerequest',
iteration: 1,
iterationCount: 1,
eventName: rawObj.requestInfo.eventName || 'prerequest',
iteration: rawObj.requestInfo.iteration || 1,
iterationCount: rawObj.requestInfo.iterationCount || 0,
requestName: rawObj.request.name,
requestId: rawObj.request._id,
});
Expand Down Expand Up @@ -204,6 +216,7 @@ export async function initInsomniaObject(
.filter(param => !param.disabled)
.map(param => ({ key: param.name, value: param.value }))
);

const reqOpt: RequestOptions = {
name: rawObj.request.name,
url: reqUrl,
Expand All @@ -218,24 +231,23 @@ export async function initInsomniaObject(
pathParameters: rawObj.request.pathParameters,
};
const request = new ScriptRequest(reqOpt);
const execution = new Execution({ location: rawObj.execution.location });

const responseBody = await readBodyFromPath(rawObj.response);
const response = rawObj.response ? toScriptResponse(request, rawObj.response, responseBody) : undefined;

return new InsomniaObject(
{
globals,
environment,
baseEnvironment,
iterationData,
variables,
request,
settings: rawObj.settings,
clientCertificates: rawObj.clientCertificates,
cookies,
requestInfo,
response,
},
log,
);
return new InsomniaObject({
globals,
environment,
baseEnvironment,
iterationData,
variables,
request,
settings: rawObj.settings,
clientCertificates: rawObj.clientCertificates,
cookies,
requestInfo,
response,
execution,
});
};
Loading

0 comments on commit 02027fe

Please sign in to comment.