Skip to content

Repository files navigation

@abovomaxlead/playwright-am-e2e

Shared Playwright end-to-end base tests for Abovo websites. One place to fix a smoke test that every site runs.

Why registrar functions and not spec files

Playwright neither transpiles TypeScript nor discovers spec files inside node_modules. A package therefore cannot ship tests that the runner picks up on its own. Instead it exports functions that register tests, and each project keeps a tiny spec file that calls the ones it wants.

Install

In a project's tests/e2e/package.json:

{
  "private": true,
  "dependencies": {
    "@abovomaxlead/playwright-am-e2e": "git+https://github.com/abovowebdevelopment/playwright-am-e2e#semver:^1.0.0"
  },
  "allowScripts": {
    "github:abovowebdevelopment/playwright-am-e2e": true
  }
}

Keep @playwright/test pinned exactly to the version in the am-dev-playwright image tag: bin/e2e compares the two and warns on drift, and an exact pin is also what stops npm update from moving Playwright.

Tags must be three-part (v1.0.0). #semver: matches only valid semver tags — a two-part tag such as 1.0 matches nothing and silently falls back to main.

Usage

tests/e2e/base.spec.ts:

import { testHomepageLoads } from '@abovomaxlead/playwright-am-e2e/global';
import { testThemeAssetsLoad } from '@abovomaxlead/playwright-am-e2e/wordpress/abovo-basis';

testHomepageLoads();
testThemeAssetsLoad();

tests/e2e/playwright.config.ts:

import { defineE2EConfig } from '@abovomaxlead/playwright-am-e2e/config';

export default defineE2EConfig();

Project-specific tests import the harness rather than @playwright/test, which gets them the screenshot-path fixture:

import { expect, test } from '@abovomaxlead/playwright-am-e2e';

Entry points

Specifier Contents
@abovomaxlead/playwright-am-e2e test, expect, and the Page, Response, Locator, BrowserContext types
@abovomaxlead/playwright-am-e2e/config defineE2EConfig()
@abovomaxlead/playwright-am-e2e/global testHomepageLoads() — platform-agnostic
@abovomaxlead/playwright-am-e2e/wordpress/abovo-basis testThemeAssetsLoad(), ABOVO_BASIS_THEME_ASSETS
@abovomaxlead/playwright-am-e2e/summary-reporter SummaryReporter — wired in by defineE2EConfig() automatically; only needed as a specifier because Playwright resolves reporters by module path

Anything not listed is internal and may change in a patch release.

Run directories

Every run gets its own directory: test-results/<runId>/, where runId is YYYYMMDD-HHMMSS (UTC) — lexicographic sort equals chronological sort. Layout:

test-results/
  20260817-104213/
    artifacts/       <- Playwright's outputDir (traces, videos, per-test dirs)
    html-report/     <- HTML reporter (a sibling of artifacts/, not nested in
                         it — Playwright refuses an HTML report folder inside
                         outputDir)
    screenshots/      <- the screenshot fixture's relative-path target
    results.json      <- Playwright's JSON reporter output
    summary.json       <- compact machine-readable summary (see below)
  20260817-102960/
  ...

bin/e2e (in dev-infra) generates the run id and passes it as E2E_RUN_ID. For standalone use (npx playwright test without the wrapper), defineE2EConfig() generates one itself and writes it into process.env at config load, in the main process, before Playwright forks any workers — every worker inherits it, so a single run never scatters across several directories. See src/internal/run-id.ts for the reasoning and how it was verified against 2+ workers.

Retention. Old run directories are pruned automatically on every run, keeping the newest E2E_KEEP_RUNS (default 3) by name — not by age. Only direct children of test-results/ whose name matches the run-id pattern exactly are ever considered, symlinks are never followed, and the current run is never deleted. See src/internal/retention.ts.

summary.json contents: pass/fail/skip counts, total duration in milliseconds, the base URL, the environment tag, the run's start timestamp, and the Playwright version.

Screenshot sandbox. page.screenshot({ path }) (via this package's test fixture) is sandboxed into the run directory:

  • a relative path lands in <run>/screenshots/<path>
  • a path with a leading slash is anchored at the run directory's root: /sub/b.jpg -> <run>/sub/b.jpg
  • a path that would escape the run directory (e.g. via ..) throws, rather than writing outside it

This is a behaviour change from 1.0.x, where an absolute path was left alone and written wherever it pointed — see the CHANGELOG.

Options

Every registrar takes one optional options object, and every one accepts tags (default ['@all']). Tags go through Playwright's tag option, so bin/e2e's --grep "@<env>|@all" selects them without cluttering titles.

testHomepageLoads({ path: './nl/', tags: ['@dev', '@staging'] });

testThemeAssetsLoad({
  assets: [
    ...ABOVO_BASIS_THEME_ASSETS,
    {
      label: 'critical css',
      filename: 'critical.css',
      domSelector: 'link[rel="stylesheet"][href]',
      urlAttribute: 'href',
    },
  ],
});

Navigate with relative paths only — './', './contact', never '/contact'. Playwright resolves goto() against baseURL with the URL() constructor, so a leading slash escapes a path-prefixed base URL such as https://site/fr/.

Filtering base tests

Playwright attributes a test's location to the file where test() was called, which for these suites is the package's compiled code — not your base.spec.ts. So a filename filter does not match them:

e2e -- base.spec.ts          # no tests found
e2e -- --grep "homepage"     # works — filter by title or tag

Your own spec files are unaffected: their tests are registered in your file, so they filter by filename normally. bin/e2e's own --grep "@<env>|@all" selection works on both, because tags and titles are matched, not paths.

Updating

bin/e2e runs npm update before every test run, so a new in-range tag is picked up automatically with no action in the project. A project that must not move pins an exact ref instead — #v1.2.3 — which npm update leaves alone.

Development

The repo has no node service of its own; run everything in the shared Playwright container:

pw() { docker exec -i --user "$(id -u):$(id -g)" -e HOME="$HOME" \
  -w /home/developer/projects/playwright-am-e2e am-dev-playwright "$@"; }

pw npm install
pw npm run typecheck
pw env E2E_BASE_URL=https://dentalclinics-nl.abovodevsites.nl/ npm test

The package's own tests import from dist/, so they exercise the artifact that ships rather than the sources. npm test builds first.

Releasing

SemVer is the contract every site depends on:

  • patch — a base test fixed
  • minor — a suite or option added
  • major — a registrar renamed or removed, or its default behaviour changed

A bad tag reaches every site on its next e2e run, so:

  1. pw env E2E_BASE_URL=<a real abovo-basis dev site> npm test — must pass.
  2. pw npm run test:registration — must list the base tests.
  3. pw npm run verify:exports — must pass. None of the other gates resolve a specifier the way a consuming project's node_modules install does, so this is the only thing standing between a rename in src/ and every site failing at collection with ERR_PACKAGE_PATH_NOT_EXPORTED.
  4. pw npm run typecheck and pw npm run typecheck:tests — must both pass.
  5. pw npm pack --dry-run — must list dist/, must not list src/.
  6. Bump version in package.json, add a CHANGELOG.md entry, run pw npm install --package-lock-only so the lockfile's own version field stays in sync, commit.
  7. git tag vX.Y.Z && git push origin main --tags.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages