From ca519cacbec6ee8e385927ad31356dacc18b2f2d Mon Sep 17 00:00:00 2001 From: cesnimda Date: Tue, 3 Nov 2026 09:50:59 +0100 Subject: [PATCH] fix(i18n): reject invalid document upload dates --- docs/i18n/CURRENT_STATUS.md | 2 ++ docs/i18n/DIRECT_CATALOGUE_REVIEW.md | 14 +++++++++++++ docs/i18n/DOCUMENT_DATE_VALIDATION.md | 11 ++++++++++ .../document-dates-SOURCE_MANIFEST.json | 15 +++++++++++++ docs/i18n/evidence/document-dates-red.json | 1 + docs/i18n/evidence/document-dates-tests.json | 1 + job-tracker-ui/src/documents-page.test.tsx | 21 +++++++++++++++++++ job-tracker-ui/src/views/DocumentsPage.tsx | 11 ++++++++-- 8 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 docs/i18n/DIRECT_CATALOGUE_REVIEW.md create mode 100644 docs/i18n/DOCUMENT_DATE_VALIDATION.md create mode 100644 docs/i18n/evidence/document-dates-SOURCE_MANIFEST.json create mode 100644 docs/i18n/evidence/document-dates-red.json create mode 100644 docs/i18n/evidence/document-dates-tests.json diff --git a/docs/i18n/CURRENT_STATUS.md b/docs/i18n/CURRENT_STATUS.md index fbce6769..cdb9435b 100644 --- a/docs/i18n/CURRENT_STATUS.md +++ b/docs/i18n/CURRENT_STATUS.md @@ -1,5 +1,7 @@ # Current localisation continuation +3 November 2026 — independent document-date fix: invalid uploaded wall-clock dates/times/trailing junk now show the existing EN/NB unknown-date message instead of JavaScript rollover.40 tests/3 suites, typecheck, scoped lint and build pass; see DOCUMENT_DATE_VALIDATION.md. All four historical direct-catalogue accesses have contextual dispositions in DIRECT_CATALOGUE_REVIEW.md; current full extraction/backend literals/every-string triage remain open. No new locales or release approval. This branch is not yet integrated into A3 dashboard/application work. + Register portability correction: schema 3 explicitly normalises CRLF to LF when hashing reviewed TS/TSX/JSON text and the original inventory; historicalSourceSha256 retains the original inventory's raw-hash meaning. This avoids treating Git checkout line-ending conversion as a source edit. Integration initially detected the raw inventory mismatch; original snapshot contents and historical source hashes were preserved, and both worktrees are revalidated with the declared encoding. This is evidence portability, not renewed runtime execution. 2 November 2026. Historical 188 dynamic-call census finite key-domain review COMPLETE; full I18N-00 / European locale release acceptance remains INCOMPLETE. Original source-bound snapshots are retained under 00/. Machine register schema 2 binds inventory indices, source hashes and selected owner dependencies; 108 original plus 80 supplemental calls cover all 188 indices without overlap. Static review does not establish all translator sensitivity/context, every visible/backend string, grammar/plural quality, runtime coverage or native review. diff --git a/docs/i18n/DIRECT_CATALOGUE_REVIEW.md b/docs/i18n/DIRECT_CATALOGUE_REVIEW.md new file mode 100644 index 00000000..35aebf43 --- /dev/null +++ b/docs/i18n/DIRECT_CATALOGUE_REVIEW.md @@ -0,0 +1,14 @@ +# Historical direct catalogue access review + +3 November 2026. All four entries in the frozen 00/DIRECT_CATALOGUE_ACCESS.json are in I18nProvider.tsx. Reviewed actual current callers and source, not re-extracted as a claim of complete current coverage. + +| Historical expression | Context and disposition | +|---|---| +| translations[l].settingsLanguageSaveFailed | Public static account-preference error copy, no runtime private value. Uses requested language, guarded by save sequence/current language before showing feedback. Deliberate provider-internal access; calling the context hook inside its owner is inappropriate. Retain. | +| translations[l].retry | Static retry action label in the same guarded feedback; no interpolation/private data. Retain. | +| translations[language][key] | Central typed message lookup inside t, passed to interpolation; all callers use this message owner. React callers render text; this review does not certify every sink. Retain. | +| translations.en[key] | Deterministic English fallback for the central lookup. No country/document-language coupling. Retain. | + +The provider's TranslationKey/UiLanguage contracts and catalogue completeness tests constrain these accesses; sequence guards prevent obsolete-save feedback/retries. No new catalogue bypass or runtime change was required. Existing provider/catalogue tests pass within the40-case document-date qualification; this is not native linguistic or full security acceptance. + +Original inventory/hash/line records are immutable historical evidence. Current source identity is bound in document-date SOURCE_MANIFEST.json. This closes contextual classification of the four historical direct accesses only. Current full re-extraction, non-catalogue/backend literal inventory and every-string sensitivity/caller review remain incomplete. No runtime user content was exported or translated externally. diff --git a/docs/i18n/DOCUMENT_DATE_VALIDATION.md b/docs/i18n/DOCUMENT_DATE_VALIDATION.md new file mode 100644 index 00000000..10274b65 --- /dev/null +++ b/docs/i18n/DOCUMENT_DATE_VALIDATION.md @@ -0,0 +1,11 @@ +# Document upload wall-clock date correction + +3 November 2026. Independent ordinary application fix, branch `codex/i18n-document-dates` from published d4b938fa. Not integrated into A3 yet; no wholesale merge of this older integration-derived tree. + +Reproduced: the document index accepted an ISO prefix and let JavaScript normalise invalid wall-clock components. `2026-02-30T09:15:00`, hour24, minute61 and trailing junk displayed plausible timestamps. Eight EN/NB regression cases failed before the fix; two valid fractional-second cases passed. These failures are retained in evidence/document-dates-red.json;21 unrelated cases were skipped in that focused red execution. + +The existing uploaded-local branch now accepts the complete unzoned .NET-style timestamp (optional1–7 fractional digits) and round-trips all calendar/time fields before formatting. Invalid input uses the existing localised Date not recorded message and emits no fabricated time element. Valid wall-clock components remain unchanged across time zones using the existing UTC formatting carrier. The raw datetime attribute remains unchanged. No API date-kind semantics, server data, UTC-history formatting, document content, download behavior, revisions or navigation changes. No new locale key/dependency/schema. + +Final validation: **40 tests /3 suites PASSED**, documents31 + provider6 + catalogue3. Tests include metadata filters/paging/history, source links, all seven resource kinds, download/focus/cancellation, ownership-safe read behavior, both languages, invalid dates and valid .NET fractional seconds. All document tests assert no POST/PUT/PATCH/DELETE. Typecheck, scoped zero-warning lint, production build and diff whitespace check PASSED. An intermediate command used a nonexistent catalogue-test filename:37 cases passed but that execution failed one suite; it is not counted as passing. Corrected final run uses translation-catalogue.test.ts. No fresh browser/backend/native/provider qualification. + +Rollback: revert this bounded view/parser and test commit; no data rollback. Broader document UTC date validation, partial-date semantics outside this surface, DST/native reviews and full European locale architecture remain open. No release or production qualification inferred. diff --git a/docs/i18n/evidence/document-dates-SOURCE_MANIFEST.json b/docs/i18n/evidence/document-dates-SOURCE_MANIFEST.json new file mode 100644 index 00000000..dab9e9a9 --- /dev/null +++ b/docs/i18n/evidence/document-dates-SOURCE_MANIFEST.json @@ -0,0 +1,15 @@ +{ + "base": "d4b938fafbf10541b62134293cea8299f25c4031", + "recordedAtUtc": "2026-11-03T08:50:34.776817+00:00", + "policy": "LF-normalised SHA256 text", + "files": { + "job-tracker-ui/src/views/DocumentsPage.tsx": "2a3187938d7f61cc1d723bae5b784f09707713606b523db176d6df6d05a91c3d", + "job-tracker-ui/src/documents-page.test.tsx": "abfa8c4bef73499c0546f7e9b8a091793b8c273f829b51159ae115fc54aa4ed3", + "job-tracker-ui/src/i18n/I18nProvider.tsx": "d22b5d033d0e405ffb5d581c752d61a24056d1e496f5f6a2f1baecef500f2113", + "docs/i18n/00/DIRECT_CATALOGUE_ACCESS.json": "c470c52c500d79f51c4cedd073c2a8474ae73b832e531df3c0c38369993cae3f", + "docs/i18n/DOCUMENT_DATE_VALIDATION.md": "602cd31d84eed1e59ed000159bdc8b998b0dbdc5b7c965ad51831d26a16b31d6", + "docs/i18n/DIRECT_CATALOGUE_REVIEW.md": "4eb88d2d1da2ed0cd52d49fc8dc7f11d1943d169c240e56ae3562d298bc6eb6a", + "docs/i18n/evidence/document-dates-tests.json": "227187b5a02473f442c8600b434e5f0922fa63ba13bfb9355254b9a19b7d4e81", + "docs/i18n/evidence/document-dates-red.json": "430ec89f685c2558d443677c596a12b587829a9a45e3f29dc03e042d3685a074" + } +} diff --git a/docs/i18n/evidence/document-dates-red.json b/docs/i18n/evidence/document-dates-red.json new file mode 100644 index 00000000..087e3d3b --- /dev/null +++ b/docs/i18n/evidence/document-dates-red.json @@ -0,0 +1 @@ +{"numFailedTestSuites":1,"numFailedTests":8,"numPassedTestSuites":0,"numPassedTests":2,"numPendingTestSuites":0,"numPendingTests":21,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":1,"numTotalTests":31,"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":1793695641023,"success":false,"testResults":[{"assertionResults":[{"ancestorTitles":["en unknown attachment purposes"],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en unknown attachment purposes uses the localized Other label for constructor","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695644740,"status":"pending","title":"uses the localized Other label for constructor"},{"ancestorTitles":["en unknown attachment purposes"],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en unknown attachment purposes uses the localized Other label for toString","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695644740,"status":"pending","title":"uses the localized Other label for toString"},{"ancestorTitles":["en unknown attachment purposes"],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en unknown attachment purposes uses the localized Other label for __proto__","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695644740,"status":"pending","title":"uses the localized Other label for __proto__"},{"ancestorTitles":["nb unknown attachment purposes"],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb unknown attachment purposes uses the localized Other label for constructor","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695644740,"status":"pending","title":"uses the localized Other label for constructor"},{"ancestorTitles":["nb unknown attachment purposes"],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb unknown attachment purposes uses the localized Other label for toString","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695644740,"status":"pending","title":"uses the localized Other label for toString"},{"ancestorTitles":["nb unknown attachment purposes"],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb unknown attachment purposes uses the localized Other label for __proto__","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695644740,"status":"pending","title":"uses the localized Other label for __proto__"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":4138,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["Error: Unable to find an element with the text: Date not recorded. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mYour documents\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen the original workspace to edit a CV, draft or file. Recorded application snapshots keep their captured contents.\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[0mRefresh\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[0mSearch documents\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[0mSearch documents\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:861:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"en uploaded wall-clock dates does not invent a timestamp from 2026-02-30T09:15:00","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793695644740,"status":"failed","title":"does not invent a timestamp from 2026-02-30T09:15:00"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":4060,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["Error: Unable to find an element with the text: Date not recorded. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mYour documents\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen the original workspace to edit a CV, draft or file. Recorded application snapshots keep their captured contents.\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[0mRefresh\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[0mSearch documents\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[0mSearch documents\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:861:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"en uploaded wall-clock dates does not invent a timestamp from 2026-02-12T24:15:00","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793695648878,"status":"failed","title":"does not invent a timestamp from 2026-02-12T24:15:00"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":4058,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["Error: Unable to find an element with the text: Date not recorded. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mYour documents\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen the original workspace to edit a CV, draft or file. Recorded application snapshots keep their captured contents.\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[0mRefresh\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[0mSearch documents\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[0mSearch documents\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:861:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"en uploaded wall-clock dates does not invent a timestamp from 2026-02-12T09:61:00","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793695652938,"status":"failed","title":"does not invent a timestamp from 2026-02-12T09:61:00"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":4054,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["Error: Unable to find an element with the text: Date not recorded. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mYour documents\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen the original workspace to edit a CV, draft or file. Recorded application snapshots keep their captured contents.\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[0mRefresh\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[0mSearch documents\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[0mSearch documents\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:861:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"en uploaded wall-clock dates does not invent a timestamp from 2026-02-12T09:15:00junk","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793695656996,"status":"failed","title":"does not invent a timestamp from 2026-02-12T09:15:00junk"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":90,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en uploaded wall-clock dates preserves fractional-second wall-clock metadata without timezone conversion","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695661051,"status":"passed","title":"preserves fractional-second wall-clock metadata without timezone conversion"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":4043,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["Error: Unable to find an element with the text: Dato er ikke registrert. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mDine dokumenter\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne det opprinnelige arbeidsområdet for å redigere en CV, en kladd eller en fil. Lagrede øyeblikksbilder av søknader beholder innholdet som ble lagret.\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[0mOppdater\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øk i dokumenter\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øk i dokumenter\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:861:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"nb uploaded wall-clock dates does not invent a timestamp from 2026-02-30T09:15:00","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793695661141,"status":"failed","title":"does not invent a timestamp from 2026-02-30T09:15:00"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":4052,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["Error: Unable to find an element with the text: Dato er ikke registrert. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mDine dokumenter\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne det opprinnelige arbeidsområdet for å redigere en CV, en kladd eller en fil. Lagrede øyeblikksbilder av søknader beholder innholdet som ble lagret.\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[0mOppdater\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øk i dokumenter\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øk i dokumenter\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:861:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"nb uploaded wall-clock dates does not invent a timestamp from 2026-02-12T24:15:00","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793695665184,"status":"failed","title":"does not invent a timestamp from 2026-02-12T24:15:00"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":4045,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["Error: Unable to find an element with the text: Dato er ikke registrert. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mDine dokumenter\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne det opprinnelige arbeidsområdet for å redigere en CV, en kladd eller en fil. Lagrede øyeblikksbilder av søknader beholder innholdet som ble lagret.\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[0mOppdater\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øk i dokumenter\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øk i dokumenter\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:861:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"nb uploaded wall-clock dates does not invent a timestamp from 2026-02-12T09:61:00","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793695669236,"status":"failed","title":"does not invent a timestamp from 2026-02-12T09:61:00"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":4052,"failing":false,"failureDetails":[{"name":"TestingLibraryElementError"}],"failureMessages":["Error: Unable to find an element with the text: Dato er ikke registrert. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\nIgnored nodes: comments, script, style\n\u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mDine dokumenter\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne det opprinnelige arbeidsområdet for å redigere en CV, en kladd eller en fil. Lagrede øyeblikksbilder av søknader beholder innholdet som ble lagret.\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[0mOppdater\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øk i dokumenter\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øk i dokumenter\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-each\\build\\index.js:80:140)\n at Promise.finally.completed (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1561:28)\n at new Promise ()\n at callAsyncCircusFn (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1501:10)\n at _callCircusTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1011:40)\n at _runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:951:3)\n at C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:853:7\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:866:11)\n at _runTestsForDescribeBlock (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:861:11)\n at run (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:765:3)\n at runAndTransformResultsToJestFormat (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\jestAdapterInit.js:1993:21)\n at jestAdapter (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-circus\\build\\runner.js:111:19)\n at runTestInternal (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:276:16)\n at runTest (C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\node_modules\\jest-runner\\build\\index.js:344:7)"],"fullName":"nb uploaded wall-clock dates does not invent a timestamp from 2026-02-12T09:15:00junk","invocations":1,"location":null,"numPassingAsserts":4,"retryReasons":[],"startAt":1793695673281,"status":"failed","title":"does not invent a timestamp from 2026-02-12T09:15:00junk"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":70,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb uploaded wall-clock dates preserves fractional-second wall-clock metadata without timezone conversion","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695677333,"status":"passed","title":"preserves fractional-second wall-clock metadata without timezone conversion"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] validates URL filters and reads one metadata page with literal Nordic search","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] validates URL filters and reads one metadata page with literal Nordic search"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] server pagination and filter history preserve unknown query, hash and router state","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] server pagination and filter history preserve unknown query, hash and router state"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] literal search all remains free text and preserves unrelated navigation context","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] literal search all remains free text and preserves unrelated navigation context"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] a batched sort selection and immediate search preserve both filters and navigation context","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] a batched sort selection and immediate search preserve both filters and navigation context"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] incompatible pending and failed queries hide old actions and late results cannot replace current metadata","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] incompatible pending and failed queries hide old actions and late results cannot replace current metadata"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] Retry is one guarded GET and a completion after leaving cannot publish or start follow-up work","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] Retry is one guarded GET and a completion after leaving cannot publish or start follow-up work"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] a true empty index, filtered no-match and request failure remain distinct","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] a true empty index, filtered no-match and request failure remain distinct"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] English and Bokmål presentation changes preserve query context without a metadata refetch","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] English and Bokmål presentation changes preserve query context without a metadata refetch"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] an out-of-range page offers explicit first-page recovery without claiming an empty index","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] an out-of-range page offers explicit first-page recovery without claiming an empty index"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] seven resource kinds retain exact source actions, frozen provenance and honest date labels","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] seven resource kinds retain exact source actions, frozen provenance and honest date labels"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] attachment download is explicit, API-relative and single-flight with original MIME, filename and URL disposal","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] attachment download is explicit, API-relative and single-flight with original MIME, filename and URL disposal"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] a completed download preserves deliberate Search focus instead of restoring the old button","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] a completed download preserves deliberate Search focus instead of restoring the old button"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] download errors retry only that file and late download completion after leaving creates no URL","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] download errors retry only that file and late download completion after leaving creates no URL"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] a published historical CV retains its percent-encoded Nordic public slug without fetching its body","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] a published historical CV retains its percent-encoded Nordic public slug without fetching its body"},{"ancestorTitles":[],"duration":null,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] malformed external and mismatched resource paths never become source, public or download actions","invocations":1,"location":null,"numPassingAsserts":0,"retryReasons":[],"startAt":1793695677404,"status":"pending","title":"[P7-07 documents] malformed external and mismatched resource paths never become source, public or download actions"}],"endTime":1793695677423,"message":" ● en uploaded wall-clock dates › does not invent a timestamp from 2026-02-30T09:15:00\n\n Unable to find an element with the text: Date not recorded. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mYour documents\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen the original workspace to edit a CV, draft or file. Recorded application snapshots keep their captured contents.\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[0mRefresh\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[0mSearch documents\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[0mSearch documents\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m 46 | expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible();\n | ^\n 47 | expect(document.querySelector('time')).not.toBeInTheDocument();\n 48 | });\n 49 |\n\n at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:163:27)\n at node_modules/@testing-library/dom/dist/query-helpers.js:86:33\n at findByText (src/documents-page.test.tsx:46:25)\n\n ● en uploaded wall-clock dates › does not invent a timestamp from 2026-02-12T24:15:00\n\n Unable to find an element with the text: Date not recorded. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mYour documents\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen the original workspace to edit a CV, draft or file. Recorded application snapshots keep their captured contents.\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[0mRefresh\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[0mSearch documents\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[0mSearch documents\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m 46 | expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible();\n | ^\n 47 | expect(document.querySelector('time')).not.toBeInTheDocument();\n 48 | });\n 49 |\n\n at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:163:27)\n at node_modules/@testing-library/dom/dist/query-helpers.js:86:33\n at findByText (src/documents-page.test.tsx:46:25)\n\n ● en uploaded wall-clock dates › does not invent a timestamp from 2026-02-12T09:61:00\n\n Unable to find an element with the text: Date not recorded. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mYour documents\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen the original workspace to edit a CV, draft or file. Recorded application snapshots keep their captured contents.\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[0mRefresh\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[0mSearch documents\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[0mSearch documents\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m 46 | expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible();\n | ^\n 47 | expect(document.querySelector('time')).not.toBeInTheDocument();\n 48 | });\n 49 |\n\n at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:163:27)\n at node_modules/@testing-library/dom/dist/query-helpers.js:86:33\n at findByText (src/documents-page.test.tsx:46:25)\n\n ● en uploaded wall-clock dates › does not invent a timestamp from 2026-02-12T09:15:00junk\n\n Unable to find an element with the text: Date not recorded. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mYour documents\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mOpen the original workspace to edit a CV, draft or file. Recorded application snapshots keep their captured contents.\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[0mRefresh\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[0mSearch documents\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[0mSearch documents\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m 46 | expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible();\n | ^\n 47 | expect(document.querySelector('time')).not.toBeInTheDocument();\n 48 | });\n 49 |\n\n at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:163:27)\n at node_modules/@testing-library/dom/dist/query-helpers.js:86:33\n at findByText (src/documents-page.test.tsx:46:25)\n\n ● nb uploaded wall-clock dates › does not invent a timestamp from 2026-02-30T09:15:00\n\n Unable to find an element with the text: Dato er ikke registrert. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mDine dokumenter\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne det opprinnelige arbeidsområdet for å redigere en CV, en kladd eller en fil. Lagrede øyeblikksbilder av søknader beholder innholdet som ble lagret.\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[0mOppdater\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øk i dokumenter\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øk i dokumenter\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m 46 | expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible();\n | ^\n 47 | expect(document.querySelector('time')).not.toBeInTheDocument();\n 48 | });\n 49 |\n\n at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:163:27)\n at node_modules/@testing-library/dom/dist/query-helpers.js:86:33\n at findByText (src/documents-page.test.tsx:46:25)\n\n ● nb uploaded wall-clock dates › does not invent a timestamp from 2026-02-12T24:15:00\n\n Unable to find an element with the text: Dato er ikke registrert. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mDine dokumenter\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne det opprinnelige arbeidsområdet for å redigere en CV, en kladd eller en fil. Lagrede øyeblikksbilder av søknader beholder innholdet som ble lagret.\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[0mOppdater\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øk i dokumenter\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øk i dokumenter\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m 46 | expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible();\n | ^\n 47 | expect(document.querySelector('time')).not.toBeInTheDocument();\n 48 | });\n 49 |\n\n at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:163:27)\n at node_modules/@testing-library/dom/dist/query-helpers.js:86:33\n at findByText (src/documents-page.test.tsx:46:25)\n\n ● nb uploaded wall-clock dates › does not invent a timestamp from 2026-02-12T09:61:00\n\n Unable to find an element with the text: Dato er ikke registrert. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mDine dokumenter\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne det opprinnelige arbeidsområdet for å redigere en CV, en kladd eller en fil. Lagrede øyeblikksbilder av søknader beholder innholdet som ble lagret.\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[0mOppdater\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øk i dokumenter\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øk i dokumenter\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m 46 | expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible();\n | ^\n 47 | expect(document.querySelector('time')).not.toBeInTheDocument();\n 48 | });\n 49 |\n\n at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:163:27)\n at node_modules/@testing-library/dom/dist/query-helpers.js:86:33\n at findByText (src/documents-page.test.tsx:46:25)\n\n ● nb uploaded wall-clock dates › does not invent a timestamp from 2026-02-12T09:15:00junk\n\n Unable to find an element with the text: Dato er ikke registrert. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.\n\n Ignored nodes: comments, script, style\n \u001b[36m\u001b[39m\n \u001b[36m
\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0m{\"pathname\":\"/documents\",\"search\":\"\",\"hash\":\"\",\"state\":null}\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[0mDine dokumenter\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[0mÅpne det opprinnelige arbeidsområdet for å redigere en CV, en kladd eller en fil. Lagrede øyeblikksbilder av søknader beholder innholdet som ble lagret.\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[0mOppdater\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øk i dokumenter\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øk i dokumenter\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[0mType\u001b[0m\n \u001b[36m\u001b[39m\n \u001b[36m\u001b[39m\n \u001b[36m 46 | expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible();\n | ^\n 47 | expect(document.querySelector('time')).not.toBeInTheDocument();\n 48 | });\n 49 |\n\n at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:163:27)\n at node_modules/@testing-library/dom/dist/query-helpers.js:86:33\n at findByText (src/documents-page.test.tsx:46:25)\n","name":"C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\src\\documents-page.test.tsx","startTime":1793695642064,"status":"failed","summary":""}],"wasInterrupted":false} diff --git a/docs/i18n/evidence/document-dates-tests.json b/docs/i18n/evidence/document-dates-tests.json new file mode 100644 index 00000000..bdaf4889 --- /dev/null +++ b/docs/i18n/evidence/document-dates-tests.json @@ -0,0 +1 @@ +{"numFailedTestSuites":0,"numFailedTests":0,"numPassedTestSuites":3,"numPassedTests":40,"numPendingTestSuites":0,"numPendingTests":0,"numRuntimeErrorTestSuites":0,"numTodoTests":0,"numTotalTestSuites":3,"numTotalTests":40,"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":1793695745093,"success":true,"testResults":[{"assertionResults":[{"ancestorTitles":["en unknown attachment purposes"],"duration":226,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en unknown attachment purposes uses the localized Other label for constructor","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793695748211,"status":"passed","title":"uses the localized Other label for constructor"},{"ancestorTitles":["en unknown attachment purposes"],"duration":94,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en unknown attachment purposes uses the localized Other label for toString","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793695748437,"status":"passed","title":"uses the localized Other label for toString"},{"ancestorTitles":["en unknown attachment purposes"],"duration":93,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en unknown attachment purposes uses the localized Other label for __proto__","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793695748531,"status":"passed","title":"uses the localized Other label for __proto__"},{"ancestorTitles":["nb unknown attachment purposes"],"duration":90,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb unknown attachment purposes uses the localized Other label for constructor","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793695748624,"status":"passed","title":"uses the localized Other label for constructor"},{"ancestorTitles":["nb unknown attachment purposes"],"duration":95,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb unknown attachment purposes uses the localized Other label for toString","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793695748714,"status":"passed","title":"uses the localized Other label for toString"},{"ancestorTitles":["nb unknown attachment purposes"],"duration":90,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb unknown attachment purposes uses the localized Other label for __proto__","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793695748809,"status":"passed","title":"uses the localized Other label for __proto__"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":78,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en uploaded wall-clock dates does not invent a timestamp from 2026-02-30T09:15:00","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695748899,"status":"passed","title":"does not invent a timestamp from 2026-02-30T09:15:00"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":60,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en uploaded wall-clock dates does not invent a timestamp from 2026-02-12T24:15:00","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695748977,"status":"passed","title":"does not invent a timestamp from 2026-02-12T24:15:00"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":47,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en uploaded wall-clock dates does not invent a timestamp from 2026-02-12T09:61:00","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695749038,"status":"passed","title":"does not invent a timestamp from 2026-02-12T09:61:00"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":47,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en uploaded wall-clock dates does not invent a timestamp from 2026-02-12T09:15:00junk","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695749085,"status":"passed","title":"does not invent a timestamp from 2026-02-12T09:15:00junk"},{"ancestorTitles":["en uploaded wall-clock dates"],"duration":42,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"en uploaded wall-clock dates preserves fractional-second wall-clock metadata without timezone conversion","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695749132,"status":"passed","title":"preserves fractional-second wall-clock metadata without timezone conversion"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":40,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb uploaded wall-clock dates does not invent a timestamp from 2026-02-30T09:15:00","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695749174,"status":"passed","title":"does not invent a timestamp from 2026-02-30T09:15:00"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":71,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb uploaded wall-clock dates does not invent a timestamp from 2026-02-12T24:15:00","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695749214,"status":"passed","title":"does not invent a timestamp from 2026-02-12T24:15:00"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":76,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb uploaded wall-clock dates does not invent a timestamp from 2026-02-12T09:61:00","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695749286,"status":"passed","title":"does not invent a timestamp from 2026-02-12T09:61:00"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":77,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb uploaded wall-clock dates does not invent a timestamp from 2026-02-12T09:15:00junk","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695749362,"status":"passed","title":"does not invent a timestamp from 2026-02-12T09:15:00junk"},{"ancestorTitles":["nb uploaded wall-clock dates"],"duration":75,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"nb uploaded wall-clock dates preserves fractional-second wall-clock metadata without timezone conversion","invocations":1,"location":null,"numPassingAsserts":6,"retryReasons":[],"startAt":1793695749439,"status":"passed","title":"preserves fractional-second wall-clock metadata without timezone conversion"},{"ancestorTitles":[],"duration":80,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] validates URL filters and reads one metadata page with literal Nordic search","invocations":1,"location":null,"numPassingAsserts":10,"retryReasons":[],"startAt":1793695749514,"status":"passed","title":"[P7-07 documents] validates URL filters and reads one metadata page with literal Nordic search"},{"ancestorTitles":[],"duration":336,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] server pagination and filter history preserve unknown query, hash and router state","invocations":1,"location":null,"numPassingAsserts":15,"retryReasons":[],"startAt":1793695749594,"status":"passed","title":"[P7-07 documents] server pagination and filter history preserve unknown query, hash and router state"},{"ancestorTitles":[],"duration":97,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] literal search all remains free text and preserves unrelated navigation context","invocations":1,"location":null,"numPassingAsserts":12,"retryReasons":[],"startAt":1793695749930,"status":"passed","title":"[P7-07 documents] literal search all remains free text and preserves unrelated navigation context"},{"ancestorTitles":[],"duration":218,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] a batched sort selection and immediate search preserve both filters and navigation context","invocations":1,"location":null,"numPassingAsserts":23,"retryReasons":[],"startAt":1793695750027,"status":"passed","title":"[P7-07 documents] a batched sort selection and immediate search preserve both filters and navigation context"},{"ancestorTitles":[],"duration":288,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] incompatible pending and failed queries hide old actions and late results cannot replace current metadata","invocations":1,"location":null,"numPassingAsserts":12,"retryReasons":[],"startAt":1793695750245,"status":"passed","title":"[P7-07 documents] incompatible pending and failed queries hide old actions and late results cannot replace current metadata"},{"ancestorTitles":[],"duration":153,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] Retry is one guarded GET and a completion after leaving cannot publish or start follow-up work","invocations":1,"location":null,"numPassingAsserts":10,"retryReasons":[],"startAt":1793695750533,"status":"passed","title":"[P7-07 documents] Retry is one guarded GET and a completion after leaving cannot publish or start follow-up work"},{"ancestorTitles":[],"duration":211,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] a true empty index, filtered no-match and request failure remain distinct","invocations":1,"location":null,"numPassingAsserts":10,"retryReasons":[],"startAt":1793695750686,"status":"passed","title":"[P7-07 documents] a true empty index, filtered no-match and request failure remain distinct"},{"ancestorTitles":[],"duration":96,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] English and Bokmål presentation changes preserve query context without a metadata refetch","invocations":1,"location":null,"numPassingAsserts":11,"retryReasons":[],"startAt":1793695750897,"status":"passed","title":"[P7-07 documents] English and Bokmål presentation changes preserve query context without a metadata refetch"},{"ancestorTitles":[],"duration":113,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] an out-of-range page offers explicit first-page recovery without claiming an empty index","invocations":1,"location":null,"numPassingAsserts":17,"retryReasons":[],"startAt":1793695750993,"status":"passed","title":"[P7-07 documents] an out-of-range page offers explicit first-page recovery without claiming an empty index"},{"ancestorTitles":[],"duration":129,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] seven resource kinds retain exact source actions, frozen provenance and honest date labels","invocations":1,"location":null,"numPassingAsserts":24,"retryReasons":[],"startAt":1793695751106,"status":"passed","title":"[P7-07 documents] seven resource kinds retain exact source actions, frozen provenance and honest date labels"},{"ancestorTitles":[],"duration":160,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] attachment download is explicit, API-relative and single-flight with original MIME, filename and URL disposal","invocations":1,"location":null,"numPassingAsserts":13,"retryReasons":[],"startAt":1793695751235,"status":"passed","title":"[P7-07 documents] attachment download is explicit, API-relative and single-flight with original MIME, filename and URL disposal"},{"ancestorTitles":[],"duration":139,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] a completed download preserves deliberate Search focus instead of restoring the old button","invocations":1,"location":null,"numPassingAsserts":12,"retryReasons":[],"startAt":1793695751395,"status":"passed","title":"[P7-07 documents] a completed download preserves deliberate Search focus instead of restoring the old button"},{"ancestorTitles":[],"duration":245,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] download errors retry only that file and late download completion after leaving creates no URL","invocations":1,"location":null,"numPassingAsserts":11,"retryReasons":[],"startAt":1793695751534,"status":"passed","title":"[P7-07 documents] download errors retry only that file and late download completion after leaving creates no URL"},{"ancestorTitles":[],"duration":87,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] a published historical CV retains its percent-encoded Nordic public slug without fetching its body","invocations":1,"location":null,"numPassingAsserts":8,"retryReasons":[],"startAt":1793695751779,"status":"passed","title":"[P7-07 documents] a published historical CV retains its percent-encoded Nordic public slug without fetching its body"},{"ancestorTitles":[],"duration":47,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"[P7-07 documents] malformed external and mismatched resource paths never become source, public or download actions","invocations":1,"location":null,"numPassingAsserts":15,"retryReasons":[],"startAt":1793695751866,"status":"passed","title":"[P7-07 documents] malformed external and mismatched resource paths never become source, public or download actions"}],"endTime":1793695751914,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\src\\documents-page.test.tsx","startTime":1793695745971,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":23,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"migrates the legacy Norwegian code and persists Bokmål using nb-NO","invocations":1,"location":null,"numPassingAsserts":5,"retryReasons":[],"startAt":1793695752565,"status":"passed","title":"migrates the legacy Norwegian code and persists Bokmål using nb-NO"},{"ancestorTitles":[],"duration":6,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"hydrates an authenticated server preference without writing it back","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793695752588,"status":"passed","title":"hydrates an authenticated server preference without writing it back"},{"ancestorTitles":[],"duration":304,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a failed account language save keeps the local choice and offers a localized retry: Norsk","invocations":1,"location":null,"numPassingAsserts":11,"retryReasons":[],"startAt":1793695752594,"status":"passed","title":"a failed account language save keeps the local choice and offers a localized retry: Norsk"},{"ancestorTitles":[],"duration":264,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a failed account language save keeps the local choice and offers a localized retry: English","invocations":1,"location":null,"numPassingAsserts":11,"retryReasons":[],"startAt":1793695752899,"status":"passed","title":"a failed account language save keeps the local choice and offers a localized retry: English"},{"ancestorTitles":[],"duration":8,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a delayed language-save failure cannot offer a retry for a newer successful choice","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793695753163,"status":"passed","title":"a delayed language-save failure cannot offer a retry for a newer successful choice"},{"ancestorTitles":[],"duration":34,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"a previously delivered language retry cannot reverse a newer choice","invocations":1,"location":null,"numPassingAsserts":3,"retryReasons":[],"startAt":1793695753171,"status":"passed","title":"a previously delivered language retry cannot reverse a newer choice"}],"endTime":1793695753205,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\src\\i18n-provider.test.tsx","startTime":1793695751925,"status":"passed","summary":""},{"assertionResults":[{"ancestorTitles":[],"duration":6,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"English and Bokmål expose the same UI message keys","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793695753414,"status":"passed","title":"English and Bokmål expose the same UI message keys"},{"ancestorTitles":[],"duration":3,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"Bokmål preserves every English substitution variable","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793695753421,"status":"passed","title":"Bokmål preserves every English substitution variable"},{"ancestorTitles":[],"duration":2,"failing":false,"failureDetails":[],"failureMessages":[],"fullName":"supported UI catalogues contain no blank messages","invocations":1,"location":null,"numPassingAsserts":1,"retryReasons":[],"startAt":1793695753424,"status":"passed","title":"supported UI catalogues contain no blank messages"}],"endTime":1793695753427,"message":"","name":"C:\\Users\\Connor\\.codex\\worktrees\\i18n-00-audit\\Job tracker\\job-tracker-ui\\src\\translation-catalogue.test.ts","startTime":1793695753213,"status":"passed","summary":""}],"wasInterrupted":false} diff --git a/job-tracker-ui/src/documents-page.test.tsx b/job-tracker-ui/src/documents-page.test.tsx index 42389a51..64090d7e 100644 --- a/job-tracker-ui/src/documents-page.test.tsx +++ b/job-tracker-ui/src/documents-page.test.tsx @@ -38,6 +38,27 @@ function deferred() { return { promise, resolve, reject }; } +describe.each(['en', 'nb'] as const)('%s uploaded wall-clock dates', locale => { + test.each(['2026-02-30T09:15:00', '2026-02-12T24:15:00', '2026-02-12T09:61:00', '2026-02-12T09:15:00junk'])('does not invent a timestamp from %s', async recordedAt => { + localStorage.setItem('uiLanguage', locale); + mockedApi.get.mockResolvedValue({ data: page([item({ recordedAt, dateKind: 'uploaded-local' })]) } as never); + renderPage(); + expect(await screen.findByText(copy('documentsDateUnknown', {}, locale))).toBeVisible(); + expect(document.querySelector('time')).not.toBeInTheDocument(); + }); + + test('preserves fractional-second wall-clock metadata without timezone conversion', async () => { + localStorage.setItem('uiLanguage', locale); + const recordedAt = '2026-02-12T09:15:00.1234567'; + mockedApi.get.mockResolvedValue({ data: page([item({ recordedAt, dateKind: 'uploaded-local' })]) } as never); + renderPage(); + await screen.findByText('Metadata CV ÆØÅ', { exact: true }); + const time = document.querySelector('time'); + expect(time).toHaveAttribute('datetime', recordedAt); + expect(time).toHaveTextContent(new Intl.DateTimeFormat(locale === 'nb' ? 'nb-NO' : 'en-GB', { dateStyle: 'medium', timeStyle: 'short', timeZone: 'UTC' }).format(new Date('2026-02-12T09:15:00Z'))); + }); +}); + function Probe() { const location = useLocation(); const navigate = useNavigate(); diff --git a/job-tracker-ui/src/views/DocumentsPage.tsx b/job-tracker-ui/src/views/DocumentsPage.tsx index e6d953ce..02f4de2e 100644 --- a/job-tracker-ui/src/views/DocumentsPage.tsx +++ b/job-tracker-ui/src/views/DocumentsPage.tsx @@ -214,9 +214,16 @@ export default function DocumentsPage() { const label: TranslationKey = item.dateKind === "uploaded-local" ? "documentsUploadedLocal" : item.dateKind === "captured-utc" ? "documentsCaptured" : item.dateKind === "history-recorded-utc" ? "documentsHistoryRecorded" : "documentsUpdated"; let value: Date | null = null; if (item.recordedAt && item.dateKind === "uploaded-local") { - const local = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)/.exec(item.recordedAt); + const local = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.\d{1,7})?$/.exec(item.recordedAt); // UTC is only a formatting carrier for the unzoned wall-clock components. - if (local) value = new Date(Date.UTC(+local[1], +local[2] - 1, +local[3], +local[4], +local[5], +local[6])); + if (local) { + const parts = local.slice(1).map(Number); + const candidate = new Date(0); + candidate.setUTCFullYear(parts[0], parts[1] - 1, parts[2]); + candidate.setUTCHours(parts[3], parts[4], parts[5], 0); + // Date normalises impossible fields; show unknown rather than inventing a date. + if ([candidate.getUTCFullYear(), candidate.getUTCMonth() + 1, candidate.getUTCDate(), candidate.getUTCHours(), candidate.getUTCMinutes(), candidate.getUTCSeconds()].every((part, index) => part === parts[index])) value = candidate; + } } else if (item.recordedAt && ["updated-utc", "captured-utc", "history-recorded-utc"].includes(item.dateKind)) value = new Date(item.recordedAt); if (!value || Number.isNaN(value.valueOf())) return {t("documentsDateUnknown")}; return {t(label)}{value.toLocaleString(locale, { dateStyle: "medium", timeStyle: "short", ...(item.dateKind === "uploaded-local" ? { timeZone: "UTC" } : {}) })};