Skip to content

Commit

Permalink
Merge pull request #83 from joomcode/fix/headers-mapping
Browse files Browse the repository at this point in the history
fix: mapping of `set-cookie` header and other headers
  • Loading branch information
uid11 authored Aug 5, 2024
2 parents 37eb24c + 5733420 commit b073b6a
Show file tree
Hide file tree
Showing 27 changed files with 122 additions and 93 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ import type {Pack} from 'autotests/configurator';
*/
export const pack: Pack = {
...allTestsPack,
browserInitTimeout: 40_000,
testIdleTimeout: 10_000,
};
```

Expand Down
15 changes: 8 additions & 7 deletions autotests/actions/setPageCookiesAndNavigateToUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -11,18 +11,19 @@ export const setPageCookiesAndNavigateToUrl = async (
url: Url,
pageCookies: readonly Cookie[],
): Promise<void> => {
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);
Expand Down
6 changes: 3 additions & 3 deletions autotests/actions/setPageRequestHeadersAndNavigateToUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> => {
const mapRequestHeaders = (): Headers => pageRequestHeaders;
const mapRequestHeaders = (): StringHeaders => pageRequestHeaders;

log(
`Navigate to ${url} and set page request headers`,
Expand Down
3 changes: 1 addition & 2 deletions autotests/packs/allTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -81,7 +80,7 @@ export const pack: Pack = {
takeFullPageScreenshotOnError: false,
takeViewportScreenshotOnError: true,
testFileGlobs: ['**/autotests/tests/**/*.ts'],
testIdleTimeout: 20_000,
testIdleTimeout: 8_000,
testTimeout: 60_000,
viewportHeight: 1080,
viewportWidth: 1920,
Expand Down
4 changes: 2 additions & 2 deletions autotests/packs/local.example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -44,7 +46,7 @@ export class E2edReportExample extends Page<CustomPageParams> {
/**
* Request headers that we add to page request.
*/
readonly pageRequestHeaders: Headers | undefined;
readonly pageRequestHeaders: StringHeaders | undefined;

override readonly pageStabilizationInterval = 600;

Expand Down
2 changes: 1 addition & 1 deletion autotests/tests/main/exists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const testScrollValue = 200;
const language = 'en';
const searchQuery = 'foo';

test('exists', {meta: {testId: '1'}, testIdleTimeout: 35_000, testTimeout: 90_000}, async () => {
test('exists', {meta: {testId: '1'}, testIdleTimeout: 10_000, testTimeout: 15_000}, async () => {
await scroll(0, testScrollValue);

assertFunctionThrows(() => {
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
},
"devDependencies": {
"@playwright/browser-chromium": "1.45.3",
"@types/node": "22.0.0",
"@types/node": "22.1.0",
"@typescript-eslint/eslint-plugin": "7.18.0",
"@typescript-eslint/parser": "7.18.0",
"assert-modules-support-case-insensitive-fs": "1.0.1",
Expand Down
1 change: 0 additions & 1 deletion src/actions/asserts/assertUrlMatchRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<MaybeUrlOrPath>,
Expand Down
1 change: 0 additions & 1 deletion src/types/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import type {OwnE2edConfig} from './ownE2edConfig';
type UserlandTestCafeConfig = Readonly<{
ajaxRequestTimeout: number;
assertionTimeout: number;
browserInitTimeout: number;
concurrency: number;
pageRequestTimeout: number;
port1: number;
Expand Down
7 changes: 6 additions & 1 deletion src/types/http/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -117,6 +117,11 @@ export type ResponseWithRequest<
}> &
SomeResponse;

/**
* Headers as strings.
*/
export type StringHeaders = Readonly<Record<string, string>>;

/**
* Brand type for the full url string.
*/
Expand Down
1 change: 1 addition & 0 deletions src/types/http/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type {
RequestWithUtcTimeInMs,
Response,
ResponseWithRequest,
StringHeaders,
Url,
} from './http';
export type {RequestKeyType, ResponseKeyType} from './internalKeys';
Expand Down
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type {
SameSite,
SetCookieHeaderString,
StatusCode,
StringHeaders,
Url,
} from './http';
export type {KeyboardPressKey} from './keyboard';
Expand Down
1 change: 1 addition & 0 deletions src/types/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export type {
SameSite,
SetCookieHeaderString,
StatusCode,
StringHeaders,
Url,
} from './http';
export type {KeyboardPressKey} from './keyboard';
Expand Down
8 changes: 1 addition & 7 deletions src/utils/config/assertUserlandPack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -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',
Expand Down
2 changes: 2 additions & 0 deletions src/utils/generalLog/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ export {writeLogsToFile} from './logFile';
export {logStartE2edError} from './logStartE2edError';
export {removeStyleFromString} from './removeStyleFromString';
/** @internal */
export {getSuccessfulTestRuns} from './successfulTestRunCount';
/** @internal */
export {truncateArrayForLogs} from './truncateArrayForLogs';
4 changes: 2 additions & 2 deletions src/utils/generalLog/logEndTestRunEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {

import {generalLog} from './generalLog';
import {getMessageWithBackgroundColor} from './getMessageWithBackgroundColor';
import {addSuccessfulInCurrentRetry, getSuccessfulTestRunCount} from './successfulTestRunCount';
import {addSuccessfulInCurrentRetry, getSuccessfulTestRuns} from './successfulTestRunCount';

import type {FullTestRun} from '../../types/internal';

Expand All @@ -27,7 +27,7 @@ export const logEndTestRunEvent = async (fullTestRun: FullTestRun): Promise<void
const messageText = `${messageSymbol} ${status} ${mainParams} ${name}`;

const message = getMessageWithBackgroundColor(messageText, messageBackgroundColor);
const successful = await getSuccessfulTestRunCount();
const successful = (await getSuccessfulTestRuns()).length;

generalLog(message, {filePath, options, runError, runId, successful});
};
37 changes: 23 additions & 14 deletions src/utils/generalLog/successfulTestRunCount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {join} from 'node:path';

import {READ_FILE_OPTIONS, TMP_DIRECTORY_PATH} from '../../constants/internal';

import {assertValueIsFalse} from '../asserts';

import type {FilePathFromRoot, TestFilePath} from '../../types/internal';

/**
Expand All @@ -11,27 +13,34 @@ import type {FilePathFromRoot, TestFilePath} from '../../types/internal';
const SUCCESSFUL_TESTS_PATH = join(TMP_DIRECTORY_PATH, 'successfulTests.txt') as FilePathFromRoot;

/**
* Adds one successful test run (in current retry).
* @internal
*/
export const addSuccessfulInCurrentRetry = async (filePath: TestFilePath): Promise<void> => {
await appendFile(SUCCESSFUL_TESTS_PATH, `${filePath}\n`);
};

/**
* Get the number of tests successful for printing (total and in the current retry).
* Get array of successful tests.
* @internal
*/
export const getSuccessfulTestRunCount = async (): Promise<number> => {
export const getSuccessfulTestRuns = async (): Promise<readonly TestFilePath[]> => {
let successfulTestsFile = '';

try {
successfulTestsFile = await readFile(SUCCESSFUL_TESTS_PATH, READ_FILE_OPTIONS);
} catch {}

if (successfulTestsFile === '') {
return 0;
}
return successfulTestsFile
.split('\n')
.map((line) => line.trim())
.filter(Boolean) as TestFilePath[];
};

/**
* Adds one successful test run (in current retry).
* @internal
*/
export const addSuccessfulInCurrentRetry = async (testFilePath: TestFilePath): Promise<void> => {
const successfulTestRuns = await getSuccessfulTestRuns();

assertValueIsFalse(
successfulTestRuns.includes(testFilePath),
'There is no duplicate test file path in successful test runs',
{successfulTestRuns, testFilePath},
);

return successfulTestsFile.split('\n').filter(Boolean).length;
await appendFile(SUCCESSFUL_TESTS_PATH, `${testFilePath}\n`);
};
8 changes: 6 additions & 2 deletions src/utils/report/writeLiteJsonReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -23,11 +25,13 @@ export const writeLiteJsonReport = async (liteReport: LiteReport): Promise<void>

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}`,
);
};
11 changes: 5 additions & 6 deletions src/utils/requestHooks/applyHeadersMapper.ts
Original file line number Diff line number Diff line change
@@ -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> = headers;
const mutableHeaders: Mutable<StringHeaders> = headers;

for (const [name, value] of Object.entries(newHeaders)) {
if (value === undefined) {
Expand All @@ -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;
}
}
};
Loading

0 comments on commit b073b6a

Please sign in to comment.