From c9138af01e6dd7cc407a9b71c921914d8c1299f0 Mon Sep 17 00:00:00 2001 From: cesnimda Date: Wed, 4 Nov 2026 00:56:57 +0100 Subject: [PATCH] style(ui): open application rows and workspace sections 65 targeted tests and focused six-state phone pilot pass. Full 216-state visual qualification remains pending; final owner acceptance is separate. --- .../visual-correction/APPLICATION_FLAT.md | 20 ++++ .../APPLICATION_FLAT_TESTS.json | 1 + .../APPLICATION_FLAT_TRANSITION_FAILURE.json | 1 + .../applications-flat/FOCUS-CLIP-FAILURE.json | 37 +++++++ .../evidence/applications-flat/PILOT.json | 103 ++++++++++++++++++ .../table-focused-en-light-320.png | Bin 0 -> 58853 bytes .../scripts/verify-a3-applications.mjs | 31 +++++- job-tracker-ui/src/components/JobTable.tsx | 58 +++++----- job-tracker-ui/src/job-table-density.test.tsx | 32 ++++++ .../src/views/ApplicationWorkspacePage.tsx | 44 ++++---- 10 files changed, 269 insertions(+), 58 deletions(-) create mode 100644 docs/ui-modernisation/visual-correction/APPLICATION_FLAT.md create mode 100644 docs/ui-modernisation/visual-correction/APPLICATION_FLAT_TESTS.json create mode 100644 docs/ui-modernisation/visual-correction/APPLICATION_FLAT_TRANSITION_FAILURE.json create mode 100644 docs/ui-modernisation/visual-correction/evidence/applications-flat/FOCUS-CLIP-FAILURE.json create mode 100644 docs/ui-modernisation/visual-correction/evidence/applications-flat/PILOT.json create mode 100644 docs/ui-modernisation/visual-correction/evidence/applications-flat/table-focused-en-light-320.png diff --git a/docs/ui-modernisation/visual-correction/APPLICATION_FLAT.md b/docs/ui-modernisation/visual-correction/APPLICATION_FLAT.md new file mode 100644 index 00000000..9fdb07c1 --- /dev/null +++ b/docs/ui-modernisation/visual-correction/APPLICATION_FLAT.md @@ -0,0 +1,20 @@ +# Application list and workspace visual correction — active + +4 November 2026. Approved IM10 continuation from published/remotely verified `af2df360624d5c48ae03d80e7281704372d860ee` (secondary source checkpoint `69621788ee53d842c82cab307be129ba8806ca26`). No owner permission is outstanding for ordinary visual correction. + +Material before evidence: `evidence/applications` has36 configurations/144 successful controlled accessibility states but still shows a bordered collection enclosing large mobile job cards and a large boxed detail header. These are functional/accessibility results, not final A3 visual acceptance. Approved A3 applications390 and detail1440 reference images were inspected without restarting design selection. + +Uncommitted correction: + +- Mobile rows use quiet separators and full available width, inline existing facts and direct44px named icon actions. Every edit/status/delete/restore handler and confirmation remains. Column/density preferences, selection, tags/signals, pagination, role/tabIndex, interactive-target guards, keyboard navigation and return state remain. +- Workspace header, continuous document/notes/calendar/correspondence/next-action/recent-activity sections and expanded recorded details/advert use open sections. Two-column phone preparation links retain all five destinations. Header/Accordion padding reduced; right-side context grid and jump/return targets unchanged. +-65 tests/six suites passed, including EN/NB mobile actions independent of row navigation and existing cover-letter preservation. Types/lint/build passed. A native test initially queried background controls before the confirmation dialog finished exiting; corrected to await accessible restoration. Its failed report is retained. +- Independent source review found no actionable findings; native touch/icon discoverability and focus visibility still require rendered inspection. + +Browser evidence is deliberately distinct: `applications-flat` is the successor directory. The first36-configuration run covers five states per configuration (180 intended captures) but does **not** exercise a focused table row. A new focused-row pilot reproduced a real clipped outline in the borderless mobile collection; see `FOCUS-CLIP-FAILURE.json`. The responsible collection overflow was changed to visible on phones, retaining desktop containment. The new verifier adds a focused-row state and an explicit outline/clipping assertion: final required successor is **36 configurations /216 states**, not180. Do not attribute the older180-state run to the focus fix or mark this package complete until the final export and216-state run pass. + +Successor update: the older non-focused run completed180 states but cannot close the focus gap; retained as `PREDECESSOR-180.json` without claiming an immutable source manifest or using it for final qualification. Focus correction export built successfully; the new six-state phone pilot passed, including an explicit visible/unclipped row outline assertion. Final36-config/216-state run is next. Types/build and full lint passed for this correction. Do not add pilot/predecessor results to final totals. + +Remaining work: run full216, inspect phone/tablet/desktop and EN/NB/dark expanded detail captures, review source/evidence identities, publish/read back validated source and evidence checkpoints. Backend/physical PDF/provider/model/native/final security/release qualifications remain separate. Only app chrome changed; do not reopen accepted physical PDF metrics without an affected renderer change. + +Next eligible packages after this bounded correction: account continuous sections (V10), remaining route visual review/connected workflows, and the bounded literal-date localisation defect (V11). Whole34-route/57-group acceptance and final owner review remain OPEN. No orchestrator, main merge, production or deferred import-engine work. diff --git a/docs/ui-modernisation/visual-correction/APPLICATION_FLAT_TESTS.json b/docs/ui-modernisation/visual-correction/APPLICATION_FLAT_TESTS.json new file mode 100644 index 00000000..084f6927 --- /dev/null +++ b/docs/ui-modernisation/visual-correction/APPLICATION_FLAT_TESTS.json @@ -0,0 +1 @@ +{"numFailedTestSuites":0,"numFailedTests":0,"numPassedTestSuites":6,"numPassedTests":65,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":6,"numTotalTests":65,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1793749605941,"success":true,"testResults":[{"assertionResults":[{"ancestorTitles":[],"duration":1227,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"row status/edit/delete controls retain selection and do not open the workspace","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749609380,"status":"passed","title":"row status/edit/delete controls retain selection and do not open the workspace"},{"ancestorTitles":[],"duration":848,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en mobile row actions remain direct, named and independent of row navigation","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793749610607,"status":"passed","title":"en mobile row actions remain direct, named and independent of row navigation"},{"ancestorTitles":[],"duration":880,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb mobile row actions remain direct, named and independent of row navigation","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793749611455,"status":"passed","title":"nb mobile row actions remain direct, named and independent of row navigation"},{"ancestorTitles":[],"duration":928,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"table sort, page-size and optional columns keep their existing independent contracts","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749612335,"status":"passed","title":"table sort, page-size and optional columns keep their existing independent contracts"},{"ancestorTitles":[],"duration":151,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Trash select-all and bulk restore use the original IDs without workspace navigation","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749613264,"status":"passed","title":"Trash select-all and bulk restore use the original IDs without workspace navigation"},{"ancestorTitles":[],"duration":586,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"density preserves selected rows, query, page, custom status, columns and listing link without refetch","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"startAt":1793749613415,"status":"passed","title":"density preserves selected rows, query, page, custom status, columns and listing link without refetch"},{"ancestorTitles":[],"duration":355,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"density is local and resets on unmount without writing settings or a saved view","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749614001,"status":"passed","title":"density is local and resets on unmount without writing settings or a saved view"},{"ancestorTitles":[],"duration":653,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"density survives an empty result and a failed refresh with the existing retry action","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749614356,"status":"passed","title":"density survives an empty result and a failed refresh with the existing retry action"},{"ancestorTitles":[],"duration":325,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Bokmål display localizes standard statuses without changing API values or custom status filters","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749615010,"status":"passed","title":"Bokmål display localizes standard statuses without changing API values or custom status filters"},{"ancestorTitles":[],"duration":569,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"partial bulk failure refreshes successful rows and retains only failed visible IDs","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749615335,"status":"passed","title":"partial bulk failure refreshes successful rows and retains only failed visible IDs"},{"ancestorTitles":[],"duration":653,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"saved view create/apply/delete stays scoped to the signed-in account","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749615904,"status":"passed","title":"saved view create/apply/delete stays scoped to the signed-in account"},{"ancestorTitles":[],"duration":548,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"changing the result set clears selection before an old row can be bulk-updated","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749616557,"status":"passed","title":"changing the result set clears selection before an old row can be bulk-updated"}],"endTime":1793749617106,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\job-table-density.test.tsx","startTime":1793749606861,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":533,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"contact copy is a reviewed canonical snapshot; cancel is inert and apply preserves recipient and design","invocations":1,"location":null,"numPassingAsserts":17,"retryReasons":[],"startAt":1793749617841,"status":"passed","title":"contact copy is a reviewed canonical snapshot; cancel is inert and apply preserves recipient and design"},{"ancestorTitles":[],"duration":401,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"contact location copies only after selection and unselected contact values preserve destination fields","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749618374,"status":"passed","title":"contact location copies only after selection and unselected contact values preserve destination fields"},{"ancestorTitles":[],"duration":244,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"blank source contacts and choosing no fields never clear destination contacts","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749618775,"status":"passed","title":"blank source contacts and choosing no fields never clear destination contacts"},{"ancestorTitles":[],"duration":444,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"letter language is an explicit document draft and saves independently of interface and CV language","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749619019,"status":"passed","title":"letter language is an explicit document draft and saves independently of interface and CV language"},{"ancestorTitles":[],"duration":222,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"design copy resolves null overrides through actual theme defaults and effective CV density","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749619463,"status":"passed","title":"design copy resolves null overrides through actual theme defaults and effective CV density"},{"ancestorTitles":[],"duration":210,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"letter template chooser uses nine actual matching themes and preserves destination letter details","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793749619685,"status":"passed","title":"letter template chooser uses nine actual matching themes and preserves destination letter details"},{"ancestorTitles":[],"duration":155,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"letter template load failures retry and cancel never changes the local letter","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749619895,"status":"passed","title":"letter template load failures retry and cancel never changes the local letter"},{"ancestorTitles":[],"duration":805,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"applying a letter template updates the existing letter preview using the current body without saving","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749620050,"status":"passed","title":"applying a letter template updates the existing letter preview using the current body without saving"},{"ancestorTitles":[],"duration":57,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"disabled letter drafting cannot open the template chooser","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749620855,"status":"passed","title":"disabled letter drafting cannot open the template chooser"},{"ancestorTitles":[],"duration":224,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"matching a customized CV copies heading density and paper but preserves letter language","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749620913,"status":"passed","title":"matching a customized CV copies heading density and paper but preserves letter language"},{"ancestorTitles":[],"duration":207,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"closing a copy dialog ignores a late selected CV read","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749621137,"status":"passed","title":"closing a copy dialog ignores a late selected CV read"},{"ancestorTitles":[],"duration":248,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"failed copy reads are retryable and cannot apply or save a partial snapshot","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749621344,"status":"passed","title":"failed copy reads are retryable and cannot apply or save a partial snapshot"},{"ancestorTitles":[],"duration":703,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"restoring a historical letter restores saved details with text after explicit dirty confirmation","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793749621592,"status":"passed","title":"restoring a historical letter restores saved details with text after explicit dirty confirmation"},{"ancestorTitles":[],"duration":448,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"successful export waits for the committed local snapshot and uses its returned revision once","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793749622295,"status":"passed","title":"successful export waits for the committed local snapshot and uses its returned revision once"},{"ancestorTitles":[],"duration":459,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a late letter PDF from a previous keyed job never downloads or replaces the current draft","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749622743,"status":"passed","title":"a late letter PDF from a previous keyed job never downloads or replaces the current draft"}],"endTime":1793749623202,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\cover-letter-document.test.tsx","startTime":1793749617118,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":877,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"opens the dedicated workspace from the whole row and preserves list state on return","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793749624120,"status":"passed","title":"opens the dedicated workspace from the whole row and preserves list state on return"},{"ancestorTitles":[],"duration":104,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"opens a direct workspace URL and returns to applications","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749624997,"status":"passed","title":"opens a direct workspace URL and returns to applications"},{"ancestorTitles":[],"duration":80,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps en context after the primary task with a keyboard jump and return across sections","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749625101,"status":"passed","title":"keeps en context after the primary task with a keyboard jump and return across sections"},{"ancestorTitles":[],"duration":127,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps nb context after the primary task with a keyboard jump and return across sections","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749625181,"status":"passed","title":"keeps nb context after the primary task with a keyboard jump and return across sections"},{"ancestorTitles":[],"duration":95,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"does not infer en application readiness from an absent next action","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749625308,"status":"passed","title":"does not infer en application readiness from an absent next action"},{"ancestorTitles":[],"duration":98,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"does not infer nb application readiness from an absent next action","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749625403,"status":"passed","title":"does not infer nb application readiness from an absent next action"},{"ancestorTitles":[],"duration":354,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"row controls do not trigger navigation","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749625501,"status":"passed","title":"row controls do not trigger navigation"},{"ancestorTitles":[],"duration":37,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"handles a deleted or inaccessible job without rendering a broken workspace","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749625855,"status":"passed","title":"handles a deleted or inaccessible job without rendering a broken workspace"},{"ancestorTitles":[],"duration":570,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"warns before section navigation would discard application edits","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749625892,"status":"passed","title":"warns before section navigation would discard application edits"},{"ancestorTitles":[],"duration":208,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"renders shared workspace navigation and progress in Norwegian Bokmål","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749626462,"status":"passed","title":"renders shared workspace navigation and progress in Norwegian Bokmål"},{"ancestorTitles":[],"duration":163,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"hydrates list filters, sort and page from a shareable URL","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749626670,"status":"passed","title":"hydrates list filters, sort and page from a shareable URL"},{"ancestorTitles":[],"duration":125,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"names the progress scroll region and identifies the current stage without making stages actions","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749626833,"status":"passed","title":"names the progress scroll region and identifies the current stage without making stages actions"},{"ancestorTitles":[],"duration":119,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps custom status literal without claiming a completed standard pipeline","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749626959,"status":"passed","title":"keeps custom status literal without claiming a completed standard pipeline"},{"ancestorTitles":[],"duration":115,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"retries a failed workspace read without creating or changing application content","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749627078,"status":"passed","title":"retries a failed workspace read without creating or changing application content"},{"ancestorTitles":[],"duration":315,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps the server-selected next action and preparation entry on the existing CV section","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749627193,"status":"passed","title":"keeps the server-selected next action and preparation entry on the existing CV section"},{"ancestorTitles":[],"duration":111,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"uses recorded dates in the summary and keeps absent dates unknown","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749627508,"status":"passed","title":"uses recorded dates in the summary and keeps absent dates unknown"},{"ancestorTitles":[],"duration":175,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"section changes retain follow-up query context and expose the selected labelled panel","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749627619,"status":"passed","title":"section changes retain follow-up query context and expose the selected labelled panel"},{"ancestorTitles":[],"duration":212,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"accordion controls identify exactly one labelled content region","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749627794,"status":"passed","title":"accordion controls identify exactly one labelled content region"},{"ancestorTitles":[],"duration":60,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"legacy document links reveal current attachments and frozen history in the named section","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749628006,"status":"passed","title":"legacy document links reveal current attachments and frozen history in the named section"},{"ancestorTitles":[],"duration":121,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"the missing-profile next task opens the existing canonical profile entry","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749628066,"status":"passed","title":"the missing-profile next task opens the existing canonical profile entry"},{"ancestorTitles":[],"duration":744,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"application subsection navigation retains metadata and protects unsaved answers","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749628188,"status":"passed","title":"application subsection navigation retains metadata and protects unsaved answers"},{"ancestorTitles":[],"duration":174,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"legacy correspondence and notes reveal distinct domain content","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749628932,"status":"passed","title":"legacy correspondence and notes reveal distinct domain content"},{"ancestorTitles":[],"duration":158,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"holds answers until their aggregate matches the route and ignores a late previous-job aggregate","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"startAt":1793749629106,"status":"passed","title":"holds answers until their aggregate matches the route and ignores a late previous-job aggregate"},{"ancestorTitles":[],"duration":207,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"entering Answers waits for a fresh coherent snapshot after sibling writes","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749629264,"status":"passed","title":"entering Answers waits for a fresh coherent snapshot after sibling writes"},{"ancestorTitles":[],"duration":295,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a late previous Answers-entry read cannot enable the current editor","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749629471,"status":"passed","title":"a late previous Answers-entry read cannot enable the current editor"},{"ancestorTitles":[],"duration":170,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a failed Answers-entry read stays closed until a successful retry","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749629766,"status":"passed","title":"a failed Answers-entry read stays closed until a successful retry"},{"ancestorTitles":[],"duration":47,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"leaving a pending direct Answers entry still loads the workspace header","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749629936,"status":"passed","title":"leaving a pending direct Answers entry still loads the workspace header"}],"endTime":1793749629983,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\application-workspace-overlay.test.tsx","startTime":1793749623209,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":2080,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Table/Board switches preserve query, complete membership, page, density and history without hidden reads","invocations":1,"location":null,"numPassingAsserts":14,"retryReasons":[],"startAt":1793749630666,"status":"passed","title":"Table/Board switches preserve query, complete membership, page, density and history without hidden reads"},{"ancestorTitles":[],"duration":251,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"direct Board and both switch directions retain exact result membership: ?q=Engineer&status=Custom+review","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749632746,"status":"passed","title":"direct Board and both switch directions retain exact result membership: ?q=Engineer&status=Custom+review"},{"ancestorTitles":[],"duration":400,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"direct Board and both switch directions retain exact result membership: ?q=absent","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749632997,"status":"passed","title":"direct Board and both switch directions retain exact result membership: ?q=absent"},{"ancestorTitles":[],"duration":1404,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Board uses the shared filter controls and saved query owner without fetching Table","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749633397,"status":"passed","title":"Board uses the shared filter controls and saved query owner without fetching Table"},{"ancestorTitles":[],"duration":194,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Trash stays a Table even when supplied a Board view parameter","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749634802,"status":"passed","title":"Trash stays a Table even when supplied a Board view parameter"},{"ancestorTitles":[],"duration":1318,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"saved filters applied in Board reset the Table page and refresh only the active population","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749634996,"status":"passed","title":"saved filters applied in Board reset the Table page and refresh only the active population"}],"endTime":1793749636315,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\jobs-view-integration.test.tsx","startTime":1793749629990,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":192,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"dashboard attention card opens follow-up workspace","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749637173,"status":"passed","title":"dashboard attention card opens follow-up workspace"},{"ancestorTitles":[],"duration":118,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"empty dashboard prioritizes onboarding and suppresses meaningless analytics","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793749637365,"status":"passed","title":"empty dashboard prioritizes onboarding and suppresses meaningless analytics"},{"ancestorTitles":[],"duration":65,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"reminders open action routes tailored-cv gaps into the tailored cv workspace","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749637483,"status":"passed","title":"reminders open action routes tailored-cv gaps into the tailored cv workspace"},{"ancestorTitles":[],"duration":693,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"job table urgency signals and next actions route into the shared workspace flow","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749637548,"status":"passed","title":"job table urgency signals and next actions route into the shared workspace flow"}],"endTime":1793749638242,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\daily-control-loop.test.tsx","startTime":1793749636323,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["end-to-end trust loop"],"duration":386,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"end-to-end trust loop overview entry opens the canonical communication workspace without sending mail","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749639020,"status":"passed","title":"overview entry opens the canonical communication workspace without sending mail"}],"endTime":1793749639406,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\end-to-end-trust-loop.test.tsx","startTime":1793749638249,"status":"passed","summary":""}],"wasInterrupted":false} diff --git a/docs/ui-modernisation/visual-correction/APPLICATION_FLAT_TRANSITION_FAILURE.json b/docs/ui-modernisation/visual-correction/APPLICATION_FLAT_TRANSITION_FAILURE.json new file mode 100644 index 00000000..6d7833a2 --- /dev/null +++ b/docs/ui-modernisation/visual-correction/APPLICATION_FLAT_TRANSITION_FAILURE.json @@ -0,0 +1 @@ +{"numFailedTestSuites":1,"numFailedTests":2,"numPassedTestSuites":5,"numPassedTests":63,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":6,"numTotalTests":65,"openHandles":[],"snapshot":{"added":0,"didUpdate":false,"failure":false,"filesAdded":0,"filesRemoved":0,"filesRemovedList":[],"filesUnmatched":0,"filesUpdated":0,"matched":0,"total":0,"unchecked":0,"uncheckedKeysByFile":[],"unmatched":0,"updated":0},"startTime":1793749544108,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":[],"duration":617,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"contact copy is a reviewed canonical snapshot; cancel is inert and apply preserves recipient and design","invocations":1,"location":null,"numPassingAsserts":17,"retryReasons":[],"startAt":1793749547851,"status":"passed","title":"contact copy is a reviewed canonical snapshot; cancel is inert and apply preserves recipient and design"},{"ancestorTitles":[],"duration":387,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"contact location copies only after selection and unselected contact values preserve destination fields","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749548468,"status":"passed","title":"contact location copies only after selection and unselected contact values preserve destination fields"},{"ancestorTitles":[],"duration":318,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"blank source contacts and choosing no fields never clear destination contacts","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749548855,"status":"passed","title":"blank source contacts and choosing no fields never clear destination contacts"},{"ancestorTitles":[],"duration":584,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"letter language is an explicit document draft and saves independently of interface and CV language","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749549173,"status":"passed","title":"letter language is an explicit document draft and saves independently of interface and CV language"},{"ancestorTitles":[],"duration":119,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"design copy resolves null overrides through actual theme defaults and effective CV density","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749549758,"status":"passed","title":"design copy resolves null overrides through actual theme defaults and effective CV density"},{"ancestorTitles":[],"duration":209,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"letter template chooser uses nine actual matching themes and preserves destination letter details","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793749549877,"status":"passed","title":"letter template chooser uses nine actual matching themes and preserves destination letter details"},{"ancestorTitles":[],"duration":213,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"letter template load failures retry and cancel never changes the local letter","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749550086,"status":"passed","title":"letter template load failures retry and cancel never changes the local letter"},{"ancestorTitles":[],"duration":824,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"applying a letter template updates the existing letter preview using the current body without saving","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749550299,"status":"passed","title":"applying a letter template updates the existing letter preview using the current body without saving"},{"ancestorTitles":[],"duration":38,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"disabled letter drafting cannot open the template chooser","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749551124,"status":"passed","title":"disabled letter drafting cannot open the template chooser"},{"ancestorTitles":[],"duration":209,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"matching a customized CV copies heading density and paper but preserves letter language","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749551162,"status":"passed","title":"matching a customized CV copies heading density and paper but preserves letter language"},{"ancestorTitles":[],"duration":191,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"closing a copy dialog ignores a late selected CV read","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749551371,"status":"passed","title":"closing a copy dialog ignores a late selected CV read"},{"ancestorTitles":[],"duration":276,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"failed copy reads are retryable and cannot apply or save a partial snapshot","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749551562,"status":"passed","title":"failed copy reads are retryable and cannot apply or save a partial snapshot"},{"ancestorTitles":[],"duration":555,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"restoring a historical letter restores saved details with text after explicit dirty confirmation","invocations":1,"location":null,"numPassingAsserts":7,"retryReasons":[],"startAt":1793749551838,"status":"passed","title":"restoring a historical letter restores saved details with text after explicit dirty confirmation"},{"ancestorTitles":[],"duration":515,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"successful export waits for the committed local snapshot and uses its returned revision once","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793749552393,"status":"passed","title":"successful export waits for the committed local snapshot and uses its returned revision once"},{"ancestorTitles":[],"duration":386,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a late letter PDF from a previous keyed job never downloads or replaces the current draft","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749552908,"status":"passed","title":"a late letter PDF from a previous keyed job never downloads or replaces the current draft"}],"endTime":1793749553295,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\cover-letter-document.test.tsx","startTime":1793749545082,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":837,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"opens the dedicated workspace from the whole row and preserves list state on return","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793749554413,"status":"passed","title":"opens the dedicated workspace from the whole row and preserves list state on return"},{"ancestorTitles":[],"duration":153,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"opens a direct workspace URL and returns to applications","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749555250,"status":"passed","title":"opens a direct workspace URL and returns to applications"},{"ancestorTitles":[],"duration":127,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps en context after the primary task with a keyboard jump and return across sections","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749555403,"status":"passed","title":"keeps en context after the primary task with a keyboard jump and return across sections"},{"ancestorTitles":[],"duration":158,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps nb context after the primary task with a keyboard jump and return across sections","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749555530,"status":"passed","title":"keeps nb context after the primary task with a keyboard jump and return across sections"},{"ancestorTitles":[],"duration":97,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"does not infer en application readiness from an absent next action","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749555688,"status":"passed","title":"does not infer en application readiness from an absent next action"},{"ancestorTitles":[],"duration":101,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"does not infer nb application readiness from an absent next action","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749555786,"status":"passed","title":"does not infer nb application readiness from an absent next action"},{"ancestorTitles":[],"duration":290,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"row controls do not trigger navigation","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749555887,"status":"passed","title":"row controls do not trigger navigation"},{"ancestorTitles":[],"duration":42,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"handles a deleted or inaccessible job without rendering a broken workspace","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749556177,"status":"passed","title":"handles a deleted or inaccessible job without rendering a broken workspace"},{"ancestorTitles":[],"duration":570,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"warns before section navigation would discard application edits","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749556219,"status":"passed","title":"warns before section navigation would discard application edits"},{"ancestorTitles":[],"duration":209,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"renders shared workspace navigation and progress in Norwegian Bokmål","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749556789,"status":"passed","title":"renders shared workspace navigation and progress in Norwegian Bokmål"},{"ancestorTitles":[],"duration":177,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"hydrates list filters, sort and page from a shareable URL","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749556998,"status":"passed","title":"hydrates list filters, sort and page from a shareable URL"},{"ancestorTitles":[],"duration":104,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"names the progress scroll region and identifies the current stage without making stages actions","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749557175,"status":"passed","title":"names the progress scroll region and identifies the current stage without making stages actions"},{"ancestorTitles":[],"duration":125,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps custom status literal without claiming a completed standard pipeline","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749557280,"status":"passed","title":"keeps custom status literal without claiming a completed standard pipeline"},{"ancestorTitles":[],"duration":114,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"retries a failed workspace read without creating or changing application content","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749557405,"status":"passed","title":"retries a failed workspace read without creating or changing application content"},{"ancestorTitles":[],"duration":313,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"keeps the server-selected next action and preparation entry on the existing CV section","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749557519,"status":"passed","title":"keeps the server-selected next action and preparation entry on the existing CV section"},{"ancestorTitles":[],"duration":94,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"uses recorded dates in the summary and keeps absent dates unknown","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749557832,"status":"passed","title":"uses recorded dates in the summary and keeps absent dates unknown"},{"ancestorTitles":[],"duration":164,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"section changes retain follow-up query context and expose the selected labelled panel","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749557926,"status":"passed","title":"section changes retain follow-up query context and expose the selected labelled panel"},{"ancestorTitles":[],"duration":157,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"accordion controls identify exactly one labelled content region","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749558090,"status":"passed","title":"accordion controls identify exactly one labelled content region"},{"ancestorTitles":[],"duration":60,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"legacy document links reveal current attachments and frozen history in the named section","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749558247,"status":"passed","title":"legacy document links reveal current attachments and frozen history in the named section"},{"ancestorTitles":[],"duration":129,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"the missing-profile next task opens the existing canonical profile entry","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749558307,"status":"passed","title":"the missing-profile next task opens the existing canonical profile entry"},{"ancestorTitles":[],"duration":695,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"application subsection navigation retains metadata and protects unsaved answers","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749558436,"status":"passed","title":"application subsection navigation retains metadata and protects unsaved answers"},{"ancestorTitles":[],"duration":177,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"legacy correspondence and notes reveal distinct domain content","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749559131,"status":"passed","title":"legacy correspondence and notes reveal distinct domain content"},{"ancestorTitles":[],"duration":157,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"holds answers until their aggregate matches the route and ignores a late previous-job aggregate","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"startAt":1793749559308,"status":"passed","title":"holds answers until their aggregate matches the route and ignores a late previous-job aggregate"},{"ancestorTitles":[],"duration":175,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"entering Answers waits for a fresh coherent snapshot after sibling writes","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749559465,"status":"passed","title":"entering Answers waits for a fresh coherent snapshot after sibling writes"},{"ancestorTitles":[],"duration":138,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a late previous Answers-entry read cannot enable the current editor","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749559640,"status":"passed","title":"a late previous Answers-entry read cannot enable the current editor"},{"ancestorTitles":[],"duration":264,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a failed Answers-entry read stays closed until a successful retry","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749559779,"status":"passed","title":"a failed Answers-entry read stays closed until a successful retry"},{"ancestorTitles":[],"duration":107,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"leaving a pending direct Answers entry still loads the workspace header","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749560043,"status":"passed","title":"leaving a pending direct Answers entry still loads the workspace header"}],"endTime":1793749560151,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\application-workspace-overlay.test.tsx","startTime":1793749553307,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":1105,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"row status/edit/delete controls retain selection and do not open the workspace","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749560910,"status":"passed","title":"row status/edit/delete controls retain selection and do not open the workspace"},{"ancestorTitles":[],"duration":275,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["TestingLibraryElementError: Unable to find an accessible element with the role \"button\" and name \"Quick status\"\n\nThere are no accessible roles. But there might be some inaccessible roles. If you wish to access them, then set the `hidden` option to `true`. Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mØstlandet\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mPlatform engineer\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mCustom review\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mDate Applied\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m8/1/2026\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mDays\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m2\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mLocation\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mTromsø\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSalary\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m-\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mJob URL\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen listing\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n\u001b[36m\u001b[39m\n at Object.getElementError (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\config.js:37:19)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:76:38\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:52:17\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:95:19\n at getByRole (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\job-table-density.test.tsx:73:33)\n at runNextTicks (node:internal/process/task_queues:65:5)\n at listOnTimeout (node:internal/timers:597:9)\n at processTimers (node:internal/timers:571:7)"],"fullName":"en mobile row actions remain direct, named and independent of row navigation","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749562016,"status":"failed","title":"en mobile row actions remain direct, named and independent of row navigation"},{"ancestorTitles":[],"duration":452,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["TestingLibraryElementError: Unable to find an accessible element with the role \"button\" and name \"Hurtigstatus\"\n\nThere are no accessible roles. But there might be some inaccessible roles. If you wish to access them, then set the `hidden` option to `true`. Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mØstlandet\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mPlatform engineer\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mCustom review\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSøkt dato\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m1.8.2026\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mDager\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m2\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSted\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mTromsø\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mLønn\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m-\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mJobb-URL\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne stilling\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n\u001b[36m\u001b[39m\n at Object.getElementError (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\config.js:37:19)\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:76:38\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:52:17\n at C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\node_modules\\@testing-library\\dom\\dist\\query-helpers.js:95:19\n at getByRole (C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\job-table-density.test.tsx:73:33)\n at runNextTicks (node:internal/process/task_queues:65:5)\n at listOnTimeout (node:internal/timers:597:9)\n at processTimers (node:internal/timers:571:7)"],"fullName":"nb mobile row actions remain direct, named and independent of row navigation","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749562302,"status":"failed","title":"nb mobile row actions remain direct, named and independent of row navigation"},{"ancestorTitles":[],"duration":1052,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"table sort, page-size and optional columns keep their existing independent contracts","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749562754,"status":"passed","title":"table sort, page-size and optional columns keep their existing independent contracts"},{"ancestorTitles":[],"duration":151,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Trash select-all and bulk restore use the original IDs without workspace navigation","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749563806,"status":"passed","title":"Trash select-all and bulk restore use the original IDs without workspace navigation"},{"ancestorTitles":[],"duration":430,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"density preserves selected rows, query, page, custom status, columns and listing link without refetch","invocations":1,"location":null,"numPassingAsserts":9,"retryReasons":[],"startAt":1793749563957,"status":"passed","title":"density preserves selected rows, query, page, custom status, columns and listing link without refetch"},{"ancestorTitles":[],"duration":510,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"density is local and resets on unmount without writing settings or a saved view","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749564387,"status":"passed","title":"density is local and resets on unmount without writing settings or a saved view"},{"ancestorTitles":[],"duration":439,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"density survives an empty result and a failed refresh with the existing retry action","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793749564897,"status":"passed","title":"density survives an empty result and a failed refresh with the existing retry action"},{"ancestorTitles":[],"duration":532,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Bokmål display localizes standard statuses without changing API values or custom status filters","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749565336,"status":"passed","title":"Bokmål display localizes standard statuses without changing API values or custom status filters"},{"ancestorTitles":[],"duration":422,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"partial bulk failure refreshes successful rows and retains only failed visible IDs","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749565868,"status":"passed","title":"partial bulk failure refreshes successful rows and retains only failed visible IDs"},{"ancestorTitles":[],"duration":812,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"saved view create/apply/delete stays scoped to the signed-in account","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749566290,"status":"passed","title":"saved view create/apply/delete stays scoped to the signed-in account"},{"ancestorTitles":[],"duration":439,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"changing the result set clears selection before an old row can be bulk-updated","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749567102,"status":"passed","title":"changing the result set clears selection before an old row can be bulk-updated"}],"endTime":1793749567555,"message":" ● en mobile row actions remain direct, named and independent of row navigation\n\n TestingLibraryElementError: Unable to find an accessible element with the role \"button\" and name \"Quick status\"\n\n There are no accessible roles. But there might be some inaccessible roles. If you wish to access them, then set the `hidden` option to `true`. Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mØstlandet\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mPlatform engineer\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mCustom review\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mDate Applied\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m8/1/2026\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mDays\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m2\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mLocation\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mTromsø\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSalary\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m-\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mJob URL\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen listing\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n\n 71 | fireEvent.click(within(await screen.findByRole(\"dialog\")).getByRole(\"button\", { name: copy.cancel }));\n 72 | expect(mockedApi.delete).not.toHaveBeenCalled();\n > 73 | fireEvent.click(within(row).getByRole(\"button\", { name: copy.jobTableQuickStatus }));\n | ^\n 74 | fireEvent.click(await screen.findByRole(\"menuitem\", { name: copy.jobTableSetStatus.replace(\"{status}\", copy.statusInterview) }));\n 75 | await waitFor(() => expect(mockedApi.patch).toHaveBeenCalledWith(\"/jobapplications/42/status\", { status: \"Interview\" }));\n 76 | expect(screen.getByLabelText(\"Current route\")).toHaveTextContent(\"/jobs?q=platform\");\n\n at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)\n at node_modules/@testing-library/dom/dist/query-helpers.js:76:38\n at node_modules/@testing-library/dom/dist/query-helpers.js:52:17\n at node_modules/@testing-library/dom/dist/query-helpers.js:95:19\n at getByRole (src/job-table-density.test.tsx:73:33)\n\n ● nb mobile row actions remain direct, named and independent of row navigation\n\n TestingLibraryElementError: Unable to find an accessible element with the role \"button\" and name \"Hurtigstatus\"\n\n There are no accessible roles. But there might be some inaccessible roles. If you wish to access them, then set the `hidden` option to `true`. Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mØstlandet\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mPlatform engineer\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mCustom review\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSøkt dato\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m1.8.2026\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mDager\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m2\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mSted\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mTromsø\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mLønn\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m-\u001b[0m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mJobb-URL\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne stilling\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m

