Skip to content

Playwright is a modern web test runner. With included features such as:

  • Cross browser support, including mobile browsers
  • Multi tab, origin, and user support
  • Automatic waiting
  • Test generation
  • Screenshots and videos

The @nx/playwright plugin supports the following package versions.

PackageSupported Versions
@playwright/test^1.36.0

Nx generators install the latest supported versions automatically when scaffolding new projects.

In any Nx workspace, you can install @nx/playwright by running the following command:

Terminal window
nx add @nx/playwright

This will install the correct version of @nx/playwright.

The @nx/playwright plugin will create a task for any project that has a Playwright configuration file present. Any of the following files will be recognized as a Playwright configuration file:

  • playwright.config.js
  • playwright.config.ts
  • playwright.config.mjs
  • playwright.config.mts
  • playwright.config.cjs
  • playwright.config.cts

The configuration directory must also contain a package.json or project.json.

To view inferred tasks for a project, open the project details view in Nx Console or run nx show project my-project --web in the command line.

The @nx/playwright/plugin is configured in the plugins array in nx.json.

nx.json
{
"plugins": [
{
"plugin": "@nx/playwright/plugin",
"options": {
"ciTargetName": "e2e-ci",
"targetName": "e2e"
}
}
]
}

The targetName and ciTargetName options control the name of the inferred Playwright tasks. The default names are e2e and e2e-ci.

When your Playwright config declares a webServer that sets reuseExistingServer to true and whose command runs an Nx task, Nx runs that task as a dependency of the Playwright tasks. The command must be nx run <project>:<target> or nx <target> <project>, optionally prefixed by a package manager runner such as npx or pnpm exec, with no extra arguments.

The Playwright docs suggest setting reuseExistingServer to !process.env.CI. Set it to true instead, since Nx already runs the web server as a task dependency. With false, Nx skips that task and Playwright starts its own server inside each Playwright task.

If that webServer also sets a port or url, Nx infers an extra task, named <targetName>--wait-for-webserver (e2e--wait-for-webserver by default), that waits for the server to be ready. The atomized CI tasks share that task when it would wait for the same servers, depend on the same serve tasks, and load the same env files. Otherwise they get their own <ciTargetName>--wait-for-webserver task. Playwright then finds the server already running and reuses it.

The webServerTimeout option sets how long, in milliseconds, that task waits before failing. Set the waitForWebServer option to false to opt out of that task. For the webServer shapes Nx leaves to Playwright and for how Nx caches and re-infers the server address, see Playwright web server readiness.

The targetName task runs the complete Playwright suite and caches the configured test and reporter outputs. The ciTargetName task uses the Atomizer.

Both options accept task names as strings. To run the non-atomized suite in CI, invoke the targetName task (the default is e2e) instead of the ciTargetName task.

Use include and exclude glob patterns on the plugin entry to scope inference. A target defaults plugin filter must use the exact identifier @nx/playwright/plugin.

By default, when creating a new frontend application, Nx will prompt for which e2e test runner to use. Select playwright or pass in the arg --e2eTestRunner=playwright

Terminal window
nx g @nx/web:app apps/frontend --e2eTestRunner=playwright

To generate an E2E project for an existing project, run the following generator

Terminal window
nx g @nx/playwright:configuration --project=your-app-name

The generator prompts for the web server option to add to the Playwright config. Pass --webServerCommand and --webServerAddress to skip the prompts.

Terminal window
nx g @nx/playwright:configuration --project=your-app-name --webServerCommand="npx nx serve your-project-name" --webServerAddress="http://localhost:4200"

Run nx e2e <your-app-name> to execute e2e tests with Playwright

By default, Playwright will run in headless mode. You will have the result of all the tests and errors (if any) in your terminal. Test output such as reports, screenshots, and videos will be accessible in dist/.playwright/apps/<your-app-name>/. This can be configured with the outputDir configuration options.

With, nx e2e frontend-e2e --ui Playwright will start in headed mode where you can see your application being tested.

From, there you can toggle on the watch icon which will rerun the tests when the spec file updates.

Terminal window
nx e2e <your-app-name> --ui

You can also use --headed flag to run Playwright where the browser can be seen without using the Playwright UI

The default generated Playwright configuration will contain a projects property that contains a list of browsers to run the tests against.

It should look similar to this:

export default defineConfig({
...,
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
},
{
name: "webkit",
use: { ...devices["Desktop Safari"] },
}
]
});

By default, Playwright will run tests against all browsers in the projects list.

You can specify a specific browser to run the tests against by passing the --project flag to the nx e2e command.

Terminal window
nx e2e frontend-e2e -- --project=firefox

The baseURL property within the Playwright configuration can control where the tests visit by default.

import { defineConfig } from '@playwright/test';
export default defineConfig({
// Rest of your config...
// Run your local dev server before starting the tests
webServer: {
command: 'npx nx serve <your-app-name>',
url: 'http://localhost:4200',
reuseExistingServer: true,
},
use: {
baseURL: 'http://localhost:4200', // url playwright visits with `await page.goto('/')`;
},
});

In order to set different baseURL values for different environments you can pass them via environment variables and Nx configurations or optionally via setting them per the environment they are needed in such as CI

import { defineConfig } from '@playwright/test';
const baseUrl =
process.env.BASE_URL ??
(process.env.CI
? 'https://some-staging-url.example.com'
: 'http://localhost:4200');
export default defineConfig({
// Rest of your config...
use: {
baseURL: baseUrl, // url playwright visits with `await page.goto('/')`;
},
});

Leave webServer out when the tests run against a deployed environment. There's no local server for Playwright to start, and pointing webServer.url at a URL that already answers makes Playwright fail unless reuseExistingServer is true.

By default Nx, provides a nxE2EPreset with predefined configuration for Playwright.

import { defineConfig } from '@playwright/test';
import { nxE2EPreset } from '@nx/playwright/preset';
import { workspaceRoot } from '@nx/devkit';
// For CI, you may want to set BASE_URL to the deployed application.
const baseURL = process.env['BASE_URL'] || 'http://localhost:4200';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
...nxE2EPreset(__filename, { testDir: './e2e' }),
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Run your local dev server before starting the tests */
webServer: {
command: 'npx nx serve <your-app-name>',
url: baseURL,
reuseExistingServer: true,
cwd: workspaceRoot,
},
});

This preset sets up the outputDir and HTML reporter to output in dist/.playwright/<path-to-project-root> and sets up chromium, firefox, webkit browsers to be used a browser targets. If you want to use mobile and/or branded browsers you can pass those options into the preset function

export default defineConfig({
...nxE2EPreset(__filename, {
testDir: './e2e',
includeMobileBrowsers: true, // includes mobile Chrome and Safari
includeBrandedBrowsers: true, // includes Google Chrome and Microsoft Edge
}),
// other settings
});

If you want to override any settings within the nxE2EPreset, You can define them after the preset like so

const config = nxE2EPreset(__filename, {
testDir: './e2e',
includeMobileBrowsers: true, // includes mobile Chrome and Safari
includeBrandedBrowsers: true, // includes Google Chrome and Microsoft Edge
});
export default defineConfig({
...config
retries: 3,
reporters: [...config.reporters, /* other reporter settings */],
});

See the Playwright configuration docs for more options for Playwright.

In CI, Nx runs nx affected to rebuild and retest only the projects a change touches, and caches results to skip repeated work.

For a complete pipeline, see Set up CI.