From 80e14c8f4155a6b704d855a1608f18573b79c106 Mon Sep 17 00:00:00 2001 From: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com> Date: Mon, 26 Oct 2026 19:20:48 +0200 Subject: [PATCH 1/5] Build/Test Tools: Run E2E specs in parallel and serial projects. The E2E suite runs on one worker. Split it into two Playwright projects: - `parallel` runs 15 spec files on several workers. - `serial` runs the 6 specs that break the site for other tests, on one worker. Each project has its own npm script. CI runs each project in a separate matrix job, so a failure in one project does not hide the results of the other. --- .../workflows/reusable-end-to-end-tests.yml | 12 ++++++--- package.json | 4 ++- tests/e2e/README.md | 2 +- tests/e2e/playwright.config.js | 27 ++++++++++++++++++- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/.github/workflows/reusable-end-to-end-tests.yml b/.github/workflows/reusable-end-to-end-tests.yml index 54bd6b4230fab..3aee407e0ed78 100644 --- a/.github/workflows/reusable-end-to-end-tests.yml +++ b/.github/workflows/reusable-end-to-end-tests.yml @@ -62,11 +62,16 @@ jobs: # - Uploads screenshots and HTML snapshots as an artifact. # - Ensures version-controlled files are not modified or deleted. e2e-tests: - name: SCRIPT_DEBUG ${{ inputs.LOCAL_SCRIPT_DEBUG && 'enabled' || 'disabled' }} + name: ${{ matrix.project }} / SCRIPT_DEBUG ${{ inputs.LOCAL_SCRIPT_DEBUG && 'enabled' || 'disabled' }} runs-on: ubuntu-24.04 permissions: contents: read timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + # See the "Projects" section in tests/e2e/README.md. + project: [ 'parallel', 'serial' ] steps: - name: Configure environment variables @@ -147,8 +152,9 @@ jobs: npm run env:cli -- language theme install de_DE --all --path="/var/www/${LOCAL_DIR}" - name: Run E2E tests - run: npm run test:e2e + run: npm run "test:e2e:${PROJECT}" env: + PROJECT: ${{ matrix.project }} # Chromium is installed above and is the only browser the suite runs. Without this, # `wp-scripts test-playwright` also downloads Firefox and WebKit on every run. PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: ${{ inputs.install-playwright && '1' || '' }} @@ -157,7 +163,7 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: always() with: - name: failures-artifacts${{ inputs.LOCAL_SCRIPT_DEBUG && '-SCRIPT_DEBUG' || '' }}-${{ github.run_id }} + name: failures-artifacts-${{ matrix.project }}${{ inputs.LOCAL_SCRIPT_DEBUG && '-SCRIPT_DEBUG' || '' }}-${{ github.run_id }} path: artifacts if-no-files-found: ignore include-hidden-files: true diff --git a/package.json b/package.json index ab44fd105f344..f5b6e0beaf82e 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,9 @@ "test:performance": "wp-scripts test-playwright --config tests/performance/playwright.config.js", "test:php": "node ./tools/local-env/scripts/docker.js run --rm php ./vendor/bin/phpunit", "test:coverage": "npm run test:php -- --coverage-html ./coverage/html/ --coverage-php ./coverage/php/report.php --coverage-text=./coverage/text/report.txt", - "test:e2e": "wp-scripts test-playwright --config tests/e2e/playwright.config.js", + "test:e2e": "npm run test:e2e:parallel && npm run test:e2e:serial", + "test:e2e:parallel": "wp-scripts test-playwright --config tests/e2e/playwright.config.js --project=parallel", + "test:e2e:serial": "wp-scripts test-playwright --config tests/e2e/playwright.config.js --project=serial", "test:visual": "wp-scripts test-playwright --config tests/visual-regression/playwright.config.js", "typecheck:php": "node ./tools/local-env/scripts/docker.js run --rm php composer phpstan --", "typecheck:php:baselines": "node ./tools/local-env/scripts/docker.js run --rm php composer phpstan:baselines --", diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 23eb8016710af..a628611ec5379 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -1 +1 @@ -# E2E Tests End-To-End (E2E) tests for WordPress. ## Running the tests The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`. If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md). Then you can launch the tests by running: ``` npm run test:e2e ``` which will run the test suite using a headless browser. If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this: ``` WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e ``` **DO NOT run these tests in an actual production environment, as they will delete all your content.** For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode: ``` npm run test:e2e -- --ui ``` [UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. You can also run a single test file separately: ``` npm run test:e2e tests/e2e/specs/hello.test.js ``` ## Documentation * Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing * Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright * Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json) \ No newline at end of file +# E2E Tests End-To-End (E2E) tests for WordPress. ## Running the tests The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`. If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md). Then you can launch the tests by running: ``` npm run test:e2e ``` which will run the test suite using a headless browser. If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this: ``` WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e ``` **DO NOT run these tests in an actual production environment, as they will delete all your content.** For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode: ``` npm run test:e2e -- --ui ``` [UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. You can also run a single test file separately: ``` npm run test:e2e tests/e2e/specs/hello.test.js ``` ## Projects The suite has two Playwright projects, defined in `playwright.config.js`. `npm run test:e2e` runs `parallel`, then `serial`. * `parallel` (`npm run test:e2e:parallel`): most specs. Spec files run at the same time on several workers (4 in CI, half the CPU cores locally). Tests inside one file still run in order. * `serial` (`npm run test:e2e:serial`): specs that break the site for other tests. They run one at a time on one worker. The serial specs, listed in `SERIAL_SPECS`: * `install.test.js` rewrites `wp-config.php` and drops the database tables. * `maintenance-mode.test.js` writes a `.maintenance` file, so every request returns the maintenance page. * `fatal-error-handler.test.js` installs a must-use plugin that causes a fatal error on every request. * `login-localize-script.test.js` installs a must-use plugin in the same directory as the spec above. * `gutenberg-plugin.test.js` activates and deactivates the Gutenberg plugin for the whole site. * `plugins.test.js` installs a plugin under a fixed slug and fails if another run installed it first. New specs go in `parallel` by default. Add a spec to `SERIAL_SPECS` only if it makes the site unusable for other tests, or if it owns a site-wide resource that a lock cannot share. ## Documentation * Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing * Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright * Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json) \ No newline at end of file diff --git a/tests/e2e/playwright.config.js b/tests/e2e/playwright.config.js index 0de694e324c24..3df5f528de9e4 100644 --- a/tests/e2e/playwright.config.js +++ b/tests/e2e/playwright.config.js @@ -2,7 +2,7 @@ * External dependencies */ import path from 'node:path'; -import { defineConfig } from '@playwright/test'; +import { defineConfig, devices } from '@playwright/test'; /** * WordPress dependencies @@ -15,6 +15,15 @@ process.env.STORAGE_STATE_PATH ??= path.join( 'storage-states/admin.json' ); +const SERIAL_SPECS = [ + 'install.test.js', + 'maintenance-mode.test.js', + 'fatal-error-handler.test.js', + 'login-localize-script.test.js', + 'gutenberg-plugin.test.js', + 'plugins.test.js', +]; + const config = defineConfig( { ...baseConfig, globalSetup: require.resolve( './config/global-setup.js' ), @@ -22,6 +31,22 @@ const config = defineConfig( { ...baseConfig.webServer, command: 'npm run env:start', }, + projects: [ + { + name: 'parallel', + testIgnore: SERIAL_SPECS, + fullyParallel: false, + workers: process.env.CI ? 4 : '50%', + use: { ...devices[ 'Desktop Chrome' ] }, + }, + { + name: 'serial', + testMatch: SERIAL_SPECS, + fullyParallel: false, + workers: 1, + use: { ...devices[ 'Desktop Chrome' ] }, + }, + ], } ); export default config; From 1875ba056d9ac2bbebbcaf34972b8eef13eeff24 Mon Sep 17 00:00:00 2001 From: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com> Date: Mon, 26 Oct 2026 19:53:09 +0200 Subject: [PATCH 2/5] Build/Test Tools: Run more E2E specs serially and use 50% workers. The base config from `@wordpress/scripts` sets `workers: 1` for the whole run, so the `parallel` project ran on one worker. Set `workers: '50%'` at the top level. This is the Playwright default. Move the 7 specs that delete all posts or media to `serial`. On several workers, they delete content that tests on other workers use. --- tests/e2e/README.md | 2 +- tests/e2e/playwright.config.js | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/e2e/README.md b/tests/e2e/README.md index a628611ec5379..831d265e19ada 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -1 +1 @@ -# E2E Tests End-To-End (E2E) tests for WordPress. ## Running the tests The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`. If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md). Then you can launch the tests by running: ``` npm run test:e2e ``` which will run the test suite using a headless browser. If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this: ``` WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e ``` **DO NOT run these tests in an actual production environment, as they will delete all your content.** For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode: ``` npm run test:e2e -- --ui ``` [UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. You can also run a single test file separately: ``` npm run test:e2e tests/e2e/specs/hello.test.js ``` ## Projects The suite has two Playwright projects, defined in `playwright.config.js`. `npm run test:e2e` runs `parallel`, then `serial`. * `parallel` (`npm run test:e2e:parallel`): most specs. Spec files run at the same time on several workers (4 in CI, half the CPU cores locally). Tests inside one file still run in order. * `serial` (`npm run test:e2e:serial`): specs that break the site for other tests. They run one at a time on one worker. The serial specs, listed in `SERIAL_SPECS`: * `install.test.js` rewrites `wp-config.php` and drops the database tables. * `maintenance-mode.test.js` writes a `.maintenance` file, so every request returns the maintenance page. * `fatal-error-handler.test.js` installs a must-use plugin that causes a fatal error on every request. * `login-localize-script.test.js` installs a must-use plugin in the same directory as the spec above. * `gutenberg-plugin.test.js` activates and deactivates the Gutenberg plugin for the whole site. * `plugins.test.js` installs a plugin under a fixed slug and fails if another run installed it first. New specs go in `parallel` by default. Add a spec to `SERIAL_SPECS` only if it makes the site unusable for other tests, or if it owns a site-wide resource that a lock cannot share. ## Documentation * Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing * Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright * Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json) \ No newline at end of file +# E2E Tests End-To-End (E2E) tests for WordPress. ## Running the tests The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`. If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md). Then you can launch the tests by running: ``` npm run test:e2e ``` which will run the test suite using a headless browser. If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this: ``` WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e ``` **DO NOT run these tests in an actual production environment, as they will delete all your content.** For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode: ``` npm run test:e2e -- --ui ``` [UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. You can also run a single test file separately: ``` npm run test:e2e tests/e2e/specs/hello.test.js ``` ## Projects The suite has two Playwright projects, defined in `playwright.config.js`. `npm run test:e2e` runs `parallel`, then `serial`. * `parallel` (`npm run test:e2e:parallel`): specs that can share the site with other tests. Spec files run at the same time on several workers, one for every two CPU cores. Tests inside one file still run in order. * `serial` (`npm run test:e2e:serial`): specs that break the site for other tests. They run one at a time on one worker. New specs go in `parallel` by default. Add a spec to `SERIAL_SPECS` only if it makes the site unusable for other tests, or if it changes content or settings that other tests use, for example with `requestUtils.deleteAllPosts()`. ## Documentation * Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing * Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright * Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json) \ No newline at end of file diff --git a/tests/e2e/playwright.config.js b/tests/e2e/playwright.config.js index 3df5f528de9e4..70bb90fb58c6f 100644 --- a/tests/e2e/playwright.config.js +++ b/tests/e2e/playwright.config.js @@ -22,11 +22,20 @@ const SERIAL_SPECS = [ 'login-localize-script.test.js', 'gutenberg-plugin.test.js', 'plugins.test.js', + // These delete all posts or media, including other workers' content. + 'cache-control-headers-directives.test.js', + 'dashboard.test.js', + 'edit-posts.test.js', + 'empty-trash-restore-trashed-posts.test.js', + 'media-library-client-side-upload.test.js', + 'media-modal-client-side-upload.test.js', + 'media-new-client-side-upload.test.js', ]; const config = defineConfig( { ...baseConfig, globalSetup: require.resolve( './config/global-setup.js' ), + workers: '50%', webServer: { ...baseConfig.webServer, command: 'npm run env:start', @@ -36,7 +45,6 @@ const config = defineConfig( { name: 'parallel', testIgnore: SERIAL_SPECS, fullyParallel: false, - workers: process.env.CI ? 4 : '50%', use: { ...devices[ 'Desktop Chrome' ] }, }, { From 74b67024ad2fea05336e1b580f7165c7c0767b76 Mon Sep 17 00:00:00 2001 From: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com> Date: Tue, 27 Oct 2026 14:30:00 +0200 Subject: [PATCH 3/5] Build/Test Tools: Keep `npm run test:e2e` serial with a default `all` project. Add an `all` project that runs every spec on one worker. It is the only default project, so `npm run test:e2e` runs the whole suite serially, as before. Set `default: false` on `parallel` and `serial`, which needs Playwright 1.64. CI selects them with `--project`, so the two npm scripts are no longer needed. Move `themes.test.js` to `serial`, because it changes the active theme for the whole site. --- .github/workflows/reusable-end-to-end-tests.yml | 2 +- package.json | 4 +--- tests/e2e/README.md | 2 +- tests/e2e/playwright.config.js | 9 +++++++++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/reusable-end-to-end-tests.yml b/.github/workflows/reusable-end-to-end-tests.yml index 3aee407e0ed78..6d0616e762076 100644 --- a/.github/workflows/reusable-end-to-end-tests.yml +++ b/.github/workflows/reusable-end-to-end-tests.yml @@ -152,7 +152,7 @@ jobs: npm run env:cli -- language theme install de_DE --all --path="/var/www/${LOCAL_DIR}" - name: Run E2E tests - run: npm run "test:e2e:${PROJECT}" + run: npm run test:e2e -- --project="${PROJECT}" env: PROJECT: ${{ matrix.project }} # Chromium is installed above and is the only browser the suite runs. Without this, diff --git a/package.json b/package.json index ae4882ede8e0f..e8329333dd6b1 100644 --- a/package.json +++ b/package.json @@ -153,9 +153,7 @@ "test:performance": "wp-scripts test-playwright --config tests/performance/playwright.config.js", "test:php": "node ./tools/local-env/scripts/docker.js run --rm php ./vendor/bin/phpunit", "test:coverage": "npm run test:php -- --coverage-html ./coverage/html/ --coverage-php ./coverage/php/report.php --coverage-text=./coverage/text/report.txt", - "test:e2e": "npm run test:e2e:parallel && npm run test:e2e:serial", - "test:e2e:parallel": "wp-scripts test-playwright --config tests/e2e/playwright.config.js --project=parallel", - "test:e2e:serial": "wp-scripts test-playwright --config tests/e2e/playwright.config.js --project=serial", + "test:e2e": "wp-scripts test-playwright --config tests/e2e/playwright.config.js", "test:visual": "wp-scripts test-playwright --config tests/visual-regression/playwright.config.js", "typecheck:php": "node ./tools/local-env/scripts/docker.js run --rm php composer phpstan --", "typecheck:php:baselines": "node ./tools/local-env/scripts/docker.js run --rm php composer phpstan:baselines --", diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 831d265e19ada..bc72f733ccf22 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -1 +1 @@ -# E2E Tests End-To-End (E2E) tests for WordPress. ## Running the tests The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`. If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md). Then you can launch the tests by running: ``` npm run test:e2e ``` which will run the test suite using a headless browser. If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this: ``` WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e ``` **DO NOT run these tests in an actual production environment, as they will delete all your content.** For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode: ``` npm run test:e2e -- --ui ``` [UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. You can also run a single test file separately: ``` npm run test:e2e tests/e2e/specs/hello.test.js ``` ## Projects The suite has two Playwright projects, defined in `playwright.config.js`. `npm run test:e2e` runs `parallel`, then `serial`. * `parallel` (`npm run test:e2e:parallel`): specs that can share the site with other tests. Spec files run at the same time on several workers, one for every two CPU cores. Tests inside one file still run in order. * `serial` (`npm run test:e2e:serial`): specs that break the site for other tests. They run one at a time on one worker. New specs go in `parallel` by default. Add a spec to `SERIAL_SPECS` only if it makes the site unusable for other tests, or if it changes content or settings that other tests use, for example with `requestUtils.deleteAllPosts()`. ## Documentation * Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing * Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright * Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json) \ No newline at end of file +# E2E Tests End-To-End (E2E) tests for WordPress. ## Running the tests The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`. If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md). Then you can launch the tests by running: ``` npm run test:e2e ``` which will run the test suite using a headless browser. If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this: ``` WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e ``` **DO NOT run these tests in an actual production environment, as they will delete all your content.** For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode: ``` npm run test:e2e -- --ui ``` [UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. You can also run a single test file separately: ``` npm run test:e2e tests/e2e/specs/hello.test.js ``` ## Projects The suite has three Playwright projects, defined in `playwright.config.js`: * `all`: every spec, one at a time on one worker. `npm run test:e2e` runs this project. * `parallel`: specs that can share the site with other tests. Spec files run at the same time on several workers, one for every two CPU cores. Tests inside one file still run in order. Run it with `npm run test:e2e -- --project=parallel`. * `serial`: specs that break the site for other tests. They run one at a time on one worker. Run it with `npm run test:e2e -- --project=serial`. CI runs `parallel` and `serial` in separate jobs. New specs go in `parallel` by default. Add a spec to `SERIAL_SPECS` only if it makes the site unusable for other tests, or if it changes content or settings that other tests use, for example with `requestUtils.deleteAllPosts()`. ## Documentation * Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing * Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright * Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json) \ No newline at end of file diff --git a/tests/e2e/playwright.config.js b/tests/e2e/playwright.config.js index 70bb90fb58c6f..d9441043d4049 100644 --- a/tests/e2e/playwright.config.js +++ b/tests/e2e/playwright.config.js @@ -22,6 +22,7 @@ const SERIAL_SPECS = [ 'login-localize-script.test.js', 'gutenberg-plugin.test.js', 'plugins.test.js', + 'themes.test.js', // These delete all posts or media, including other workers' content. 'cache-control-headers-directives.test.js', 'dashboard.test.js', @@ -41,14 +42,22 @@ const config = defineConfig( { command: 'npm run env:start', }, projects: [ + { + name: 'all', + fullyParallel: false, + workers: 1, + use: { ...devices[ 'Desktop Chrome' ] }, + }, { name: 'parallel', + default: false, testIgnore: SERIAL_SPECS, fullyParallel: false, use: { ...devices[ 'Desktop Chrome' ] }, }, { name: 'serial', + default: false, testMatch: SERIAL_SPECS, fullyParallel: false, workers: 1, From c415f68074c6359107f004cac2502d5f6035d974 Mon Sep 17 00:00:00 2001 From: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com> Date: Tue, 27 Oct 2026 15:23:40 +0200 Subject: [PATCH 4/5] Build/Test Tools: Move the E2E project matrix to the calling workflow. Release branches call the `trunk` copy of the reusable E2E workflow, and their Playwright configs have no `parallel` or `serial` project. Add a `test-group` input to the reusable workflow. When it is empty, the workflow runs `npm run test:e2e` as before. `end-to-end-tests.yml` sets it from its own matrix. Document `--shuffle` in the E2E README as a check for new specs. --- .github/workflows/end-to-end-tests.yml | 3 +++ .../workflows/reusable-end-to-end-tests.yml | 23 +++++++++++-------- tests/e2e/README.md | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/end-to-end-tests.yml b/.github/workflows/end-to-end-tests.yml index e249f6e25475c..9e03641b978fd 100644 --- a/.github/workflows/end-to-end-tests.yml +++ b/.github/workflows/end-to-end-tests.yml @@ -82,10 +82,13 @@ jobs: fail-fast: false matrix: LOCAL_SCRIPT_DEBUG: [ true, false ] + # See the "Projects" section in tests/e2e/README.md. + test-group: [ 'parallel', 'serial' ] # A matrix value is needed in the 'name' directive for proper grouping in the GitHub UI. label: [ 'E2E Tests' ] with: LOCAL_SCRIPT_DEBUG: ${{ matrix.LOCAL_SCRIPT_DEBUG }} + test-group: ${{ matrix.test-group }} slack-notifications: name: Slack Notifications diff --git a/.github/workflows/reusable-end-to-end-tests.yml b/.github/workflows/reusable-end-to-end-tests.yml index 6d0616e762076..73c4a3bc5954d 100644 --- a/.github/workflows/reusable-end-to-end-tests.yml +++ b/.github/workflows/reusable-end-to-end-tests.yml @@ -32,6 +32,11 @@ on: required: false type: 'boolean' default: true + test-group: + description: 'The Playwright project to run. Runs the default projects when empty.' + required: false + type: 'string' + default: '' env: LOCAL_DIR: build @@ -62,16 +67,11 @@ jobs: # - Uploads screenshots and HTML snapshots as an artifact. # - Ensures version-controlled files are not modified or deleted. e2e-tests: - name: ${{ matrix.project }} / SCRIPT_DEBUG ${{ inputs.LOCAL_SCRIPT_DEBUG && 'enabled' || 'disabled' }} + name: ${{ inputs.test-group && format( '{0} / ', inputs.test-group ) || '' }}SCRIPT_DEBUG ${{ inputs.LOCAL_SCRIPT_DEBUG && 'enabled' || 'disabled' }} runs-on: ubuntu-24.04 permissions: contents: read timeout-minutes: 20 - strategy: - fail-fast: false - matrix: - # See the "Projects" section in tests/e2e/README.md. - project: [ 'parallel', 'serial' ] steps: - name: Configure environment variables @@ -152,9 +152,14 @@ jobs: npm run env:cli -- language theme install de_DE --all --path="/var/www/${LOCAL_DIR}" - name: Run E2E tests - run: npm run test:e2e -- --project="${PROJECT}" + run: | + if [ -n "${TEST_GROUP}" ]; then + npm run test:e2e -- --project="${TEST_GROUP}" + else + npm run test:e2e + fi env: - PROJECT: ${{ matrix.project }} + TEST_GROUP: ${{ inputs.test-group }} # Chromium is installed above and is the only browser the suite runs. Without this, # `wp-scripts test-playwright` also downloads Firefox and WebKit on every run. PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: ${{ inputs.install-playwright && '1' || '' }} @@ -163,7 +168,7 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: always() with: - name: failures-artifacts-${{ matrix.project }}${{ inputs.LOCAL_SCRIPT_DEBUG && '-SCRIPT_DEBUG' || '' }}-${{ github.run_id }} + name: failures-artifacts${{ inputs.test-group && format( '-{0}', inputs.test-group ) || '' }}${{ inputs.LOCAL_SCRIPT_DEBUG && '-SCRIPT_DEBUG' || '' }}-${{ github.run_id }} path: artifacts if-no-files-found: ignore include-hidden-files: true diff --git a/tests/e2e/README.md b/tests/e2e/README.md index bc72f733ccf22..597ac99896bd8 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -1 +1 @@ -# E2E Tests End-To-End (E2E) tests for WordPress. ## Running the tests The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`. If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md). Then you can launch the tests by running: ``` npm run test:e2e ``` which will run the test suite using a headless browser. If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this: ``` WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e ``` **DO NOT run these tests in an actual production environment, as they will delete all your content.** For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode: ``` npm run test:e2e -- --ui ``` [UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. You can also run a single test file separately: ``` npm run test:e2e tests/e2e/specs/hello.test.js ``` ## Projects The suite has three Playwright projects, defined in `playwright.config.js`: * `all`: every spec, one at a time on one worker. `npm run test:e2e` runs this project. * `parallel`: specs that can share the site with other tests. Spec files run at the same time on several workers, one for every two CPU cores. Tests inside one file still run in order. Run it with `npm run test:e2e -- --project=parallel`. * `serial`: specs that break the site for other tests. They run one at a time on one worker. Run it with `npm run test:e2e -- --project=serial`. CI runs `parallel` and `serial` in separate jobs. New specs go in `parallel` by default. Add a spec to `SERIAL_SPECS` only if it makes the site unusable for other tests, or if it changes content or settings that other tests use, for example with `requestUtils.deleteAllPosts()`. ## Documentation * Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing * Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright * Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json) \ No newline at end of file +# E2E Tests End-To-End (E2E) tests for WordPress. ## Running the tests The e2e tests require a production-like environment to run. By default, they will assume an environment is available at `http://localhost:8889`, with username `admin` and password `password`. If you don't already have an environment ready, you can set one up by following [these instructions](https://github.com/WordPress/wordpress-develop/blob/master/README.md). Then you can launch the tests by running: ``` npm run test:e2e ``` which will run the test suite using a headless browser. If your environment has a different url, username or password to the default, you can provide the base URL, username and password like this: ``` WP_BASE_URL=http://mycustomurl WP_USERNAME=username WP_PASSWORD=password npm run test:e2e ``` **DO NOT run these tests in an actual production environment, as they will delete all your content.** For debugging purposes, you might want to follow the test visually. You can do so by running the tests in an interactive mode: ``` npm run test:e2e -- --ui ``` [UI Mode](https://playwright.dev/docs/test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. You can also run a single test file separately: ``` npm run test:e2e tests/e2e/specs/hello.test.js ``` ## Projects The suite has three Playwright projects, defined in `playwright.config.js`: * `all`: every spec, one at a time on one worker. `npm run test:e2e` runs this project. * `parallel`: specs that can share the site with other tests. Spec files run at the same time on several workers, one for every two CPU cores. Tests inside one file still run in order. Run it with `npm run test:e2e -- --project=parallel`. * `serial`: specs that break the site for other tests. They run one at a time on one worker. Run it with `npm run test:e2e -- --project=serial`. CI runs `parallel` and `serial` in separate jobs. New specs go in `parallel` by default. Add a spec to `SERIAL_SPECS` only if it makes the site unusable for other tests, or if it changes content or settings that other tests use, for example with `requestUtils.deleteAllPosts()`. Before you open a pull request with a new spec, run its project a few times with `--shuffle`. Playwright then runs the spec files in a random order, so a spec that needs another spec to run first, or that breaks a spec that runs after it, fails: ``` npm run test:e2e -- --project=parallel --shuffle ``` Playwright prints the seed of each run, for example `shuffle seed 317753389`. To run the same order again, give the seed: `--shuffle 317753389`. ## Documentation * Block Editor Handbook end to end testing overview: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/#end-to-end-testing * Gutenberg e2e-test-utils-playwright package API docs: https://github.com/WordPress/gutenberg/tree/trunk/packages/e2e-test-utils-playwright * Playwright API docs: https://playwright.dev/docs (the version we are using is indicated in the `@wordpress/scripts` package: https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/package.json) \ No newline at end of file From eceda2e925ed81d2c6ec2f3ad55e59ea10535671 Mon Sep 17 00:00:00 2001 From: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com> Date: Tue, 27 Oct 2026 16:41:33 +0200 Subject: [PATCH 5/5] Build/Test Tools: Show the E2E project name in the job list of the run page. See #66392. --- .github/workflows/reusable-end-to-end-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-end-to-end-tests.yml b/.github/workflows/reusable-end-to-end-tests.yml index 73c4a3bc5954d..40db644c5a2d6 100644 --- a/.github/workflows/reusable-end-to-end-tests.yml +++ b/.github/workflows/reusable-end-to-end-tests.yml @@ -67,7 +67,7 @@ jobs: # - Uploads screenshots and HTML snapshots as an artifact. # - Ensures version-controlled files are not modified or deleted. e2e-tests: - name: ${{ inputs.test-group && format( '{0} / ', inputs.test-group ) || '' }}SCRIPT_DEBUG ${{ inputs.LOCAL_SCRIPT_DEBUG && 'enabled' || 'disabled' }} + name: ${{ inputs.test-group && format( '{0}, ', inputs.test-group ) || '' }}SCRIPT_DEBUG ${{ inputs.LOCAL_SCRIPT_DEBUG && 'enabled' || 'disabled' }} runs-on: ubuntu-24.04 permissions: contents: read