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.
npm i -D @playwright/testCreate 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(".navbar__title");
expect(name).toBe("Playwright");
});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. Thepageobject belongs to this context.contextOptions: Default options passed to context creation. Learn how to modify them.
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/launch creation.
- Use
itanddescribeto write test functions. Run a single test withit.onlyand skip a test withit.skip. - For assertions, use the
expectAPI.
const { it, describe } = require("@playwright/test");
describe("feature foo", () => {
it("is working correctly", async ({ page }) => {
// Test function
});
});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 --helpTest runner CLI can be customized with Folio parameters.
Save the run command as an NPM script.
{
"scripts": {
"test": "npx folio --param screenshotOnFailure"
}
}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
});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
});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
});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-snapshotsYou 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 options
viewport: { width: 1440, height: 900 }
ignoreHTTPSErrors: true
}
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 }) => {
// ...
});You can modify the built-in fixtures. This example modifies the default browserOptions with a slowMo.
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 browserOptions fixture to configure the slowMo.
// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
+ import { LaunchOptions } from "playwright";
const builder = baseFolio.extend();
+ builder.browserOptions.override(async ({ browserOptions }, runTest) => {
+ const modifiedOptions: LaunchOptions = {
+ ...browserOptions, // Default options
+ slowMo: 50,
+ }
+ 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 { LaunchOptions } from "playwright";
const builder = baseFolio.extend();
builder.browserOptions.override(async ({ browserOptions }, runTest) => {
const modifiedOptions: LaunchOptions = {
...browserOptions, // default
slowMo: 50,
}
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 the slow mo", async ({ context }) => {
// ...
});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
});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