{"id":19176991,"url":"https://github.com/joomcode/e2ed","last_synced_at":"2025-05-07T20:07:21.410Z","repository":{"id":40630370,"uuid":"488519375","full_name":"joomcode/e2ed","owner":"joomcode","description":"E2E testing framework over Playwright","archived":false,"fork":false,"pushed_at":"2025-04-18T05:34:15.000Z","size":7616,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-05-07T20:06:25.599Z","etag":null,"topics":["e2e","playwright","testing"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joomcode.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-04T09:03:28.000Z","updated_at":"2025-04-09T05:47:06.000Z","dependencies_parsed_at":"2023-12-30T01:53:45.719Z","dependency_job_id":"d73b2481-13e1-4af3-a421-52ed70cf3766","html_url":"https://github.com/joomcode/e2ed","commit_stats":{"total_commits":774,"total_committers":5,"mean_commits":154.8,"dds":"0.014211886304909549","last_synced_commit":"fc941f29f87b75e67e5a2591bbece2c351e0247c"},"previous_names":[],"tags_count":280,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joomcode%2Fe2ed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joomcode%2Fe2ed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joomcode%2Fe2ed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joomcode%2Fe2ed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joomcode","download_url":"https://codeload.github.com/joomcode/e2ed/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252949272,"owners_count":21830151,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["e2e","playwright","testing"],"created_at":"2024-11-09T10:31:31.975Z","updated_at":"2025-05-07T20:07:21.385Z","avatar_url":"https://github.com/joomcode.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![e2ed logo](https://raw.githubusercontent.com/joomcode/e2ed/main/logo.svg)\n\n# e2ed\n\n[![NPM version][npm-image]][npm-url]\n[![code style: prettier][prettier-image]][prettier-url]\n[![TypeScript][typescript-image]][typescript-url]\n[![Contributor Covenant][code-of-conduct-image]][code-of-conduct-url]\n[![Conventional Commits][conventional-commits-image]][conventional-commits-url]\n[![License MIT][license-image]][license-url]\n\nE2E testing framework over [Playwright](https://playwright.dev/).\n\n`e2ed` is designed to quickly parallel run a large number of independent atomic tests\n(or others tasks) in an arbitrary browser inside a docker container.\nTests are written in TypeScript, using explicit dependencies and the concept of page objects.\nAfter the run, a detailed HTML report and a summary lite report in JSON format are generated.\n\n## Adding e2ed to a project\n\nPrerequisites: [node](https://nodejs.org/en/) \u003e=20,\n[TypeScript](https://www.typescriptlang.org/) \u003e=5.\n\nAll commands below are run from the root directory of the project.\n\n### Install\n\nInstall the latest version of `e2ed` in devDependencies with the exact version:\n\n```sh\nnpm install e2ed --save-dev --save-exact\n```\n\nInstall [Playwright](https://playwright.dev/) [browsers](https://playwright.dev/docs/browsers)\n(only `Chromium` for now):\n\n```sh\nnpx e2ed-install-browsers\n```\n\n### Initialize\n\nInitialize `e2ed` in the project; this will add an `autotests` directory\nwith working sample tests and pageObject-s to the project:\n\n```sh\nnpx e2ed-init\n```\n\nAll the code related to `e2ed` will be in the `autotests` directory in the root of the project.\n\n### Add to TypeScript config\n\n[Add](tsconfig.json#L36) the `autotests` directory in field `include` of the project's `tsconfig.json`\nin the form `\"./autotests/**/*.ts\"`, to make type checking work in the tests code:\n\n```json\n  \"include\": [\n    \"./autotests/**/*.ts\",\n    \"...\"\n  ],\n```\n\n### Re-map imports\n\nAlso [add](tsconfig.json#L21-L24) the re-map of imports from the `autotests` directory in field `paths`\nof the project's `tsconfig.json`, to use bare imports from the `autotests` directory\n(`import {...} from 'autotests/...';`):\n\n```json\n  \"paths\": {\n    \"autotests\": [\"./autotests/index.ts\"],\n    \"autotests/*\": [\"./autotests/*\"]\n  },\n```\n\nIt is assumed here that the `baseUrl` field is not specified in the project's `tsconfig.json`,\nor that the `baseUrl` is specified as `\"baseUrl\": \".\"`.\n\nIf, for example, `baseUrl` is equal to `./src`, then it will be necessary\nto correct the path to `autotests` directory accordingly:\n\n```json\n  \"paths\": {\n    \"autotests\": [\"../autotests/index.ts\"],\n    \"autotests/*\": [\"../autotests/*\"]\n  },\n```\n\nAfter that you can run pack with tests in the project locally (sample tests are run on `bing.com`):\n\n```sh\nE2ED_ORIGIN=https://bing.com npx e2ed ./autotests/packs/allTests.ts\n```\n\nNow you can edit tests, pageObject-s and other files in the `autotests` directory as you need.\n\n## Usage\n\n### Pack\n\n`e2ed` always runs packs of tests (or tasks), one pack at a time.\nA [pack](autotests/packs/allTests.ts) is a set of tests (tasks) with their run config,\ndescribed in one file. `e2ed` takes one mandatory argument — the path\nto the pack (absolute or relative to the current directory,\nwhich should be the root directory of the project).\n\nPacks are usually stored in the `autotests/packs` directory.\n\n### Run local\n\nTo run pack with tests locally for `https://bing.com`:\n\n```sh\nE2ED_ORIGIN=https://bing.com npx e2ed ./autotests/packs/allTests.ts\n```\n\nFor convenience, you can add a command to run concrete pack in the `scripts` field\nof the `package.json`:\n\n```json\n  \"scripts\": {\n    \"e2ed:allTests\": \"e2ed ./autotests/packs/allTests.ts\",\n    \"...\"\n  },\n```\n\nAfter that, you can run the pack like this:\n\n```sh\nE2ED_ORIGIN=https://bing.com npm run e2ed:allTests\n```\n\nAlso, when running locally, you can pass additional\ncommand-line arguments, such as the path to a specific test file from a pack, to run just that test:\n\n```sh\nE2ED_ORIGIN=https://bing.com npm run e2ed:allTests ./autotests/tests/main/exists.ts\n```\n\n### Run in docker\n\nYou can download the latest `e2ed` docker image from https://hub.docker.com/r/e2edhub/e2ed:\n\n```sh\ndocker pull e2edhub/e2ed\n```\n\nAnd run tests for `https://bing.com` in docker container:\n\n```sh\nE2ED_ORIGIN=https://bing.com ./autotests/bin/runDocker.sh ./autotests/packs/allTests.ts\n```\n\nFor convenience, you can add a command to run concrete pack in docker in the `scripts` field\nof the `package.json`:\n\n```json\n  \"scripts\": {\n    \"e2ed:docker:allTests\": \"./autotests/bin/runDocker.sh ./autotests/packs/allTests.ts\",\n    \"...\"\n  },\n```\n\nAfter that, you can run the pack in docker like this:\n\n```sh\nE2ED_ORIGIN=https://bing.com npm run e2ed:docker:allTests\n```\n\n### Personal local pack for development\n\nYou can add your local pack with custom settings for developing tests\nthat will not be stored in the repository, under the name `local.ts` in directory `autotests/packs`\n(it's already [listed](autotests/.gitignore#L1) in `.gitignore`).\n\nThis pack might look like this:\n\n```ts\nimport {pack as allTestsPack} from './allTests';\n\nimport type {Pack} from 'autotests/configurator';\n\n/**\n * Pack from .gitignore for local development.\n */\nexport const pack: Pack = {\n  ...allTestsPack,\n  testIdleTimeout: 10_000,\n};\n```\n\nThe `npx e2ed-init` command is already creating such a file as an example.\n\n### How to debug tests\n\nFor debugging tests, the local run of the pack is intended.\n\nFor example, you can use the `pause` action from `e2ed/actions` in the test code:\n\n```ts\nawait pause();\n```\n\nWhen calling the `pause` action, `e2ed` will stop the test execution and enter\nthe debug-mode.\n\nAfter debugging is complete, remember to remove the call of the `pause` action.\n\n[pause](https://playwright.dev/docs/api/class-page#page-pause) is a function of the `Playwright` itself.\n\nIn addition, you can set any non-empty value to the `E2ED_DEBUG` environment variable,\nwhich will also run `e2ed` in debug mode. If this variable has the form `inspect-brk:9229`,\nthen additionally `nodejs` debugging is started on port `9229` (via `--inspect-brk=9229`):\n\n```sh\nE2ED_DEBUG=true npm run e2ed:allTests ./autotests/tests/main/exists.ts\n```\n\n```sh\nE2ED_DEBUG=inspect-brk:8230 npm run e2ed:allTests ./autotests/tests/main/exists.ts\n```\n\n`E2ED_DEBUG` also works for run in docker, and allows you to connect a debugger\nto the `e2ed` running in docker container.\n\nWhen developing a test, you can run it in [UI-mode](https://playwright.dev/docs/test-ui-mode)\nby passing the `--ui` parameter (for local run only):\n\n```sh\nnpm run e2ed:allTests ./autotests/tests/main/exists.ts -- --ui\n```\n\nAs a result, `Playwright` will launch its [UI-mode](https://playwright.dev/docs/test-ui-mode),\nallowing you to quickly rerun tests and see errors.\n\n### Basic fields of pack config\n\nThe [pack](autotests/packs/allTests.ts) is a single `ts` file\nthat exports the pack's config under the name `pack`.\n\nHere are the basic fields of the pack config.\n\n`addLogsWithTags: readonly LogTag[]`: array of additional log tags. Logs with a specific tag\n(in `logTag` field) will be added only if their tag is specified in this array.\n\n`browserFlags: string[]`: array of browser flags, like `--disable-dev-shm-usage`,\nwith which the browser is launched to run tests.\n\n`browserName: BrowserName`: browser name (one of `chromium`, `firefox`, `webkit`).\n\n`concurrency: number`: the number of browser windows in which tests will run in parallel.\n\n`customPackProperties: CustomPackProperties`: a custom set of fields defined within the project.\nThese fields allow, for example, to customize the behavior of hooks for different packs.\n\n`deviceScaleFactor: number`: device scale factor (aka `window.devicePixelRatio`).\n\n`doAfterPack: ((liteReport: LiteReport) =\u003e CustomReportProperties | undefined)[]`:\nan array of functions that will be executed, in order, after the pack completes.\nThe functions accept a lite report object, and can return custom report properties,\nwhich in this case will be included in the lite report.\nEach function can thus access the results of the previous function.\n\n`doBeforePack: ((startInfo: StartInfo) =\u003e FullPackConfig | undefined)[]`:\nan array of functions that will be executed, in order, before the pack starts.\nThe functions accept a start info object, and can return new full pack config,\nwhich in this case will be included in the start info object, and will be used for running pack.\nEach function can thus access the results of the previous function.\n\n`enableCsp: boolean`: enables Content-Security-Policy checks in browser.\n\n`enableHeadlessMode: boolean`: enables headless mode (if browser supports such mode).\n\n`enableMobileDeviceMode: boolean`: enables Chromium [mobile device mode](https://developer.chrome.com/docs/devtools/device-mode).\n\n`enableTouchEventEmulation: boolean`: enables touch event emulation.\nIf `true`, page fires `touch` events when test interact with the page (instead of `click` events).\n\n`filterTestsIntoPack: (testStaticOptions: TestStaticOptions\u003cTestMeta\u003e) =\u003e boolean`: this function\nfilters tests (tasks) by their static options —\nonly those tests for which the function returned `true` get into the pack.\n\n`fullMocks: FullMocks | null`: functions that specify the \"full mocks\" functionality.\n\n`getTestNamePrefixInUiMode: (testOptions: TestOptions\u003cTestMeta\u003e) =\u003e string`: get prefix for test name in UI mode by test options.\n\n`liteReportFileName: string | null`: the name of the file under which, after running the tests,\nthe lite JSON report will be saved in the `autotests/reports` directory, for example, `lite-report.json`.\nIf `null`, the lite report will not be saved.\n\n`logFileName: string | null`: the name of the file under which, after running the tests,\nthe pack logs will be saved in the `autotests/reports` directory, for example, `pack-logs.log`.\nIf `null`, the log will not be saved.\n\n`mapBackendResponseErrorToLog: (response: Response) =\u003e Payload | undefined`: maps responses\nwith errors from the backend to \"red\" logs (as errors) during the test.\nIt is assumed that the function will select responses with statuse codes\nof 400 and higher (client and server errors).\nBackend responses with errors are accumulated in separate \"red\" log step (with `logEventStatus: 'failed'`).\nLog the `responseBody` field carefully, as the body of backend response can be very large.\nIf the function returns `undefined`, the response is not logged (skipped).\n\n`mapBackendResponseToLog: (response: Response) =\u003e Payload | undefined`: maps responses\nfrom the backend to logs during the test.\nBackend responses received during a certain test step are accumulated\nin an array in the `backendResponses` field of the log of this step.\nLog the `responseBody` field carefully, as the body of backend response can be very large.\nIf the function returns `undefined`, the response is not logged (skipped).\n\n`mapLogPayloadInConsole: (message: string, payload: LogPayload | undefined, logEventType?: LogEventType)\n=\u003e LogPayload | 'skipLog' | undefined`: maps log payload for logging in console to clarify,\nshorten or skip a console log entry.\nIf the mapping returns `'skipLog'`, the log entry is skipped.\nIf the mapping returns `undefined`, the log entry is not skipped, but is printed with an empty payload.\n\n`mapLogPayloadInLogFile: (message: string, payload: LogPayload | undefined, logEventType?: LogEventType)\n=\u003e LogPayload | 'skipLog' | undefined`: maps log payload for logging in file to clarify,\nshorten or skip a file log entry.\nIf the mapping returns `'skipLog'`, the log entry is skipped.\nIf the mapping returns `undefined`, the log entry is not skipped, but is printed with an empty payload.\n\n`mapLogPayloadInReport: (message: string, payload: LogPayload | undefined, logEventType?: LogEventType)\n=\u003e LogPayload | null | undefined`: maps log payload for logging step in HTML report and lite report to clarify,\nshorten or skip a report step.\nIf the mapping returns `null`, the step is skipped.\nIf the mapping returns `undefined`, the log entry is not skipped, but is printed with an empty payload.\n\n`matchScreenshot: MatchScreenshot`: functions that describe the `toMatchScreenshot` assert (in `expect`).\n\n`maxRetriesCountInDocker: number`: the maximum number of retries to run a test with the command\n`your-project/autotests/bin/runDocker.sh` (until the test passes).\nFor example, if it is equal to three, the test will be run no more than three times.\n\n`navigationTimeout: number`: default timeout for navigation to url\n(`navigateToPage`, `navigateToUrl` actions) in milliseconds.\n\n`overriddenConfigFields: PlaywrightTestConfig | null`: if not `null`, then this value will override\nfields of internal `Playwright` config.\n\n`packTimeout: number`: timeout (in millisecond) for the entire pack of tests (tasks).\nIf the test pack takes longer than this timeout, the pack will fail with the appropriate error.\n\n`pathToScreenshotsDirectoryForReport: string | null`: path to the directory where screenshots\nwill be stored for displaying them in the HTML report.\nThis path must be either relative (from the HTML report file) or absolute (i.e. with http/https protocol).\nThe screenshot directory should be served by the web server with appropriate headers,\nlike a normal static directory. The `autotests/reports/screenshots` directory from the project\nshould be copied to this directory after the pack is completed,\nand then screenshots from this directory will be displayed in the HTML report.\nIf `null`, screenshots will not be displayed in the HTML report.\n\n`reportFileName: string | null`: the name of the file under which, after running the tests,\nthe HTML report will be saved in the `autotests/reports` directory, for example, `report.html`.\nAlso this name is used as the title of the report page.\nIf `null`, the report will not be saved.\n\n`skipTests: SkipTests`: this setting allows you to describe a set of skipped tests in a custom form.\nYou can define the `SkipTests` type and `skipTests` processing rules in the hook `autotests/hooks/isTestSkipped.ts`.\n\n`takeFullPageScreenshotOnError: boolean`: if `true`, then takes a screenshot of the full page\n(not just the viewport) at the time of the test error, for display in the HTML report.\n\n`takeViewportScreenshotOnError: boolean`: if `true`, then takes a screenshot of the page viewport\nat the time of the test error, for display in the HTML report.\n\n`testFileGlobs: readonly string[]`: an array of globs with pack test (task) files.\nhttps://www.npmjs.com/package/globby is used for matching globs.\n\n`testIdleTimeout: number`: timeout (in milliseconds) for each individual test step.\nIf the test step (interval between two `log` function calls) takes longer than this timeout,\nthe test fails and rerun on the next retry.\nThis parameter can be overridden in the test-specific options.\n\n`testTimeout: number`: timeout (in milliseconds) for each individual test run.\nIf the test run takes longer than this timeout, the test fails and rerun on the next retry.\nThis parameter can be overridden in the test-specific options.\n\n`userAgent: string`: `userAgent` string of browser (device) in tests.\n\n`viewportHeight: number`: height of viewport of page in pixels.\n\n`viewportWidth: number`: width of viewport of page in pixels.\n\n`waitBeforeRetry: (options: Options) =\u003e number`: returns how many milliseconds `e2ed`\nshould wait before running test (for retries).\n\n`waitForAllRequestsComplete.maxIntervalBetweenRequestsInMs: number`: default maximum interval\n(in milliseconds) between requests for `waitForAllRequestsComplete` function.\nIf there are no new requests for more than this interval, then the promise\nreturned by the `waitForAllRequestsComplete` function will be successfully resolved.\n\n`waitForAllRequestsComplete.timeout: number`: default timeout (in milliseconds) for `waitForAllRequestsComplete` function.\nIf the wait is longer than this timeout, then the promise\nreturned by the `waitForAllRequestsComplete` function will be rejected.\n\n`waitForInterfaceStabilization.stabilizationInterval: number`: default stabilization interval for `waitForInterfaceStabilization` function.\n\n`waitForInterfaceStabilization.timeout: number`: default timeout (in milliseconds) for `waitForInterfaceStabilization` function.\nIf the wait is longer than this timeout, then the promise\nreturned by the `waitForInterfaceStabilization` function will be rejected.\n\n`waitForRequestTimeout: number`: default timeout (in milliseconds) for `waitForRequest`/`waitForRequestToRoute` functions.\nIf the wait is longer than this timeout, then the promise returned by the `waitForRequest`/`waitForRequestToRoute` function will be rejected.\n\n`waitForResponseTimeout: number`: default timeout (in milliseconds) for `waitForResponse`/`waitForResponseToRoute` functions.\nIf the wait is longer than this timeout, then the promise returned by the `waitForResponse`/`waitForResponseToRoute` function will be rejected.\n\n### Environment variables\n\nRequired environment variables are defined in the `./autotests/variables.env` file (they cannot be deleted):\n\n`E2ED_DOCKER_IMAGE`: the name of the docker image where the tests will run.\nThe image must be based on the `e2ed` base image.\n\n`E2ED_PATH_TO_TS_CONFIG_OF_PROJECT_FROM_ROOT`: the path to TypeScript config file of the project\nfrom the root directory of the project. The project should have one common TypeScript config\nfor both the application code and the autotest code.\n\nYou can pass the following optional environment variables to the `e2ed` process in any standard way:\n\n`E2ED_ORIGIN`: origin-part of the url (`protocol` + `host`) on which the tests will be run. For example, `https://bing.com`.\n\n`E2ED_DEBUG`: run `e2ed` in debug mode if this variable is not empty. If this variable has the form `inspect-brk:9229`,\nthen `nodejs` debugging is started on port `9229` (via `--inspect-brk=9229`).\n\n`E2ED_TERMINATION_SIGNAL`: the termination signal received by the `e2ed` process (if any).\nTypically this value is `'SIGUSR1'`.\n\n`E2ED_TIMEOUT_FOR_GRACEFUL_SHUTDOWN_IN_SECONDS`: default timeout for \"graceful shutdown\" of `e2ed` process (in seconds).\nIf the variable is not set, the default value of `16` is used.\n\n## License\n\n[MIT][license-url]\n\n[code-of-conduct-image]: https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg 'Contributor Covenant Code of Conduct'\n[code-of-conduct-url]: CODE_OF_CONDUCT.md\n[conventional-commits-image]: https://img.shields.io/badge/Conventional_Commits-1.0.0-yellow.svg 'The Conventional Commits specification'\n[conventional-commits-url]: https://www.conventionalcommits.org/en/v1.0.0/\n[license-image]: https://img.shields.io/badge/license-MIT-blue.svg 'The MIT License'\n[license-url]: LICENSE\n[npm-image]: https://img.shields.io/npm/v/e2ed.svg 'e2ed'\n[npm-url]: https://www.npmjs.com/package/e2ed\n[prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg 'Prettier code formatter'\n[prettier-url]: https://prettier.io/\n[typescript-image]: https://img.shields.io/badge/types-TypeScript-blue.svg 'Full TypeScript support'\n[typescript-url]: https://www.typescriptlang.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoomcode%2Fe2ed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoomcode%2Fe2ed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoomcode%2Fe2ed/lists"}