Commit 5d7d4aa63f9 for woocommerce
commit 5d7d4aa63f9de6def195a1be250fde16c7ecafdf
Author: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com>
Date: Tue Oct 20 11:26:38 2026 +0200
e2e tests: split Blocks e2e tests into blocks-parallel and blocks-serial projects (#69409)
* Split Blocks e2e tests into blocks-parallel and blocks-serial projects
* Add changelog entry for Blocks e2e project split
* Reduce Blocks e2e serial shards from 10 to 7
* Use 8 shards for Blocks e2e serial jobs
* Document the parallel and serial e2e projects for core and Blocks
diff --git a/plugins/woocommerce/changelog/dev-testops-231-blocks-e2e-parallel b/plugins/woocommerce/changelog/dev-testops-231-blocks-e2e-parallel
new file mode 100644
index 00000000000..d988a323ece
--- /dev/null
+++ b/plugins/woocommerce/changelog/dev-testops-231-blocks-e2e-parallel
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+Comment: Split Blocks e2e tests into serial and parallel Playwright projects; no production change.
+
diff --git a/plugins/woocommerce/client/blocks/CLAUDE.md b/plugins/woocommerce/client/blocks/CLAUDE.md
index 9186df66a39..009223eb142 100644
--- a/plugins/woocommerce/client/blocks/CLAUDE.md
+++ b/plugins/woocommerce/client/blocks/CLAUDE.md
@@ -217,6 +217,7 @@ Webpack writes directly to `plugins/woocommerce/assets/client/blocks/` so PHP en
### Playwright E2E Tests
- Config: `../../tests/e2e/playwright.config.ts` (Blocks e2e now lives in the core e2e suite)
+- Projects: `blocks-parallel` (default) and `blocks-serial` (specs in `blocksSerialSpecs`, database reset after each test). Write new specs parallel-safe, or use a test lock; add them to `blocksSerialSpecs` only as a last resort. See `../../tests/e2e/README.md#parallel-locked-and-serial-specs`.
- Test themes: `block-theme`, `classic-theme`, `block-theme-with-templates`
- Setup script: `../../tests/e2e/bin/blocks/test-env-setup.sh`
- Uses MSW for API mocking, Allure for reporting
diff --git a/plugins/woocommerce/client/blocks/docs/contributors/javascript-testing.md b/plugins/woocommerce/client/blocks/docs/contributors/javascript-testing.md
index e79c49c5f50..6c75ff2ef47 100644
--- a/plugins/woocommerce/client/blocks/docs/contributors/javascript-testing.md
+++ b/plugins/woocommerce/client/blocks/docs/contributors/javascript-testing.md
@@ -40,7 +40,8 @@ Additionally,
The Blocks end-to-end tests were merged into the WooCommerce Core e2e suite. They now
live at `plugins/woocommerce/tests/e2e/tests/blocks/` and run through the shared
-Playwright config (`tests/e2e/playwright.config.ts`, project `blocks-chromium`).
+Playwright config (`tests/e2e/playwright.config.ts`, projects `blocks-parallel` and
+`blocks-serial`).
From `plugins/woocommerce`:
@@ -48,10 +49,18 @@ From `plugins/woocommerce`:
# Start wp-env, run the Blocks test-env setup, and install the browser
pnpm env:start:blocks
-# Run the Blocks e2e suite
+# Run the Blocks e2e suite: blocks-parallel first, then blocks-serial
pnpm test:e2e:blocks
```
+Do not run both projects in one `playwright test` call. `blocks-serial` resets
+the database after each test, which breaks the tests that `blocks-parallel` runs
+at the same time.
+
+New specs run in `blocks-parallel` by default. Write them parallel-safe, or use
+a test lock. Add a spec to `blocksSerialSpecs` only when neither can work. See
+[Parallel, locked, and serial specs](../../../../tests/e2e/README.md#parallel-locked-and-serial-specs).
+
For the full setup and available environments, see the
[core e2e documentation](../../../../tests/e2e/README.md).
diff --git a/plugins/woocommerce/package.json b/plugins/woocommerce/package.json
index f0a63ec4b65..cef89fff8bf 100644
--- a/plugins/woocommerce/package.json
+++ b/plugins/woocommerce/package.json
@@ -77,8 +77,11 @@
"test:e2e:core-parallel": "pnpm test:e2e:default --project=core-parallel",
"test:e2e:default": "pnpm test:e2e:install && pnpm test:e2e:with-env default",
"test:e2e:install": "pnpm playwright install chromium",
- "test:e2e:blocks": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON --test tests/e2e/utils/blocks/*.test.mjs && pnpm playwright test --config=tests/e2e/playwright.config.ts --project=blocks-chromium",
- "test:e2e:blocks:unified-editor-assets": "pnpm wp-env:e2e run cli wp option update woocommerce_feature_block_editor_unified_assets_enabled yes && pnpm test:e2e:blocks",
+ "test:e2e:blocks": "pnpm test:e2e:blocks:parallel && pnpm test:e2e:blocks:serial",
+ "test:e2e:blocks:parallel": "node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON --test tests/e2e/utils/blocks/*.test.mjs && pnpm playwright test --config=tests/e2e/playwright.config.ts --project=blocks-parallel",
+ "test:e2e:blocks:serial": "pnpm playwright test --config=tests/e2e/playwright.config.ts --project=blocks-serial",
+ "test:e2e:blocks:unified-editor-assets:parallel": "pnpm wp-env:e2e run cli wp option update woocommerce_feature_block_editor_unified_assets_enabled yes && pnpm test:e2e:blocks:parallel",
+ "test:e2e:blocks:unified-editor-assets:serial": "pnpm wp-env:e2e run cli wp option update woocommerce_feature_block_editor_unified_assets_enabled yes && pnpm test:e2e:blocks:serial",
"test:e2e:blocks:performance": "pnpm playwright test --config=tests/e2e/playwright.performance.config.ts --project=blocks-performance",
"test:e2e:email-update-propagation:pr": "pnpm test:e2e:default --project=core-parallel --grep @pr tests/email-editor/update-propagation",
"test:e2e:email-update-propagation:nightly": "pnpm test:e2e:default --project=core-parallel tests/email-editor/update-propagation",
@@ -956,21 +959,67 @@
}
},
{
- "name": "Blocks e2e tests - PHP 8.3",
+ "name": "Blocks e2e tests - parallel - PHP 8.3",
"testType": "e2e",
"usesSharedPluginBuild": true,
- "command": "test:e2e:blocks",
+ "command": "test:e2e:blocks:parallel",
+ "shardingArguments": [],
+ "changes": [
+ "patterns/**/*.php",
+ "includes/**/*.php",
+ "src/Blocks/**/*.php",
+ "src/StoreApi/**/*.php",
+ "templates/**/*.php",
+ "templates/**/*.html",
+ "sample-data/sample_products.xml",
+ "tests/e2e/bin/**",
+ "tests/e2e/fixtures/blocks-setup.ts",
+ "tests/e2e/playwright.config.ts",
+ "tests/e2e/content-templates/blocks/**",
+ "tests/e2e/test-data/blocks/**",
+ "tests/e2e/test-data/images/**",
+ "tests/e2e/test-plugins/**",
+ "tests/e2e/tests/blocks/**",
+ "tests/e2e/themes/blocks/**",
+ "tests/e2e/utils/blocks/**",
+ ".wp-env.e2e.json"
+ ],
+ "onlyForDependencies": [
+ "@woocommerce/block-library"
+ ],
+ "testEnv": {
+ "start": "env:start:blocks",
+ "config": {
+ "phpVersion": "8.3"
+ }
+ },
+ "events": [
+ "pull_request",
+ "push",
+ "nightly-checks",
+ "release-checks",
+ "blocks-e2e"
+ ],
+ "report": {
+ "resultsBlobName": "blocks-e2e-report",
+ "resultsPath": "tests/e2e/test-results",
+ "allure": true
+ }
+ },
+ {
+ "name": "Blocks e2e tests - serial - PHP 8.3",
+ "testType": "e2e",
+ "usesSharedPluginBuild": true,
+ "command": "test:e2e:blocks:serial",
"shardingArguments": [
- "--shard=1/10",
- "--shard=2/10",
- "--shard=3/10",
- "--shard=4/10",
- "--shard=5/10",
- "--shard=6/10",
- "--shard=7/10",
- "--shard=8/10",
- "--shard=9/10",
- "--shard=10/10"
+ "--shard=1/8",
+ "--shard=2/8",
+ "--shard=3/8",
+ "--shard=4/8",
+ "--shard=5/8",
+ "--shard=6/8",
+ "--shard=7/8",
+ "--shard=8/8"
],
"changes": [
"patterns/**/*.php",
@@ -1015,21 +1064,44 @@
}
},
{
- "name": "Blocks e2e tests - PHP 7.4",
+ "name": "Blocks e2e tests - parallel - PHP 7.4",
"testType": "e2e",
"usesSharedPluginBuild": true,
- "command": "test:e2e:blocks",
+ "command": "test:e2e:blocks:parallel",
+ "shardingArguments": [],
+ "changes": [],
+ "onlyForDependencies": [
+ "@woocommerce/block-library"
+ ],
+ "testEnv": {
+ "start": "env:start:blocks",
+ "config": {
+ "phpVersion": "7.4"
+ }
+ },
+ "events": [
+ "nightly-checks"
+ ],
+ "report": {
+ "resultsBlobName": "blocks-e2e-report-php-7.4",
+ "resultsPath": "tests/e2e/test-results",
+ "allure": true
+ }
+ },
+ {
+ "name": "Blocks e2e tests - serial - PHP 7.4",
+ "testType": "e2e",
+ "usesSharedPluginBuild": true,
+ "command": "test:e2e:blocks:serial",
"shardingArguments": [
- "--shard=1/10",
- "--shard=2/10",
- "--shard=3/10",
- "--shard=4/10",
- "--shard=5/10",
- "--shard=6/10",
- "--shard=7/10",
- "--shard=8/10",
- "--shard=9/10",
- "--shard=10/10"
+ "--shard=1/8",
+ "--shard=2/8",
+ "--shard=3/8",
+ "--shard=4/8",
+ "--shard=5/8",
+ "--shard=6/8",
+ "--shard=7/8",
+ "--shard=8/8"
],
"changes": [],
"onlyForDependencies": [
@@ -1051,21 +1123,44 @@
}
},
{
- "name": "Blocks e2e tests - PHP 8.5",
+ "name": "Blocks e2e tests - parallel - PHP 8.5",
+ "testType": "e2e",
+ "usesSharedPluginBuild": true,
+ "command": "test:e2e:blocks:parallel",
+ "shardingArguments": [],
+ "changes": [],
+ "onlyForDependencies": [
+ "@woocommerce/block-library"
+ ],
+ "testEnv": {
+ "start": "env:start:blocks",
+ "config": {
+ "phpVersion": "8.5"
+ }
+ },
+ "events": [
+ "nightly-checks"
+ ],
+ "report": {
+ "resultsBlobName": "blocks-e2e-report-php-8.5",
+ "resultsPath": "tests/e2e/test-results",
+ "allure": true
+ }
+ },
+ {
+ "name": "Blocks e2e tests - serial - PHP 8.5",
"testType": "e2e",
"usesSharedPluginBuild": true,
- "command": "test:e2e:blocks",
+ "command": "test:e2e:blocks:serial",
"shardingArguments": [
- "--shard=1/10",
- "--shard=2/10",
- "--shard=3/10",
- "--shard=4/10",
- "--shard=5/10",
- "--shard=6/10",
- "--shard=7/10",
- "--shard=8/10",
- "--shard=9/10",
- "--shard=10/10"
+ "--shard=1/8",
+ "--shard=2/8",
+ "--shard=3/8",
+ "--shard=4/8",
+ "--shard=5/8",
+ "--shard=6/8",
+ "--shard=7/8",
+ "--shard=8/8"
],
"changes": [],
"onlyForDependencies": [
@@ -1087,21 +1182,61 @@
}
},
{
- "name": "Blocks e2e tests - unified editor assets - PHP 8.3",
+ "name": "Blocks e2e tests - unified editor assets - parallel - PHP 8.3",
"testType": "e2e",
"usesSharedPluginBuild": true,
- "command": "test:e2e:blocks:unified-editor-assets",
+ "command": "test:e2e:blocks:unified-editor-assets:parallel",
+ "shardingArguments": [],
+ "changes": [
+ "patterns/**/*.php",
+ "includes/**/*.php",
+ "src/Blocks/**/*.php",
+ "src/StoreApi/**/*.php",
+ "src/Internal/Features/BlockEditorUnifiedAssets.php",
+ "templates/**/*.php",
+ "templates/**/*.html",
+ "tests/e2e/bin/blocks/**",
+ "tests/e2e/fixtures/blocks-setup.ts",
+ "tests/e2e/playwright.config.ts",
+ "tests/e2e/content-templates/blocks/**",
+ "tests/e2e/test-data/blocks/**",
+ "tests/e2e/test-plugins/blocks/**",
+ "tests/e2e/tests/blocks/**",
+ "tests/e2e/themes/blocks/**",
+ "tests/e2e/utils/blocks/**"
+ ],
+ "onlyForDependencies": [
+ "@woocommerce/block-library"
+ ],
+ "testEnv": {
+ "start": "env:start:blocks",
+ "config": {
+ "phpVersion": "8.3"
+ }
+ },
+ "events": [
+ "nightly-checks"
+ ],
+ "report": {
+ "resultsBlobName": "blocks-e2e-unified-editor-assets-report",
+ "resultsPath": "tests/e2e/test-results",
+ "allure": true
+ }
+ },
+ {
+ "name": "Blocks e2e tests - unified editor assets - serial - PHP 8.3",
+ "testType": "e2e",
+ "usesSharedPluginBuild": true,
+ "command": "test:e2e:blocks:unified-editor-assets:serial",
"shardingArguments": [
- "--shard=1/10",
- "--shard=2/10",
- "--shard=3/10",
- "--shard=4/10",
- "--shard=5/10",
- "--shard=6/10",
- "--shard=7/10",
- "--shard=8/10",
- "--shard=9/10",
- "--shard=10/10"
+ "--shard=1/8",
+ "--shard=2/8",
+ "--shard=3/8",
+ "--shard=4/8",
+ "--shard=5/8",
+ "--shard=6/8",
+ "--shard=7/8",
+ "--shard=8/8"
],
"changes": [
"patterns/**/*.php",
@@ -1140,22 +1275,61 @@
}
},
{
- "name": "Blocks e2e tests - WP pre-release - PHP 8.3",
+ "name": "Blocks e2e tests - WP pre-release - parallel - PHP 8.3",
+ "optional": true,
+ "testType": "e2e",
+ "usesSharedPluginBuild": true,
+ "command": "test:e2e:blocks:parallel",
+ "shardingArguments": [],
+ "changes": [
+ "sample-data/sample_products.xml",
+ "tests/e2e/bin/**",
+ "tests/e2e/fixtures/blocks-setup.ts",
+ "tests/e2e/playwright.config.ts",
+ "tests/e2e/content-templates/blocks/**",
+ "tests/e2e/test-data/blocks/**",
+ "tests/e2e/test-data/images/**",
+ "tests/e2e/test-plugins/**",
+ "tests/e2e/tests/blocks/**",
+ "tests/e2e/themes/blocks/**",
+ "tests/e2e/utils/blocks/**",
+ ".wp-env.e2e.json"
+ ],
+ "onlyForDependencies": [],
+ "testEnv": {
+ "start": "env:start:blocks",
+ "config": {
+ "phpVersion": "8.3",
+ "wpVersion": "prerelease"
+ }
+ },
+ "events": [
+ "pull_request",
+ "nightly-checks",
+ "release-checks",
+ "blocks-e2e-wp-pre-release"
+ ],
+ "report": {
+ "resultsBlobName": "blocks-e2e-report-wp-pre-release",
+ "resultsPath": "tests/e2e/test-results",
+ "allure": true
+ }
+ },
+ {
+ "name": "Blocks e2e tests - WP pre-release - serial - PHP 8.3",
"optional": true,
"testType": "e2e",
"usesSharedPluginBuild": true,
- "command": "test:e2e:blocks",
+ "command": "test:e2e:blocks:serial",
"shardingArguments": [
- "--shard=1/10",
- "--shard=2/10",
- "--shard=3/10",
- "--shard=4/10",
- "--shard=5/10",
- "--shard=6/10",
- "--shard=7/10",
- "--shard=8/10",
- "--shard=9/10",
- "--shard=10/10"
+ "--shard=1/8",
+ "--shard=2/8",
+ "--shard=3/8",
+ "--shard=4/8",
+ "--shard=5/8",
+ "--shard=6/8",
+ "--shard=7/8",
+ "--shard=8/8"
],
"changes": [
"sample-data/sample_products.xml",
@@ -1192,21 +1366,59 @@
}
},
{
- "name": "Blocks e2e tests - WP latest-1 - PHP 8.3",
+ "name": "Blocks e2e tests - WP latest-1 - parallel - PHP 8.3",
+ "testType": "e2e",
+ "usesSharedPluginBuild": true,
+ "command": "test:e2e:blocks:parallel",
+ "shardingArguments": [],
+ "changes": [
+ "sample-data/sample_products.xml",
+ "tests/e2e/bin/**",
+ "tests/e2e/fixtures/blocks-setup.ts",
+ "tests/e2e/playwright.config.ts",
+ "tests/e2e/content-templates/blocks/**",
+ "tests/e2e/test-data/blocks/**",
+ "tests/e2e/test-data/images/**",
+ "tests/e2e/test-plugins/**",
+ "tests/e2e/tests/blocks/**",
+ "tests/e2e/themes/blocks/**",
+ "tests/e2e/utils/blocks/**",
+ ".wp-env.e2e.json"
+ ],
+ "onlyForDependencies": [],
+ "testEnv": {
+ "start": "env:start:blocks",
+ "config": {
+ "phpVersion": "8.3",
+ "wpVersion": "latest-1"
+ }
+ },
+ "events": [
+ "pull_request",
+ "nightly-checks",
+ "release-checks",
+ "blocks-e2e-wp-latest-1"
+ ],
+ "report": {
+ "resultsBlobName": "blocks-e2e-report-wp-latest-1",
+ "resultsPath": "tests/e2e/test-results",
+ "allure": true
+ }
+ },
+ {
+ "name": "Blocks e2e tests - WP latest-1 - serial - PHP 8.3",
"testType": "e2e",
"usesSharedPluginBuild": true,
- "command": "test:e2e:blocks",
+ "command": "test:e2e:blocks:serial",
"shardingArguments": [
- "--shard=1/10",
- "--shard=2/10",
- "--shard=3/10",
- "--shard=4/10",
- "--shard=5/10",
- "--shard=6/10",
- "--shard=7/10",
- "--shard=8/10",
- "--shard=9/10",
- "--shard=10/10"
+ "--shard=1/8",
+ "--shard=2/8",
+ "--shard=3/8",
+ "--shard=4/8",
+ "--shard=5/8",
+ "--shard=6/8",
+ "--shard=7/8",
+ "--shard=8/8"
],
"changes": [
"sample-data/sample_products.xml",
diff --git a/plugins/woocommerce/tests/e2e/README.md b/plugins/woocommerce/tests/e2e/README.md
index c51733c32ec..511a80ea0dd 100644
--- a/plugins/woocommerce/tests/e2e/README.md
+++ b/plugins/woocommerce/tests/e2e/README.md
@@ -179,10 +179,23 @@ read: [Playwright Best Practices](https://playwright.dev/docs/best-practices).
### Parallel, locked, and serial specs
-Core specs run on one shared site, in two Playwright projects: `core-parallel` runs specs in several workers at the same time, and `core-serial` runs them one at a time. Put each spec in one of three groups:
+Core and Blocks specs each run in two Playwright projects on one shared site. The parallel project runs specs in several workers at the same time. The serial project runs them one at a time, in one worker.
-1. **Parallel.** The spec does not change site-wide state. It makes its own products, orders, customers, and pages, and does not change shared settings. This is the default: every spec runs in `core-parallel` unless something else is set.
-2. **Parallel with a lock.** The spec changes a site-wide option, but only specs that change the same option read it. Give all those specs the same [test lock](https://playwright.dev/docs/test-parallel#test-locks) from `locks` in `fixtures/fixtures.ts`. Specs that share a lock never run at the same time, in any worker or project. Add a new entry to `locks` if none fits.
+| Project | Specs | Workers | After each test | Command |
+| --- | --- | --- | --- | --- |
+| `core-parallel` | Core specs not in `serialRunSpecs` | Several | Nothing | `pnpm test:e2e:core-parallel` |
+| `core-serial` | Core specs in `serialRunSpecs` | 1 | Nothing | `pnpm test:e2e:core-serial` |
+| `blocks-parallel` | Blocks specs not in `blocksSerialSpecs` | Several | Nothing | `pnpm test:e2e:blocks:parallel` |
+| `blocks-serial` | Blocks specs in `blocksSerialSpecs` | 1 | Database reset | `pnpm test:e2e:blocks:serial` |
+
+Both lists are in `playwright.config.ts`. A spec that is not on a list runs in the parallel project.
+
+Run one project at a time, as CI does: each project runs in its own CI jobs. A serial spec changes state that parallel specs read, and the `blocks-serial` database reset deletes the data of the tests that run in parallel. `pnpm test:e2e:blocks` runs `blocks-parallel` first, then `blocks-serial`.
+
+Put each new spec in the first of these three types that works for it:
+
+1. **Parallel.** The spec does not change site-wide state. It makes its own products, orders, customers, pages, and templates, with unique names, and does not change shared settings. It cleans up what it makes, because `core-parallel` and `blocks-parallel` do not reset the database.
+2. **Parallel with a lock.** The spec changes a site-wide option, but only specs that change the same option read it. Give all those specs the same [test lock](https://playwright.dev/docs/test-parallel#test-locks) from `locks` in `fixtures/fixtures.ts`. Specs that share a lock never run at the same time, in any worker or project. Add a new entry to `locks` if none fits. Set the option back in `afterEach` or `afterAll`.
```ts
import { test, locks } from '../../fixtures/fixtures';
@@ -192,11 +205,11 @@ Core specs run on one shared site, in two Playwright projects: `core-parallel` r
} );
```
- The core projects do not use `fullyParallel`, so one worker runs a whole spec file. A lock on one test holds for the whole file, including `beforeAll` and `afterAll`.
+ The projects do not use `fullyParallel`, so one worker runs a whole spec file. A lock on one test holds for the whole file, including `beforeAll` and `afterAll`. Blocks specs import `locks` from the same file.
-3. **Serial.** The spec changes a setting that many other specs read, such as tax, store address, or permalinks. A lock cannot help here, because the specs that read the setting do not take the lock. Add the spec to `serialRunSpecs` in `playwright.config.ts`, so it runs in `core-serial`.
+3. **Serial.** Use this type only when the first two cannot work: the spec changes a setting that many other specs read, such as tax, store address, permalinks, the active theme, or a site-wide template. A lock cannot help here, because the specs that read the setting do not take the lock. Add the spec to `serialRunSpecs` or `blocksSerialSpecs`, under the comment that gives the reason.
-Prefer the first group. A spec that changes a setting only for itself can often use its own data instead, for example its own tax class or customer.
+A spec that changes a setting only for itself can often use its own data instead, for example its own tax class, customer, product, or template. Each serial spec makes the serial project slower and adds to the CI time of every pull request.
### Gotchas
diff --git a/plugins/woocommerce/tests/e2e/bin/blocks/test-env-setup.sh b/plugins/woocommerce/tests/e2e/bin/blocks/test-env-setup.sh
index c7630ba0ad1..65ebbe01442 100755
--- a/plugins/woocommerce/tests/e2e/bin/blocks/test-env-setup.sh
+++ b/plugins/woocommerce/tests/e2e/bin/blocks/test-env-setup.sh
@@ -17,12 +17,17 @@ $wp_cli -- rm -f blocks_e2e.sql
$wp_cli -- bash wp-content/plugins/woocommerce/blocks-bin/playwright/scripts/index.sh
# Disable the LYS Coming Soon banner.
$wp_cli -- wp option update woocommerce_coming_soon 'no'
-# Dismiss the site editor welcome guide for the admin user so it does not
-# block interactions during tests. The preference is stored in user meta and
-# will be included in the database snapshot that is restored between tests.
+# Dismiss the editor welcome guides for the admin user so they do not block
+# interactions during tests. The preferences are stored in user meta and will
+# be included in the database snapshot that is restored between tests. Each
+# editor tab saves the whole preferences object, so a guide dismissed only at
+# runtime can be overwritten by another parallel worker's tab.
$wp_cli -- wp eval '
$prefs = get_user_meta( 1, "wp_persisted_preferences", true );
if ( ! is_array( $prefs ) ) { $prefs = array(); }
+if ( ! isset( $prefs["core/edit-post"] ) ) { $prefs["core/edit-post"] = array(); }
+$prefs["core/edit-post"]["welcomeGuide"] = false;
+$prefs["core/edit-post"]["fullscreenMode"] = false;
if ( ! isset( $prefs["core/edit-site"] ) ) { $prefs["core/edit-site"] = array(); }
$prefs["core/edit-site"]["welcomeGuide"] = false;
$prefs["core/edit-site"]["welcomeGuideStyles"] = false;
diff --git a/plugins/woocommerce/tests/e2e/playwright.config.ts b/plugins/woocommerce/tests/e2e/playwright.config.ts
index 0d6bb7881a3..3fb4a77ffb1 100644
--- a/plugins/woocommerce/tests/e2e/playwright.config.ts
+++ b/plugins/woocommerce/tests/e2e/playwright.config.ts
@@ -175,7 +175,113 @@ const nonCoreSpecs = [
'**/tests/blocks/**',
];
-export default defineConfig( {
+/**
+ * Blocks specs that must run serially in `blocks-serial`, which resets the
+ * database after each test. Every other blocks spec runs in `blocks-parallel`
+ * by default, without that reset, against a site that other workers use at the
+ * same time.
+ *
+ * A parallel spec must clean up what it creates and must not change state that
+ * other specs read, unless it shares a `locks` entry (see `fixtures/fixtures.ts`)
+ * with every spec that reads that state.
+ *
+ * Never run `blocks-serial` and `blocks-parallel` in the same invocation: the
+ * serial resets wipe the data of the parallel workers.
+ */
+const blocksSerialSpecs = [
+ // Switch the active theme, which every other spec renders with.
+ '**/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.block_theme_with_templates.spec.ts',
+ '**/tests/blocks/cart/cart-checkout-block-notices.shopper.block_theme.spec.ts',
+ '**/tests/blocks/cart/cart-checkout-block-notices.shopper.classic_theme.spec.ts',
+ '**/tests/blocks/mini-cart/mini-cart.classic_theme.spec.ts',
+ '**/tests/blocks/product-button/product-button.classic_theme.spec.ts',
+ '**/tests/blocks/style.classic_theme.spec.ts',
+ '**/tests/blocks/templates/single-product-template.block_theme_with_templates.spec.ts',
+ '**/tests/blocks/templates/template-customization.block_theme.spec.ts',
+ '**/tests/blocks/templates/template-customization.block_theme_with_templates.spec.ts',
+ '**/tests/blocks/templates/template-part-customization.classic_theme_with_template_parts.spec.ts',
+ '**/tests/blocks/templates/template-part-customization.classic_theme_with_template_parts_support.spec.ts',
+ '**/tests/blocks/templates/template-priority.block_theme.spec.ts',
+ '**/tests/blocks/widget-area/widget-area.classic_theme.spec.ts',
+
+ // Save site-wide templates, template parts or pages (single product, product
+ // archive, header, cart, checkout, order confirmation), or the
+ // `wc_blocks_use_blockified_product_grid_block_as_template` option. Every
+ // spec that visits those pages reads them.
+ '**/tests/blocks/add-to-cart-form/add-to-cart-form.block_theme.spec.ts',
+ '**/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.block_theme.spec.ts',
+ '**/tests/blocks/all-products/all-products.block_theme.spec.ts',
+ '**/tests/blocks/attributes-filter/attribute-filter.block_theme.spec.ts',
+ '**/tests/blocks/cart-store/cart-line-identity.block_theme.spec.ts',
+ '**/tests/blocks/checkout/checkout-block.merchant.block_theme.spec.ts',
+ '**/tests/blocks/classic-template/classic-template.block_theme.spec.ts',
+ '**/tests/blocks/mini-cart/mini-cart-block.shopper.block_theme.spec.ts',
+ '**/tests/blocks/on-sale-badge/on-sale-badge-single-product-template.block_theme.spec.ts',
+ '**/tests/blocks/page-content-wrapper/page-content-wrapper.block_theme.spec.ts',
+ '**/tests/blocks/price-filter/price-filter.block_theme.spec.ts',
+ '**/tests/blocks/product-collection/product-collection.block_theme.spec.ts',
+ '**/tests/blocks/product-filters/active-filter-frontend.block_theme.spec.ts',
+ '**/tests/blocks/product-filters/attribute-filter-frontend.block_theme.spec.ts',
+ '**/tests/blocks/product-filters/product-filters-frontend.block_theme.spec.ts',
+ '**/tests/blocks/product-gallery/inner-blocks/product-gallery-large-image/product-gallery-large-image.block_theme.spec.ts',
+ '**/tests/blocks/product-gallery/inner-blocks/product-gallery-thumbnails/product-gallery-thumbnails.block_theme.spec.ts',
+ '**/tests/blocks/product-gallery/product-gallery.block_theme.spec.ts',
+ '**/tests/blocks/products/products.block_theme.spec.ts',
+ '**/tests/blocks/rating-filter/rating-filter.block_theme.spec.ts',
+ '**/tests/blocks/stock-filter/stock-filter.block_theme.spec.ts',
+ '**/tests/blocks/templates/legacy-templates.block_theme.spec.ts',
+ '**/tests/blocks/templates/order-confirmation.block_theme.spec.ts',
+ '**/tests/blocks/templates/single-product-template.block_theme.spec.ts',
+
+ // Activate test plugins that change every cart, checkout or product page, or
+ // race other specs on the `active_plugins` option.
+ '**/tests/blocks/cart/cart-block.shopper.block_theme.spec.ts',
+ '**/tests/blocks/cart/cart-checkout-block-extension-callbacks.shopper.block_theme.spec.ts',
+ '**/tests/blocks/cart/cart-store.block_theme.spec.ts',
+ '**/tests/blocks/checkout/additional-fields.guest-shopper.block_theme.spec.ts',
+ '**/tests/blocks/checkout/additional-fields.merchant.block_theme.spec.ts',
+ '**/tests/blocks/checkout/additional-fields.shopper.block_theme.spec.ts',
+ '**/tests/blocks/checkout/checkout-block-custom-place-order-button.block_theme.spec.ts',
+ '**/tests/blocks/checkout/checkout-block-extensibility.shopper.block_theme.spec.ts',
+ '**/tests/blocks/checkout/checkout-block-locale-hide-country.block_theme.spec.ts',
+ '**/tests/blocks/mini-cart/mini-cart.block_theme.spec.ts',
+ '**/tests/blocks/product-button/product-button.block_theme.spec.ts',
+ '**/tests/blocks/product-collection/compatibility-layer.block_theme.spec.ts',
+ '**/tests/blocks/product-collection/product-picker.block_theme.spec.ts',
+ '**/tests/blocks/product-collection/register-product-collection.block_theme.spec.ts',
+ '**/tests/blocks/single-product-template/single-product-template-compatibility-layer.spec.ts',
+
+ // Change global settings that cart, checkout and storefront specs read:
+ // shipping, taxes, local pickup, account creation, site language, the shop
+ // page slug, product reviews and feature flags.
+ '**/tests/blocks/cart/cart-checkout-block-shipping.block_theme.spec.ts',
+ '**/tests/blocks/cart/cart-checkout-block-taxes.shopper.block_theme.spec.ts',
+ '**/tests/blocks/cart/cart-checkout-block-translations.shopper.block_theme.spec.ts',
+ '**/tests/blocks/checkout/checkout-block.shopper.block_theme.spec.ts',
+ '**/tests/blocks/checkout/order-confirmation.block_theme.spec.ts',
+ '**/tests/blocks/local-pickup/local-pickup.merchant.block_theme.spec.ts',
+ '**/tests/blocks/product-collection/inspector-controls.block_theme.spec.ts',
+ '**/tests/blocks/single-product-template/single-product-template.product-rating.spec.ts',
+ '**/tests/blocks/templates/shop-page.block_theme.spec.ts',
+
+ // Add to the cart as the admin user, whose cart all workers share.
+ '**/tests/blocks/cart-store/mutation-batcher.block_theme.spec.ts',
+ '**/tests/blocks/cart/cart-checkout-block-coupons.shopper.block_theme.spec.ts',
+
+ // Create or edit products and categories that catalog specs count.
+ '**/tests/blocks/featured-category/featured-category.block_theme.spec.ts',
+ '**/tests/blocks/featured-product/featured-product.block_theme.spec.ts',
+ '**/tests/blocks/product-collection/product-collection-errors.block_theme.spec.ts',
+
+ // Create a template or pattern with a fixed slug or name, which collides
+ // with other specs or with a retry.
+ '**/tests/blocks/breadcrumbs/breadcrumbs.block_theme.spec.ts',
+ '**/tests/blocks/catalog-sorting/catalog-sorting.block_theme.spec.ts',
+ '**/tests/blocks/patterns/add-new-pattern.block_theme.spec.ts',
+ '**/tests/blocks/product-results-count/product-results-count.block_theme.spec.ts',
+];
+
+export default defineConfig< { resetDatabaseAfterEachTest: boolean } >( {
timeout: 120 * 1000,
expect: { timeout: CI ? 20 * 1000 : 10 * 1000 },
outputDir: TESTS_RESULTS_PATH,
@@ -231,8 +337,9 @@ export default defineConfig( {
workers: 1,
},
{
- name: 'blocks-chromium',
+ name: 'blocks-serial',
testDir: `${ TESTS_ROOT_PATH }/tests/blocks`,
+ testMatch: blocksSerialSpecs,
dependencies: [ 'blocks setup' ],
workers: 1,
use: {
@@ -240,5 +347,16 @@ export default defineConfig( {
storageState: BLOCKS_ADMIN_STATE,
},
},
+ {
+ name: 'blocks-parallel',
+ testDir: `${ TESTS_ROOT_PATH }/tests/blocks`,
+ testIgnore: blocksSerialSpecs,
+ dependencies: [ 'blocks setup' ],
+ use: {
+ ...devices[ 'Desktop Chrome' ],
+ storageState: BLOCKS_ADMIN_STATE,
+ resetDatabaseAfterEachTest: false,
+ },
+ },
],
} );
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.page.ts b/plugins/woocommerce/tests/e2e/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.page.ts
index e9393b1d148..da29c33cc86 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.page.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/add-to-cart-with-options/add-to-cart-with-options.page.ts
@@ -126,6 +126,14 @@ class AddToCartWithOptionsPage {
const addToCartFormBlock = await this.editor.getBlockByName(
'woocommerce/add-to-cart-form'
);
+ const addToCartWithOptionsBlock = await this.editor.getBlockByName(
+ 'woocommerce/add-to-cart-with-options'
+ );
+ // `isVisible()` does not wait, so wait for the canvas to render either
+ // block first.
+ await expect(
+ addToCartFormBlock.or( addToCartWithOptionsBlock ).first()
+ ).toBeVisible();
if ( await addToCartFormBlock.isVisible() ) {
await this.editor.selectBlocks( addToCartFormBlock );
diff --git a/plugins/woocommerce/tests/e2e/utils/blocks/admin/index.ts b/plugins/woocommerce/tests/e2e/utils/blocks/admin/index.ts
index 5d407882de4..b6cef503837 100644
--- a/plugins/woocommerce/tests/e2e/utils/blocks/admin/index.ts
+++ b/plugins/woocommerce/tests/e2e/utils/blocks/admin/index.ts
@@ -27,6 +27,34 @@ export class Admin extends CoreAdmin {
}: AdminConstructorProps ) {
super( { page, pageUtils, editor } );
this.wpCoreVersion = wpCoreVersion;
+
+ // The editors load the settings sidebar state from the admin user's
+ // preferences, which every parallel worker shares and saves. Open it
+ // on load so a sidebar closed in another worker does not leak into
+ // this test. Core Admin binds these helpers in its constructor, so
+ // they are wrapped here instead of overridden as methods.
+ const { createNewPost, editPost, visitSiteEditor } = this;
+ this.createNewPost = async ( ...args ) => {
+ await createNewPost.call( this, ...args );
+ await this.openSettingsSidebar();
+ };
+ this.editPost = async ( ...args ) => {
+ await editPost.call( this, ...args );
+ await this.openSettingsSidebar();
+ };
+ this.visitSiteEditor = async ( ...args ) => {
+ await visitSiteEditor.call( this, ...args );
+ await this.openSettingsSidebar();
+ };
+ }
+
+ private async openSettingsSidebar() {
+ await this.page.waitForFunction( () => window?.wp?.data );
+ await this.page.evaluate( () =>
+ window.wp.data
+ .dispatch( 'core/preferences' )
+ .set( 'core', 'isComplementaryAreaVisible', true )
+ );
}
async visitWidgetEditor() {
diff --git a/plugins/woocommerce/tests/e2e/utils/blocks/test.ts b/plugins/woocommerce/tests/e2e/utils/blocks/test.ts
index a6458e52ac3..d13531aa7ac 100644
--- a/plugins/woocommerce/tests/e2e/utils/blocks/test.ts
+++ b/plugins/woocommerce/tests/e2e/utils/blocks/test.ts
@@ -117,6 +117,7 @@ const test = base.extend<
shippingUtils: ShippingUtils;
localPickupUtils: LocalPickupUtils;
miniCartUtils: MiniCartUtils;
+ resetDatabaseAfterEachTest: boolean;
},
{
requestUtils: RequestUtils;
@@ -129,7 +130,10 @@ const test = base.extend<
editor: async ( { page, wpCoreVersion }, use ) => {
await use( new Editor( { page, wpCoreVersion } ) );
},
- page: async ( { page }, use ) => {
+ // Workers share one site, so a project that runs specs in parallel must turn
+ // this off: one worker's reset would wipe the data of the others.
+ resetDatabaseAfterEachTest: [ true, { option: true } ],
+ page: async ( { page, resetDatabaseAfterEachTest }, use ) => {
page.on( 'console', observeConsoleLogging );
await use( page );
@@ -148,24 +152,26 @@ const test = base.extend<
// Dispose the current APIRequestContext to free up resources.
await page.request.dispose();
- // Navigate away before resetting the DB so the page stops issuing
- // Store API requests against a half-dropped database. Otherwise late
- // in-flight fetches are served the WordPress install page (HTTP 200,
- // text/html) and surface as "The response is not a valid JSON
- // response." console noise.
- try {
- await page.goto( 'about:blank' );
- } catch ( error ) {
- // Ignore errors if page is already closed/navigated away.
- // eslint-disable-next-line no-console
- console.log(
- 'Failed to navigate away before DB reset:',
- error.message
- );
- }
+ if ( resetDatabaseAfterEachTest ) {
+ // Navigate away before resetting the DB so the page stops issuing
+ // Store API requests against a half-dropped database. Otherwise late
+ // in-flight fetches are served the WordPress install page (HTTP 200,
+ // text/html) and surface as "The response is not a valid JSON
+ // response." console noise.
+ try {
+ await page.goto( 'about:blank' );
+ } catch ( error ) {
+ // Ignore errors if page is already closed/navigated away.
+ // eslint-disable-next-line no-console
+ console.log(
+ 'Failed to navigate away before DB reset:',
+ error.message
+ );
+ }
- // Reset the database to the initial state via snapshot import.
- await restoreBlocksDatabase( DB_EXPORT_FILE );
+ // Reset the database to the initial state via snapshot import.
+ await restoreBlocksDatabase( DB_EXPORT_FILE );
+ }
},
pageUtils: async ( { page }, use ) => {
await use( new PageUtils( { page } ) );