Notwithstanding Precautions, Misadventure

    TypeScript icon, indicating that this package has built-in type declarations

    1.7.0 • Public • Published

    Jest Playwright

    CI Coverage Status npm

    ⚠️ We recommend the official Playwright test-runner ⚠️

    It's more flexible, lightweight, optimized for Playwright, and has TypeScript support out of the box. This doesn't mean, that we stop with maintaining this package.

    Running your tests using Jest & Playwright

    npm install -D jest jest-playwright-preset playwright

    Also you can use jest-playwright-preset with specific playwright packages: playwright-webkit, playwright-chromium and playwright-firefox

    npm install -D jest jest-playwright-preset playwright-firefox


    • Node.js >= 10.15.0
    • Playwright >= 0.12.1
    • Jest >= 25


    Update your Jest configuration, either:

    with package.json:

    "jest": {
      "preset": "jest-playwright-preset"

    or with jest.config.js:

    module.exports = {
      preset: 'jest-playwright-preset',

    And add the Jest command as in the script section of your package.json:

      "scripts": {
        "test": "jest"

    Now you can use Playwright in your tests:

    beforeAll(async () => {
      await page.goto('')
    test('should display correct browser', async () => {
      const browser = await page.$eval('.string-major', (el) => el.innerHTML)


    playwright actions can take some time for execution, because of it jest-playwright overrides jest default timeout interval from 5 to 15 seconds. You can change this interval with testTimeout in your jest configuration.


    It's recommend to use a separate Jest configuration jest.e2e.config.js for jest-playwright to gain speed improvements and by that to only use Playwright in the end-to-end tests. For that you have to use the -c flag when calling Jest and use the testMatch or testRegex in your Jest config to split them.

    Be sure to remove any existing testEnvironment option from your Jest configuration. The jest-playwright-preset preset needs to manage that option itself.

    Configuration options can be specified using a jest-playwright.config.js file at the root of your project:

    // jest-playwright.config.js
    module.exports = {
      // Options...

    Similar to Jest globalSetup configuration can except the export of an async function:

    module.exports = async () => {
      await ...

    A custom path can be specified to the jest-playwright.config.js file within your jest.config.js file:

    process.env.JEST_PLAYWRIGHT_CONFIG = '/path/to/jest-playwright.config.js'

    Alternatively, configuration options can specified using Jest's own testEnvironmentOptions option within your jest.config.js file:

    // jest.config.js
    module.exports = {
      preset: 'jest-playwright-preset',
      testEnvironmentOptions: {
        'jest-playwright': {
          // Options...


    • launchOptions <[object]>. All Playwright launch options can be specified in config. Since it is JavaScript, you can use all stuff you need, including environment.
    • launchType <LAUNCH | PERSISTENT | SERVER>. Method to launch browser instance. jest-playwright attaches Playwright to an existing browser instance by default.
    • connectOptions <[object]>. All Playwright connect options can be specified in config.
    • contextOptions <[object]>. All Playwright context options can be specified in config.
    • browsers <[(string | object)[]]>. Define browsers to run tests in.
      • chromium Each test runs Chromium (default).
      • firefox Each test runs Firefox.
      • webkit Each test runs Webkit.
    • devices <[(string | object)[] | RegExp]>. Define a devices to run tests in. Actual list of devices can be found here.
    • exitOnPageError <[boolean]>. Exits process on any page error. Defaults to true.
    • collectCoverage <[boolean]>. Enables the coverage collection of the saveCoverage(page) calls to the .nyc_output/coverage.json file.
    • serverOptions <[object]>. All jest-process-manager options.
    • selectors <[array]>. Define selectors. Each selector must be an object with name and script properties.
    • skipInitialization <[boolean]>. Add you ability to skip first setup playwright process. Possible use cases can be found here
    • useDefaultBrowserType <[boolean]>. Sometimes browser + device combinations don't have any sense. With this option tests will be run with defaultBrowserType of device. Pay attention that you should define devices to correct usage of this option.

    Usage of process environment to define browser

    You can control the browser with passing environment variable.

    // jest-playwright.config.js
    module.exports = {
      browsers: [process.env.BROWSER],

    Specific browser options

    For launchOptions, connectOptions and contextOptions you can define special browser options.

    // jest-playwright.config.js
    module.exports = {
      connectOptions: {
        chromium: {
          wsEndpoint: 'ws://'
        firefox: {
          wsEndpoint: 'ws://'

    Browser configuration

    There are different ways to define devices in your configuration file:

    • You can use array of browser names:
    module.exports = {
      browsers: ["chromium", "webkit"],
    • You can define custom browser. You can find out use cases here:
      // Name of browser
      name: 'chromium' | 'firefox' | 'webkit'
      // Display name for test
      displayName: string
      // Browser options

    Device configuration

    There are different ways to define devices in your configuration file:

    • You can use array of device names:
    module.exports = {
      devices: ["iPhone 6", "Pixel 2"],
    • You can use RegExp:
    module.exports = {
      devices: /iPhone 8/,
    • Also you can define custom device:
      // Name of device
      name: string
      // Page width and height
      viewport: {
        width: number
        height: number
      // user agent
      userAgent: string
      // device scale factor
      deviceScaleFactor: number
      // is device is mobile
      isMobile: boolean
      // support of touch events
      hasTouch: boolean
      // device default browser
      defaultBrowserType: chromium, firefox or webkit


    • browserName <[string]> - name of the current browser (chromium, firefox or webkit)
    • deviceName <[string]> - name of the current device
    • browser <[Browser]> - Playwright browser instance
    • context <[Context]> - a new Playwright context instance for each new test file
    • page <[Page]> - Playwright page instance (since a new context for every test file also creates a new page for it)

    All of them are available globally in each Jest test. If you are using ESLint and JavaScript, its recommend to use it in combination with the eslint-plugin-jest-playwright.

    Debug mode

    Playwright give you ability to configure the browser for debugging with the PWDEBUG environment variable. It will launch the browser in headful mode, disables playwright timeout and Jest won't timeout anymore.:

    PWDEBUG=1 jest

    Reset helper functions

    Reset current page

    beforeEach(async () => {
      await jestPlaywright.resetPage()

    To create a new page for each test, you can use this snippet to have a new page object for each individual test.

    Reset current context

    beforeEach(async () => {
      await jestPlaywright.resetContext()

    To create a new context for each test, you can use this snippet to have a new context object for each individual test.

    Reset current browser

    beforeEach(async () => {
      await jestPlaywright.resetBrowser()

    You can use this snippet to reset current browser for each individual test. It will reset browser, context and page.

    Debug helper functions

    jest-playwright provides some functions to debug your tests.

    IMPORTANT NOTE: For these kind of tests you should use properties passed through callback function instead of globals


    This helper function provide you ability to run specific tests in debug mode. It will disable headless mode. You can find more information here

    test.jestPlaywrightDebug('failed', async ({ page }) => {
      await page.goto('')
      const title = await page.title()
      await expect(title).toBe('Google')

    Also you can define options for debug mode with debugOptions:

    // jest-playwright.config.js
    module.exports = {
      debugOptions: {
        contextOptions: {
          offline: true


    This helper function provide you ability to run specific tests with passed options. You can define browser and device properties to run test for them, otherwise test run for current configuration.

        // your jest-playwright options
      'test name',
      async ({ browser, context, page }) => {
        /* ... */

    Tracking the coverage

    It's possible to track the coverage of the end-to-end tests with the babel-plugin-istanbul Babel plugin configured. It needs to be included in the web application which you are gonna test otherwise it won't work. To use it, you have to set collectCoverage in the jest-playwright.config.js to true. Per default the test coverage will be automatically saved after each navigation change (beforeunload event). If a certain code path is not covered, you can manually call and add the corresponding saveCoverage(page) call to your tests like that:

    await jestPlaywright.saveCoverage(page)

    By using coverage collection, it will write the coverage data to the .nyc_output/coverage.json file which can be transformed using nyc to the lcov format:

    npx nyc report --reporter=lcovonly

    or to HTML:

    npx nyc report --reporter=html

    which will create a HTML website in the coverage directory.

    Skip tests for specific browsers and devices

    It's possible to skip tests for browsers or combination of browsers and devices

      { browsers: ['chromium'] },
      'should skip this one',
      async () => {
        const title = await page.title()

    Using shadow DOM selectors

    Playwright engine pierces open shadow DOM by default.

    beforeAll(async () => {
      await page.goto(
    test('should display "google" text on page', async () => {
      const shadowElem = await page.$('.info')
      const shadowElemText = await shadowElem.innerHTML()
        'Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card.',

    Start a server

    Jest Playwright integrates a functionality to start a server when running your test suite, like jest-puppeteer. It automatically closes the server when tests are done.

    To use it, specify a server section in your jest-playwright.config.js.

    // jest-playwright.config.js
    module.exports = {
      serverOptions: {
        command: 'node server.js',
        port: 4444,

    Other options are documented in jest-process-manager.

    Using with different jest environments

    The default jest-playwright environment is node, but you can use a browser-like environment through jest-playwright-jsdom


    There is a utility package expect-playwright which simplifies the expect statements in combination with Playwright to make e.g. shorter text comparisons.

    ESLint globals / 'page' is not defined

    There is an ESLint plugin available eslint-plugin-jest-playwright available which includes the globals for using jest-playwright.

    Unstable and experimental API

    You can run tests for multiple browsers and devices:

    • You must have installed the playwright package
    • You must define browsers to test with your jest-playwright.config.js:
    module.exports = {
        browsers: ["chromium", "webkit"],
        devices: ["iPhone 6", "Pixel 2"],

    It will run your tests for:

    • Chromium browser and iPhone 6 device;
    • Chromium browser and Pixel 2 device;
    • Webkit browser and iPhone 6 device;
    • Webkit browser and Pixel 2 device;

    If there is no defined browsers in config it will run tests for chromium browser.

    Usage with custom testEnvironment

    You can use jest-playwright with custom test environment for taking screenshots during test failures for example:


    "testEnvironment": "./CustomEnvironment.js"


    const PlaywrightEnvironment = require('jest-playwright-preset/lib/PlaywrightEnvironment')
    class CustomEnvironment extends PlaywrightEnvironment {
      async setup() {
        await super.setup()
        // Your setup
      async teardown() {
        // Your teardown
        await super.teardown()
      async handleTestEvent(event) {
        await super.handleTestEvent(event);
        if ( === 'test_done' && event.test.errors.length > 0) {
          const parentName =\W/g, '-')
          const specName =\W/g, '-')
            path: `screenshots/${parentName}_${specName}.png`,
    module.exports = CustomEnvironment

    Usage with custom runner

    jest-playwright using custom runner underhood. So if you need implement your own runner, you should extend it:


    "runner": "./CustomRunner.js"


    const PlaywrightRunner = require('jest-playwright-preset/lib/PlaywrightRunner')
    class CustomRunner extends PlaywrightRunner {
      constructor(...args) {
        this.isSerial = true
    module.exports = CustomRunner

    Usage with custom globalSetup and globalTeardown

    For this use case, jest-playwright-preset exposes two methods: globalSetup and globalTeardown, so that you can wrap them with your own global setup and global teardown methods as the following example:

    Getting authentication state once for all test cases as per playwright reference:

    // global-setup.js
    import { globalSetup as playwrightGlobalSetup } from 'jest-playwright-preset';
    module.exports = async function globalSetup(globalConfig) {
      await playwrightGlobalSetup(globalConfig);
      const browserServer = await chromium.launchServer();
      const wsEndpoint = browserServer.wsEndpoint();
      const browser = await chromium.connect({ wsEndpoint: wsEndpoint });
      const page = await browser.newPage();
      // your login function
      await doLogin(page);
      // store authentication data
      const storage = await page.context().storageState();
      process.env.STORAGE = JSON.stringify(storage);
    // global-teardown.js
    import { globalTeardown as playwrightGlobalTeardown } from 'jest-playwright-preset';
    module.exports = async function globalTeardown(globalConfig) {
      // Your global teardown
      await playwrightGlobalTeardown(globalConfig);

    Then assigning your js file paths to the globalSetup and globalTeardown property in your Jest configuration.

      // ...
      "globalSetup": "./global-setup.js",
      "globalTeardown": "./global-teardown.js"

    Now your custom globalSetup and globalTeardown will be triggered once before and after all test suites.

    Usage with Typescript

    Example Jest configuration in combination with ts-jest:

    module.exports = {
      preset: 'jest-playwright-preset',
      transform: {
        '^.+\\.ts$': 'ts-jest',

    Types are also available, which you can either use via directly in your test:

    /// <reference types="jest-playwright-preset" />
    /// <reference types="expect-playwright" />

    or at your central tsconfig.json either via files:

      "files": [

    or via types:

      "compilerOptions": {
        "types": ["jest-playwright-preset", "expect-playwright"]

    It's important to not change the testEnvironment to node. Otherwise it won't work.

    Known issues

    Error reporting with Jest

    If you face into error messages like

    UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.


    Timeout - Async callback was not invoked within the 20000ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 20000ms timeout specified by jest.setTimeout.Error:

    and your Jest error reporting will only show that an entire test (it() function) has failed, then you need to increase the Jest timeout because the Playwright timeout is greater than the Jest timeout. So Jest in the end will simply stop the execution and no verbose (which exact line) error reporting can be generated.

    To fix this behavior simply call

    jest.setTimeout(35 * 1000)

    in your tests at the top. (30 seconds is the default Playwright timeout for waiting for an specific element.)

    New Browser instance for each test

    If for your individual tests a new entire browser instance spins up each time and it won't be reused, then you probably run them in parallel. If you run them in a synchronous way with the --runInBand CLI option for Jest, then the same browser instance will be re-used and this should fix the issue.


    Demonstration the usage of jest-playwright for various test cases can be found in playwright-jest-examples


    Thanks to Smooth Code for the great jest-puppeteer.




    npm i jest-playwright-preset

    DownloadsWeekly Downloads






    Unpacked Size

    66.2 kB

    Total Files


    Last publish


    • mapkeji
    • mxschmitt
    • mskelton