\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n\n 71 | fireEvent.click(within(await screen.findByRole(\"dialog\")).getByRole(\"button\", { name: copy.cancel }));\n 72 | expect(mockedApi.delete).not.toHaveBeenCalled();\n > 73 | fireEvent.click(within(row).getByRole(\"button\", { name: copy.jobTableQuickStatus }));\n | ^\n 74 | fireEvent.click(await screen.findByRole(\"menuitem\", { name: copy.jobTableSetStatus.replace(\"{status}\", copy.statusInterview) }));\n 75 | await waitFor(() => expect(mockedApi.patch).toHaveBeenCalledWith(\"/jobapplications/42/status\", { status: \"Interview\" }));\n 76 | expect(screen.getByLabelText(\"Current route\")).toHaveTextContent(\"/jobs?q=platform\");\n\n at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)\n at node_modules/@testing-library/dom/dist/query-helpers.js:76:38\n at node_modules/@testing-library/dom/dist/query-helpers.js:52:17\n at node_modules/@testing-library/dom/dist/query-helpers.js:95:19\n at getByRole (src/job-table-density.test.tsx:73:33)\n","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\job-table-density.test.tsx","startTime":1793749560159,"status":"failed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":2039,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Table/Board switches preserve query, complete membership, page, density and history without hidden reads","invocations":1,"location":null,"numPassingAsserts":14,"retryReasons":[],"startAt":1793749568275,"status":"passed","title":"Table/Board switches preserve query, complete membership, page, density and history without hidden reads"},{"ancestorTitles":[],"duration":225,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"direct Board and both switch directions retain exact result membership: ?q=Engineer&status=Custom+review","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749570314,"status":"passed","title":"direct Board and both switch directions retain exact result membership: ?q=Engineer&status=Custom+review"},{"ancestorTitles":[],"duration":250,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"direct Board and both switch directions retain exact result membership: ?q=absent","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749570539,"status":"passed","title":"direct Board and both switch directions retain exact result membership: ?q=absent"},{"ancestorTitles":[],"duration":1529,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Board uses the shared filter controls and saved query owner without fetching Table","invocations":1,"location":null,"numPassingAsserts":2,"retryReasons":[],"startAt":1793749570789,"status":"passed","title":"Board uses the shared filter controls and saved query owner without fetching Table"},{"ancestorTitles":[],"duration":251,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Trash stays a Table even when supplied a Board view parameter","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749572318,"status":"passed","title":"Trash stays a Table even when supplied a Board view parameter"},{"ancestorTitles":[],"duration":1062,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"saved filters applied in Board reset the Table page and refresh only the active population","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793749572569,"status":"passed","title":"saved filters applied in Board reset the Table page and refresh only the active population"}],"endTime":1793749573631,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\jobs-view-integration.test.tsx","startTime":1793749567565,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":187,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"dashboard attention card opens follow-up workspace","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749574484,"status":"passed","title":"dashboard attention card opens follow-up workspace"},{"ancestorTitles":[],"duration":116,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"empty dashboard prioritizes onboarding and suppresses meaningless analytics","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793749574671,"status":"passed","title":"empty dashboard prioritizes onboarding and suppresses meaningless analytics"},{"ancestorTitles":[],"duration":67,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"reminders open action routes tailored-cv gaps into the tailored cv workspace","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749574787,"status":"passed","title":"reminders open action routes tailored-cv gaps into the tailored cv workspace"},{"ancestorTitles":[],"duration":679,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"job table urgency signals and next actions route into the shared workspace flow","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793749574854,"status":"passed","title":"job table urgency signals and next actions route into the shared workspace flow"}],"endTime":1793749575534,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\daily-control-loop.test.tsx","startTime":1793749573638,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":["end-to-end trust loop"],"duration":359,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"end-to-end trust loop overview entry opens the canonical communication workspace without sending mail","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793749576370,"status":"passed","title":"overview entry opens the canonical communication workspace without sending mail"}],"endTime":1793749576730,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\src\\end-to-end-trust-loop.test.tsx","startTime":1793749575540,"status":"passed","summary":""}],"wasInterrupted":false} diff --git a/docs/ui-modernisation/visual-correction/evidence/applications-flat/FOCUS-CLIP-FAILURE.json b/docs/ui-modernisation/visual-correction/evidence/applications-flat/FOCUS-CLIP-FAILURE.json new file mode 100644 index 00000000..229ae04a --- /dev/null +++ b/docs/ui-modernisation/visual-correction/evidence/applications-flat/FOCUS-CLIP-FAILURE.json @@ -0,0 +1,37 @@ +{ + "screens": [ + { + "width": 320, + "language": "en", + "mode": "light", + "state": "table", + "violations": [] + } + ], + "journeys": [], + "aliases": [], + "focusChecks": [ + { + "width": 320, + "language": "en", + "mode": "light", + "outlineStyle": "solid", + "outlineWidth": "3px", + "clippedBy": [ + "DIV" + ] + } + ], + "errors": [], + "unexpectedWrites": [], + "mockedWrites": [], + "unavailableReads": [], + "blockedExternal": [ + "https://fonts.googleapis.com" + ], + "limits": [ + "controlled fixtures, not real backend integration", + "secondary service reads may return honest unavailable states", + "no native device, provider, model, security or release qualification" + ] +} \ No newline at end of file diff --git a/docs/ui-modernisation/visual-correction/evidence/applications-flat/PILOT.json b/docs/ui-modernisation/visual-correction/evidence/applications-flat/PILOT.json new file mode 100644 index 00000000..e786fc3c --- /dev/null +++ b/docs/ui-modernisation/visual-correction/evidence/applications-flat/PILOT.json @@ -0,0 +1,103 @@ +{ + "screens": [ + { + "width": 320, + "language": "en", + "mode": "light", + "state": "table", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "table-focused", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "add-job", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "board", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "detail", + "violations": [] + }, + { + "width": 320, + "language": "en", + "mode": "light", + "state": "detail-expanded", + "violations": [] + } + ], + "journeys": [ + { + "width": 320, + "language": "en", + "mode": "light", + "searchBoardPreciseStatusDetailContextReturn": "PASS" + } + ], + "aliases": [ + { + "legacy": "/kanban?q=nurse#retained", + "destination": "/jobs", + "queryPreserved": "PASS" + }, + { + "legacy": "/applications/42?section=overview", + "destination": "/jobs/42", + "queryPreserved": "PASS" + }, + { + "legacy": "/correspondence/review?q=recorded#retained", + "destination": "/correspondence", + "queryPreserved": "PASS" + } + ], + "focusChecks": [ + { + "width": 320, + "language": "en", + "mode": "light", + "outlineStyle": "solid", + "outlineWidth": "3px", + "clippedBy": [] + } + ], + "errors": [], + "unexpectedWrites": [], + "mockedWrites": [ + { + "width": 320, + "language": "en", + "mode": "light", + "status": "Waiting" + } + ], + "unavailableReads": [], + "blockedExternal": [ + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com", + "https://fonts.googleapis.com" + ], + "limits": [ + "controlled fixtures, not real backend integration", + "secondary service reads may return honest unavailable states", + "no native device, provider, model, security or release qualification" + ] +} \ No newline at end of file diff --git a/docs/ui-modernisation/visual-correction/evidence/applications-flat/table-focused-en-light-320.png b/docs/ui-modernisation/visual-correction/evidence/applications-flat/table-focused-en-light-320.png new file mode 100644 index 0000000000000000000000000000000000000000..4f70002ccde16a1b7d253d3d68974a98a171b6b6 GIT binary patch literal 58853 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

7eht-NN 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 ['en', 'nb'].flatMap(language => ['light', 'dark'].map(mode => [width, language, mode]))); -const out = path.resolve(import.meta.dirname, visualMatrix ? '../../docs/ui-modernisation/visual-correction/evidence/applications' : '../../docs/ui-modernisation/evidence/applications/browser'); +const out = path.resolve(import.meta.dirname, flatWorkspace ? '../../docs/ui-modernisation/visual-correction/evidence/applications-flat' : visualMatrix ? '../../docs/ui-modernisation/visual-correction/evidence/applications' : '../../docs/ui-modernisation/evidence/applications/browser'); fs.mkdirSync(out, { recursive: true }); -const report = { screens: [], journeys: [], aliases: [], errors: [], unexpectedWrites: [], mockedWrites: [], unavailableReads: [], blockedExternal: [] }; +const report = { screens: [], journeys: [], aliases: [], focusChecks: [], errors: [], unexpectedWrites: [], mockedWrites: [], unavailableReads: [], blockedExternal: [] }; const browser = await chromium.launch(); try { for (const [width, language, mode] of configurations) { @@ -55,6 +57,24 @@ try { const search = page.getByRole('textbox', { name: language === 'en' ? 'Search' : 'Søk', exact: true }); await search.waitFor(); await page.locator('[data-job-row-id="42"], [data-job-card-id="42"]').first().waitFor(); await scan('table'); + if (flatWorkspace) { + await page.keyboard.press('Tab'); + const row = page.locator('[data-job-row-id="42"]').first(); await row.focus(); await expect(row).toBeFocused(); + const focus = await row.evaluate(element => { + const style = getComputedStyle(element), rect = element.getBoundingClientRect(); + const extension = parseFloat(style.outlineWidth) + parseFloat(style.outlineOffset); + const clippedBy = []; + for (let parent = element.parentElement; parent; parent = parent.parentElement) { + const bounds = parent.getBoundingClientRect(), overflow = getComputedStyle(parent).overflowX; + if (['hidden', 'clip', 'auto', 'scroll'].includes(overflow) && (rect.left - extension < bounds.left || rect.right + extension > bounds.right)) clippedBy.push(parent.tagName); + } + return { outlineStyle: style.outlineStyle, outlineWidth: style.outlineWidth, clippedBy }; + }); + report.focusChecks.push({ width, language, mode, ...focus }); + assert.notEqual(focus.outlineStyle, 'none'); + if (width < 768) assert.deepEqual(focus.clippedBy, [], 'mobile row focus ring is clipped'); + await scan('table-focused'); + } if (visualMatrix) { await page.getByRole('button', { name: language === 'en' ? 'Add Job' : 'Legg til jobb', exact: true }).click(); await expect(page.getByRole('dialog')).toBeVisible(); await scan('add-job'); @@ -78,6 +98,11 @@ try { const main = await page.getByRole('tabpanel').boundingBox(), side = await aside.boundingBox(); assert.ok(width > 1000 ? side.x > main.x + main.width - 2 && Math.abs(side.y - main.y) < 2 : side.y >= main.y + main.height - 2); await scan('detail'); + if (flatWorkspace) { + await page.getByRole('button', { name: language === 'en' ? 'Job details' : 'Stillingsdetaljer', exact: true }).click(); + await expect(page.getByText('Recorded source advertisement.', { exact: true })).toBeVisible(); + await scan('detail-expanded'); + } await page.getByRole('button', { name: language === 'en' ? 'Back to applications' : 'Tilbake til søknader', exact: true }).click(); await page.waitForURL(/view=board/); assert.equal(new URL(page.url()).searchParams.get('q'), 'nurse'); await page.locator('[data-kanban-card-id="42"] [role="button"]').waitFor(); @@ -93,7 +118,7 @@ try { } await context.close(); } - assert.equal(report.screens.length, configurations.length * (visualMatrix ? 4 : 3)); assert.equal(report.journeys.length, configurations.length); assert.equal(report.mockedWrites.length, configurations.length); assert.equal(report.aliases.length, visualMatrix ? 3 : 0); + assert.equal(report.screens.length, configurations.length * (flatWorkspace ? 6 : visualMatrix ? 4 : 3)); assert.equal(report.journeys.length, configurations.length); assert.equal(report.mockedWrites.length, configurations.length); assert.equal(report.aliases.length, visualMatrix ? 3 : 0); assert.deepEqual(report.errors, []); assert.deepEqual(report.unexpectedWrites, []); assert.ok(report.blockedExternal.every(origin => origin === 'https://fonts.googleapis.com')); console.log(`PASS:${report.journeys.length} controlled table/board/detail journeys,${report.screens.length} axe scans/captures;${report.mockedWrites.length} mocked status writes.`); diff --git a/job-tracker-ui/src/components/JobTable.tsx b/job-tracker-ui/src/components/JobTable.tsx index d860cf12..80df0f1c 100644 --- a/job-tracker-ui/src/components/JobTable.tsx +++ b/job-tracker-ui/src/components/JobTable.tsx @@ -673,15 +673,16 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col data-content-density={density} sx={{ mt: 1.5, - overflow: "hidden", - borderRadius: 1, - border: "1px solid", + overflow: isMobile ? "visible" : "hidden", + borderRadius: isMobile ? 0 : 1, + border: isMobile ? 0 : "1px solid", borderColor: "divider", + backgroundColor: isMobile ? "transparent" : "background.paper", boxShadow: "none", }} > {isMobile ? ( - + 0 && !selectedAllOnPage} onChange={(e) => toggleSelectAll(e.target.checked)} />} label={t("jobTableSelectAll")} sx={{ mr: 0 }} /> @@ -690,7 +691,7 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col {!jobsResource.loading && !jobsResource.error && rowModels.map(({ job, toneName, actionSignals, tags, appliedDateLabel, isSelected }) => { const compactTags = tags.slice(0, 6); return ( - : null} - + {actionSignals.length > 0 && {actionSignals.map((signal) => ( ))} - + } {columns.dateApplied ? ( - - {t("jobTableDateApplied")} + + {t("jobTableDateApplied")} {appliedDateLabel} ) : null} {columns.daysSince ? ( - - {t("jobTableDays")} + + {t("jobTableDays")} {job.daysSince} ) : null} - - {t("jobTableLocation")} + + {t("jobTableLocation")} {job.location ?? "-"} - - {t("addJobModalSalary")} + + {t("addJobModalSalary")} {formatSalary(job) ?? "-"} @@ -785,25 +785,17 @@ export default function JobTable({ refreshToken, pageSize, onPageSizeChange, col ) : null} - - - + + setEditJobId(job.id)}> + { setStatusJobId(job.id); setStatusAnchor(e.currentTarget); }}> {(mode === "trash" || (includeDeleted && job.isDeleted)) ? ( - + void restore(job.id)}> ) : ( - + void softDelete(job)}> )} - + ); })} {filteredJobs.length === 0 && !jobsResource.loading && !jobsResource.error ? ( diff --git a/job-tracker-ui/src/job-table-density.test.tsx b/job-tracker-ui/src/job-table-density.test.tsx index ffbe7b17..cac6df5f 100644 --- a/job-tracker-ui/src/job-table-density.test.tsx +++ b/job-tracker-ui/src/job-table-density.test.tsx @@ -51,6 +51,38 @@ test("row status/edit/delete controls retain selection and do not open the works expect(screen.getByLabelText("Current route")).toHaveTextContent(/^\/jobs$/); }); +test.each(["en", "nb"] as const)("%s mobile row actions remain direct, named and independent of row navigation", async language => { + const originalMedia = Object.getOwnPropertyDescriptor(window, "matchMedia"); + Object.defineProperty(window, "matchMedia", { configurable: true, writable: true, value: (query: string) => ({ + matches: query.includes("max-width:767.95px"), media: query, onchange: null, + addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: () => true, + }) }); + try { + localStorage.setItem("uiLanguage", language); + const copy = translations[language]; + show("jobs", "?q=platform"); + const row = await screen.findByRole("link", { name: copy.jobTableOpenJob.replace("{title}", job.jobTitle).replace("{company}", job.company.name) }); + fireEvent.click(within(row).getByRole("checkbox")); + fireEvent.click(within(row).getByRole("button", { name: copy.jobTableEdit })); + expect(screen.getByRole("dialog", { name: "Edit job" })).toBeVisible(); + fireEvent.click(screen.getByText("Close editor")); + expect(within(row).getByRole("checkbox")).toBeChecked(); + fireEvent.click(within(row).getByRole("button", { name: copy.jobTableSoftDelete })); + fireEvent.click(within(await screen.findByRole("dialog")).getByRole("button", { name: copy.cancel })); + expect(mockedApi.delete).not.toHaveBeenCalled(); + fireEvent.click(await within(row).findByRole("button", { name: copy.jobTableQuickStatus })); + fireEvent.click(await screen.findByRole("menuitem", { name: copy.jobTableSetStatus.replace("{status}", copy.statusInterview) })); + await waitFor(() => expect(mockedApi.patch).toHaveBeenCalledWith("/jobapplications/42/status", { status: "Interview" })); + expect(screen.getByLabelText("Current route")).toHaveTextContent("/jobs?q=platform"); + fireEvent.keyDown(row, { key: "Enter" }); + expect(screen.getByLabelText("Current route")).toHaveTextContent(/^\/jobs\/42$/); + expect(window.history.state.jobListFocusId).toBe(job.id); + } finally { + if (originalMedia) Object.defineProperty(window, "matchMedia", originalMedia); + else delete (window as Partial).matchMedia; + } +}); + test("table sort, page-size and optional columns keep their existing independent contracts", async () => { show("jobs", "?q=platform&location=Troms%C3%B8"); await screen.findByRole("row", { name: /open platform engineer/i }); diff --git a/job-tracker-ui/src/views/ApplicationWorkspacePage.tsx b/job-tracker-ui/src/views/ApplicationWorkspacePage.tsx index e2f86490..a8dede7e 100644 --- a/job-tracker-ui/src/views/ApplicationWorkspacePage.tsx +++ b/job-tracker-ui/src/views/ApplicationWorkspacePage.tsx @@ -4,7 +4,7 @@ import { } from "react-router-dom"; import { - Accordion, AccordionDetails, AccordionSummary, Alert, Box, Button, Chip, IconButton, Paper, + Accordion, AccordionDetails, AccordionSummary, Alert, Box, Button, Chip, IconButton, Skeleton, Stack, Tab, Tabs, Tooltip, Typography, } from "@mui/material"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; @@ -218,14 +218,14 @@ export function ApplicationWorkspace({ return ( - - + + - + {t("workspace")} {overview ? : null} @@ -252,11 +252,11 @@ export function ApplicationWorkspace({ variant="scrollable" scrollButtons="auto" aria-label={t("workspaceSections")} - sx={{ px: { xs: 0.5, sm: 1.5 }, borderTop: 1, borderColor: "divider", minHeight: 46 }} + sx={{ borderBottom: 1, borderColor: "divider", minHeight: 46 }} > {WORKSPACE_SECTIONS.map((s) => )} - + @@ -288,22 +288,22 @@ export function ApplicationWorkspace({ />} {section === "application" && subsection === "submission" && jobId > 0 && } {section === "timeline" && subsection === "activity" && jobId > 0 && } - {section === "timeline" && subsection === "correspondence" && jobId > 0 && } + {section === "timeline" && subsection === "correspondence" && jobId > 0 && } } {section === "documents" && jobId > 0 && <> - + }> } {section === "tasks" && jobId > 0 && <> - } onClick={() => setEditOpen(true)}>{t("workspaceEdit")}}> + } onClick={() => setEditOpen(true)}>{t("workspaceEdit")}}> {overview?.notes || t("workspaceNoNotes")} - + } {overview ? @@ -358,7 +358,7 @@ function WorkspaceHeader({ overview, onEdit }: { overview: WorkspaceOverview | n const { language, t } = useI18n(); if (!overview) return ; return ( - + {overview.jobUrl ? : null} @@ -440,7 +440,7 @@ function OverviewSection({ overview, onGo, onReload, onEdit }: { return ( {overview.nextStep ? ( - + {nextStepLabel} {nextStepReason} }> + {t("workspaceRefresh")}}> {overview.recentActivity.length === 0 ? ( {t("workspaceNoActivity")} ) : ( @@ -510,11 +510,11 @@ function OverviewDetails({ overview, onEdit }: { overview: WorkspaceOverview; on return ( {panels.map((panel) => ( - setExpanded((current) => ({ ...current, [panel.id]: open }))} disableGutters elevation={0} sx={{ border: 1, borderColor: "divider", "&:not(:last-child)": { borderBottom: 0 }, "&:before": { display: "none" } }}> + setExpanded((current) => ({ ...current, [panel.id]: open }))} disableGutters elevation={0} sx={{ borderTop: 1, borderBottom: 1, borderInline: 0, borderColor: "divider", borderRadius: 0, "&:first-of-type, &:last-of-type": { borderRadius: 0 }, "&:not(:last-child)": { borderBottom: 0 }, "&:before": { display: "none" } }}> { triggers.current[panel.id] = node; }} expandIcon={} aria-controls={`${prefix}-${panel.id}-content`} id={`${prefix}-${panel.id}-header`}> {panel.title} - {panel.content} + {panel.content} ))} @@ -552,7 +552,7 @@ function JobDetailsSection({ overview, onEdit }: { overview: WorkspaceOverview | ]; return ( - + {t("workspaceApplicationInfo")} @@ -576,9 +576,9 @@ function JobDetailsSection({ overview, onEdit }: { overview: WorkspaceOverview | {overview.notes} ) : null} - + - + {t("workspaceJobDescription")} {!overview.hasJobDescription ? ( {t("workspaceAddAdvert")}}> @@ -600,7 +600,7 @@ function JobDetailsSection({ overview, onEdit }: { overview: WorkspaceOverview | ) : null} )} - + ); }