Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

165 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wp-media-e2e

End-to-end tests for WP Media products (WP Rocket, BackWPup), on Playwright + playwright-bdd (Cucumber/Gherkin). ESM, Node 24, TypeScript 6 (strict). Design: docs/plans/e2e-modernization-plan.md.

Quick start

npm install          # also downloads Chromium (see "Browsers")
E2E_CELL=apache npm run test:wp-rocket

A fresh checkout has no sites.json / sites.*.json, so placeholder data is used: the auth setup is skipped and the @noauth smoke scenarios pass, proving the harness is wired. --grep @noauth runs only those (what CI does); anything else needs a real WordPress.

Concepts

  • Product — wp-rocket / backwpup, each with its features, steps, sites and (BackWPup only) service credentials; configs in src/projects/<product>/config/.
  • Cell — a named environment (apache, nginx, pro@nginx): the merged top-level keys of a product's sites files.
  • Pool — a cell's interchangeable WordPress sites; each worker binds to one by parallelIndex, spreading scenarios over the pool.
  • Run unit — one (product × cell). Run exactly one cell per invocation, pinned with E2E_CELL=<cell>; two cells at once fail fast (the global parallelIndex would overflow the smaller pool — execution-model.md).

Running

E2E_CELL=<cell> npm run test:wp-rocket     # one product, one cell
E2E_CELL=<cell> npm run test:backwpup
E2E_CELL=apache npm run test:wp-rocket -- --grep @smoke

E2E_CELL pins bddgen, the runner and its workers to one cell (the config holds it alone), so bddgen regenerates only its specs and runs of different cells of one product can go side by side. --project=<cell> also runs one cell, but bddgen never sees it and deletes and regenerates every cell's specs, breaking another run of the product started beside it. Each run prints a [cell] line before Running …: its cell, how it was chosen, its workers and report folder. A pin naming no cell of the product, or a --project selecting none of the pinned cell's projects, fails at once naming E2E_CELL. With a pin, --project narrows within the cell (--project=artifacts:<cell> resolves its zips only).

Never set E2E_CELL in .env: read from the working directory, it would pin every run started there. A command-line --reporter replaces the configured reporters, the [cell] line with them.

Health check

npm run healthcheck       # headless
npm run healthcheck:ui    # same checks, browser visible (watch a login, debug a flaky site)

Checks every configured site across all products, cells and pools (healthcheck.ts): transport, WP-CLI, a real installed WordPress, a working UI login. Output is grouped per product; each site is checked independently and printed as soon as it finishes (✔/✖/⚠), listing every check it ran, with the failing check and a hint on failure. A placeholder-only cell is skipped, not failed. Exits 0 only when every real site passed, else 1 (fit for CI or cron). Tune with HEALTHCHECK_CONCURRENCY / HEALTHCHECK_LOGIN_TIMEOUT_MS.

Orchestrator (cells in loops)

Runs cells on this machine in loops (a run, a cooldown, the next) and reports each run to Slack and Datator. Every option goes after --.

mkdir -p .orchestrator && chmod 700 .orchestrator
cp orchestrator/config.example.json .orchestrator/config.json && chmod 600 .orchestrator/config.json
# edit it: one task per cell, the secrets, Slack's webhook, Datator's key
npm run orchestrator -- start --dry-run              # check it; runs and writes nothing
npm run orchestrator -- start --task <id> --once     # one run, exit 0 (passed/flaky), 1, or 130 if stopped
tmux new -d -s orchestrator 'npm run orchestrator -- start'   # every task, until stopped
tmux send-keys -t orchestrator C-c                   # stop: runs finish their scenario

Install, config fields, stopping, kept files, refusals: docs/guides/orchestrator.md.

Configuring sites

Sites are declared in git-ignored JSON files (they hold credentials) under src/projects/<product>/config/: sites.json plus any sites.<name>.json overlays (sites.docker.json, sites.ssh.json, …), merged alphabetically; each file owns disjoint cells (a cell in two files is a hard error). With none, the committed sites.example.json (placeholder .example.test data) is used, so a fresh checkout still loads and passes the @noauth smoke.

cp src/projects/wp-rocket/config/sites.example.json src/projects/wp-rocket/config/sites.json

Credentials live only in sites files and never enter Playwright reports. Schema: configuration.md.

Environment

Copy .env.example to .env and fill what you need (BackWPup storage credentials, optional runtime flags). Real environment variables always win; E2E_LOAD_DOTENV=false in the environment skips the file.

Browsers

npm install downloads Chromium via postinstall; the committed .npmrc sets ignore-scripts=false so it runs even where install scripts are disabled globally. If browsers are missing: npm run setup (playwright install chromium).

Local WordPress (Docker) — the docker transport

docker/ runs two independent installs over one MariaDB — Apache on :8100, Nginx (php-fpm) on :8101 — each with a kept-alive wp-cli container the suite drives via docker exec.

