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

runner refactoring pass #7975

Merged
merged 6 commits into from
Sep 19, 2024
Merged
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
27 changes: 24 additions & 3 deletions packages/insomnia-inso/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import * as commander from 'commander';
import consola, { BasicReporter, FancyReporter, LogLevel, logType } from 'consola';
import { cosmiconfig } from 'cosmiconfig';
import fs from 'fs';
import { JSON_ORDER_PREFIX, JSON_ORDER_SEPARATOR } from 'insomnia/src/common/constants';
import { getSendRequestCallbackMemDb } from 'insomnia/src/common/send-request';
import { UserUploadEnvironment } from 'insomnia/src/models/environment';
import { type RequestTestResult } from 'insomnia-sdk';
import { generate, runTestsCli } from 'insomnia-testing';
import orderedJSON from 'json-order';
import { parseArgsStringToArgv } from 'string-argv';

import packageJson from '../package.json';
Expand Down Expand Up @@ -236,10 +239,13 @@ const readFileFromPathOrUrl = async (pathOrUrl: string) => {
}
return readFile(pathOrUrl, 'utf8');
};

const getIterationDataFromFileOrUrl = async (pathOrUrl: string): Promise<Record<string, string>[]> => {
const pathToIterationData = async (pathOrUrl: string): Promise<UserUploadEnvironment[]> => {
const fileType = pathOrUrl.split('.').pop()?.toLowerCase();
const content = await readFileFromPathOrUrl(pathOrUrl);
const list = getListFromFileOrUrl(content, fileType);
return transformIterationDataToEnvironmentList(list);
};
const getListFromFileOrUrl = (content: string, fileType?: string): Record<string, string>[] => {
if (fileType === 'json') {
try {
const jsonDataContent = JSON.parse(content);
Expand Down Expand Up @@ -267,6 +273,21 @@ const getIterationDataFromFileOrUrl = async (pathOrUrl: string): Promise<Record<
throw new Error(`Uploaded file is unsupported ${fileType}`);
};

const transformIterationDataToEnvironmentList = (list: Record<string, string>[]): UserUploadEnvironment[] => {
return list?.map(data => {
const orderedJson = orderedJSON.parse<Record<string, any>>(
JSON.stringify(data),
JSON_ORDER_PREFIX,
JSON_ORDER_SEPARATOR,
);
return {
name: 'User Upload',
data: orderedJson.object,
dataPropertyOrder: orderedJson.map || null,
};
});
};

export const go = (args?: string[]) => {

const program = new commander.Command();
Expand Down Expand Up @@ -470,7 +491,7 @@ export const go = (args?: string[]) => {

try {
const iterationCount = parseInt(options.iterationCount, 10);
const iterationData = options.iterationData ? await getIterationDataFromFileOrUrl(options.iterationData) : undefined;
const iterationData = options.iterationData ? await pathToIterationData(options.iterationData) : undefined;
const sendRequest = await getSendRequestCallbackMemDb(environment._id, db, { validateSSL: !options.disableCertValidation }, iterationData, iterationCount);
let success = true;
for (let i = 0; i < iterationCount; i++) {
Expand Down
24 changes: 12 additions & 12 deletions packages/insomnia/src/common/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ export async function buildRenderContext(
subEnvironment,
rootGlobalEnvironment,
subGlobalEnvironment,
userUploadEnv,
userUploadEnvironment,
baseContext = {},
}: {
ancestors?: RenderContextAncestor[];
rootEnvironment?: Environment;
subEnvironment?: Environment;
rootGlobalEnvironment?: Environment | null;
subGlobalEnvironment?: Environment | null;
userUploadEnv?: UserUploadEnvironment;
userUploadEnvironment?: UserUploadEnvironment;
baseContext?: Record<string, any>;
},
) {
Expand Down Expand Up @@ -130,10 +130,10 @@ export async function buildRenderContext(
}

// user upload env in collection runner has highest priority
if (userUploadEnv) {
if (userUploadEnvironment) {
const ordered = orderedJSON.order(
userUploadEnv.data,
userUploadEnv.dataPropertyOrder,
userUploadEnvironment.data,
userUploadEnvironment.dataPropertyOrder,
JSON_ORDER_SEPARATOR,
);
envObjects.push(ordered);
Expand Down Expand Up @@ -336,7 +336,7 @@ interface BaseRenderContextOptions {
baseEnvironment?: Environment;
rootGlobalEnvironment?: Environment;
subGlobalEnvironment?: Environment;
userUploadEnv?: UserUploadEnvironment;
userUploadEnvironment?: UserUploadEnvironment;
purpose?: RenderPurpose;
extraInfo?: ExtraRenderInfo;
ignoreUndefinedEnvVariable?: boolean;
Expand All @@ -350,7 +350,7 @@ export async function getRenderContext(
request,
environment,
baseEnvironment,
userUploadEnv,
userUploadEnvironment,
ancestors: _ancestors,
purpose,
extraInfo,
Expand Down Expand Up @@ -455,8 +455,8 @@ export async function getRenderContext(
}

// Get Keys from user upload environment
if (userUploadEnv) {
getKeySource(userUploadEnv.data || {}, inKey, userUploadEnv.name || 'uploadData');
if (userUploadEnvironment) {
getKeySource(userUploadEnvironment.data || {}, inKey, userUploadEnvironment.name || 'uploadData');
}

// Add meta data helper function
Expand Down Expand Up @@ -490,7 +490,7 @@ export async function getRenderContext(
subGlobalEnvironment,
rootEnvironment,
subEnvironment: subEnvironment || undefined,
userUploadEnv,
userUploadEnvironment,
baseContext,
});
}
Expand Down Expand Up @@ -556,7 +556,7 @@ export async function getRenderedRequestAndContext(
request,
environment,
baseEnvironment,
userUploadEnv,
userUploadEnvironment,
extraInfo,
purpose,
ignoreUndefinedEnvVariable,
Expand All @@ -566,7 +566,7 @@ export async function getRenderedRequestAndContext(
const workspace = ancestors.find(isWorkspace);
const parentId = workspace ? workspace._id : 'n/a';
const cookieJar = await models.cookieJar.getOrCreateForParentId(parentId);
const renderContext = await getRenderContext({ request, environment, ancestors, purpose, extraInfo, baseEnvironment, userUploadEnv });
const renderContext = await getRenderContext({ request, environment, ancestors, purpose, extraInfo, baseEnvironment, userUploadEnvironment });

// HACK: Switch '#}' to '# }' to prevent Nunjucks from barfing
// https://github.com/kong/insomnia/issues/895
Expand Down
21 changes: 4 additions & 17 deletions packages/insomnia/src/common/send-request.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import orderedJSON from 'json-order';
import path from 'path';

import { type BaseModel, types as modelTypes } from '../models';
Expand All @@ -19,7 +18,6 @@ import {
tryToInterpolateRequest,
} from '../network/network';
import { invariant } from '../utils/invariant';
import { JSON_ORDER_PREFIX, JSON_ORDER_SEPARATOR } from './constants';
import { database } from './database';
import { generateId } from './misc';

Expand All @@ -35,7 +33,7 @@ const wrapAroundIterationOverIterationData = (list?: UserUploadEnvironment[], cu
};
return list[(currentIteration + 1) % list.length];
};
export async function getSendRequestCallbackMemDb(environmentId: string, memDB: any, settingsOverrides?: SettingsOverride, iterationData?: Record<string, any>[], iterationCount?: number) {
export async function getSendRequestCallbackMemDb(environmentId: string, memDB: any, settingsOverrides?: SettingsOverride, iterationData?: UserUploadEnvironment[], iterationCount?: number) {
// Initialize the DB in-memory and fill it with data if we're given one
await database.init(
modelTypes(),
Expand Down Expand Up @@ -95,23 +93,12 @@ export async function getSendRequestCallbackMemDb(environmentId: string, memDB:

return { request, settings, clientCertificates, caCert, environment, activeEnvironmentId, workspace, timelinePath, responseId, ancestors };
};
const userUploadEnvs = iterationData?.map(data => {
const orderedJson = orderedJSON.parse<Record<string, any>>(
JSON.stringify(data),
JSON_ORDER_PREFIX,
JSON_ORDER_SEPARATOR,
);
return {
name: 'User Upload',
data: orderedJson.object,
dataPropertyOrder: orderedJson.map || null,
};
});

// Return callback helper to send requests
return async function sendRequest(requestId: string, iteration?: number) {
const requestData = await fetchInsoRequestData(requestId, environmentId);
const mutatedContext = await tryToExecutePreRequestScript(requestData, requestData.workspace._id, wrapAroundIterationOverIterationData(userUploadEnvs, iteration), iteration, iterationCount);
const getCurrentRowOfIterationData = wrapAroundIterationOverIterationData(iterationData, iteration);
const mutatedContext = await tryToExecutePreRequestScript(requestData, requestData.workspace._id, getCurrentRowOfIterationData, iteration, iterationCount);
if (mutatedContext === null) {
console.error('Time out while executing pre-request script');
return null;
Expand All @@ -125,7 +112,7 @@ export async function getSendRequestCallbackMemDb(environmentId: string, memDB:
purpose: 'send',
extraInfo: undefined,
baseEnvironment: mutatedContext.baseEnvironment,
userUploadEnv: mutatedContext.userUploadEnv,
userUploadEnvironment: mutatedContext.userUploadEnvironment,
ignoreUndefinedEnvVariable,
});
// skip plugins
Expand Down
1 change: 1 addition & 0 deletions packages/insomnia/src/models/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface BaseEnvironment {
}

export type Environment = BaseModel & BaseEnvironment;
// This is a representation of the data taken from a csv or json file AKA iterationData
export type UserUploadEnvironment = Pick<Environment, 'data' | 'dataPropertyOrder' | 'name'>;

export const isEnvironment = (model: Pick<BaseModel, 'type'>): model is Environment => (
Expand Down
9 changes: 4 additions & 5 deletions packages/insomnia/src/models/runner-test-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export interface RunnerResultPerRequest {
requestName: string;
requestUrl: string;
responseCode: number;
// TODO: add request name, url, etc
}

export interface ResponseInfo {
Expand All @@ -28,15 +27,16 @@ export interface ResponseInfo {
originalRequestId: string;
}

export type RunnerResultPerRequestPerIteration = RunnerResultPerRequest[][];

export interface BaseRunnerTestResult {
source: RunnerSource;
// environmentId: string;
iterations: number;
duration: number; // millisecond
avgRespTime: number; // millisecond
iterationResults: RunnerResultPerRequest[][];
iterationResults: RunnerResultPerRequestPerIteration;
responsesInfo: ResponseInfo[];
version: '1';
version: '1'; // We might want to add or remove result features in future
}

export type RunnerTestResult = BaseModel & BaseRunnerTestResult;
Expand All @@ -48,7 +48,6 @@ export const isRunnerTestResult = (model: Pick<BaseModel, 'type'>): model is Run
export function init() {
return {
source: 'runner',
// environmentId: string;
iterations: 0,
duration: 0,
avgRespTime: 0,
Expand Down
2 changes: 1 addition & 1 deletion packages/insomnia/src/network/concurrency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface TransformedExecuteScriptContext {
globals?: Environment;
cookieJar: CookieJar;
requestTestResults?: RequestTestResult[];
userUploadEnv?: UserUploadEnvironment;
userUploadEnvironment?: UserUploadEnvironment;
}

interface Task {
Expand Down
32 changes: 16 additions & 16 deletions packages/insomnia/src/network/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export const tryToExecutePreRequestScript = async (
ancestors,
}: Awaited<ReturnType<typeof fetchRequestData>>,
workspaceId: string,
userUploadEnv?: UserUploadEnvironment,
userUploadEnvironment?: UserUploadEnvironment,
iteration?: number,
iterationCount?: number,
) => {
Expand Down Expand Up @@ -185,7 +185,7 @@ export const tryToExecutePreRequestScript = async (
settings,
cookieJar,
globals: activeGlobalEnvironment,
userUploadEnv,
userUploadEnvironment,
requestTestResults: new Array<RequestTestResult>(),
};
}
Expand All @@ -201,7 +201,7 @@ export const tryToExecutePreRequestScript = async (
clientCertificates,
cookieJar,
globals: activeGlobalEnvironment,
userUploadEnv,
userUploadEnvironment,
iteration,
iterationCount,
ancestors,
Expand Down Expand Up @@ -231,7 +231,7 @@ export const tryToExecutePreRequestScript = async (
globals: mutatedContext.globals,
cookieJar: mutatedContext.cookieJar,
requestTestResults: mutatedContext.requestTestResults,
userUploadEnv: mutatedContext.userUploadEnv,
userUploadEnvironment: mutatedContext.userUploadEnvironment,
execution: mutatedContext.execution,
};
};
Expand Down Expand Up @@ -294,7 +294,7 @@ export async function savePatchesMadeByScript(
}

export const tryToExecuteScript = async (context: RequestAndContextAndOptionalResponse) => {
const { script, request, environment, timelinePath, responseId, baseEnvironment, clientCertificates, cookieJar, response, globals, userUploadEnv, iteration, iterationCount, ancestors, eventName } = context;
const { script, request, environment, timelinePath, responseId, baseEnvironment, clientCertificates, cookieJar, response, globals, userUploadEnvironment, iteration, iterationCount, ancestors, eventName } = context;
invariant(script, 'script must be provided');

const settings = await models.settings.get();
Expand Down Expand Up @@ -334,9 +334,9 @@ export const tryToExecuteScript = async (context: RequestAndContextAndOptionalRe
},
response,
globals: globals?.data || undefined,
iterationData: userUploadEnv ? {
name: userUploadEnv.name,
data: userUploadEnv.data || {},
iterationData: userUploadEnvironment ? {
name: userUploadEnvironment.name,
data: userUploadEnvironment.data || {},
} : undefined,
execution: {
location: requestLocation,
Expand Down Expand Up @@ -374,14 +374,14 @@ export const tryToExecuteScript = async (context: RequestAndContextAndOptionalRe
globals.dataPropertyOrder = globalEnvPropertyOrder.map;
}

if (userUploadEnv) {
if (userUploadEnvironment) {
const userUploadEnvPropertyOrder = orderedJSON.parse(
JSON.stringify(output?.iterationData?.data || {}),
JSON_ORDER_PREFIX,
JSON_ORDER_SEPARATOR,
);
userUploadEnv.data = output?.iterationData?.data || {};
userUploadEnv.dataPropertyOrder = userUploadEnvPropertyOrder.map;
userUploadEnvironment.data = output?.iterationData?.data || {};
userUploadEnvironment.dataPropertyOrder = userUploadEnvPropertyOrder.map;
}

return {
Expand All @@ -392,7 +392,7 @@ export const tryToExecuteScript = async (context: RequestAndContextAndOptionalRe
clientCertificates: output.clientCertificates,
cookieJar: output.cookieJar,
globals,
userUploadEnv,
userUploadEnvironment,
requestTestResults: output.requestTestResults,
execution: output.execution,
};
Expand Down Expand Up @@ -440,7 +440,7 @@ type RequestAndContextAndResponse = RequestContextForScript & {
type RequestAndContextAndOptionalResponse = RequestContextForScript & {
script: string;
response?: sendCurlAndWriteTimelineError | sendCurlAndWriteTimelineResponse;
userUploadEnv?: UserUploadEnvironment;
userUploadEnvironment?: UserUploadEnvironment;
iteration?: number;
iterationCount?: number;
eventName?: RequestContext['requestInfo']['eventName'];
Expand Down Expand Up @@ -488,15 +488,15 @@ export const tryToInterpolateRequest = async ({
purpose,
extraInfo,
baseEnvironment,
userUploadEnv,
userUploadEnvironment,
ignoreUndefinedEnvVariable,
}: {
request: Request;
environment: string | Environment;
purpose?: RenderPurpose;
extraInfo?: ExtraRenderInfo;
baseEnvironment?: Environment;
userUploadEnv?: UserUploadEnvironment;
userUploadEnvironment?: UserUploadEnvironment;
ignoreUndefinedEnvVariable?: boolean;
}
) => {
Expand All @@ -505,7 +505,7 @@ export const tryToInterpolateRequest = async ({
request: request,
environment,
baseEnvironment,
userUploadEnv,
userUploadEnvironment,
purpose,
extraInfo,
ignoreUndefinedEnvVariable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import type { WorkspaceLoaderData } from '../../routes/workspace';
import { CopyButton } from '../base/copy-button';
import { Icon } from '../icon';

export const CLIPreviewModal = ({ onClose, requestIds, allSelected, iterations, delay, filePath }: { onClose: () => void; requestIds: string[]; allSelected: boolean; iterations: number; delay: number; filePath: string }) => {
export const CLIPreviewModal = ({ onClose, requestIds, allSelected, iterationCount, delay, filePath }: { onClose: () => void; requestIds: string[]; allSelected: boolean; iterationCount: number; delay: number; filePath: string }) => {
const { workspaceId } = useParams() as { workspaceId: string };
const { activeEnvironment } = useRouteLoaderData(':workspaceId') as WorkspaceLoaderData;
const workspaceIdOrRequestIds = allSelected ? workspaceId.slice(0, 10) : '-i ' + requestIds.join(' -i ');
const iterationsArgument = iterations > 1 ? ` -n ${iterations}` : '';
const iterationCountArgument = iterationCount > 1 ? ` -n ${iterationCount}` : '';
const delayArgument = delay > 0 ? ` --delay-request ${delay}` : '';
const iterationFilePath = filePath ? ` -d "${filePath}"` : '';
const cliCommand = `inso run collection ${workspaceIdOrRequestIds} -e ${activeEnvironment._id.slice(0, 10)}${iterationsArgument}${delayArgument}${iterationFilePath}`;
const cliCommand = `inso run collection ${workspaceIdOrRequestIds} -e ${activeEnvironment._id.slice(0, 10)}${iterationCountArgument}${delayArgument}${iterationFilePath}`;

return (
<ModalOverlay
Expand Down
Loading
Loading