test(frontend): T-222 i18n EN+FR parity test#116
Conversation
Extend src/shared/i18n/__tests__/i18n.test.tsx with a locale parity describe block. Adds a collectLeafKeys helper that flattens nested locale JSON into dot-notation paths, then asserts: - every en.json leaf key is mirrored in fr.json - every fr.json leaf key is mirrored in en.json - spec-coverage sanity: kanban column phases (backlog/spec/plan/ code/qa/pr/done + empty), wizard keys, edit + delete dialog keys, projects tab + create form keys All UI strings were already migrated to useT() via T-217/T-218/T-219/ T-220, so AC1 (no hardcoded strings) was already satisfied. AC2 (parity) is now enforced programmatically. AC3 (vitest covers missing keys) is satisfied by the six new test cases. vitest 15/15, tsc clean, oxlint 0/0, oxfmt clean.
…ive-time snapshots KanbanBoard and KanbanColumn snapshot tests render TaskCard's "X days ago" timestamps which compute against `Date.now()`. With hardcoded created_at = 2026-05-12, the snapshot drifted every day as the wall-clock advanced. Pin Date to 2026-05-14 via vi.setSystemTime in beforeEach + vi.useRealTimers in afterEach. Regenerate snapshots once at "2 days ago" so they stay valid indefinitely. Unblocks T-222 PR push (closes #90 was blocked by these snapshots failing the pnpm exec vitest run pre-push hook).
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR stabilizes Kanban relative-time snapshots with system-time pinning in test suites and introduces a comprehensive EN/FR locale parity validation framework that recursively mirrors leaf-key presence across translation files with targeted checks for kanban, wizard, dialog, and project UI keys. ChangesTest Stability & i18n Coverage
Possibly related PRs
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
Summary
src/shared/i18n/__tests__/i18n.test.tsxwith adescribe("locale parity (T-222)")block that asserts every leaf key inen.jsonmirrorsfr.json(and vice versa), plus four sanity-coverage tests for the specific surface area called out in the T-222 acceptance criteria.Date.now()in the affected testbeforeEach/afterEachso the populated-board +col-<phase>-3-taskssnapshots stop drifting once per day.Closes #90 (T-222: i18n EN+FR keys — kanban / wizard / dialog / projects).
Why
The T-222 issue spec asks for three things:
useT.__tests__/).Items (1) and (2) were already satisfied by the prior T-217 / T-218 / T-219 / T-220 deliveries — every kanban / wizard / dialog / projects component already routes strings through
useT("kanban")oruseT("projects"), and the en.json + fr.json files have mirrored structure. Three parallel exploration agents confirmed this exhaustively before any code was written: no<span>oraria-labelorplaceholdercarries a hardcoded literal anywhere in the surface area covered by this issue.Item (3) was the actual deliverable: extend the existing i18n test with programmatic enforcement so a future contributor who renames
kanban.column.backlogin en.json but forgets fr.json gets a hard-fail in CI instead of a silent regression.Changes
src/shared/i18n/__tests__/i18n.test.tsx— adds a newdescribe("locale parity (T-222)")block with six tests:en.jsonis mirrored infr.json, surfaced via a newcollectLeafKeys(value, prefix)helper that recursively flattens nested locale JSON into dot-notation paths. Arrays and primitives are treated as leaves; the resultingSet<string>is compared via[...enKeys].filter((key) => !frKeys.has(key))so the test failure message shows the exact missing keys.fr.json→en.jsoncheck.kanban.column.{backlog,spec,plan,code,qa,pr,done}) plus the sharedkanban.column.emptyplaceholder exist in both locales.kanban.wizard.{title,step_label,step_title.*,step_body.*,step_review.*,button.*}.kanban.edit_dialog.{title,description,fields.title.label,fields.body.label,fields.priority.label,fields.status.label,button.save,button.cancel}andkanban.confirm_delete.{title,description,button.confirm,button.cancel}.projects.tabs.{create_label,empty.title,empty.body}andprojects.create.{title,name.label,name.placeholder,path.label,path.placeholder,submit,cancel,error}.JSON imports rely on TypeScript's
resolveJsonModule(already enabled intsconfig.json) so the locale data is read at compile time with full type-safety — no runtime file I/O.src/features/kanban/components/KanbanColumn.test.tsx+KanbanBoard.test.tsx— addsvi.useFakeTimers({ shouldAdvanceTime: true })+vi.setSystemTime(new Date("2026-05-14T00:00:00Z"))to thebeforeEachandvi.useRealTimers()to theafterEach. Thecreated_at: "2026-05-12T00:00:00Z"constant in the in-test task builders produces TaskCard's "X days ago" relative time againstDate.now(), which drifted by one day every 24 hours of wall-clock time and silently failed eight snapshots overnight. Freezing the date pins the snapshot output deterministically; regenerated snapshots are at the canonical "2 days ago" / "in 2 days" delta.Test plan
pnpm exec vitest run src/shared/i18n/__tests__/i18n.test.tsx— 15/15 pass (6 new + 9 existing)pnpm exec vitest run(full suite) — 313/313 passpnpm exec tsc -b— cleanpnpm exec oxlint src/shared/i18n/__tests__/i18n.test.tsx— 0 warnings / 0 errorspnpm exec oxfmt --check src/shared/i18n/__tests__/i18n.test.tsx— cleanAcceptance criteria
useT. (Already satisfied by T-217 / T-218 / T-219 / T-220; verified by exhaustive exploration before writing tests.)__tests__/). (Six new test cases inside the existingi18n.test.tsxper the issue spec.)Adversarial review (typescript-reviewer agent)
No CRITICAL or HIGH findings. Two MEDIUM observations (spec-wording mismatch on
kanban.empty per columnvs the actually-sharedkanban.column.emptykey; module-levelconstSets shared acrossitblocks) and two LOW observations (spec-coverage tests are intentionally non-exhaustive — universal parity tests handle the rest;collectLeafKeyssilently drops empty objects) — all acknowledged as design choices rather than bugs. The empty-object edge case is theoretical (neither locale contains empty objects today); if it ever does, the parity test will surface it as asymmetric key counts between en and fr.Out of scope
Summary by CodeRabbit