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: fail tests run if doAfterPack/doBeforePack throw an error #52

Merged
merged 1 commit into from
Dec 13, 2023
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
3 changes: 2 additions & 1 deletion .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ rules:
- src/*/internal.ts
- src/bin/*.ts
- src/createLocator.ts
- src/esm/*.ts
- src/getModulesGraph.ts
- src/globby.ts
- src/esm/testcafe.ts
- src/index.ts
- src/testcafe.ts
- src/types/extends.ts
Expand Down Expand Up @@ -174,6 +174,7 @@ rules:
'@typescript-eslint/no-unnecessary-boolean-literal-compare': off
'@typescript-eslint/no-use-before-define': error
'@typescript-eslint/quotes': [error, single, {avoidEscape: true}]
'@typescript-eslint/sort-type-constituents': [error, {checkIntersections: false}]
settings:
import/extensions: [.ts]
import/resolver: {node: {extensions: [.ts]}}
2 changes: 1 addition & 1 deletion autotests/configurator/logFieldReplacer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {FieldReplacer} from 'e2ed/types';
*/
export const logFieldReplacer: FieldReplacer = (path, value) => {
if (typeof value === 'string') {
return getStringTrimmedToMaxLength(value, 512);
return getStringTrimmedToMaxLength(value, 500);
}

const key = path[path.length - 1];
Expand Down
2 changes: 1 addition & 1 deletion autotests/configurator/mapBackendResponseToLog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import type {MapBackendResponseToLog} from 'autotests/types/packSpecific';
*/
export const mapBackendResponseToLog: MapBackendResponseToLog = ({
duration,
statusCode,
request,
statusCode,
}) => {
if (statusCode >= 400) {
return undefined;
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
},
"peerDependencies": {
"@types/node": ">=16.11.1",
"typescript": ">=4.4"
"typescript": ">=4.8"
},
"exports": {
".": "./index.js",
Expand Down Expand Up @@ -104,8 +104,9 @@
"build:copy:example": "cp -R ./autotests ./build/node_modules/e2ed/",
"postbuild:copy:example": "(cd ./build/node_modules/e2ed/autotests && rm -r ./node_modules ./tests/internalTypeTests && mv ./.gitignore ./gitignore && mv ./packs/local.example.ts ./packs/local.ts)",
"build:copy:tsconfig": "cp ./tsconfig.json ./build",
"prebuild:esm": "rm -r ./build/node_modules/e2ed/esm/*",
"prebuild:esm": "rm -r ./build/node_modules/e2ed/esm/*.js ./build/node_modules/e2ed/esm/testcafe.d.ts",
"build:esm": "cp ./src/esm/testcafe.ts ./build/node_modules/e2ed/esm/testcafe.mjs",
"postbuild:esm": "(cd ./build/node_modules/e2ed/esm && mv ./testcafe.types.d.ts ./testcafe.d.mts)",
"build:init": "(cd ./build && ./node_modules/e2ed/bin/init.js)",
"postbuild:init": "cp ./src/package.json ./build && cp -R ./autotests/tests/internalTypeTests ./build/autotests/tests",
"preversion": "npm run check:all",
Expand Down
29 changes: 14 additions & 15 deletions src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,22 @@ Modules in the dependency graph should only import the modules above them:
12. `utils/valueToString`
13. `utils/error`
14. `utils/asserts`
15. `utils/userlandHooks`
15. `utils/userland`
16. `utils/fn`
17. `utils/environment`
18. `utils/getFullPackConfig`
19. `utils/runLabel`
20. `utils/generalLog`
21. `utils/runArrayOfFunctionsSafely`
22. `utils/fs`
23. `selectors`
24. `Route`
25. `ApiRoute`
26. `PageRoute`
27. `testController`
28. `useContext`
29. `context`
30. `utils/log`
31. `utils/waitForEvents`
32. `utils/expect`
33. `expect`
34. ...
21. `utils/fs`
22. `selectors`
23. `Route`
24. `ApiRoute`
25. `PageRoute`
26. `testController`
27. `useContext`
28. `context`
29. `utils/log`
30. `utils/waitForEvents`
31. `utils/expect`
32. `expect`
33. ...
2 changes: 1 addition & 1 deletion src/actions/pages/navigateToPage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {LogEventType} from '../../constants/internal';
import {getDurationWithUnits} from '../../utils/getDurationWithUnits';
import {log} from '../../utils/log';
import {getUserlandHooks} from '../../utils/userlandHooks';
import {getUserlandHooks} from '../../utils/userland';

import {createPageInstance} from './createPageInstance';

Expand Down
2 changes: 1 addition & 1 deletion src/actions/setFilesToUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {Selector, TestCafeSelector} from '../types/internal';
*/
export const setFilesToUpload = (
selector: Selector,
filePath: string | string[],
filePath: string[] | string,
): Promise<void> => {
const hasManyFiles = Array.isArray(filePath) && filePath.length > 0;
const description = getDescriptionFromSelector(selector);
Expand Down
2 changes: 1 addition & 1 deletion src/actions/setNativeDialogHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {LogEventType} from '../constants/internal';
import {testController} from '../testController';
import {log} from '../utils/log';

type NativeDialogType = 'alert' | 'confirm' | 'beforeunload' | 'prompt';
type NativeDialogType = 'alert' | 'beforeunload' | 'confirm' | 'prompt';

/**
* Specifies handler function for the browser native dialogs
Expand Down
10 changes: 8 additions & 2 deletions src/configurator/getReplacedObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import type {AnyObject, FieldReplacer, PropertyKey} from '../types/internal';

const maxPathLength = 512;
const maxKeysCount = 1_000;
const maxPathLength = 500;

/**
* Recursively get replaced object with replaced fields.
Expand All @@ -21,10 +22,15 @@ export const getReplacedObject = <Value extends object>(

const replacedObject = (Array.isArray(value) ? [] : {}) as Value;

const keys: PropertyKey[] = Object.keys(value);
const keys: PropertyKey[] =
value instanceof Error ? Object.getOwnPropertyNames(value) : Object.keys(value);

keys.push(...Object.getOwnPropertySymbols(value));

if (keys.length > maxKeysCount) {
keys.length = maxKeysCount;
}

for (const key of keys) {
path[pathLength] = key;

Expand Down
2 changes: 2 additions & 0 deletions src/constants/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ export const enum ExitCode {
HasErrors = 2,
NoRetries = 3,
NoReportData = 4,
HasErrorsInDoAfterPackFunctions = 5,
HasErrorsInDoBeforePackFunctions = 6,
}
2 changes: 1 addition & 1 deletion src/createTestFunction.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {setUserlandHooks} from './utils/userlandHooks';
import {setUserlandHooks} from './utils/userland';
import {test} from './test';

import type {AnyPack, GetPackParameters, TestFunction, UserlandHooks} from './types/internal';
Expand Down
1 change: 1 addition & 0 deletions src/esm/testcafe.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {createTestCafe} from '../testcafe';
8 changes: 4 additions & 4 deletions src/types/clientFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ export type ClientFunctionState<Args extends readonly unknown[], Result> = {
* @internal
*/
export type ClientFunctionWrapperResult<Result = unknown> = Readonly<
| {
errorMessage: undefined;
result: Result;
}
| {
errorMessage: string;
result: undefined;
}
| {
errorMessage: undefined;
result: Result;
}
>;

/**
Expand Down
8 changes: 4 additions & 4 deletions src/types/http/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ export type Query =
| Readonly<
Record<
string,
| string
| number
| boolean
| readonly string[]
| readonly number[]
| number
| string
| readonly boolean[]
| readonly number[]
| readonly string[]
| null
| undefined
>
Expand Down
2 changes: 1 addition & 1 deletion src/types/mockApiRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type ApiMockFunction<
> = (
routeParams: RouteParams,
request: SomeRequest,
) => Promise<Partial<SomeResponse>> | Partial<SomeResponse>;
) => Partial<SomeResponse> | Promise<Partial<SomeResponse>>;

/**
* Internal state of mockApiRoute/unmockApiRoute.
Expand Down
2 changes: 1 addition & 1 deletion src/types/promise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type AsyncVoid = MaybePromise<void>;
/**
* A value of a type `Type` that may be wrapped in a promise.
*/
export type MaybePromise<Type> = Type | Promise<Type>;
export type MaybePromise<Type> = Promise<Type> | Type;

/**
* Reexecutable promise from TestCafe.
Expand Down
8 changes: 4 additions & 4 deletions src/types/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type DataPropertyDescriptor<Value> = Readonly<
GenericPropertyDescriptor;

type AccessorPropertyDescriptor<Value> = Readonly<
{get(): Value; set?(value: Value): void} | {get?(): Value; set(value: Value): void}
{get?(): Value; set(value: Value): void} | {get(): Value; set?(value: Value): void}
> &
GenericPropertyDescriptor;

Expand All @@ -31,15 +31,15 @@ export type FieldReplacer = (
/**
* Primitive value.
*/
export type PrimitiveValue = bigint | boolean | null | number | string | symbol | undefined;
export type PrimitiveValue = bigint | boolean | number | string | symbol | null | undefined;

/**
* Property descriptor.
*/
export type PropertyDescriptor<Value = unknown> =
| GenericPropertyDescriptor
| AccessorPropertyDescriptor<Value>
| DataPropertyDescriptor<Value>
| AccessorPropertyDescriptor<Value>;
| GenericPropertyDescriptor;

/**
* Property key.
Expand Down
2 changes: 1 addition & 1 deletion src/types/testRun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type RejectTestRun = (error: E2edError) => void;
/**
* Test run error (in string presentation), if any.
*/
export type RunError = string | StringForLogs | undefined;
export type RunError = StringForLogs | string | undefined;

/**
* Hash string of each test run, generated by userland hook.
Expand Down
9 changes: 8 additions & 1 deletion src/utils/events/registerEndE2edRunEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {ExitCode} from '../../constants/internal';
import {processExit} from '../exit';
import {failMessage, generalLog, okMessage} from '../generalLog';
import {collectReportData, getLiteReport, writeHtmlReport, writeLiteJsonReport} from '../report';
import {setReadonlyProperty} from '../setReadonlyProperty';

import {collectFullEventsData} from './collectFullEventsData';
import {runAfterPackFunctions} from './runAfterPackFunctions';
Expand All @@ -29,7 +30,13 @@ export const registerEndE2edRunEvent = async (): Promise<void> => {

const liteReport = getLiteReport(reportData);

await runAfterPackFunctions(liteReport);
try {
await runAfterPackFunctions(liteReport);
} catch (error) {
generalLog('Caught an error on run "after pack" functions', {error});

setReadonlyProperty(reportData, 'exitCode', ExitCode.HasErrorsInDoAfterPackFunctions);
}

const {customReportProperties} = liteReport;

Expand Down
2 changes: 1 addition & 1 deletion src/utils/events/registerEndTestRunEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {cloneWithoutLogEvents} from '../clone';
import {getRunErrorFromError} from '../error';
import {writeTestRunToJsonFile} from '../fs';
import {generalLog, logEndTestRunEvent, writeLogsToFile} from '../generalLog';
import {getUserlandHooks} from '../userlandHooks';
import {getUserlandHooks} from '../userland';

import {calculateTestRunStatus} from './calculateTestRunStatus';
import {getTestRunEvent} from './getTestRunEvent';
Expand Down
12 changes: 10 additions & 2 deletions src/utils/events/registerStartE2edRunEvent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {RunEnvironment} from '../../configurator';
import {EVENTS_DIRECTORY_PATH, TMP_DIRECTORY_PATH} from '../../constants/internal';
import {EVENTS_DIRECTORY_PATH, ExitCode, TMP_DIRECTORY_PATH} from '../../constants/internal';

import {E2edError} from '../error';
import {setGlobalExitCode} from '../exit';
import {createDirectory, removeDirectory, writeStartInfo} from '../fs';
import {generalLog, writeLogsToFile} from '../generalLog';
import {getFullPackConfig, updateConfig} from '../getFullPackConfig';
Expand All @@ -21,7 +23,13 @@ export const registerStartE2edRunEvent = async (): Promise<void> => {

const startInfo = getStartInfo();

await runBeforePackFunctions(startInfo);
try {
await runBeforePackFunctions(startInfo);
} catch (cause) {
setGlobalExitCode(ExitCode.HasErrorsInDoBeforePackFunctions);

throw new E2edError('Caught an error on running "before pack" functions', {cause});
}

const fullPackConfig = getFullPackConfig();

Expand Down
12 changes: 10 additions & 2 deletions src/utils/events/runAfterPackFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {generalLog} from '../generalLog';
import {getFullPackConfig} from '../getFullPackConfig';
import {runArrayOfFunctionsSafely} from '../runArrayOfFunctionsSafely';
import {runArrayOfUserlandFunctions} from '../userland';

import type {CustomReportPropertiesPlaceholder, LiteReport, Void} from '../../types/internal';

Expand All @@ -19,5 +20,12 @@ export const runAfterPackFunctions = async (liteReport: LiteReport): Promise<voi
Object.assign<LiteReport, Partial<LiteReport>>(liteReport, {customReportProperties: result});
};

await runArrayOfFunctionsSafely(functions, () => args, processCurrentFunctionResult);
const message =
functions.length > 0
? `Will be run ${functions.length} after pack function${functions.length > 1 ? 's' : ''}`
: 'There are no after pack functions';

generalLog(message);

await runArrayOfUserlandFunctions(functions, () => args, processCurrentFunctionResult);
};
12 changes: 10 additions & 2 deletions src/utils/events/runBeforePackFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {runArrayOfFunctionsSafely} from '../runArrayOfFunctionsSafely';
import {generalLog} from '../generalLog';
import {runArrayOfUserlandFunctions} from '../userland';

import type {
FullPackConfig,
Expand Down Expand Up @@ -33,7 +34,14 @@ export const runBeforePackFunctions = async (startInfo: StartInfo): Promise<void
});
};

await runArrayOfFunctionsSafely(functions, () => args, processCurrentFunctionResult);
const message =
functions.length > 0
? `Will be run ${functions.length} before pack function${functions.length > 1 ? 's' : ''}`
: 'There are no before pack functions';

generalLog(message);

await runArrayOfUserlandFunctions(functions, () => args, processCurrentFunctionResult);

Object.assign<FullPackConfigWithoutDoBeforePack, Partial<FullPackConfig>>(
startInfo.fullPackConfig,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/exit/getExitCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {assertValueIsDefined} from '../asserts';
import type {Retry} from '../../types/internal';

/**
* Get e2ed exit code by hasErrors flag and array of retries.
* Get e2ed exit code by `hasErrors` flag and array of retries.
* @internal
*/
export const getExitCode = (hasErrors: boolean, retries: readonly Retry[]): ExitCode => {
Expand Down
23 changes: 23 additions & 0 deletions src/utils/exit/globalExitCode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {assertValueIsDefined, assertValueIsUndefined} from '../asserts';

import type {ExitCode} from '../../constants/internal';

let globalExitCode: ExitCode | undefined;

/**
* Get global exit code.
* @internal
*/
export const getGlobalExitCode = (): ExitCode | undefined => globalExitCode;

/**
* Set global exit code (once).
* @internal
*/
export const setGlobalExitCode = (exitCode: ExitCode): void => {
assertValueIsUndefined(globalExitCode, 'globalExitCode is not defined', {exitCode});

assertValueIsDefined(exitCode, 'exitCode is defined', {globalExitCode});

globalExitCode = exitCode;
};
2 changes: 2 additions & 0 deletions src/utils/exit/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/** @internal */
export {getExitCode} from './getExitCode';
/** @internal */
export {setGlobalExitCode} from './globalExitCode';
/** @internal */
export {processExit} from './processExit';
Loading
Loading