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

Setting Up @nx/playwright

Installation

Keep Nx Package Versions In Sync

Make sure to install the @nx/playwright version that matches the version of nx in your repository. If the version numbers get out of sync, you can encounter some difficult to debug errors. You can fix Nx version mismatches with this recipe.

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

nx add @nx/playwright

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

How @nx/playwright Infers Tasks

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

View Inferred Tasks

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.

@nx/playwright Configuration

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

nx.json
1{ 2 "plugins": [ 3 { 4 "plugin": "@nx/playwright/plugin", 5 "options": { 6 "ciTargetName": "e2e-ci", 7 "targetName": "e2e" 8 } 9 } 10 ] 11} 12

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

Splitting E2E Tests

The @nx/playwright/plugin will automatically split your e2e tasks by file if you provide a ciTargetName. You can read more about the Atomizer feature here. This will create a target with that name which can be used in CI to run the tests for each file in a distributed fashion.

nx.json
1{ 2 "plugins": [ 3 { 4 "plugin": "@nx/playwright/plugin", 5 "options": { 6 "targetName": "e2e", 7 "ciTargetName": "e2e-ci" 8 } 9 } 10 ] 11} 12

Splitting E2E tasks by file

The @nx/playwright/plugin will automatically split your e2e tasks by file. You can read more about this feature here.

E2E Testing

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

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

Add Playwright e2e to an existing project

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

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

Optionally, you can use the --webServerCommand and --webServerAddress option, to auto setup the web server option in the playwright config

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

Testing Applications

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

Selecting Specific Specs

You can use the --grep/-g flag to glob for test files. You can use the --grepInvert/-gv flag to glob for files to not run.

1# run the tests in the feat-a/ directory 2nx e2e frontend-e2e --grep="**feat-a/**" 3 4# run everything except feat-a/ directory 5nx e2e frontend-e2e --grepInvert=**feat-a/** 6

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.

Output Caching

If changing the output directory or report output, make sure to update the target outputs so the artifacts are correctly cached

Watching for Changes

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.

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

Specifying a Base Url

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

1import { defineConfig } from '@playwright/test'; 2 3export default defineConfig({ 4 // Rest of your config... 5 6 // Run your local dev server before starting the tests 7 webServer: { 8 command: 'npx serve <your-app-name>', 9 url: 'http://localhost:4200', 10 reuseExistingServer: !process.env.CI, 11 }, 12 use: { 13 baseURL: 'http://localhost:4200', // url playwright visits with `await page.goto('/')`; 14 }, 15}); 16

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

1import { defineConfig } from '@playwright/test'; 2 3const baseUrl = 4 process.env.BASE_URL ?? process.env.CI 5 ? 'https://some-staging-url.example.com' 6 : 'http://localhost:4200'; 7 8export default defineConfig({ 9 // Rest of your config... 10 11 // Run your local dev server before starting the tests 12 webServer: { 13 command: 'npx serve <your-app-name>', 14 url: baseUrl, 15 reuseExistingServer: !process.env.CI, 16 }, 17 use: { 18 baseURL: baseUrl, // url playwright visits with `await page.goto('/')`; 19 }, 20}); 21

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

1import { defineConfig } from '@playwright/test'; 2import { nxE2EPreset } from '@nx/playwright/preset'; 3import { workspaceRoot } from '@nx/devkit'; 4 5// For CI, you may want to set BASE_URL to the deployed application. 6const baseURL = process.env['BASE_URL'] || 'http://localhost:4200'; 7 8/** 9 * Read environment variables from file. 10 * https://github.com/motdotla/dotenv 11 */ 12// require('dotenv').config(); 13 14/** 15 * See https://playwright.dev/docs/test-configuration. 16 */ 17export default defineConfig({ 18 ...nxE2EPreset(__filename, { testDir: './e2e' }), 19 /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ 20 use: { 21 baseURL, 22 /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ 23 trace: 'on-first-retry', 24 }, 25 /* Run your local dev server before starting the tests */ 26 webServer: { 27 command: 'npx nx serve <your-app-name>', 28 url: baseURL, 29 reuseExistingServer: !process.env.CI, 30 cwd: workspaceRoot, 31 }, 32}); 33

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

1export default defineConfig({ 2 ...nxE2EPreset(__filename, { 3 testDir: './e2e', 4 includeMobileBrowsers: true, // includes mobile Chrome and Safari 5 includeBrandedBrowsers: true, // includes Google Chrome and Microsoft Edge 6 }), 7 // other settings 8}); 9

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

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

See the Playwright configuration docs for more options for Playwright.