Playwright flows

End-to-end user journeys in e2e/** tagged @uidex:flow, and the registry's touches metadata.

End-to-end user journeys are Playwright tests in e2e/**. Any top-level test.describe auto-promotes to a flow; the @uidex:flow tag adds richer metadata. Opt out by adding export const uidex = { notFlow: true } as const satisfies Uidex.NotFlow at the top of the spec file.

Rules

  • One tagged describe per flow-*.spec.ts.
  • Component ids inside uidex(...) MUST be string literals (static-analysable). Variables, concatenation, and template literals are invisible to the static scanner and will not contribute to touches.
  • page-*.spec.ts and feature-*.spec.ts scoped tests remain untagged.

Touches and meta.flows

Each uidex(...) call in a tagged describe contributes to the flow's touches array. The scanner inverts that index per registered entity, so for any page, feature, or widget you can ask "which flows cover me?" via entity.meta.flows: FlowId[].

For widgets specifically, meta.flows includes flows that touch any descendant element of the widget — not just the widget root.

Scaffolding from acceptance

uidex scaffold widget <id> emits a Playwright spec stub from the widget's declared acceptance criteria. See uidex scan for the full reference.

Emits a Playwright spec with exactly one test() per declared criterion. The describe carries { tag: "@uidex:flow" }. Each test has a // TODO body for you to fill in.

Behaviour:

  • Deterministic file path: the scaffold writes to <flows-glob-root>/flow-<id>.spec.ts.
  • Idempotent: re-running will refuse to overwrite an existing file unless --force is passed.
  • Without --force, exits with a clear message naming the existing path.

Opting out

A spec file under the flows glob that does not model a user journey (a shared fixture, a utility) opts out with:

The scanner leaves the file's describes alone; nothing in the file contributes to touches.