Skip to content

178 Playwright specs skip fleet-wide, and a skip is counted as a pass #609

Description

@rubenvdlinde

178 Playwright specs skip fleet-wide, and a skip is counted as a pass

Measured 2026-08-27 from the Playwright job logs of each app's most recent completed E2E run on development.

app skipped biggest clusters
buildiq 62 hydra-console 12, spec-coverage/buildiq-runtime 11, nldesign-theme-selection 6, chat-companion-streaming 6, docudesk-document-templates 5
decidiq 46 integration-registry 21, spec-coverage/resolution-minutes 5, rbac-authorization-workflow 4
dossiq 37 brp-kvk-initiator 6, pages 6, workflow-editor-canvas 3, related-case-linking 3
shillinq 21 budget-grid-view 5, budget-charts 4, receipt-extraction-consume 3, budget-known-costs 3
integriq 12 spec-coverage/connector-catalog 6, synchronization-workflow 2

Fleet totals for context: 3,041 specs passing, 0 failing — so this is the only material gap in E2E coverage.

Why these are not benign

The recurring shape is a skip conditioned on seeded data that the CI seeder never creates:

// decidiq/tests/e2e/integration-registry.spec.ts  (21 tests)
test.skip(!first, 'no meeting objects on this instance — seed at least one')

// shillinq/tests/e2e/budget-grid-view.spec.ts     (5 tests)
test.skip(!rendered, 'no LedgerGroup seeded for this administration')

Both seeders deliberately provision registers and schemas only — decidiq's ci-seed.sh header calls the register import "the ONLY legitimate seed source". So the object never exists unless an earlier spec happened to create one, which makes coverage depend on spec execution order and reports nothing-was-tested as success.

A skip cannot distinguish "not applicable here" from "the thing this needed was never created", and it reports the second as a pass.

The gate for this exists and now works

e2e-skip-blocking in the shared quality workflow reads the run's Playwright report — the only place a runtime test.skip(cond, reason) is visible, since the CI log prints counts with no reasons. It reports a spec file that executed zero tests, a skip deferring to a deploy state CI itself decides, and a skip carrying no reason.

It had never run in any app. Four independent breaks, each hiding the next:

  1. check_e2e_skips.py existed only on .github main and was in none of the last 12 release tags → fixed by cutting v1.10.0
  2. the workflow looked for it without the inner hydra-gates/ path segment composer installs it under → fix(quality): a missing skip-discipline gate must fail, not warn #595
  3. a missing gate warned and exited 0, so opting in was a silent no-op → same PR
  4. launchpad's lock pinned v1.9.0, predating the script → chore(deps): hydra-gates 1.10, so the skip-discipline gate can run launchpad#359

All four are now merged. launchpad is the first app with the gate genuinely enforcing.

Suggested path per app

  1. Seed what the specs need, following each repo's documented fixture-marker convention — create through the established helper, track in a per-run ledger, delete in afterAll, and add any new schema to TEARDOWN_ORDER (a schema in the ledger but absent from that array leaks silently).
  2. Where a skip really is legitimate — a genuinely absent optional app or external service — leave it, and make the reason say which service.
  3. Then set e2e-skip-blocking: true for that app, so it can only stay clean.

Worked example: ConductionNL/decidiq#941 converts the 21-test integration-registry cluster using decidiq's existing governance-fixture helper (meeting was already in its TEARDOWN_ORDER).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions