wcb/test/e2e
ayo 20e31e4796
Some checks are pending
Tests / Unit (push) Waiting to run
Tests / E2E (push) Waiting to run
fix: nested components no longer wipe each other on re-render (#59)
2026-07-20 23:46:14 +02:00
..
attribute-converters-demo.test.mjs feat: custom prop <> attr conversion 2026-07-20 20:18:06 +02:00
attribute-lifecycle.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
boolean-props-demo.test.mjs feat!: reflect boolean props as bare attributes 2026-07-20 19:57:23 +02:00
boolean-reflection.test.mjs feat!: reflect boolean props as bare attributes 2026-07-20 19:57:23 +02:00
constructed-styles.test.mjs feat: composing stylesheets 2026-07-19 21:19:01 +02:00
demo.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
just-parts.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
lifecycle-order.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
nested-composition.test.mjs fix: nested components no longer wipe each other on re-render (#59) 2026-07-20 23:46:14 +02:00
on-changes.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
props-blueprint.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
README.md feat: smart diffing 2026-07-19 23:32:19 +02:00
render-reconciliation.test.mjs feat: smart diffing 2026-07-19 23:32:19 +02:00
strict-props.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
style-objects.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
templating.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
type-restore.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00
use-shadow.test.mjs chore: new demo workspace & e2e tests 2026-07-05 15:40:53 +02:00

End-to-end example tests

These specs load each demo/examples/* component into a real browser (Chromium, Firefox, and WebKit via Playwright) and drive it the way a user would. They exist because the v5 correctness work targets behaviors that happy-dom cannot reproduce — custom element upgrade ordering, the constructor-attribute rule, empty-string/removed attributes, and adopted stylesheets — so the unit suite alone can pass while a real browser misbehaves. Running across engines also catches cross-browser differences.

Running

pnpm test:e2e           # default: Chromium only (fast, universal)
pnpm test:e2e:chromium  # Chromium
pnpm test:e2e:firefox   # Firefox
pnpm test:e2e:webkit    # WebKit (the engine behind Safari)
pnpm test:e2e:all       # Chromium + Firefox + WebKit

pnpm test               # fast unit suite (happy-dom), unchanged
pnpm test:all           # unit + full e2e (all 3 engines)

pnpm test:e2e stays on Chromium so it works everywhere with minimal setup; use test:e2e:all for the full cross-browser run. Each script just sets the E2E_BROWSERS env var (comma-separated), which the config reads.

Where each runs

Stage e2e scope
pre-commit none (unit only)
pre-push test:e2e (Chromium)
CI on push to main / PRs test:e2e (Chromium)
CI nightly (nightly.yml) test:e2e:all (all 3 engines)

The full Firefox/WebKit matrix is heavy to provision, so it runs once a day (and on-demand via workflow_dispatch) rather than on every push/PR.

Config lives in vitest.e2e.config.mjs (Vitest browser mode + the @vitest/browser-playwright provider), kept separate from vitest.config.mjs so pnpm test stays fast and needs no browser.

Browser setup

npx playwright install chromium firefox webkit   # download the browsers
npx playwright install-deps                       # Linux only: system libraries

Firefox and especially WebKit need extra OS libraries on Linux (libwoff1, etc.); playwright install-deps requires root. Without them those engines fail to launch — which is why the default target is Chromium, and only the nightly workflow installs the deps before running test:e2e:all.

Coverage

One spec per example folder:

Example folder Behavior exercised
on-changes v5 onChanges payload — camelCase property vs kebab attribute
strict-props v5 default log-and-skip vs static strictProps throwing
attribute-lifecycle v5 empty-string stays '', removal resets to default, markup wins
lifecycle-order v5 buffering — onInit runs before the first render, no replayed onChanges
just-parts html + createElement on a vanilla HTMLElement
demo counter / toggle / hello-world / boolean props / onDestroy span
type-restore number, boolean, string, and object prop round-trips
props-blueprint non-zero default, camelCase↔kebab, authored attribute override
style-objects computed inline style objects, type-driven style sets
use-shadow rendering into an open shadow root
constructed-styles static styles via adoptedStyleSheets in the shadow root
templating interpolated lists / links via the built-in html
render-reconciliation in-place patching — focus/caret/uncommitted value, attribute-only updates, uninterrupted transitions, prop+style removal, list grow/shrink, and the non-keyed reorder limitation

Intentionally not covered

  • demo/examples/pens/counter-toggle.html and demo/examples/templating/with-lit.js load their dependencies from a CDN (esm.sh / unpkg) at runtime. They are omitted from the hermetic e2e run to avoid a network dependency; the same WebComponent behaviors they show are already covered by the local specs above (the templating spec covers demo/examples/templating/index.js).