test(e2e): cover 10 gate-19 scenarios with real tests, and fix the icon-remove 404 they found - #175
test(e2e): cover 10 gate-19 scenarios with real tests, and fix the icon-remove 404 they found#175rubenvdlinde wants to merge 2 commits into
Conversation
…on-remove 404 they found gate-19 e2e-coverage on openbuild: 186 -> 176 uncovered scenarios, all closed with tests that actually drive the surface. No scenario was closed by adding an annotation to something that does not exercise it, and no exclude was added. app-icon-management (3 scenarios) --------------------------------- Two of the three were ALREADY covered by real, running tests in tests/e2e/iconUpload.spec.ts that simply carried no @e2e tag — they are annotated there rather than duplicated. The third, user-removes-the-dark-icon, was covered by nothing, and writing it found a product defect. IconUploadSection.removeIcon() called DELETE .../objects/{register}/{schema}/{uuid}/files/app-icon-dark.svg but OpenRegister's files#delete route constrains fileId to \d+, so a filename never matched the route and Nextcloud answered its HTML 404 page. The catch painted the generic "Remove failed" string, so the button looked implemented and could never work. Measured both ways on a live instance: DELETE by filename -> 404, DELETE by the numeric id from GET .../files -> 200 and the attachment is gone. removeIcon() now resolves the numeric id from the object's file index first, and the test pins the numeric shape so the regression cannot return looking green. The three tests this file used to hold were unconditional test.skip stubs citing "openbuild#41: admin UI not functional". That reason was stale — the detail page and the whole icon section render — but un-skipping alone would have produced three green tests asserting expect(page.locator('main')).toBeVisible(). version-lifecycle-ui (7 scenarios, new file) -------------------------------------------- All 17 of this spec's scenarios were uncovered; VersionHistory.vue and ManifestLayersDetail.vue implement the surface in full. Covers the slug-based list endpoint, one row per version, the production marker, click-to-open scoped and canonical, per-row Edit carrying ?_version=, and New draft cloning the production manifest while SHARING its register. REQ-OBV-VLU-007 (the Open-app split button) and REQ-OBV-VLU-008 (the NL catalogue) are deliberately left uncovered and counted rather than claimed. Verification ------------ Driven against a disposable Nextcloud, never the shared dev container (this suite writes). All 10 tests green. Proven in both directions: the dark-icon test was RED on the real 404 before the product fix and GREEN after, and a planted true positive (expecting _version=PLANTED-TRUE-POSITIVE) turned the Edit test RED and reverting turned it GREEN again. Every write arms waitForResponse() BEFORE the interaction that fires it; no networkidle, no sleeps, no conditional skips that would let a test pass by not running.
Quality Report — ConductionNL/openbuild @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| composer | ✅ | ✅ 101/101 | |||
| npm | ✅ | ✅ 654/654 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-11 09:13 UTC
Download the full PDF report from the workflow artifacts.
… rewrite
CI reported "Expected: visible / Received: hidden" on `.ob-icon-section`, one
assertion AFTER the sidebar tab panel check passed — so the panel mounts and the
section inside it is laid out at zero width.
The Application detail page is a three-pane desktop surface; at the project
default of 1280x720 the right-hand sidebar collapses. An earlier draft of this
file carried `test.use({ viewport: 1600x1200 })` and got past this point; the
rewrite that reduced the file to the single remove-scenario dropped it, and it
still passed locally, so nothing surfaced until CI.
No assertion is weakened: the test drives the same clicks and still pins the
numeric DELETE URL shape, the null-iconDark PATCH payload and the read-back.
Quality Report — ConductionNL/openbuild @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| composer | ✅ | ✅ 101/101 | |||
| npm | ✅ | ✅ 654/654 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-11 09:54 UTC
Download the full PDF report from the workflow artifacts.
Checked whether these are real tests or markers — they are real, and the count is exactly rightThe standing worry with any gate-19 remediation PR is that it satisfies the gate The count is not approximateExtracted every So "cover 10 gate-19 scenarios" is exact — floor 160 → 150, no anchor landing The tests assert behaviour, and they are positioned where the gate actually looks
More to the point, the bodies defend against the exact false-coverage shapes this // the marker must sit on the row the view considers production
await expect(page.locator('.version-history__row--current .version-history__badge--production'))
.toHaveCount(1)
// And the other rows must NOT carry it — a marker on every row would
// satisfy a naive "is it visible" check while marking nothing.
const rows = await page.locator('.version-history__row').count()
expect(rows, 'the fixture chain must give more than one row').toBeGreaterThan(1)and it asserts the fixture is non-empty before asserting on it All 6 pass in run The un-quarantining is legitimate, and the reasoning was checked before it was done
Two of the three scenarios are annotated where they are actually exercised 🔴 What blocks this: one of the ten is backed by a failing testThe element is in the DOM and is hidden — it resolved 33 times. So this is So of the ten anchors: nine are backed by green tests, and Also: this branch is staleIts run is from 2026-08-11 09:16 and predates #185, #184, #176 and #177. Two of its Suggested order
Left open for that. Nothing here needs rewriting — the work is good, it is one |
What
gate-19
e2e-coverageon openbuild: 186 → 176 uncovered scenarios. Every one closed with a test that actually drives the surface.No scenario was closed by tagging something that does not exercise it, and no
@e2e excludewas added.app-icon-management — 3 scenarios, and a product defect the tests found
Two of the three were already covered by real, running tests in
tests/e2e/iconUpload.spec.tsthat simply carried no@e2etag. They are annotated there rather than duplicated.The third —
user-removes-the-dark-icon— was covered by nothing, and writing it surfaced a genuine bug.IconUploadSection.removeIcon()calledbut OpenRegister's
files#deleteroute constrainsfileIdto\d+, so a filename never matched the route and Nextcloud answered its HTML 404 page. Thecatchpainted the generic "Remove failed — please try again" string, so the button looked implemented and could never work.Measured both ways on a live instance:
DELETE .../files/app-icon-dark.svgDELETE .../files/400(numeric id)removeIcon()now resolves the numeric id fromGET .../filesfirst. The test pins the numeric URL shape so the regression cannot come back looking green.The three tests this file used to hold were unconditional
test.skipstubs citing "openbuild#41: openbuild admin UI not functional in this build". That reason was stale — the detail page and the whole icon section render — but un-skipping alone would have produced three green tests whose only assertion wasexpect(page.locator('main')).toBeVisible().version-lifecycle-ui — 7 scenarios, new file
All 17 of this spec's scenarios were uncovered even though
VersionHistory.vueandManifestLayersDetail.vueimplement the surface in full. Now covered:applicationUuidfallback) and renders one row per version?_version=<slug>; the production row → the canonical URL with no_version?_version=REQ-OBV-VLU-007(the Open-app split button) andREQ-OBV-VLU-008(the NL catalogue) are a different component and a build-time artefact; they stay uncovered and counted rather than claimed by a test that does not drive them.Verification
Driven against a disposable Nextcloud, never the shared dev container — this suite writes applications, schemas and users.
All 10 tests green. Proven in both directions:
_version=PLANTED-TRUE-POSITIVE) turned the Edit test RED; reverting turned it GREEN againEvery write arms
waitForResponse()before the interaction that fires it. Nonetworkidle, no sleeps, and no conditional skips that would let a test pass by not running.Not in scope here
openbuild#173's two RBAC failures stay filed (an architecture choice), andbuilder-host.spec.ts:44remains a known pre-existing flake that also fails ondevelopment.