Skip to content

test(e2e): gate-19 100% — 219/219 scenarios, +1 more install/security bug fixed#112

Merged
rubenvdlinde merged 7 commits into
developmentfrom
wip/e2e-100-coverage-2
Jul 25, 2026
Merged

test(e2e): gate-19 100% — 219/219 scenarios, +1 more install/security bug fixed#112
rubenvdlinde merged 7 commits into
developmentfrom
wip/e2e-100-coverage-2

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Completes Playwright e2e coverage to gate-19 100%: every one of the 219 spec scenarios now carries a real @e2e test or a reason-bearing @e2e exclude (up from 26). Builds on the fixture forge from #111.

Coverage by spec (all 13 at 100%)

cli-commands 8/8 · version-management 39/39 · app-discovery 22/22 · audit-trail 18/18 · external-sources 42/42 · version-pinning 20/20 · migration-safety 9/9 · artifact-cache 8/8 · changelog-visibility 7/7 · auto-update-policies 10/10 · security-advisory 3/3 · pat-management 31/31 · source-license-headers 2/2.

New specs: cli, version-management, external-sources, pinning-guards, install-effects, pat-management, audit (+ discovery/panels extensions). Installs driven via occ (opcache-safe); the fixture control plane rewrites/deletes assets, forces statuses, serves advisories, and rejects a revoked token.

Fourth bug caught by the new coverage

GET /api/pats (and PatResolver during forge fetches) 500'd whenever any PAT existed: shared_with_admins was created notnull => false with no default, the mapper omits the non-dirty field on insert, so every row stored NULL — and reading it fatals on the non-nullable bool property. Breaks the whole PAT feature on every DB; latent because no test had created then read a PAT live. Migration Version1004 backfills NULLs + sets a false default; app → 1.4.1.

Honesty

Excludes are specific and true — genuinely-not-e2e paths only: TimedJob behavior (auto-update, expiry warnings, retention), failure/fault injection (finalize, cache write, migration diff), real-external dependencies (GitHub scope headers, private repos, unreachable App Store), multi-admin ownership, and internal invariants — each already unit/vitest-covered. No blanket exclusions.

Verified

  • 493 PHP tests · 58 vitest · 86 Playwright (all specs, 5 flaky recovered on retry) · eslint 0 errors
  • scripts-style coverage check: 219/219

🤖 Generated with Claude Code

- tests/e2e/cli.spec.ts (8): human/JSON listing, unknown app, reproducible
  install, downgrade-flag, dry-run, integrity exit code, self-management refusal.
- tests/e2e/version-management.spec.ts (13): bound-source query, forge binding +
  re-bind overwrite, one-off query, dry-run, clean install, rollback, failure
  category → HTTP status, manageable/core card flags, settings placement.
- @e2e traceability: cli-commands 8/8; version-management 39/39 (26 driven +
  13 reason-bearing excludes for paths not reachable in a browser — non-writable
  dest, dev-checkout, finalize-fault injection, password-confirm, real-install
  opcache-503, unreachable App Store, out-of-scope init-swallow).
- discovery.spec.ts: +no-match empty state, +installed-only (API contract).
- audit.spec.ts (new): install recorded (who/what/when), filter by app,
  immutable (no mutation endpoints), non-admin blocked, History tab render.
- @e2e: app-discovery 22/22, audit-trail 18/18 — driven where reachable,
  reason-bearing excludes for provider/cache/PAT-private/retention-job paths.

Running total: 110/219 scenarios annotated.
external-sources.spec.ts (13): forge listing, repo-not-found, appId/version
mismatch rejection, digest-without-sibling, failed-install-records-nothing,
acceptNewSha-harmless-on-first-install, rebind-discards-digests, digests-in-
version-list, untrusted-bind-403, curated allowlist add/remove/owner-wildcard/
over-broad-rejection. Remaining scenarios tagged to existing specs or excluded
(TrustedSourceList/ForgeRegistry/driver unit tests, PAT-auth-scheme).

Running total: 145/219 annotated.
pinning-guards.spec.ts (3): install-over-pin rejected, reinstall-pinned-needs-
no-override, list-pins-with-live-status. Drift/notification/override scenarios
excluded with reasons (monitored-not-enforced NC-core drift, daily reconcile
job, occ lacks --pin/--override-pin, web-install opcache-503).

Running total: 161/219 annotated.
…/auto-update)

install-effects.spec.ts (7): last-known-good updated-on-success / preserved-on-
failure, artifact cache populate + clear, forge release body -> changelog,
invalid policy level rejected. Fixture releases now carry a body.
Remaining scenarios tagged or excluded (migration-diff needs an app with
migrations, retention/tamper/write-failure cache injection, changelog range +
truncation vitest/unit, nightly auto-update job, slow all-apps advisory
endpoint — advisory correlation confirmed live: pinned-to-vulnerable).

Running total: 188/219 annotated — only pat-management remains.
…2e coverage

The fixture-backed PAT e2e caught a fourth latent crash. `shared_with_admins`
was created `notnull => false` with no default, and QBMapper omits the field on
insert when it equals the entity default (false) — so every stored PAT persisted
a NULL there. Reading such a row then fatals (`Pat::$sharedWithAdmins` is a
non-nullable `bool`), which 500s `GET /api/pats` AND PatResolver during forge
fetches the moment any token exists — breaking the whole PAT feature on every
database, latent because no test had created and then read a PAT on a live
instance.

Migration Version1004 backfills existing NULLs to false and gives the column a
`false` default + NOT NULL, so an omitted insert stores false. App version → 1.4.1.

pat-management.spec.ts (8): codeberg token accepted with unverifiable-scope
warning, revoked token rejected, no-plaintext-in-API, edit + delete, per-forge
deeplinks (classic/fine-grained/codeberg), Tokens panel redaction, non-admin
blocked. Fixture /user now rejects a "revoked" token.

@e2e: pat-management 31/31 — 12 driven, 19 reason-bearing excludes (github
scope-header validation, private-repo auth, expiry-warning TimedJob, multi-admin
ownership, internal invariants). TOTAL: 219/219 scenarios annotated.
@rubenvdlinde
rubenvdlinde merged commit 4bc5887 into development Jul 25, 2026
10 of 19 checks passed
@rubenvdlinde
rubenvdlinde deleted the wip/e2e-100-coverage-2 branch July 25, 2026 19:39
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/app-versions @ 58a2bc3

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 17/17
npm ✅ 282/282
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-07-25 19:41 UTC

Download the full PDF report from the workflow artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant