From 81e30e3da9e36e4cb0271122711fddc7b28b75e3 Mon Sep 17 00:00:00 2001 From: cesnimda Date: Sun, 11 Oct 2026 10:33:30 +0200 Subject: [PATCH] test(ui): require accessible company save errors --- docs/redesign/phase-6/COMMITS.md | 1 + docs/redesign/phase-6/p6-02/README.md | 4 + .../phase-6/p6-05/evidence/modal-results.json | 87 +++++++++++++++++++ .../e2e/named-controls-modal-state.spec.ts | 8 +- 4 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 docs/redesign/phase-6/p6-05/evidence/modal-results.json diff --git a/docs/redesign/phase-6/COMMITS.md b/docs/redesign/phase-6/COMMITS.md index 2972c6f..59d00a1 100644 --- a/docs/redesign/phase-6/COMMITS.md +++ b/docs/redesign/phase-6/COMMITS.md @@ -8,6 +8,7 @@ Every completed logical unit is pushed to `codex/ui-redesign-phase4`, without fo | Historical system/workflow audit at execution entry | `9d6d29dba4733778e478909d4ff74a25409b3115` | Fresh fetch: development HEAD=origin; seven modified files preserved | | Current P6-00 baseline and design audit | `7da083c374abcb6b34600f3c6667830d47b14760` | Whitespace/source/document review; pushed normally; HEAD=origin immediately after push, main unchanged | | P6-01 shared semantic/contrast/panel corrections | `a94ea0a4a4695d1c196366ac39793a901485e919` | Final521 units/85 suites, type/lint/build and4 native Settings cases green; normal push, HEAD=origin | +| P6-02 cross-application save/retry and localisation corrections | `c135d03602fd273658cfa1c087491c7442060c6a` | Company/language native4/4 with persistence after retry/reload; final521 units; normal push, HEAD=origin | ## Current execution evidence diff --git a/docs/redesign/phase-6/p6-02/README.md b/docs/redesign/phase-6/p6-02/README.md index 60bdd4e..b11e6f2 100644 --- a/docs/redesign/phase-6/p6-02/README.md +++ b/docs/redesign/phase-6/p6-02/README.md @@ -1,5 +1,9 @@ # P6-02 — Cross-application UX and workflow review +## Companion regression correction + +The first fresh full browser attempt recorded153 passes and four failures in `named-controls-modal-state.spec.ts`: its historical P4-02-D02 assertion deliberately required the company error to be hidden from the dialog. P6's verified error repair makes that expectation obsolete. The test now scopes the alert to the active company dialog and requires no aria-hidden ancestor, while preserving draft, no-write, keyboard/focus and subsequent CV/document assertions. The focused four theme/locale/width cases pass with no skips/retries; [exact evidence](../p6-05/evidence/modal-results.json). Final full regression is recorded separately in P6-05. This strengthens the intended current contract rather than weakening the assertion or masking a failure. + Fresh bounded repair result: **4/4 native EN/Bokmål company and language error/retry/persistence/reload workflows pass**, retries0, skips0; [portable feedback proof](../p6-05/evidence/feedback-results.json). The final complete521-unit run also passes. The first native company cases exposed generic English Axios500 text; the shared API helper now uses translated caller fallbacks for transport failures, while server validation and explicit cancellation/session explanations remain. Five actual-helper cases pass after2 localized RED cases. Company list/card dates and pending company-filter labels also reuse the established locale/translation owners. Full integrated native evidence follows in P6-05. ## Scope and baseline diff --git a/docs/redesign/phase-6/p6-05/evidence/modal-results.json b/docs/redesign/phase-6/p6-05/evidence/modal-results.json new file mode 100644 index 0000000..2e82cba --- /dev/null +++ b/docs/redesign/phase-6/p6-05/evidence/modal-results.json @@ -0,0 +1,87 @@ +{ + "command": { + "name": "modal", + "command": [ + "rtk", + "proxy", + "node", + "node_modules/@playwright/test/cli.js", + "test", + "e2e/named-controls-modal-state.spec.ts", + "--retries=0", + "--reporter=list,json", + "--output=E:\\Storage\\Projects\\Active\\Job tracker\\.artifacts\\phase6\\current\\ui\\modal-results" + ], + "startedUtc": "2026-10-11T08:29:22.055451+00:00", + "finishedUtc": "2026-10-11T08:30:11.562991+00:00", + "exitCode": 0, + "stats": { + "startTime": "2026-10-11T08:29:22.590Z", + "duration": 48931.805, + "expected": 4, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + }, + "reportSha256": "9fd4d78d4cf5e0b53385115b82e354f8361c1a0917c1a9d694dea281250ad9c5", + "logSha256": "d99d15e42c69da4e13796418b2ac7cc7c332ac334b13d273c640a960167ec6ff", + "stats": { + "startTime": "2026-10-11T08:29:22.590Z", + "duration": 48931.805, + "expected": 4, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "[PRES-E07 PRES-E08 PRES-J08 PRES-C08 PRES-C09 PRES-W06 PRES-W08] light/en/1440 named controls, modal keyboard and retained draft", + "expectedStatus": "passed", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "durationMs": 11675 + } + ] + }, + { + "title": "[PRES-E07 PRES-E08 PRES-J08 PRES-C08 PRES-C09 PRES-W06 PRES-W08] dark/nb/1440 named controls, modal keyboard and retained draft", + "expectedStatus": "passed", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "durationMs": 10471 + } + ] + }, + { + "title": "[PRES-E07 PRES-E08 PRES-J08 PRES-C08 PRES-C09 PRES-W06 PRES-W08] light/nb/390 named controls, modal keyboard and retained draft", + "expectedStatus": "passed", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "durationMs": 9975 + } + ] + }, + { + "title": "[PRES-E07 PRES-E08 PRES-J08 PRES-C08 PRES-C09 PRES-W06 PRES-W08] dark/en/390 named controls, modal keyboard and retained draft", + "expectedStatus": "passed", + "status": "expected", + "results": [ + { + "status": "passed", + "retry": 0, + "durationMs": 9608 + } + ] + } + ] +} diff --git a/job-tracker-ui/e2e/named-controls-modal-state.spec.ts b/job-tracker-ui/e2e/named-controls-modal-state.spec.ts index 2ab61fa..a7f333d 100644 --- a/job-tracker-ui/e2e/named-controls-modal-state.spec.ts +++ b/job-tracker-ui/e2e/named-controls-modal-state.spec.ts @@ -93,13 +93,11 @@ for (const [mode, language, width] of [["light", "en", 1440], ["dark", "nb", 144 await companyDialog.getByRole("textbox", { name: t.companiesRecruiterName, exact: true }).fill("Retained æøå draft"); await page.route(`${apiUrl}/companies/${owner.companyId}`, route => route.request().method() === "PUT" ? route.fulfill({ status: 503, contentType: "application/json", body: JSON.stringify({ message: "Synthetic save failure" }) }) : route.continue()); await companyDialog.getByRole("button", { name: t.save, exact: true }).click(); - // Existing P4-02-D02: this caller reports save errors in the shared toast, - // outside the modal's accessible subtree. Preserve the draft proof while - // recording the hidden-alert defect instead of claiming an AT error pass. - const saveError = page.getByRole("alert", { includeHidden: true }).filter({ hasText: "Synthetic save failure" }); + // P6 closes P4-02-D02: the retained draft's error belongs to the dialog. + const saveError = companyDialog.getByRole("alert"); await expect(saveError).toContainText("Synthetic save failure"); await expect(saveError).toBeVisible(); - expect(await saveError.evaluate(node => !!node.closest('[aria-hidden="true"]'))).toBe(true); + expect(await saveError.evaluate(node => !!node.closest('[aria-hidden="true"]'))).toBe(false); await expect(companyDialog.getByRole("textbox", { name: t.companiesRecruiterName, exact: true })).toHaveValue("Retained æøå draft"); expect(await statusNode!.getAttribute("data-test-announcements")).toBeNull(); await capture(page, info, `retained-draft-${suffix}`);