Skip to content

mlankamp/playwright-test

 
 

🎭 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

Installation

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("https://playwright.dev/");
  const name = await page.innerText(".home-navigation");
  expect(name).toBe("🎭 Playwright");
});

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"
  }
}

Examples

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({
    ...contextOptions,
    ...devices["iPhone 11"]
  });
});
const { it, describe, extend } = fixtures.build();

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
  runTest(context);
});

export folio = fixtures.build();
// 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("https://stackoverflow.com");
  // 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("https://stackoverflow.com");
  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

Configuration

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 = builder.build();

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 = builder.build();

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 = builder.build();

+ export const it = folio.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
set FOLIO_JUNIT_OUTPUT_NAME=junit.xml

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

# See all supported reporters
npx folio --help

About

Build a cross-browser end-to-end test suite with Playwright.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 66.6%
  • JavaScript 33.4%