npm run env:up      # start containers + install both sites (idempotent); needs the Docker daemon
npm run env:down    # stop and remove everything (incl. volumes)
npm run env:logs    # tail container logs

# point a product at it
cp docker/sites.example.json src/projects/wp-rocket/config/sites.docker.json
E2E_CELL=apache npm run test:wp-rocket    # or E2E_CELL=nginx

The cells use transport: { mode: "docker", container: "wpme-wpcli-apache" | "wpme-wpcli-nginx" } (the compose container_names). Sites are installed as admin / admin_password.

Reporting

Each run writes reports/<product>/<cell>/<RUN_ID>/:

  • playwright/ — Playwright's HTML report: trace viewer, video, screenshots. Open the newest with npm run report (-- <product> <cell> to target one), or one with npx playwright show-report reports/<product>/<cell>/<RUN_ID>/playwright.
  • cucumber/ — the Gherkin report: one portable HTML, screenshots/video embedded on failure; REPORT_MODE=rich makes it external with the trace viewer embedded (serve over http, not file://).
  • allure-results/ — raw results for Allure (history/trends, flaky detection, dashboard).
  • results.jsonl — every attempt and the totals, one JSON line each, written as the run goes: what a script watches and what the orchestrator reads at the end. Schema: results-schema.ts.
  • run-facts.json — what the run tested: the plugin (ref, full commit, zip, SHA-256), each site's WordPress, PHP, web server and database, the run's name and verdict. Rewritten as each setup ends, so a killed run's still says what it had ("status": "running").

Every report says up front what it tested, in one line — backwpup · pro@nginx (pro) · BackWPup Pro 9.99.99 · develop @ 1dceea8966 · WordPress 7.1.3 · PHP 8.5.11 64bit · <run>, plus RUNNING, INTERRUPTED, STOPPED, COULD NOT TEST or NO TESTS (which the reports cannot say themselves) — as the Playwright report's title (every fact in its Metadata panel, with #?show-metadata-other in the URL), a banner above the Cucumber report (expand it for every fact), and the Allure report's name and Metadata. An unknown fact says why (site unknown: auth setup failed). E2E_RUN_NAME names the run and E2E_REQUESTED_REF shows the ref asked for (both display only); a PLAYWRIGHT_HTML_TITLE you set wins.

The run ends with a summary below everything: the verdict (✘ COULD NOT TEST when a setup failed, ■ STOPPED when stopped), counts, the plugin and sites tested, how to open each report, and which old reports it pruned.

Old reports are pruned as each run ends, for its cell only: at most E2E_REPORTS_KEEP (20; 0 lifts the cap, not the age rules), none older than 30 days except the cell's newest complete report, kept up to 182 days. Prune a cell that no longer runs by hand:

npm run report:prune                                   # dry run: every report, its decision and why
npm run report:prune -- --apply                        # remove what the policy says goes
npm run report:prune -- --product backwpup --cell pro@nginx --keep 5 --older-than 2w --apply

Allure, from the newest run:

npm run report:allure                              # newest run of any cell
npm run report:allure -- wp-rocket apache          # a specific product/cell
npm run report:allure -- wp-rocket apache --open   # generate and serve in the browser

It lands in reports/<product>/<cell>/<RUN_ID>/allure/, named by the run's facts line. Trends accumulate via a per-cell reports/<product>/<cell>/allure-history.jsonl, so the trend chart fills from the second run; flaky tests are flagged per run from retries. Content (categories, widgets, single-file output) is set in allurerc.mjs.

Visual regression

Visual checks assert a page renders the same with optimizations active as bypassed (?nowprocket), i.e. lazy-load, CSS/JS handling etc. don't break it visually. Both renders are captured live in one run and pixel-diffed against each other (no baseline), via src/common/visual/ab.ts:

import { expectOptimizedToMatchUnoptimized } from "../../../common/visual/ab";

await expectOptimizedToMatchUnoptimized(page, "/pricing");
await expectOptimizedToMatchUnoptimized(page, "/pricing", {
  mask: [page.locator(".ad-slot")], // ignore regions that legitimately differ
  maxDiffPixelRatio: 0.02, // loosen tolerance for this page
});

It loads the bypassed and the optimized page, stabilises each (scrolls to load lazy media, waits for fonts) and fails if they differ beyond tolerance, attaching both renders and a highlighted diff. A size difference fails too (a layout change is a regression). Tolerances: src/common/config/visual.ts. Tag such scenarios @visual to run them as a group, and run them in the Playwright container image for pixel-deterministic rendering:

E2E_CELL=apache npm run test:wp-rocket -- --grep @visual

Quality gates

npm run typecheck    # tsc --noEmit
npm run lint         # eslint .
npm run format:check # prettier --check .
npm run test:unit    # unit/integration specs

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages