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: stricter type of expect function #49

Merged
merged 1 commit into from
Dec 7, 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
18 changes: 9 additions & 9 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,35 @@ jobs:
build-docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: npm
node-version: 16.11.1
node-version: 20.10.0
- run: npm ci
- run: npm run build
- run: npm run build:docker

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: npm
node-version: 16.11.1
node-version: 20.10.0
- run: npm ci
- run: npm run build
- run: npm run lint

test-local:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: npm
node-version: 16.11.1
node-version: 20.10.0
- run: npm ci
- run: npm run build
- run: npm run test:local
11 changes: 9 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
FROM alpine:3.18.4
FROM node:20.10.0-alpine AS node

FROM alpine:3.18.5

COPY --from=node /usr/lib /usr/lib
COPY --from=node /usr/local/lib /usr/local/lib
COPY --from=node /usr/local/include /usr/local/include
COPY --from=node /usr/local/bin /usr/local/bin

RUN apk --no-cache upgrade && \
apk --no-cache add \
bash libevent nodejs npm chromium firefox xwininfo xvfb dbus eudev ttf-freefont fluxbox procps tzdata icu-data-full
bash libevent npm chromium firefox xwininfo xvfb dbus eudev ttf-freefont fluxbox procps tzdata icu-data-full

COPY ./build/node_modules/e2ed /node_modules/e2ed

Expand Down
2 changes: 2 additions & 0 deletions autotests/configurator/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export {doAfterPack} from './doAfterPack';
export {doBeforePack} from './doBeforePack';
export {mapBackendResponseErrorToLog} from './mapBackendResponseErrorToLog';
export {mapBackendResponseToLog} from './mapBackendResponseToLog';
export {mapLogPayloadInConsole} from './mapLogPayloadInConsole';
export {mapLogPayloadInLogFile} from './mapLogPayloadInLogFile';
export {mapLogPayloadInReport} from './mapLogPayloadInReport';
Expand Down
38 changes: 38 additions & 0 deletions autotests/configurator/mapBackendResponseErrorToLog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {getDurationWithUnits} from 'e2ed/utils';

import type {MapBackendResponseErrorToLog} from 'autotests/types/packSpecific';

/**
* Maps responses with errors from the backend to "red" logs (as errors) during the test.
* It is assumed that the function will select responses with
* statuse codes of 400 and higher (client and server errors).
* Backend responses with errors are accumulated in separate "red" log step
* (with `logEventStatus: 'failed'`).
* Log the `responseBody` field carefully, as the body of backend response can be very large.
* If the function returns `undefined`, the response is not logged (skipped).
*/
export const mapBackendResponseErrorToLog: MapBackendResponseErrorToLog = ({
completionTimeInMs,
request,
responseBody,
responseHeaders,
statusCode,
}) => {
if (statusCode < 400) {
return undefined;
}

const {requestBody, utcTimeInMs, ...requestWithoutBody} = request;

const duration = getDurationWithUnits(completionTimeInMs - utcTimeInMs);

return {
duration,
request: {
requestBody: requestBody instanceof Buffer ? String(requestBody) : requestBody,
...requestWithoutBody,
},
responseBody: responseBody instanceof Buffer ? String(responseBody) : responseBody,
responseHeaders,
};
};
38 changes: 38 additions & 0 deletions autotests/configurator/mapBackendResponseToLog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {getDurationWithUnits} from 'e2ed/utils';

import type {MapBackendResponseToLog} from 'autotests/types/packSpecific';

/**
* Maps responses from the backend to logs during the test.
* Backend responses received during a certain test step are accumulated
* in an array in the `backendResponses` field of the log of this step.
* Log the `responseBody` field carefully, as the body of backend response can be very large.
* If the function returns `undefined`, the response is not logged (skipped).
*/
export const mapBackendResponseToLog: MapBackendResponseToLog = ({
completionTimeInMs,
request,
responseBody,
responseHeaders,
statusCode,
}) => {
if (statusCode >= 400) {
return undefined;
}

if (request) {
const maybeWithDuration: {duration?: string} = {};

if (completionTimeInMs !== undefined && request.utcTimeInMs !== undefined) {
maybeWithDuration.duration = getDurationWithUnits(completionTimeInMs - request.utcTimeInMs);
}

return {...maybeWithDuration, statusCode, url: request?.url};
}

return {
responseBody: responseBody instanceof Buffer ? String(responseBody) : responseBody,
responseHeaders,
statusCode,
};
};
2 changes: 1 addition & 1 deletion autotests/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export {it} from './it';
export {test} from './test';
10 changes: 5 additions & 5 deletions autotests/packs/allTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {RunEnvironment, runEnvironment} from 'e2ed/configurator';
import {
doAfterPack,
doBeforePack,
mapBackendResponseErrorToLog,
mapBackendResponseToLog,
mapLogPayloadInConsole,
mapLogPayloadInLogFile,
mapLogPayloadInReport,
Expand All @@ -30,7 +32,7 @@ const filterTestsIntoPack: FilterTestsIntoPack = ({options}) => options.meta.tes
*/
export const pack: Pack = {
ajaxRequestTimeout: 40_000,
assertionTimeout: 10_000,
assertionTimeout: 5_000,
browser: [browser, ...browserFlags].join(' '),
browserInitTimeout: 60_000,
concurrency: isLocalRun ? 1 : 2,
Expand All @@ -42,10 +44,8 @@ export const pack: Pack = {
filterTestsIntoPack,
liteReportFileName: 'lite-report.json',
logFileName: 'pack-logs.log',
mapBackendResponseErrorToLog: ({request, responseHeaders, statusCode}) =>
statusCode >= 400 ? {request, responseHeaders, statusCode} : undefined,
mapBackendResponseToLog: ({request, statusCode}) =>
statusCode < 400 ? {statusCode, url: request?.url} : undefined,
mapBackendResponseErrorToLog,
mapBackendResponseToLog,
mapLogPayloadInConsole,
mapLogPayloadInLogFile,
mapLogPayloadInReport,
Expand Down
20 changes: 13 additions & 7 deletions autotests/pageObjects/pages/Main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,19 @@ export class Main extends Page<CustomPageParams> {
}

override async waitForPageLoaded(): Promise<void> {
await waitForAllRequestsComplete(({url}) => {
if (url.startsWith('https://adservice.google.com/')) {
return false;
}

return true;
});
await waitForAllRequestsComplete(
({url}) => {
if (
url.startsWith('https://adservice.google.com/') ||
url.startsWith('https://play.google.com/')
) {
return false;
}

return true;
},
{maxIntervalBetweenRequestsInMs: this.maxIntervalBetweenRequestsInMs},
);

await waitForInterfaceStabilization(this.pageStabilizationInterval);
}
Expand Down
27 changes: 15 additions & 12 deletions autotests/pageObjects/pages/Search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,21 @@ export class Search extends MobilePage<CustomPageParams> {
}

override async waitForPageLoaded(): Promise<void> {
await waitForAllRequestsComplete(({url}) => {
if (
url.startsWith('https://adservice.google.com/') ||
url.startsWith('https://googleads.g.doubleclick.net/') ||
url.startsWith('https://play.google.com/') ||
url.startsWith('https://static.doubleclick.net/')
) {
return false;
}

return true;
});
await waitForAllRequestsComplete(
({url}) => {
if (
url.startsWith('https://adservice.google.com/') ||
url.startsWith('https://googleads.g.doubleclick.net/') ||
url.startsWith('https://play.google.com/') ||
url.startsWith('https://static.doubleclick.net/')
) {
return false;
}

return true;
},
{maxIntervalBetweenRequestsInMs: this.maxIntervalBetweenRequestsInMs},
);

await waitForInterfaceStabilization(this.pageStabilizationInterval);
}
Expand Down
2 changes: 1 addition & 1 deletion autotests/it.ts → autotests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ import type {Pack} from 'autotests/types/packSpecific';
* Test function that describes the test or the task
* (test does not necessarily contain checks).
*/
export const it = createTestFunction<Pack>(hooks);
export const test = createTestFunction<Pack>(hooks);
4 changes: 2 additions & 2 deletions autotests/tests/e2edReportExample/browserData.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-console */

import {it} from 'autotests';
import {test} from 'autotests';
import {E2edReportExample} from 'autotests/pageObjects/pages';
import {createClientFunction, expect} from 'e2ed';
import {
Expand All @@ -11,7 +11,7 @@ import {
waitForInterfaceStabilization,
} from 'e2ed/actions';

it('correctly read data from browser', {meta: {testId: '14'}}, async () => {
test('correctly read data from browser', {meta: {testId: '14'}}, async () => {
await navigateToPage(E2edReportExample);

await setPageElementsIgnoredOnInterfaceStabilization(['.retry']);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {it} from 'autotests';
import {test} from 'autotests';
import {E2edReportExample} from 'autotests/pageObjects/pages';
import {expect} from 'e2ed';
import {click, navigateToPage} from 'e2ed/actions';

it('custom selector methods', {meta: {testId: '15'}}, async () => {
test('selector custom methods', {meta: {testId: '15'}}, async () => {
const reportPage = await navigateToPage(E2edReportExample);

await expect(reportPage.navigationRetries.exists, 'navigation retries exists').ok();
Expand Down
4 changes: 2 additions & 2 deletions autotests/tests/e2edReportExample/setPageCookies.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {it} from 'autotests';
import {test} from 'autotests';
import {E2edReportExample} from 'autotests/pageObjects/pages';
import {expect} from 'e2ed';
import {navigateToPage} from 'e2ed/actions';
Expand All @@ -14,7 +14,7 @@ const cookie = {
value: 'bar',
} as const;

it('set page cookies', {meta: {testId: '5'}, testIdleTimeout: 35_000}, async () => {
test('set page cookies correctly', {meta: {testId: '5'}, testIdleTimeout: 35_000}, async () => {
await navigateToPage(E2edReportExample, {pageCookies: [cookie]});

const documentCookie = await getDocumentCookie();
Expand Down
35 changes: 35 additions & 0 deletions autotests/tests/expect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {test} from 'autotests';
import {createSelectorByCss} from 'autotests/selectors';
import {expect} from 'e2ed';
import {assertFunctionThrows, getTimeoutPromise} from 'e2ed/utils';

test('expect function works correctly', {meta: {testId: '16'}}, async () => {
await assertFunctionThrows(async () => {
await expect(1, 'should throws').eql(2);
}, 'throws an error when actual value do not fit expected value');

await assertFunctionThrows(async () => {
await expect(getTimeoutPromise(5_100), 'should failed by timeout').ok();
}, 'throws an timeout error when actual value is a pending promise');

await expect(Promise.resolve('foo'), 'awaits usual promises').eql('foo');

await assertFunctionThrows(async () => {
await expect(
Promise.resolve('foo'),
'throws an error when comparing for equality of values of different types',
// @ts-expect-error: actual value and expected value has different types
).eql(3);
}, 'throws an error when actual value and expected value has different types');

// eslint-disable-next-line @typescript-eslint/no-floating-promises
expect(1, 'should be an eslint error when we call expect without await').eql(1);

// eslint-disable-next-line @typescript-eslint/await-thenable
await expect(1, 'should be an eslint error when we do not call the assertion method');

const htmlSelector = createSelectorByCss('html');

// @ts-expect-error: expect function should not accept a selector as a actual value
await expect(htmlSelector, 'should be type error when actual value is a selector').ok();
});
Loading
Loading