Skip to content

Commit

Permalink
FI-1237 feat: run tests via Playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
uid11 committed Jun 19, 2024
1 parent 63199a9 commit 1ca5784
Show file tree
Hide file tree
Showing 50 changed files with 483 additions and 5,434 deletions.
13 changes: 13 additions & 0 deletions autotests/tests/example.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {test} from 'autotests';

import {expect} from '@playwright/test';

test('get started link', {meta: {testId: '19'}}, async ({page}) => {
await page.goto('https://playwright.dev/');

// Click the get started link.
await page.getByRole('link', {name: 'Get started'}).click();

// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', {name: 'Installation'})).toBeVisible();
});
5,125 changes: 186 additions & 4,939 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
"url": "git+https://github.com/joomcode/e2ed.git"
},
"dependencies": {
"@playwright/browser-chromium": "1.44.1",
"@playwright/test": "1.44.1",
"bin-v8-flags-filter": "1.2.0",
"create-locator": "0.0.23",
"get-modules-graph": "0.0.9",
"globby": "11.1.0",
"pngjs": "7.0.0",
"testcafe-without-typecheck": "3.5.0-rc.2"
"pngjs": "7.0.0"
},
"devDependencies": {
"@types/node": "20.12.12",
Expand All @@ -46,7 +47,6 @@
"eslint-plugin-typescript-sort-keys": "3.2.0",
"husky": "9.0.11",
"prettier": "3.2.5",
"testcafe": "3.5.0",
"typescript": "5.4.5"
},
"peerDependencies": {
Expand Down Expand Up @@ -84,7 +84,7 @@
"lint:types:build": "if [ -f ./build/tsconfig.json ]; then tsc --noEmit --project ./build; else echo 'No build directory'; fi",
"make:executable": "./bin/makeExecutable.sh",
"parallel": "./bin/runParallel.sh",
"test": "npm run parallel test:dependencies test:docker test:esm test:local",
"test": "npm run parallel test:docker test:local",
"build:clear": "rm -rf ./build",
"prebuild": "npm run build:clear",
"build": "tsc; echo 'Compilation completed'",
Expand All @@ -99,7 +99,6 @@
"build:copy:bin": "cp ./bin/dockerEntrypoint.sh ./build/node_modules/e2ed/bin",
"postbuild:copy:bin": "npm run make:executable build/node_modules/e2ed/bin/init.js build/node_modules/e2ed/bin/localEntrypoint.js build/node_modules/e2ed/bin/runE2edInDockerEnvironment.js",
"build:copy:scripts": "cp ./build/scripts/*.js ./build",
"postbuild:copy:scripts": "cp ./scripts/testEsmExports.ts ./build/testEsmExports.mjs",
"build:copy:meta": "cp -R ./LICENSE ./logo.svg ./README.md ./styles ./build/node_modules/e2ed",
"postbuild:copy:meta": "node ./build/writePrunedPackageJson.js",
"prebuild:copy:example": "rm -r ./build/autotests",
Expand All @@ -126,8 +125,6 @@
"test:docker:copy": "cp -R ./build/autotests ./build/docker/autotests && cp ./build/tsconfig.json ./build/docker",
"posttest:docker:copy": "rm -rf ./build/docker/autotests/reports && ./bin/addPackageJsonToBuildDocker.sh",
"test:docker": "(cd ./build/docker && E2ED_ORIGIN=https://google.com ./autotests/bin/runDocker.sh ./autotests/packs/allTests.ts)",
"test:dependencies": "node ./build/testDependencies.js",
"test:esm": "node ./build/testEsmExports.mjs",
"test:local": "(cd ./build && E2ED_ORIGIN=https://google.com ./node_modules/e2ed/bin/localEntrypoint.js ./autotests/packs/allTests.ts)",
"testcafe-hammerhead-up:publish": "./bin/forks/testcafe-hammerhead-up/publish.sh",
"testcafe-hammerhead-up:clean": "./bin/forks/testcafe-hammerhead-up/clean.sh",
Expand Down
39 changes: 0 additions & 39 deletions scripts/testDependencies.ts

This file was deleted.

5 changes: 3 additions & 2 deletions src/actions/mock/mockApiRoute.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import {RequestMock} from 'testcafe-without-typecheck';

import {LogEventType} from '../../constants/internal';
import {getApiMockState} from '../../context/apiMockState';
import {getFullMocksState} from '../../context/fullMocks';
Expand All @@ -18,6 +16,9 @@ import type {
Response,
} from '../../types/internal';

// TODO: mocks
class RequestMock {}

/**
* Mock API for some API route.
* Applicable only for routes with the `getParamsFromUrl` method.
Expand Down
65 changes: 30 additions & 35 deletions src/testcaferc.ts → src/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @file Full pack configuration (extended TestCafe configuration) for running tests.
* @file Full pack configuration for running tests.
* Don't import this module. Instead, use `getFullPackConfig` from `utils/config`.
*/

Expand All @@ -12,13 +12,13 @@ import {
} from './constants/internal';
import {assertValueIsTrue} from './utils/asserts';
import {getTestCafeBrowsersString} from './utils/browser';
// eslint-disable-next-line import/no-internal-modules
import {assertUserlandPack} from './utils/config/assertUserlandPack';
import {getPathToPack} from './utils/environment';
import {setCustomInspectOnFunction} from './utils/fn';

import type {FrozenPartOfTestCafeConfig, FullPackConfig, UserlandPack} from './types/internal';

import {defineConfig, devices} from '@playwright/test';

const pathToPack = getPathToPack();
const tsExtension = '.ts';

Expand All @@ -37,34 +37,6 @@ const absoluteCompiledUserlandPackPath = join(
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-dynamic-require
const userlandPack = require<{pack: UserlandPack}>(absoluteCompiledUserlandPackPath).pack;

assertUserlandPack(userlandPack);

const frozenPartOfTestCafeConfig: FrozenPartOfTestCafeConfig = {
color: true,
compilerOptions: {typescript: {options: {esModuleInterop: true, resolveJsonModule: true}}},
disableMultipleWindows: true,
hostname: 'localhost',
pageLoadTimeout: 0,
reporter: [{name: 'for-e2ed'}],
retryTestPages: true,
screenshots: {
path: SCREENSHOTS_DIRECTORY_PATH,
// eslint-disable-next-line no-template-curly-in-string
pathPattern: '${DATE}_${TIME}_${BROWSER}_${BROWSER_VERSION}/${TEST}/${FILE_INDEX}.png',
takeOnFails: false,
thumbnails: false,
},
skipJsErrors: true,
};

const fullPackConfig: FullPackConfig = {
...userlandPack,
browsers: getTestCafeBrowsersString(userlandPack),
disableNativeAutomation: !userlandPack.enableChromeDevToolsProtocol,
src: userlandPack.testFileGlobs,
...frozenPartOfTestCafeConfig,
};

const {
doAfterPack,
doBeforePack,
Expand All @@ -74,7 +46,7 @@ const {
mapLogPayloadInConsole,
mapLogPayloadInLogFile,
mapLogPayloadInReport,
} = fullPackConfig;
} = userlandPack;

for (const fn of doAfterPack) {
setCustomInspectOnFunction(fn);
Expand All @@ -91,7 +63,30 @@ setCustomInspectOnFunction(mapLogPayloadInConsole);
setCustomInspectOnFunction(mapLogPayloadInLogFile);
setCustomInspectOnFunction(mapLogPayloadInReport);

Object.assign(exports, fullPackConfig);
const config = defineConfig({
fullyParallel: true,

outputDir: '../../autotests/reports/internal',

projects: [
{
name: 'chromium',
use: {...devices['Desktop Chrome']},
},
],

retries: 1,

testDir: '../../autotests/tests',
testMatch: 'example.spec.ts',

use: {
trace: 'on-first-retry',
},

workers: 2,
});

Object.assign(config, userlandPack);

// eslint-disable-next-line import/no-unused-modules
export {fullPackConfig};
export default config;
2 changes: 1 addition & 1 deletion src/constants/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ export {
ABSOLUTE_PATH_TO_PROJECT_ROOT_DIRECTORY,
AUTOTESTS_DIRECTORY_PATH,
COMPILED_USERLAND_CONFIG_DIRECTORY,
CONFIG_PATH,
DOT_ENV_PATH,
EVENTS_DIRECTORY_PATH,
INSTALLED_E2ED_DIRECTORY_PATH,
REPORTS_DIRECTORY_PATH,
SCREENSHOTS_DIRECTORY_PATH,
START_INFO_PATH,
TESTCAFERC_PATH,
TMP_DIRECTORY_PATH,
} from './paths';
/** @internal */
Expand Down
17 changes: 7 additions & 10 deletions src/constants/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ export const COMPILED_USERLAND_CONFIG_DIRECTORY = join(
'config',
) as DirectoryPathFromRoot;

/**
* Relative (from root) path to `config` file,
* that plays the role of the internal Playwright config.
* @internal
*/
export const CONFIG_PATH = join(INSTALLED_E2ED_DIRECTORY_PATH, 'config.js') as FilePathFromRoot;

/**
* Relative (from root) path to events directory.
* @internal
Expand All @@ -86,13 +93,3 @@ export const SCREENSHOTS_DIRECTORY_PATH = join(
* @internal
*/
export const START_INFO_PATH = join(TMP_DIRECTORY_PATH, 'startInfo.json') as FilePathFromRoot;

/**
* Relative (from root) path to `testcaferc` file,
* that plays the role of the internal TestCafe config.
* @internal
*/
export const TESTCAFERC_PATH = join(
INSTALLED_E2ED_DIRECTORY_PATH,
'testcaferc.js',
) as FilePathFromRoot;
8 changes: 5 additions & 3 deletions src/context/apiMockState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {useContext} from '../useContext';

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

import type {Page} from '@playwright/test';

/**
* Raw get and set internal (maybe `undefined`) API mock state.
* @internal
Expand All @@ -12,8 +14,8 @@ const [getRawApiMockState, setRawApiMockState] = useContext<ApiMockState>();
* Get internal always defined API mock state (for `mockApiRoute`).
* @internal
*/
export const getApiMockState = (): ApiMockState => {
const maybeApiMockState = getRawApiMockState();
export const getApiMockState = (page: Page): ApiMockState => {
const maybeApiMockState = getRawApiMockState(page);

if (maybeApiMockState !== undefined) {
return maybeApiMockState;
Expand All @@ -26,7 +28,7 @@ export const getApiMockState = (): ApiMockState => {
optionsWithRouteByUrl: Object.create(null) as {},
};

setRawApiMockState(apiMockState);
setRawApiMockState(page, apiMockState);

return apiMockState;
};
6 changes: 3 additions & 3 deletions src/context/cdpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ export {getCdpClient};
* Set test `cdpClient` (can only be called once).
* @internal
*/
export const setCdpClient: typeof setRawCdpClient = (cdpClient) => {
const currentCdpClient = getCdpClient();
export const setCdpClient: typeof setRawCdpClient = (page, cdpClient) => {
const currentCdpClient = getCdpClient(page);

assertValueIsUndefined(currentCdpClient, 'currentCdpClient is not defined', {cdpClient});

return setRawCdpClient(cdpClient);
return setRawCdpClient(page, cdpClient);
};
6 changes: 3 additions & 3 deletions src/context/fullMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ export {getFullMocksState};
* Set state of full mocks (can only be called once).
* @internal
*/
export const setFullMocksState: typeof setRawFullMocksState = (fullMocksState) => {
const currentFullMocksState = getFullMocksState();
export const setFullMocksState: typeof setRawFullMocksState = (page, fullMocksState) => {
const currentFullMocksState = getFullMocksState(page);

assertValueIsUndefined(currentFullMocksState, 'currentFullMocksState is not defined', {
fullMocksState,
});

return setRawFullMocksState(fullMocksState);
return setRawFullMocksState(page, fullMocksState);
};
12 changes: 7 additions & 5 deletions src/context/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {assertValueIsDefined, assertValueIsUndefined} from '../utils/asserts';

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

import type {Page} from '@playwright/test';

/**
* Raw get and set test metadata functions.
*/
Expand All @@ -11,8 +13,8 @@ const [getRawMeta, setRawMeta] = useContext<TestMetaPlaceholder>();
/**
* Get test metadata.
*/
export const getMeta = <TestMeta>(): TestMeta => {
const meta = getRawMeta() as TestMeta;
export const getMeta = <TestMeta>(page: Page): TestMeta => {
const meta = getRawMeta(page) as TestMeta;

assertValueIsDefined(meta, 'meta is defined');

Expand All @@ -23,10 +25,10 @@ export const getMeta = <TestMeta>(): TestMeta => {
* Set test metadata.
* @internal
*/
export const setMeta: typeof setRawMeta = (meta) => {
const currentMeta = getRawMeta();
export const setMeta: typeof setRawMeta = (page, meta) => {
const currentMeta = getRawMeta(page);

assertValueIsUndefined(currentMeta, 'currentMeta is not defined', {meta});

setRawMeta(meta);
setRawMeta(page, meta);
};
12 changes: 7 additions & 5 deletions src/context/runId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {assertValueIsDefined, assertValueIsUndefined} from '../utils/asserts';

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

import type {Page} from '@playwright/test';

/**
* Raw versions of `getRunId` and `setRunId`.
* @internal
Expand All @@ -13,8 +15,8 @@ const [getRawRunId, setRawRunId] = useContext<RunId>();
* Get test `runId`.
* @internal
*/
export const getRunId = (): RunId => {
const runId = getRawRunId();
export const getRunId = (page: Page): RunId => {
const runId = getRawRunId(page);

assertValueIsDefined(runId, 'runId is defined');

Expand All @@ -25,10 +27,10 @@ export const getRunId = (): RunId => {
* Set test `runId` (can only be called once).
* @internal
*/
export const setRunId: typeof setRawRunId = (runId) => {
const currentRunId = getRawRunId();
export const setRunId: typeof setRawRunId = (page, runId) => {
const currentRunId = getRawRunId(page);

assertValueIsUndefined(currentRunId, 'currentRunId is not defined', {runId});

return setRawRunId(runId);
return setRawRunId(page, runId);
};
Loading

0 comments on commit 1ca5784

Please sign in to comment.