From a0514f5a05c4f21522afde756d2d91252e506c81 Mon Sep 17 00:00:00 2001 From: uid11 Date: Wed, 13 Dec 2023 10:56:25 +0300 Subject: [PATCH] FI-1072 fix: fail tests run if `doAfterPack`/`doBeforePack` throw an error fix: do not lose error fields after `replaceFields` --- .../configurator/mapBackendResponseToLog.ts | 2 +- src/README.md | 29 +++++++++---------- src/actions/pages/navigateToPage.ts | 2 +- src/configurator/getReplacedObject.ts | 3 +- src/constants/report.ts | 2 ++ src/createTestFunction.ts | 2 +- src/utils/events/registerEndE2edRunEvent.ts | 9 +++++- src/utils/events/registerEndTestRunEvent.ts | 2 +- src/utils/events/registerStartE2edRunEvent.ts | 12 ++++++-- src/utils/events/runAfterPackFunctions.ts | 12 ++++++-- src/utils/events/runBeforePackFunctions.ts | 12 ++++++-- src/utils/exit/getExitCode.ts | 2 +- src/utils/exit/globalExitCode.ts | 23 +++++++++++++++ src/utils/exit/index.ts | 2 ++ src/utils/exit/processExit.ts | 10 ++++++- src/utils/log/logWithPreparedOptions.ts | 2 +- src/utils/test/beforeTest.ts | 2 +- src/utils/userland/index.ts | 4 +++ .../runArrayOfUserlandFunctions.ts} | 12 ++++---- src/utils/{ => userland}/userlandHooks.ts | 4 +-- 20 files changed, 109 insertions(+), 39 deletions(-) create mode 100644 src/utils/exit/globalExitCode.ts create mode 100644 src/utils/userland/index.ts rename src/utils/{runArrayOfFunctionsSafely.ts => userland/runArrayOfUserlandFunctions.ts} (56%) rename src/utils/{ => userland}/userlandHooks.ts (80%) diff --git a/autotests/configurator/mapBackendResponseToLog.ts b/autotests/configurator/mapBackendResponseToLog.ts index e61baa5c..615d89ca 100644 --- a/autotests/configurator/mapBackendResponseToLog.ts +++ b/autotests/configurator/mapBackendResponseToLog.ts @@ -9,8 +9,8 @@ import type {MapBackendResponseToLog} from 'autotests/types/packSpecific'; */ export const mapBackendResponseToLog: MapBackendResponseToLog = ({ duration, - statusCode, request, + statusCode, }) => { if (statusCode >= 400) { return undefined; diff --git a/src/README.md b/src/README.md index 2d9748eb..1117717c 100644 --- a/src/README.md +++ b/src/README.md @@ -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. ... diff --git a/src/actions/pages/navigateToPage.ts b/src/actions/pages/navigateToPage.ts index f5af33b5..8085e003 100644 --- a/src/actions/pages/navigateToPage.ts +++ b/src/actions/pages/navigateToPage.ts @@ -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'; diff --git a/src/configurator/getReplacedObject.ts b/src/configurator/getReplacedObject.ts index 2503aa55..2c0d0ee6 100644 --- a/src/configurator/getReplacedObject.ts +++ b/src/configurator/getReplacedObject.ts @@ -21,7 +21,8 @@ export const getReplacedObject = ( 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)); diff --git a/src/constants/report.ts b/src/constants/report.ts index b437956d..df622e3f 100644 --- a/src/constants/report.ts +++ b/src/constants/report.ts @@ -18,4 +18,6 @@ export const enum ExitCode { HasErrors = 2, NoRetries = 3, NoReportData = 4, + HasErrorsInDoAfterPackFunctions = 5, + HasErrorsInDoBeforePackFunctions = 6, } diff --git a/src/createTestFunction.ts b/src/createTestFunction.ts index d029f890..aeee711f 100644 --- a/src/createTestFunction.ts +++ b/src/createTestFunction.ts @@ -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'; diff --git a/src/utils/events/registerEndE2edRunEvent.ts b/src/utils/events/registerEndE2edRunEvent.ts index d8dcc61c..2072d9b8 100644 --- a/src/utils/events/registerEndE2edRunEvent.ts +++ b/src/utils/events/registerEndE2edRunEvent.ts @@ -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'; @@ -29,7 +30,13 @@ export const registerEndE2edRunEvent = async (): Promise => { 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; diff --git a/src/utils/events/registerEndTestRunEvent.ts b/src/utils/events/registerEndTestRunEvent.ts index 4b3301d4..56fe7d63 100644 --- a/src/utils/events/registerEndTestRunEvent.ts +++ b/src/utils/events/registerEndTestRunEvent.ts @@ -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'; diff --git a/src/utils/events/registerStartE2edRunEvent.ts b/src/utils/events/registerStartE2edRunEvent.ts index 9fcfb3a9..506d0a0f 100644 --- a/src/utils/events/registerStartE2edRunEvent.ts +++ b/src/utils/events/registerStartE2edRunEvent.ts @@ -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'; @@ -21,7 +23,13 @@ export const registerStartE2edRunEvent = async (): Promise => { 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(); diff --git a/src/utils/events/runAfterPackFunctions.ts b/src/utils/events/runAfterPackFunctions.ts index bb07d48f..1177865e 100644 --- a/src/utils/events/runAfterPackFunctions.ts +++ b/src/utils/events/runAfterPackFunctions.ts @@ -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'; @@ -19,5 +20,12 @@ export const runAfterPackFunctions = async (liteReport: LiteReport): Promise>(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); }; diff --git a/src/utils/events/runBeforePackFunctions.ts b/src/utils/events/runBeforePackFunctions.ts index 913f4c18..bf2061ef 100644 --- a/src/utils/events/runBeforePackFunctions.ts +++ b/src/utils/events/runBeforePackFunctions.ts @@ -1,4 +1,5 @@ -import {runArrayOfFunctionsSafely} from '../runArrayOfFunctionsSafely'; +import {generalLog} from '../generalLog'; +import {runArrayOfUserlandFunctions} from '../userland'; import type { FullPackConfig, @@ -33,7 +34,14 @@ export const runBeforePackFunctions = async (startInfo: StartInfo): Promise 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>( startInfo.fullPackConfig, diff --git a/src/utils/exit/getExitCode.ts b/src/utils/exit/getExitCode.ts index 18ff842a..a31b527d 100644 --- a/src/utils/exit/getExitCode.ts +++ b/src/utils/exit/getExitCode.ts @@ -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 => { diff --git a/src/utils/exit/globalExitCode.ts b/src/utils/exit/globalExitCode.ts new file mode 100644 index 00000000..df64c626 --- /dev/null +++ b/src/utils/exit/globalExitCode.ts @@ -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; +}; diff --git a/src/utils/exit/index.ts b/src/utils/exit/index.ts index 048398fd..ed183b18 100644 --- a/src/utils/exit/index.ts +++ b/src/utils/exit/index.ts @@ -1,4 +1,6 @@ /** @internal */ export {getExitCode} from './getExitCode'; /** @internal */ +export {setGlobalExitCode} from './globalExitCode'; +/** @internal */ export {processExit} from './processExit'; diff --git a/src/utils/exit/processExit.ts b/src/utils/exit/processExit.ts index 15365a61..5f02c28a 100644 --- a/src/utils/exit/processExit.ts +++ b/src/utils/exit/processExit.ts @@ -2,11 +2,19 @@ import {ExitCode} from '../../constants/internal'; import {generalLog, writeLogsToFile} from '../generalLog'; +import {getGlobalExitCode} from './globalExitCode'; + /** * Exit from e2ed process with correct exit code. * @internal */ -export const processExit = async (exitCode: ExitCode = ExitCode.NoReportData): Promise => { +export const processExit = async ( + exitCodeFromReport: ExitCode = ExitCode.NoReportData, +): Promise => { + const globalExitCode = getGlobalExitCode(); + + const exitCode = globalExitCode === undefined ? exitCodeFromReport : globalExitCode; + generalLog(`Exit from e2ed with code ${exitCode}`); await writeLogsToFile(); diff --git a/src/utils/log/logWithPreparedOptions.ts b/src/utils/log/logWithPreparedOptions.ts index 449ae2fb..a8e20359 100644 --- a/src/utils/log/logWithPreparedOptions.ts +++ b/src/utils/log/logWithPreparedOptions.ts @@ -1,7 +1,7 @@ import {getRunId} from '../../context/runId'; import {generalLog} from '../generalLog'; -import {getUserlandHooks} from '../userlandHooks'; +import {getUserlandHooks} from '../userland'; import type {LogEventType} from '../../constants/internal'; import type {LogPayload, RunId, UtcTimeInMs} from '../../types/internal'; diff --git a/src/utils/test/beforeTest.ts b/src/utils/test/beforeTest.ts index 75ac71fb..6b411f7e 100644 --- a/src/utils/test/beforeTest.ts +++ b/src/utils/test/beforeTest.ts @@ -7,7 +7,7 @@ import {setTestTimeout} from '../../context/testTimeout'; import {getRunLabel} from '../environment'; import {registerStartTestRunEvent} from '../events'; import {getFullPackConfig} from '../getFullPackConfig'; -import {getUserlandHooks} from '../userlandHooks'; +import {getUserlandHooks} from '../userland'; import {getTestFnAndReject} from './getTestFnAndReject'; import {processBrokenTestRuns} from './processBrokenTestRuns'; diff --git a/src/utils/userland/index.ts b/src/utils/userland/index.ts new file mode 100644 index 00000000..0261288f --- /dev/null +++ b/src/utils/userland/index.ts @@ -0,0 +1,4 @@ +/** @internal */ +export {getUserlandHooks, setUserlandHooks} from './userlandHooks'; +/** @internal */ +export {runArrayOfUserlandFunctions} from './runArrayOfUserlandFunctions'; diff --git a/src/utils/runArrayOfFunctionsSafely.ts b/src/utils/userland/runArrayOfUserlandFunctions.ts similarity index 56% rename from src/utils/runArrayOfFunctionsSafely.ts rename to src/utils/userland/runArrayOfUserlandFunctions.ts index e5d321da..4ac27083 100644 --- a/src/utils/runArrayOfFunctionsSafely.ts +++ b/src/utils/userland/runArrayOfUserlandFunctions.ts @@ -1,12 +1,12 @@ -import {generalLog} from './generalLog'; +import {E2edError} from '../error'; -import type {Fn} from '../types/internal'; +import type {Fn} from '../../types/internal'; /** - * Safely run array of userland function (from `doBeforePack`/`doAfterPack`). + * Run array of userland function (from `doBeforePack`/`doAfterPack`). * @internal */ -export const runArrayOfFunctionsSafely = async ( +export const runArrayOfUserlandFunctions = async ( functions: readonly Fn[], getCurrentFunctionArgs: () => Args, processCurrentFunctionResult: (result: Awaited) => void, @@ -21,8 +21,8 @@ export const runArrayOfFunctionsSafely = async