test(e2e): close gate-19 e2e-coverage findings — real tests where observable, checked reasons where not - #90
Merged
Conversation
…es 7 gate-19 findings Every scenario in this spec asserts a property of the repository's own source files — SPDX identifiers, PHPDoc @license/@copyright tags, the README badge — so there is no running instance for a browser to observe. The exclusion names coverage that exists and was checked before it was written: scripts/check-license-headers.sh (composer lint:licenses, part of composer check:strict) fails the build on a reintroduced AGPL-3.0 identifier under lib/, src/ or appinfo/, which is REQ-LIC-005 exactly; hydra gate-1 enforces the PHPDoc pair under lib/; the hydra license-triangle gate cross-checks LICENSE, composer.json, publiccode.yml and REUSE.toml. gate-19: 249 -> 242.
…, closes 35 gate-19 findings
Every scenario in this spec is one of four shapes, none of which a
browser can observe:
* which PHP collaborator the service layer delegated to. REQ-GFSB-010
requires the HTTP response to be identical whichever backend served
it, so a UI assertion here is one that cannot fail.
* the GroupFolder backend itself. The groupfolders app is NOT
installed on the Playwright CI fixture — code-quality.yml provisions
only ConductionNL/openregister via additional-apps, and neither seed
script adds it — and AdminController::setWizardStorage() answers
HTTP 400 to any attempt to select it.
* fault injection: app removed mid-operation, permission denied, disk
full, database connection lost.
* HTTP response shape, which this repo routes to Newman by standing
convention (playwright.config.ts excludes **/api-direct/** for that
reason) and whose requests the collection already carries.
Every named test was opened and confirmed before its reason was
written. Two branches that are NOT covered are named as gaps rather
than papered over: the locale branch of GroupFolderContentStorage::
resolvePath(), and the dashboard_content_storage_unavailable error key.
gate-19: 242 -> 207.
…ring excludes Closes 20 gate-19 findings, 1 of them with an actual test. NEW TEST — tests/e2e/manifest-boot.spec.ts. src/main.js registers the bundled manifest synchronously and then fires an async GET /apps/launchpad/api/manifest whose failure branch has never had a test: it must keep the stub, warn, and leave the app usable. The second test forces that endpoint to 500 via page.route and asserts the app still renders. A refactor that awaits the manifest, or that lets the rejection escape the IIFE, turns a degraded-but-working app into a blank page — and nothing else in the suite would catch it. --list: 65 tests in 16 files -> 67 in 17. The other 19 are static file reads (appinfo/info.xml, composer.json, src/manifest.json), build-script exit codes, docblock text, or an OR-LESS instance the CI fixture deliberately is not — it installs openregister via additional-apps on purpose. Three spec-ahead-of-code divergences are named in the reasons rather than papered over: useOrFeatureDetect() appears nowhere under src/; no widget fetches OpenRegister from the browser at all, so there is no ?_lang= request to assert on; and lib/Db/ColumnTypeRegistry.php, whose docblock one requirement is entirely about, does not exist. gate-19: 207 -> 187.
rubenvdlinde
requested review from
Rem-Dam,
SudoThijn and
remko48
as code owners
August 11, 2026 08:00
Contributor
Quality Report — ConductionNL/launchpad @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| composer | ✅ | ✅ 102/102 | |||
| npm | ✅ | ✅ 548/548 | |||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-11 08:11 UTC
Download the full PDF report from the workflow artifacts.
…tags on the tests that prove them Closes 11 gate-19 findings of the second shape: tags that were present but sat in files no Playwright project ran. THE REAL DEFECT WAS NOT THE CONFIG. Both files carried a HEADER BLOCK of @e2e tags above their tests — 8 tags over 3 tests in image-widget, 4 over 3 in label-widget. A tag above the first declaration binds to that declaration, so a header block claims every scenario it lists on the strength of whichever test comes first. Six of those twelve tags were proven by nothing at all: no test touched the fit select, forced an upload error, read the cell cursor, or used a <script> tag; the pre-fill tag sat on a test asserting ONE field where the scenario names six. Promoting the files as they stood would have handed gate-19 six false green. So: every tag now sits on the test that proves it, and the six unproven scenarios got real tests — fit options, upload failure, pointer/no- pointer cursor, direct-URL preview, script-tag XSS. testIgnore is FILE-granular, so the one red test in each file was holding two green ones hostage. Each moved to its own file, unchanged, still runnable via > launchpad@1.0.0 test:e2e:excluded > playwright test --config=playwright.excluded.config.ts — not skipped, not deleted, not weakened. REQ-IMG-003 is now proven BETTER than before: it says the cell MUST call window.open(link, '_blank', 'noopener,noreferrer'). Recording window.open asserts the two flag arguments a real popup cannot show, and dispatching the click event directly does not depend on the cell being in the viewport — which is exactly what made the popup version red. form-pre-fills-all-six-fields-when-editing takes a reason-bearing exclude naming the run that measured its test red (31367057618) and the fact that the test checks one field of six. --list: 67 tests in 17 files -> 77 in 19 (excluded config: 31 in 10). gate-19: 187 -> 176.
Contributor
Quality Report — ConductionNL/launchpad @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| composer | ✅ | ✅ 102/102 | |||
| npm | ✅ | ✅ 548/548 | |||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-11 08:25 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Closes hydra gate-19 (e2e-coverage) findings on launchpad, capability by capability.
Baseline measured on this branch point: 249 scenarios without a running e2e test.
How each finding was closed
Two mechanisms, and the choice between them is never a matter of convenience:
@e2e excludeonly where it genuinely is not — a unit-levelinvariant, a static/source-hygiene check, a fault-injection path, or a feature the
CI fixture does not provision.
Every reason names something that was checked first. Where a reason says
"covered by
FooTest::testBar", that file was opened and the method confirmed toexist before the sentence was written. Where no such test exists, the reason says so
instead of inventing one — see the two named gaps below.
Divergences found while classifying (reported, not fixed)
GET /api/admin/setup-wizard/statereturns only{complete, currentRecommendedStep, stepStatuses}, butSetupWizardModal.loadState()readsdata.contentStorageanddata.groupfolderAvailable. Both are alwaysundefined, so the wizard's storageradio is pinned to "database" on every instance regardless of the persisted setting,
and the GroupFolder option is permanently disabled even where the app is
installed. The server-side gate in
AdminController::setWizardStorage()is correct;the client-side one is decorative.
useOrFeatureDetect()appears nowhere undersrc/, and no widget fetchesOpenRegister from the browser at all — so the
?_lang=stamping requirement has norequest to attach to.
lib/Db/ColumnTypeRegistry.php, whose docblock one whole requirement is about, doesnot exist anywhere in the repo.
Known-uncovered branches, named rather than papered over
GroupFolderContentStorage::resolvePath()— no unit testdashboard_content_storage_unavailableerror key — no test at allBoth belong to the unit/Newman suites, not to a browser.
Verification
npx playwright test --list: 65 tests in 16 files -> 67 in 17.test.skip, nogrepInvert, no widenedtestIgnore, no raisedtimeouts, no deleted tests.
Measured progress
gate-19: 249 -> 176 (official runner,
run-hydra-gates.sh).groupfolder-storage-backendlaunchpad-adopt-or-abstractionsimage-widgetlicense-header-consistencylabel-widgetCI-verified, not assumed
quality / E2E Tests (Playwright)is green: 77 passed (8.0m), and every newtest appears by name in the run list — including all five new image-widget tests
and the new
<script>XSS test.--list: 65 tests in 16 files -> 77 in 19(excluded config: 31 in 10).
Both directions proven
image-widget.spec.ts(8 anchors): 176 -> 184, exactly +8.Still open — 176
role-feature-permissions27 ·dashboard-kiosk-mode23 ·conditional-visibility-editor23 ·clock-weather-widgets19 ·service-health-ping15 ·live-data-tile-widget15 ·iframe-embed-widget15 ·dashboard-public-share14 ·tile-quick-search13 ·dashboard-sharing11 ·runtime-shell1.These are widget capabilities with real, implemented UI, so most of them want real
tests rather than excludes. They are deliberately not closed with annotations
here.