diff --git a/README.md b/README.md index 0fe59e86..bc9b756a 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ import type {Pack} from 'autotests/configurator'; */ export const pack: Pack = { ...allTestsPack, - browserInitTimeout: 40_000, + testIdleTimeout: 10_000, }; ``` diff --git a/autotests/actions/setPageCookiesAndNavigateToUrl.ts b/autotests/actions/setPageCookiesAndNavigateToUrl.ts index 77818565..b7fe7ba8 100644 --- a/autotests/actions/setPageCookiesAndNavigateToUrl.ts +++ b/autotests/actions/setPageCookiesAndNavigateToUrl.ts @@ -2,7 +2,7 @@ import {setHeadersAndNavigateToUrl} from 'e2ed/actions'; import {LogEventType} from 'e2ed/constants'; import {getHeaderValue, log, replaceSetCookie} from 'e2ed/utils'; -import type {Cookie, Headers, Url} from 'e2ed/types'; +import type {Cookie, SetCookieHeaderString, StringHeaders, Url} from 'e2ed/types'; /** * Navigate to the url and set custom page cookies. @@ -11,18 +11,19 @@ export const setPageCookiesAndNavigateToUrl = async ( url: Url, pageCookies: readonly Cookie[], ): Promise => { - const mapResponseHeaders = (headers: Headers): Headers => { - let setCookies = getHeaderValue(headers, 'set-cookie'); + const mapResponseHeaders = (headers: StringHeaders): StringHeaders => { + let cookiesArray: SetCookieHeaderString[] = []; + const setCookies = getHeaderValue(headers, 'set-cookie'); - if (setCookies === undefined) { - setCookies = []; + if (setCookies !== undefined) { + cookiesArray.push(setCookies as SetCookieHeaderString); } for (const cookie of pageCookies) { - setCookies = replaceSetCookie(setCookies, cookie); + cookiesArray = replaceSetCookie(cookiesArray, cookie); } - return {'set-cookie': setCookies}; + return {'set-cookie': cookiesArray.join('\n')}; }; log(`Navigate to ${url} and set page cookie`, {pageCookies, url}, LogEventType.Action); diff --git a/autotests/actions/setPageRequestHeadersAndNavigateToUrl.ts b/autotests/actions/setPageRequestHeadersAndNavigateToUrl.ts index a2ce174b..4879f5ec 100644 --- a/autotests/actions/setPageRequestHeadersAndNavigateToUrl.ts +++ b/autotests/actions/setPageRequestHeadersAndNavigateToUrl.ts @@ -2,16 +2,16 @@ import {setHeadersAndNavigateToUrl} from 'e2ed/actions'; import {LogEventType} from 'e2ed/constants'; import {log} from 'e2ed/utils'; -import type {Headers, Url} from 'e2ed/types'; +import type {StringHeaders, Url} from 'e2ed/types'; /** * Navigate to the url and set additional page request headers. */ export const setPageRequestHeadersAndNavigateToUrl = async ( url: Url, - pageRequestHeaders: Headers, + pageRequestHeaders: StringHeaders, ): Promise => { - const mapRequestHeaders = (): Headers => pageRequestHeaders; + const mapRequestHeaders = (): StringHeaders => pageRequestHeaders; log( `Navigate to ${url} and set page request headers`, diff --git a/autotests/packs/allTests.ts b/autotests/packs/allTests.ts index c37868a2..735b8e20 100644 --- a/autotests/packs/allTests.ts +++ b/autotests/packs/allTests.ts @@ -47,7 +47,6 @@ export const pack: Pack = { assertionTimeout: 5_000, browser, browserFlags, - browserInitTimeout: 60_000, concurrency: isLocalRun ? 1 : 2, customPackProperties: {internalPackRunId: 0, name: 'allTests'}, doAfterPack, diff --git a/autotests/packs/local.example.ts b/autotests/packs/local.example.ts index 8d1caf07..a4d9d363 100644 --- a/autotests/packs/local.example.ts +++ b/autotests/packs/local.example.ts @@ -3,9 +3,9 @@ import {pack as allTestsPack} from './allTests'; import type {Pack} from 'autotests/configurator'; /** - * Pack from .gitignore for local development. + * Pack from `.gitignore` for local development. */ export const pack: Pack = { ...allTestsPack, - browserInitTimeout: 40_000, + testIdleTimeout: 10_000, }; diff --git a/autotests/pageObjects/pages/E2edReportExample/E2edReportExample.ts b/autotests/pageObjects/pages/E2edReportExample/E2edReportExample.ts index 61da5d18..7049b5f8 100644 --- a/autotests/pageObjects/pages/E2edReportExample/E2edReportExample.ts +++ b/autotests/pageObjects/pages/E2edReportExample/E2edReportExample.ts @@ -10,9 +10,11 @@ import {createPageObjectsFromMultiLocator, setReadonlyProperty} from 'e2ed/utils import {TestRunButton} from './TestRunButton'; -import type {Cookie, Headers, Selector, Url} from 'e2ed/types'; +import type {Cookie, Selector, StringHeaders, Url} from 'e2ed/types'; -type CustomPageParams = {pageCookies?: readonly Cookie[]; pageRequestHeaders?: Headers} | undefined; +type CustomPageParams = + | {pageCookies?: readonly Cookie[]; pageRequestHeaders?: StringHeaders} + | undefined; /** * The e2ed report example page. @@ -44,7 +46,7 @@ export class E2edReportExample extends Page { /** * Request headers that we add to page request. */ - readonly pageRequestHeaders: Headers | undefined; + readonly pageRequestHeaders: StringHeaders | undefined; override readonly pageStabilizationInterval = 600; diff --git a/src/actions/asserts/assertUrlMatchRoute.ts b/src/actions/asserts/assertUrlMatchRoute.ts index d728e59d..fb51c630 100644 --- a/src/actions/asserts/assertUrlMatchRoute.ts +++ b/src/actions/asserts/assertUrlMatchRoute.ts @@ -10,7 +10,6 @@ type MaybeUrlOrPath = Url | string | null | undefined; /** * Asserts that url or url path (which can be wrapped in a promise) match route. - * TODO: support Smart Assertions. */ export const assertUrlMatchRoute = async ( maybeUrlOrPath: MaybeUrlOrPath | Promise, diff --git a/src/types/config/config.ts b/src/types/config/config.ts index 7ebb048c..b50e2a7d 100644 --- a/src/types/config/config.ts +++ b/src/types/config/config.ts @@ -16,7 +16,6 @@ import type {OwnE2edConfig} from './ownE2edConfig'; type UserlandTestCafeConfig = Readonly<{ ajaxRequestTimeout: number; assertionTimeout: number; - browserInitTimeout: number; concurrency: number; pageRequestTimeout: number; port1: number; diff --git a/src/types/http/http.ts b/src/types/http/http.ts index dce48104..1fde72e2 100644 --- a/src/types/http/http.ts +++ b/src/types/http/http.ts @@ -26,7 +26,7 @@ export type Headers = Readonly< * Maps headers to new (overridden) headers. * All headers must be in lower case. */ -export type MapHeaders = (this: void, headers: Headers) => Headers; +export type MapHeaders = (this: void, headers: StringHeaders) => StringHeaders; /** * Options for mappers of headers. @@ -117,6 +117,11 @@ export type ResponseWithRequest< }> & SomeResponse; +/** + * Headers as strings. + */ +export type StringHeaders = Readonly>; + /** * Brand type for the full url string. */ diff --git a/src/types/http/index.ts b/src/types/http/index.ts index 16d954ec..78f9ee7d 100644 --- a/src/types/http/index.ts +++ b/src/types/http/index.ts @@ -10,6 +10,7 @@ export type { RequestWithUtcTimeInMs, Response, ResponseWithRequest, + StringHeaders, Url, } from './http'; export type {RequestKeyType, ResponseKeyType} from './internalKeys'; diff --git a/src/types/index.ts b/src/types/index.ts index 7d815ca4..440eb505 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -31,6 +31,7 @@ export type { SameSite, SetCookieHeaderString, StatusCode, + StringHeaders, Url, } from './http'; export type {KeyboardPressKey} from './keyboard'; diff --git a/src/types/internal.ts b/src/types/internal.ts index 2fcbcc18..d79d22b8 100644 --- a/src/types/internal.ts +++ b/src/types/internal.ts @@ -54,6 +54,7 @@ export type { SameSite, SetCookieHeaderString, StatusCode, + StringHeaders, Url, } from './http'; export type {KeyboardPressKey} from './keyboard'; diff --git a/src/utils/config/assertUserlandPack.ts b/src/utils/config/assertUserlandPack.ts index 08f0d5ea..fe426d8d 100644 --- a/src/utils/config/assertUserlandPack.ts +++ b/src/utils/config/assertUserlandPack.ts @@ -6,7 +6,7 @@ import type {UserlandPack} from '../../types/internal'; * Asserts that userland pack is correct. * @internal */ -// eslint-disable-next-line max-lines-per-function, max-statements +// eslint-disable-next-line max-lines-per-function export const assertUserlandPack = (userlandPack: UserlandPack): void => { const logParams = {userlandPack}; @@ -28,12 +28,6 @@ export const assertUserlandPack = (userlandPack: UserlandPack): void => { logParams, ); - assertNumberIsPositiveInteger( - userlandPack.browserInitTimeout, - 'browserInitTimeout is positive integer', - logParams, - ); - assertNumberIsPositiveInteger( userlandPack.maxRetriesCountInDocker, 'maxRetriesCountInDocker is positive integer', diff --git a/src/utils/report/writeLiteJsonReport.ts b/src/utils/report/writeLiteJsonReport.ts index 5a0077fd..ef1bddc8 100644 --- a/src/utils/report/writeLiteJsonReport.ts +++ b/src/utils/report/writeLiteJsonReport.ts @@ -8,6 +8,8 @@ import {getDurationWithUnits} from '../getDurationWithUnits'; import type {FilePathFromRoot, LiteReport, UtcTimeInMs} from '../../types/internal'; +const bytesInKb = 1_024; + /** * Writes lite JSON report (`lite-report.json` file) with test runs results * (and without test run logs). @@ -23,11 +25,13 @@ export const writeLiteJsonReport = async (liteReport: LiteReport): Promise await writeFile(reportFilePath, reportJson); - const reportFileSize = await getFileSize(reportFilePath); + const reportFileSizeInBytes = await getFileSize(reportFilePath); + + const reportFileSizeInKb = (reportFileSizeInBytes / bytesInKb).toFixed(2); const durationWithUnits = getDurationWithUnits(Date.now() - startTimeInMs); generalLog( - `Lite JSON report was written (${reportFileSize} bytes) to "${reportFilePath}" in ${durationWithUnits}`, + `Lite JSON report was written (${reportFileSizeInKb} bytes) to "${reportFilePath}" in ${durationWithUnits}`, ); }; diff --git a/src/utils/requestHooks/applyHeadersMapper.ts b/src/utils/requestHooks/applyHeadersMapper.ts index ea98b918..96896289 100644 --- a/src/utils/requestHooks/applyHeadersMapper.ts +++ b/src/utils/requestHooks/applyHeadersMapper.ts @@ -1,17 +1,16 @@ -import {getCopyOfHeaders} from './getCopyOfHeaders'; import {getEquivalentHeadersNames} from './getEquivalentHeadersNames'; -import type {Headers, MapHeaders, Mutable} from '../../types/internal'; +import type {MapHeaders, Mutable, StringHeaders} from '../../types/internal'; /** * Map exists headers to new headers and merge this new headers to exists headers. * @internal */ -export const applyHeadersMapper = (headers: Headers, mapper: MapHeaders): void => { - const copyOfHeaders = getCopyOfHeaders(headers); +export const applyHeadersMapper = (headers: StringHeaders, mapper: MapHeaders): void => { + const copyOfHeaders = {...headers}; const newHeaders = mapper(copyOfHeaders); - const mutableHeaders: Mutable = headers; + const mutableHeaders: Mutable = headers; for (const [name, value] of Object.entries(newHeaders)) { if (value === undefined) { @@ -22,7 +21,7 @@ export const applyHeadersMapper = (headers: Headers, mapper: MapHeaders): void = delete mutableHeaders[currentName]; } } else { - mutableHeaders[name] = value as string[] | string | undefined; + mutableHeaders[name] = value; } } }; diff --git a/src/utils/requestHooks/getCopyOfHeaders.ts b/src/utils/requestHooks/getCopyOfHeaders.ts deleted file mode 100644 index 9325b170..00000000 --- a/src/utils/requestHooks/getCopyOfHeaders.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type {Headers} from '../../types/internal'; - -/** - * Get copy of headers object. - * @internal - */ -export const getCopyOfHeaders = (headers: Headers): Headers => { - const copyOfHeaders = {...headers}; - - for (const [key, value] of Object.entries(copyOfHeaders)) { - if (Array.isArray(value)) { - copyOfHeaders[key] = [...value]; - } - } - - return copyOfHeaders; -}; diff --git a/src/utils/test/preparePage.ts b/src/utils/test/preparePage.ts index 5240d476..2d6a8a3d 100644 --- a/src/utils/test/preparePage.ts +++ b/src/utils/test/preparePage.ts @@ -4,7 +4,6 @@ import {getIsPageNavigatingNow, setIsPageNavigatingNow} from '../../context/isPa import {getNavigationDelay} from '../../context/navigationDelay'; import {getOnResponseCallbacks} from '../../context/onResponseCallbacks'; -import {assertValueIsNotNull} from '../asserts'; import {getResponseFromPlaywrightResponse} from '../requestHooks'; import type {Page} from '@playwright/test'; @@ -76,9 +75,17 @@ export const preparePage = async (page: Page): Promise => { return; } - const playwrightResponse = await request.response(); + const playwrightResponse = await request.response().catch((error) => { + if (String(error).includes('Target page, context or browser has been closed')) { + return null; + } - assertValueIsNotNull(playwrightResponse, 'response is not null', {url: request.url()}); + throw error; + }); + + if (playwrightResponse === null) { + return; + } const responseWithRequest = await getResponseFromPlaywrightResponse(playwrightResponse); diff --git a/src/utils/tests/runTests.ts b/src/utils/tests/runTests.ts index 10c20ff3..556ae8fd 100644 --- a/src/utils/tests/runTests.ts +++ b/src/utils/tests/runTests.ts @@ -24,7 +24,7 @@ export const runTests = async ({runLabel}: RunRetryOptions): Promise => { setRunLabel(runLabel); try { - const {browserInitTimeout, enableLiveMode, resourceUsageReadingInternal} = getFullPackConfig(); + const {enableLiveMode, testIdleTimeout, resourceUsageReadingInternal} = getFullPackConfig(); startResourceUsageReading(resourceUsageReadingInternal); @@ -36,7 +36,7 @@ export const runTests = async ({runLabel}: RunRetryOptions): Promise => { beforeRunFirstTest(); } - }, browserInitTimeout); + }, testIdleTimeout); beforeRunFirstTestTimeoutId.unref(); diff --git a/src/utils/tests/stripExtraLogs.ts b/src/utils/tests/stripExtraLogs.ts index 9b9d748e..3465c11e 100644 --- a/src/utils/tests/stripExtraLogs.ts +++ b/src/utils/tests/stripExtraLogs.ts @@ -1,3 +1,5 @@ +import {sep} from 'node:path'; + /** * Strip extra Playwright logs. * @internal @@ -8,7 +10,7 @@ export const stripExtraLogs = (text: string): string => { for (let index = 0; index < lines.length; index += 1) { const line = lines[index]; - if (line?.includes('../node_modules/e2ed/test.js:')) { + if (line?.includes(`${sep}node_modules${sep}e2ed${sep}test.js:`)) { const startIndex = line.indexOf('›'); const endIndex = line.lastIndexOf('›');