diff --git a/README.md b/README.md index 10ad3cd2..57e6b253 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,50 @@ +Let's find a balance between detailed explanations and clarity. Here’s a more comprehensive version that retains structure but elaborates more where needed: + +--- + # 🎪 jest-puppeteer [![npm version](https://img.shields.io/npm/v/jest-puppeteer.svg)](https://www.npmjs.com/package/jest-puppeteer) -[![npm dm](https://img.shields.io/npm/dm/jest-puppeteer.svg)](https://www.npmjs.com/package/jest-puppeteer) -[![npm dt](https://img.shields.io/npm/dt/jest-puppeteer.svg)](https://www.npmjs.com/package/jest-puppeteer) +[![npm downloads](https://img.shields.io/npm/dm/jest-puppeteer.svg)](https://www.npmjs.com/package/jest-puppeteer) -`jest-puppeteer` is a Jest preset that enables end-to-end testing with Puppeteer. It offers a straightforward API for launching new browser instances and interacting with web pages through them. +`jest-puppeteer` is a Jest preset designed for seamless integration with Puppeteer, enabling end-to-end testing in a browser environment. With a simple API, it allows you to launch browsers and interact with web pages, making it perfect for testing UI interactions in web applications. ## Table of Contents 1. [Getting Started](#getting-started) - - [Install the packages](#install-the-packages) - - [Write a test](#write-a-test) - - [Use with Typescript](#use-with-typescript) - - [Visual testing with Argos](#visual-testing-with-argos) + - [Installation](#installation) + - [Basic Setup](#basic-setup) + - [Writing Your First Test](#writing-your-first-test) + - [TypeScript Setup](#typescript-setup) + - [Visual Testing with Argos](#visual-testing-with-argos) 2. [Recipes](#recipes) - - [Enhance testing with `expect-puppeteer` lib](#enhance-testing-with-expect-puppeteer-lib) - - [Debug mode](#debug-mode) - - [Automatic server starting](#automatic-server-starting) - - [Customizing Puppeteer instance](#customizing-puppeteer-instance) - - [Customizing `setupTestFrameworkScriptFile` or `setupFilesAfterEnv`](#customizing-setupTestFrameworkScriptFile-or-setupFilesAfterEnv) - - [Extend `PuppeteerEnvironment`](#extend-puppeteerenvironment) - - [Implementing custom `globalSetup` and `globalTeardown`](#implementing-custom-globalsetup-and-globalteardown) -3. [Configuring Jest-Puppeteer](#configuring-jest-puppeteer) -4. [API](#api) + - [Using `expect-puppeteer`](#using-expect-puppeteer) + - [Debugging Tests](#debugging-tests) + - [Automatic Server Management](#automatic-server-management) + - [Customizing the Puppeteer Instance](#customizing-the-puppeteer-instance) + - [Custom Test Setup](#custom-test-setup) + - [Extending `PuppeteerEnvironment`](#extending-puppeteerenvironment) + - [Global Setup and Teardown](#global-setup-and-teardown) +3. [Jest-Puppeteer Configuration](#jest-puppeteer-configuration) +4. [API Reference](#api-reference) 5. [Troubleshooting](#troubleshooting) 6. [Acknowledgements](#acknowledgements) ## Getting Started -### Install the packages +### Installation + +To start using `jest-puppeteer`, you’ll need to install the following packages: ```bash npm install --save-dev jest-puppeteer puppeteer jest ``` -### Update your Jest configuration +This will install Jest (the testing framework), Puppeteer (the headless browser tool), and `jest-puppeteer` (the integration between the two). + +### Basic Setup -Add jest-puppeteer as a preset in your Jest configuration file "jest.config.js": +In your Jest configuration file (`jest.config.js`), add `jest-puppeteer` as the preset: ```json { @@ -44,202 +52,131 @@ Add jest-puppeteer as a preset in your Jest configuration file "jest.config.js": } ``` -> **Note** -> Ensure you remove any existing `testEnvironment` options from your Jest configuration +This will configure Jest to use Puppeteer for running your tests. Make sure to remove any conflicting `testEnvironment` settings that might be present in your existing Jest configuration, as `jest-puppeteer` manages the environment for you. -### Write a test +### Writing Your First Test -To write a test, create a new file with a `.test.js` extension, and include your test logic using the `page` exposed by `jest-puppeteer`. Here's a basic example: +Once you’ve configured Jest, you can start writing tests using Puppeteer’s `page` object, which is automatically provided by `jest-puppeteer`. + +Create a test file (e.g., `google.test.js`): ```js import "expect-puppeteer"; -describe("Google", () => { +describe("Google Homepage", () => { beforeAll(async () => { await page.goto("https://google.com"); }); - it('should display "google" text on page', async () => { - await expect(page).toMatchTextContent("google"); + it('should display "Google" in the page title', async () => { + await expect(page).toMatchTitle(/Google/); }); }); ``` -### Use with TypeScript +This example test navigates to Google’s homepage and checks if the title contains the word "Google". `jest-puppeteer` simplifies working with Puppeteer by exposing the `page` object, allowing you to write tests using a familiar syntax. + +### TypeScript Setup -TypeScript is natively supported from v8.0.0, for previous versions, you have to use [community-provided types](https://github.com/DefinitelyTyped/DefinitelyTyped). +If you’re using TypeScript, `jest-puppeteer` natively supports it from version `8.0.0`. To get started with TypeScript, follow these steps: -_Note : If you have upgraded to version v10.1.2 or above, we strongly recommend that you uninstall them :_ +1. Make sure your project is using the correct type definitions. If you’ve upgraded to version `10.1.2` or above, uninstall old types: ```bash npm uninstall --save-dev @types/jest-environment-puppeteer @types/expect-puppeteer ``` -Native types definitions are available whether you use `@types/jest` or `@jest/globals` for [jest types](https://jestjs.io/docs/getting-started#type-definitions). +2. Jest will automatically pick up type definitions from either `@types/jest` or `@jest/globals`. Once you’ve set up the environment, you can start writing tests in TypeScript just like in JavaScript: -Once setup, import the jest-puppeteer modules in your test file, then write your test logic the same way you would in Javascript. - -- If using `@types/jest` : +- Example using `@types/jest`: ```ts -// import jest-puppeteer globals import "jest-puppeteer"; import "expect-puppeteer"; -describe("Google", (): void => { +describe("Google Homepage", (): void => { beforeAll(async (): Promise => { await page.goto("https://google.com"); }); - it('should display "google" text on page', async (): Promise => { - await expect(page).toMatchTextContent("google"); + it('should display "Google" in the title', async (): Promise => { + await expect(page).toMatchTitle(/Google/); }); }); ``` -- If using `@jest/globals` : +- Example using `@jest/globals`: ```ts -// import jest types import { expect, describe, beforeAll, it } from "@jest/globals"; - -// import jest-puppeteer globals import "jest-puppeteer"; import "expect-puppeteer"; -describe("Google", (): void => { +describe("Google Homepage", (): void => { beforeAll(async (): Promise => { await page.goto("https://google.com"); }); - it('should display "google" text on page', async (): Promise => { - await expect(page).toMatchTextContent("google"); + it('should display "Google" in the title', async (): Promise => { + await expect(page).toMatchTitle(/Google/); }); }); ``` -### Visual testing with Argos - -[Argos](https://argos-ci.com) is a powerful visual testing tool that allows to review visual changes introduced by each pull request. -By integrating Argos with jest-puppeteer, you can easily capture and compare screenshots to ensure the visual consistency of your application. - -To get started with Argos, follow these steps: - -1. [Install Argos GitHub App](https://github.com/apps/argos-ci) -2. Install the packages - -```sh -npm install --save-dev @argos-ci/cli @argos-ci/puppeteer -``` - -3. Take screenshots during E2E tests with: `await argosScreenshot(page, "/screenshots/myScreenshot.png")` -4. Include the following command in your CI workflow to upload screenshots to Argos: `npx @argos-ci/cli upload ./screenshots` - -After installing Argos, learn how to [review visual changes](https://argos-ci.com/docs/review-changes) in your development workflow. - -#### Synchronous configuration - -```js -// jest-puppeteer.config.cjs - -/** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */ -module.exports = { - launch: { - dumpio: true, - headless: process.env.HEADLESS !== "false", - }, - server: { - command: "node server.js", - port: 4444, - launchTimeout: 10000, - debug: true, - }, -}; -``` - -#### Asynchronous configuration - -In this example, an already-running instance of Chrome is used by passing the active WebSocket endpoint to the `connect` option. This can be particularly helpful when connecting to a Chrome instance running in the cloud. - -```js -// jest-puppeteer.config.cjs -const dockerHost = "http://localhost:9222"; - -async function getConfig() { - const data = await fetch(`${dockerHost}/json/version`).json(); - const browserWSEndpoint = data.webSocketDebuggerUrl; - /** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */ - return { - connect: { - browserWSEndpoint, - }, - server: { - command: "node server.js", - port: 3000, - launchTimeout: 10000, - debug: true, - }, - }; -} +### Visual Testing with Argos -module.exports = getConfig(); -``` +[Argos](https://argos-ci.com) is a powerful tool for visual testing, allowing you to track visual changes introduced by each pull request. By integrating Argos with `jest-puppeteer`, you can easily capture and compare screenshots to maintain the visual consistency of your application. -## Recipes +To get started, check out the [Puppeteer Quickstart Guide](https://argos-ci.com/docs/quickstart/puppeteer). -### Enhance testing with `expect-puppeteer` lib +## Recipes -It can be challenging to write integration tests with the [Puppeteer API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md), as it is not specifically designed for testing purposes. -To simplify the writing tests process, the [expect-puppeteer API](https://github.com/smooth-code/jest-puppeteer/tree/master/packages/expect-puppeteer/README.md#api) offers specific matchers when making expectations on a [Puppeteer Page](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page). +### Using `expect-puppeteer` -Here are some examples: +Writing tests with Puppeteer’s core API can be verbose. The `expect-puppeteer` library simplifies this by adding custom matchers, such as checking for text content or interacting with elements. Some examples: -#### Find a text in the page +- Assert that a page contains certain text: ```js -// Assert that the current page contains 'Text in the page' -await expect(page).toMatchTextContent("Text in the page"); +await expect(page).toMatchTextContent("Expected text"); ``` -#### Click a button +- Simulate a button click: ```js -// Assert that a button containing text "Home" will be clicked -await expect(page).toClick("button", { text: "Home" }); +await expect(page).toClick("button", { text: "Submit" }); ``` -#### Fill a form +- Fill out a form: ```js -// Assert that a form will be filled -await expect(page).toFillForm('form[name="myForm"]', { - firstName: "James", - lastName: "Bond", +await expect(page).toFillForm('form[name="login"]', { + username: "testuser", + password: "password", }); ``` -### Debug mode +### Debugging Tests -Debugging tests can sometimes be challenging. Jest Puppeteer provides a debug mode that allows you to pause test execution and inspect the browser. To activate debug mode, call jestPuppeteer.debug() in your test: +Debugging can sometimes be tricky in headless browser environments. `jest-puppeteer` provides a helpful `debug()` function, which pauses test execution and opens the browser for manual inspection: ```js await jestPuppeteer.debug(); ``` -Remember that using `jestPuppeteer.debug()` will pause the test indefinitely. To resume, remove or comment out the line and rerun the test. To prevent timeouts during debugging, consider increasing Jest's default timeout: +To prevent the test from timing out, increase Jest’s timeout: ```js -jest.setTimeout(300000); // Set the timeout to 5 minutes (300000 ms) +jest.setTimeout(300000); // 5 minutes ``` -### Automatic server starting +This can be particularly useful when you need to step through interactions or inspect the state of the page during test execution. -Jest Puppeteer allows to start a server before running your tests suite and will close it after the tests end. To automatically start a server, you have to add a server section to your `jest-puppeteer.config.cjs` file and specify the command to start server and a port number: +### Automatic Server Management -```js -// jest-puppeteer.config.cjs +If your tests depend on a running server (e.g., an Express app), you can configure `jest-puppeteer` to automatically start and stop the server before and after tests: -/** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */ +```js module.exports = { server: { command: "node server.js", @@ -248,118 +185,55 @@ module.exports = { }; ``` -Other options are documented in [jest-dev-server](https://github.com/smooth-code/jest-puppeteer/tree/master/packages/jest-dev-server). - -### Customizing Puppeteer instance - -To customize Puppeteer instance, you can update the `jest-puppeteer.config.cjs` file. - -For example, to launch Firefox browser instead of default chrome, you can set the `launch.product` property to "firefox". +This eliminates the need to manually manage your server during testing. -You can also update the browser context to use the incognito mode to have isolation between instances. Read [jest-puppeteer-environment readme](https://github.com/smooth-code/jest-puppeteer/blob/master/packages/jest-environment-puppeteer/README.md) to learn more about the possible options. +### Customizing the Puppeteer Instance -Default config values: +You can easily customize the Puppeteer instance used in your tests by modifying the `jest-puppeteer.config.js` file. For example, if you want to launch Firefox instead of Chrome: ```js -// jest-puppeteer.config.cjs - -/** @type {import('jest-environment-puppeteer').JestPuppeteerConfig} */ module.exports = { launch: { - dumpio: true, + product: "firefox", headless: process.env.HEADLESS !== "false", - product: "chrome", }, - browserContext: "default", }; ``` -### Customizing `setupTestFrameworkScriptFile` or `setupFilesAfterEnv` +This file allows you to configure browser options, set up browser contexts, and more. + +### Custom Test Setup -If you are using custom setup files, you must include `expect-puppeteer` in your setup to access the matchers it offers. Add the following to your custom setup file: +If you have custom setup requirements, you can define setup files to initialize your environment before each test. For instance, you may want to import `expect-puppeteer` globally: ```js // setup.js require("expect-puppeteer"); - -// Your custom setup -// ... ``` -```js -// jest.config.js -module.exports = { - // ... - setupTestFrameworkScriptFile: "./setup.js", - // or - setupFilesAfterEnv: ["./setup.js"], -}; -``` - -Be cautious when setting your custom setupFilesAfterEnv and globalSetup, as it may result in undefined globals. Using multiple projects in Jest is one way to mitigate this issue. +Then, in your Jest config: ```js module.exports = { - projects: [ - { - displayName: "integration", - preset: "jest-puppeteer", - transform: { - "\\.tsx?$": "babel-jest", - ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": - "jest-transform-stub", - }, - moduleNameMapper: { - "^.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": - "jest-transform-stub", - }, - modulePathIgnorePatterns: [".next"], - testMatch: [ - "/src/**/__integration__/**/*.test.ts", - "/src/**/__integration__/**/*.test.tsx", - ], - }, - { - displayName: "unit", - transform: { - "\\.tsx?$": "babel-jest", - ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": - "jest-transform-stub", - }, - moduleNameMapper: { - "^.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": - "jest-transform-stub", - }, - globalSetup: "/setupEnv.ts", - setupFilesAfterEnv: ["/setupTests.ts"], - modulePathIgnorePatterns: [".next"], - testMatch: [ - "/src/**/__tests_/**/*.test.ts", - "/src/**/__tests__/**/*.test.tsx", - ], - }, - ], + setupFilesAfterEnv: ["./setup.js"], }; ``` -### Extend `PuppeteerEnvironment` - -If you need to use your custom environment, you can extend the `PuppeteerEnvironment`. +### Extending `PuppeteerEnvironment` -First, create a JavaScript file for your custom environment: +For advanced use cases, you can extend the default `PuppeteerEnvironment` class to add custom functionality: ```js -// custom-environment.js const PuppeteerEnvironment = require("jest-environment-puppeteer"); class CustomEnvironment extends PuppeteerEnvironment { async setup() { await super.setup(); - // Your setup + // Custom setup logic } async teardown() { - // Your teardown + // Custom teardown logic await super.teardown(); } } @@ -367,20 +241,9 @@ class CustomEnvironment extends PuppeteerEnvironment { module.exports = CustomEnvironment; ``` -Next, assign your JavaScript file's path to the [`testEnvironment`](https://facebook.github.io/jest/docs/en/configuration.html#testenvironment-string) property in your Jest configuration: - -```js -{ - // ... - "testEnvironment": "./custom-environment.js" -} -``` - -Your custom `setup` and `teardown` will now be executed before and after each test suite, respectively. - -### Implementing custom `globalSetup` and `globalTeardown` +### Global Setup and Teardown -You can create custom [`globalSetup`](https://facebook.github.io/jest/docs/en/configuration.html#globalsetup-string) and [`globalTeardown`](https://facebook.github.io/jest/docs/en/configuration.html#globalteardown-string) methods. For this purpose, jest-environment-puppeteer exposes the setup and teardown methods, allowing you to integrate them with your custom global setup and teardown methods, as shown in the example below: +Sometimes, tests may require a global setup or teardown step that only runs once per test suite. You can define custom `globalSetup` and `globalTeardown` scripts: ```js // global-setup.js @@ -388,180 +251,147 @@ const setupPuppeteer = require("jest-environment-puppeteer/setup"); module.exports = async function globalSetup(globalConfig) { await setupPuppeteer(globalConfig); - // Your global setup + // Additional setup logic }; ``` -```js -// global-teardown.js -const teardownPuppeteer = require("jest-environment-puppeteer/teardown"); - -module.exports = async function globalTeardown(globalConfig) { - // Your global teardown - await teardownPuppeteer(globalConfig); -}; -``` +In your Jest configuration, reference these files: -Then assigning your js file paths to the [`globalSetup`](https://facebook.github.io/jest/docs/en/configuration.html#globalsetup-string) and [`globalTeardown`](https://facebook.github.io/jest/docs/en/configuration.html#globalteardown-string) property in your Jest configuration. - -```js +```json { - // ... "globalSetup": "./global-setup.js", "globalTeardown": "./global-teardown.js" } ``` -Now, your custom `globalSetup` and `globalTeardown` will be executed once before and after all test suites, respectively. - -## Configuring Jest-Puppeteer +### Jest-Puppeteer Configuration -Jest Puppeteer employs cosmiconfig for configuration file support, allowing you to configure Jest Puppeteer in various ways (listed in order of precedence): +Jest-Puppeteer supports various configuration formats through [cosmiconfig](https://github.com/davidtheclark/cosmiconfig), allowing flexible ways to define your setup. By default, the configuration is looked for at the root of your project, but you can also define a custom path using the `JEST_PUPPETEER_CONFIG` environment variable. -- A `"jest-puppeteer"` key in your `package.json` file. -- A `.jest-puppeteerrc` file in either JSON or YAML format. -- A `.jest-puppeteerrc.json`, `.jest-puppeteerrc.yml`, `.jest-puppeteerrc.yaml`, or `.jest-puppeteerrc.json5` file. -- A `.jest-puppeteerrc.js`, `.jest-puppeteerrc.cjs`, `jest-puppeteer.config.js`, or `jest-puppeteer.config.cjs` file that exports an object using `module.exports`. -- A `.jest-puppeteerrc.toml` file. +Possible configuration formats: -By default, the configuration is searched for at the root of the project. To define a custom path, use the `JEST_PUPPETEER_CONFIG` environment variable. +- A `"jest-puppeteer"` key in your `package.json`. +- A `.jest-puppeteerrc` file (JSON, YAML, or JavaScript). +- A `.jest-puppeteer.config.js` or `.jest-puppeteer.config.cjs` file that exports a configuration object. -Ensure that the exported configuration is either a config object or a Promise that returns a config object. +Example of a basic configuration file (`jest-puppeteer.config.js`): -```ts -interface JestPuppeteerConfig { - /** - * Puppeteer connect options. - * @see https://pptr.dev/api/puppeteer.connectoptions - */ - connect?: ConnectOptions; - /** - * Puppeteer launch options. - * @see https://pptr.dev/api/puppeteer.launchoptions - */ - launch?: PuppeteerLaunchOptions; - /** - * Server config for `jest-dev-server`. - * @see https://www.npmjs.com/package/jest-dev-server - */ - server?: JestDevServerConfig | JestDevServerConfig[]; - /** - * Allow to run one browser per worker. - * @default false - */ - browserPerWorker?: boolean; - /** - * Browser context to use. - * @default "default" - */ - browserContext?: "default" | "incognito"; - /** - * Exit on page error. - * @default true - */ - exitOnPageError?: boolean; - /** - * Use `runBeforeUnload` in `page.close`. - * @see https://pptr.dev/api/puppeteer.page.close - * @default false - */ - runBeforeUnloadOnClose?: boolean; -} +```js +module.exports = { + launch: { + headless: process.env.HEADLESS !== "false", + dumpio: true, // Show browser console logs + }, + browserContext: "default", // Use "incognito" if you want isolated sessions per test + server: { + command: "node server.js", + port: 4444, + launchTimeout: 10000, + debug: true, + }, +}; ``` -## API +You can further extend this configuration to connect to a remote instance of Chrome or customize the environment for your test runs. -### `global.browser` +## API Reference -Provides access to the [Puppeteer Browser](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-browser). +Jest-Puppeteer exposes several global objects and methods to facilitate test writing: -```js -it("should open a new page", async () => { - const page = await browser.newPage(); - await page.goto("https://google.com"); -}); -``` +- **`global.browser`**: Provides access to the Puppeteer [Browser](https://pptr.dev/#?product=Puppeteer&version=v13.0.0&show=api-class-browser) instance. -### `global.page` + Example: -Provides access to a [Puppeteer Page](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page) that is opened at the start (most commonly used). + ```js + const page = await browser.newPage(); + await page.goto("https://example.com"); + ``` -```js -it("should fill an input", async () => { - await page.type("#myinput", "Hello"); -}); -``` +- **`global.page`**: The default Puppeteer [Page](https://pptr.dev/#?product=Puppeteer&version=v13.0.0&show=api-class-page) object, automatically created and available in tests. -### `global.context` + Example: -Provides access to a [browser context](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-browsercontext) that is instantiated when the browser is launched. You can control whether each test has its own isolated browser context using the `browserContext` option in your configuration file. + ```js + await page.type("#input", "Hello World"); + ``` -### `global.expect(page)` +- **`global.context`**: Gives access to the [browser context](https://pptr.dev/#?product=Puppeteer&version=v13.0.0&show=api-class-browsercontext), useful for isolating tests in separate contexts. -A helper for making Puppeteer assertions. For more information, refer to [the documentation](https://github.com/smooth-code/jest-puppeteer/tree/master/packages/expect-puppeteer/README.md#api). +- **`global.expect(page)`**: The enhanced `expect` API provided by `expect-puppeteer`. You can use this to make assertions on the Puppeteer `page`. -```js -await expect(page).toMatchTextContent("A text in the page"); -// ... -``` + Example: -### `global.jestPuppeteer.debug()` + ```js + await expect(page).toMatchTextContent("Expected text on page"); + ``` -Put test in debug mode. +- **`global.jestPuppeteer.debug()`**: Suspends test execution, allowing you to inspect the browser and debug. -- Jest is suspended (no timeout) -- A `debugger` instruction to Chromium, if Puppeteer has been launched with `{ devtools: true }` it will pause + Example: -```js -it("should put test in debug mode", async () => { + ```js await jestPuppeteer.debug(); -}); -``` + ``` -### `global.jestPuppeteer.resetPage()` +- **`global.jestPuppeteer.resetPage()`**: Resets the `page` object before each test. -To reset `global.page` before each test, use the following code: + Example: -```js -beforeEach(async () => { - await jestPuppeteer.resetPage(); -}); -``` + ```js + beforeEach(async () => { + await jestPuppeteer.resetPage(); + }); + ``` -### `global.jestPuppeteer.resetBrowser()` +- **`global.jestPuppeteer.resetBrowser()`**: Resets the `browser`, `context`, and `page` objects, ensuring a clean slate for each test. -To reset `global.browser`, `global.context`, and `global.page` before each test, use the following code: + Example: -```js -beforeEach(async () => { - await jestPuppeteer.resetBrowser(); -}); -``` + ```js + beforeEach(async () => { + await jestPuppeteer.resetBrowser(); + }); + ``` -## Troubleshooting +These methods simplify the setup and teardown process for tests, making it easier to work with Puppeteer in a Jest environment. -### CI Timeout +## Troubleshooting -Most Continuous Integration (CI) platforms restrict the number of threads you can use. If you run multiple test suites, the tests may timeout due to Jest attempting to run Puppeteer in parallel, and the CI platform being unable to process all parallel jobs in time. +### CI Timeout Issues -A solution to this issue is to run your tests serially in a CI environment. Users have found that [running tests serially in such environments can result in up to 50% performance improvements](https://jestjs.io/docs/en/troubleshooting#tests-are-extremely-slow-on-docker-and-or-continuous-integration-ci-server). +In CI environments, tests may occasionally time out due to limited resources. Jest-Puppeteer allows you to control the number of workers used to run tests. Running tests serially can help avoid these timeouts: -You can achieve this through the CLI by running: +Run tests in a single process: -```sh +```bash jest --runInBand ``` -Alternatively, you can set Jest to use a maximum number of workers that your CI environment supports: +Alternatively, you can limit the number of parallel workers: -``` +```bash jest --maxWorkers=2 ``` -### Prevent ESLint errors on global variables +This ensures that your CI environment doesn’t get overloaded by too many concurrent processes, which can improve the reliability of your tests. + +### Debugging CI Failures -Jest Puppeteer provides five global variables: browser, page, context, puppeteerConfig, and jestPuppeteer. -To prevent errors related to these globals, include them in your ESLint configuration: +Sometimes, failures happen only in CI environments and not locally. In such cases, use the `debug()` method to open a browser during CI runs and inspect the page manually: + +```js +await jestPuppeteer.debug(); +``` + +To avoid test timeouts in CI, set a larger timeout during the debugging process: + +```js +jest.setTimeout(600000); // 10 minutes +``` + +### Preventing ESLint Errors with Global Variables + +Jest-Puppeteer introduces global variables like `page`, `browser`, `context`, etc., which ESLint may flag as undefined. You can prevent this by adding these globals to your ESLint configuration: ```js // .eslintrc.js @@ -579,6 +409,8 @@ module.exports = { }; ``` +This configuration will prevent ESLint from throwing errors about undefined globals. + ## Acknowledgements -Special thanks to Fumihiro Xue for providing an excellent [Jest example](https://github.com/xfumihiro/jest-puppeteer-example). +Special thanks to [Fumihiro Xue](https://github.com/xfumihiro) for providing an excellent [Jest Puppeteer example](https://github.com/xfumihiro/jest-puppeteer-example), which served as an inspiration for this package.