Awesome Open Source
Awesome Open Source

🎭 Playwright test runner npm version

Zero config cross-browser end-to-end testing for web apps. Browser automation with Playwright, Jest-like assertions and built-in support for TypeScript.

Playwright test runner is available in preview and minor breaking changes could happen. We welcome your feedback to shape this towards 1.0.

Get started


npm i -D @playwright/test

Write a test

Create foo.spec.ts to define your test. The test function uses the page argument for browser automation.

import { it, expect } from "@playwright/test";

it("is a basic test with the page", async ({ page }) => {
  await page.goto("");
  const name = await page.innerText(".navbar__title");

Default arguments

The test runner provides browser primitives as arguments to your test functions. Test functions can use one or more of these arguments.

  • page: Instance of Page. Each test gets a new isolated page to run the test.
  • context: Instance of BrowserContext. Each test gets a new isolated context to run the test. The page object belongs to this context.
  • browser: Instance of Browser. Browsers are shared across tests to optimize resources. Each worker process gets a browser instance.
    • browserOptions: Default options passed to browser creation.

Specs and assertions

  • Use it and describe to write test functions. Run a single test with it.only and skip a test with it.skip.
  • For assertions, use the expect API.
const { it, describe } = require("@playwright/test");

describe("feature foo", () => {
  it("is working correctly", async ({ page }) => {
    // Test function

Run the test

Tests can be run on single or multiple browsers and with flags to generate screenshot on test failures.

# Run all tests across Chromium, Firefox and WebKit
npx folio

# Run tests on a single browser
npx folio --param browserName=chromium

# Run all tests in headful mode
npx folio --param headful

# Run tests with slowMo (slows down Playwright operations by n milliseconds)
npx folio --param slowMo=100

# Save screenshots on failure in test-results directory
npx folio --param screenshotOnFailure

# Record videos
npx folio --param video

# Retry test failures
npx folio --retries 3

# See all options
npx folio --help

Test runner CLI can be customized with Folio parameters.

Configure NPM scripts

Save the run command as an NPM script.

  "scripts": {
    "test": "npx folio --param screenshotOnFailure"


Multiple pages

The default context argument is a BrowserContext. Browser contexts are isolated execution environments that can host multiple pages. See multi-page scenarios for more examples.

import { it } from "@playwright/test";

it("tests on multiple web pages", async ({ context }) => {
  const pageFoo = await context.newPage();
  const pageBar = await context.newPage();
  // Test function

Mobile emulation

The contextOptions fixture defines default options used for context creation. This fixture can be overriden to configure mobile emulation in the default context.

import { folio } from "@playwright/test";
import { devices } from "playwright";

const fixtures = folio.extend();
fixtures.contextOptions.override(async ({ contextOptions }, runTest) => {
  await runTest({
    ...devices["iPhone 11"]
const { it, describe, extend } =;

it("uses mobile emulation", async ({ context }) => {
  // Test function

Network mocking

Define a custom argument that mocks networks call for a browser context.

// In fixtures.ts
import { folio as base } from "@playwright/test";
import { BrowserContext } from "playwright";

// Extend base fixtures with a new test-level fixture
const fixtures = base.extend<{ mockedContext: BrowserContext }>();

fixtures.mockedContext.init(async ({ context }, runTest) => {
  // Modify existing `context` fixture to add a route
  context.route(/.css/, route => route.abort());
  // Pass fixture to test functions

export folio =;
// In foo.spec.ts
import { folio } from "./fixtures";
const { it, expect } = folio;

it("loads pages without css requests", async ({ mockedContext }) => {
  const page = await mockedContext.newPage();
  await page.goto("");
  // Test function code

Visual comparisons

The expect API supports visual comparisons with toMatchSnapshot. This uses the pixelmatch library, and you can pass threshold as an option.

import { it, expect } from "@playwright/test";

it("compares page screenshot", async ({ page, browserName }) => {
  await page.goto("");
  const screenshot = await page.screenshot();
  expect(screenshot).toMatchSnapshot(`test-${browserName}.png`, { threshold: 0.2 });

On first execution, this will generate golden snapshots. Subsequent runs will compare against the golden snapshots. To update golden snapshots with new actuals, run with the --update-snapshots flag.

# Update golden snapshots when they differ from actual
npx folio --update-snapshots


Modify context options

You can modify the built-in fixtures. This example modifies the default contextOptions with a custom viewport size.

Step 1: Create a new file (say test/fixtures.ts) which contains our modifications.

// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";

const builder = baseFolio.extend();

// Fixture modifications go here

const folio =;

Step 2: Override the existing contextOptions fixture to configure viewport size and HTTPS error handling.

// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
+ import { BrowserContextOptions } from "playwright";

const builder = baseFolio.extend();

+ builder.contextOptions.override(async ({ contextOptions }, runTest) => {
+   const modifiedOptions: BrowserContextOptions = {
+     ...contextOptions, // Default options
+     viewport: { width: 1440, height: 900 },
+     ignoreHTTPSErrors: true
+   }
+   await runTest(modifiedOptions);
+ });

const folio =;

Step 3: Export it and other helpers from the modified fixtures. In your test files, import the modified fixture.

// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
import { BrowserContextOptions } from "playwright";

const builder = baseFolio.extend();

builder.contextOptions.override(async ({ contextOptions }, runTest) => {
  const modifiedOptions: BrowserContextOptions = {
    ...contextOptions, // default
    viewport: { width: 1440, height: 900 }
  await runTest(modifiedOptions);

const folio =;

+ export const it =;
+ export const expect = folio.expect;
// test/index.spec.ts
import { it, expect } from "./fixtures";

// Test functions go here
it("should have modified viewport", async ({ context }) => {
  // ...

Skip tests with annotations

The Playwright test runner can annotate tests to skip under certain parameters. This is enabled by Folio annotations.

it("should be skipped on firefox", (test, { browserName }) => {
  test.skip(browserName === "firefox", "optional description for the skip")
}, async ({ page, browserName }) => {
  // Test function

Export JUnit report

The Playwright test runner supports various reporters, including exporting as a JUnit compatible XML file.

# Specify output file as an environment variable
# Linux/macOS
export FOLIO_JUNIT_OUTPUT_NAME=junit.xml
# Windows

# Use junit and CLI reporters
npx folio --reporter=junit,line

# See all supported reporters
npx folio --help

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
typescript (9,961
e2e-tests (34
playwright (22

Find Open Source By Browsing 7,000 Topics Across 59 Categories