Skip to content

test: unify i18next mocks into centralized helpers#20

Open
tomerqodo wants to merge 5 commits intocoderabbit_combined_20260121_augment_sentry_coderabbit_1_base_test_unify_i18next_mocks_into_centralized_helpers_pr437from
coderabbit_combined_20260121_augment_sentry_coderabbit_1_head_test_unify_i18next_mocks_into_centralized_helpers_pr437
Open

test: unify i18next mocks into centralized helpers#20
tomerqodo wants to merge 5 commits intocoderabbit_combined_20260121_augment_sentry_coderabbit_1_base_test_unify_i18next_mocks_into_centralized_helpers_pr437from
coderabbit_combined_20260121_augment_sentry_coderabbit_1_head_test_unify_i18next_mocks_into_centralized_helpers_pr437

Conversation

@tomerqodo
Copy link

@tomerqodo tomerqodo commented Jan 22, 2026

Benchmark PR from qodo-benchmark#437

Summary by CodeRabbit

  • Refactor

    • Standardized internationalization testing utilities for improved consistency across test suite.
  • Tests

    • Unified mock setup for translation testing, reducing duplicate code and enhancing maintainability of test infrastructure.

✏️ Tip: You can customize this high-level summary in your review settings.

hyoban and others added 5 commits January 21, 2026 15:55
Consolidate scattered i18next mock implementations across test files into
a single source of truth. This reduces duplication and ensures consistent
mock behavior.

- Create test/i18n-mock.ts with reusable factory functions
- Update vitest.setup.ts to use the centralized helpers
- Remove redundant mock definitions from 8 test files
- Update testing.md documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…eateReactI18nextMock` and detail global mock provisions.
@coderabbitai
Copy link

coderabbitai bot commented Jan 22, 2026

Walkthrough

A new i18n test mock utility is introduced in web/test/i18n-mock.ts that centralizes react-i18next mock factories. Multiple test files are refactored to use this utility instead of maintaining inline i18n mocks. Documentation and setup files are updated to reference the new approach. The vitest setup delegates mock construction to the utility.

Changes

Cohort / File(s) Summary
Documentation & Templates
.claude/skills/frontend-testing/assets/component-test.template.tsx, .claude/skills/frontend-testing/references/mocking.md, web/testing/testing.md
Updated guidance and examples for i18n mocking to reference the new createReactI18nextMock helper, clarified global mock behavior, and replaced inline mock snippets with factory-based approaches.
Test Utility Creation
web/test/i18n-mock.ts
New module introducing four exported factories: createTFunction, createUseTranslationMock, createTransMock, and createReactI18nextMock to support streamlined i18n mocking across tests.
Core Test Setup
web/vitest.setup.ts
Replaced inline react-i18next mock implementation with call to createReactI18nextMock() helper, delegating mock construction to the utility module.
Tests: Mock Removal
web/app/components/app/configuration/config/agent-setting-button.spec.tsx, web/app/components/app/configuration/config/config-audio.spec.tsx, web/app/components/billing/pricing/footer.spec.tsx, web/app/components/datasets/create/index.spec.tsx, web/app/components/datasets/documents/create-from-pipeline/processing/index.spec.tsx, web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.spec.tsx, web/app/components/plugins/plugin-detail-panel/subscription-list/create/common-modal.spec.tsx, web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth-client.spec.tsx, web/app/components/plugins/plugin-detail-panel/subscription-list/edit/index.spec.tsx, web/app/components/plugins/plugin-mutation-model/index.spec.tsx, web/app/components/plugins/card/index.spec.tsx
Removed inline i18n mock implementations, relying on global mocks instead.
Tests: Mock Replacement
web/app/components/base/inline-delete-confirm/index.spec.tsx, web/app/components/base/input-with-copy/index.spec.tsx, web/app/components/base/input/index.spec.tsx
Replaced inline i18n mocks with createReactI18nextMock calls, providing explicit translations while removing bespoke mock logic.
Tests: Special Updates
web/app/components/plugins/marketplace/index.spec.tsx, web/app/components/plugins/install-plugin/install-from-local-package/steps/install.spec.tsx
Updated getFixedT mock signature to support optional namespace prefixing and adjusted test expectations for prefixed translation keys; install.spec.tsx now uses dynamic module import with mock merging.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Poem

🐰 With mocks now centralized and neat,
Our test suite's grown a wee more sweet,
No more inline i18n care,
One factory function, clean and fair!
The testing burrows hop with glee,
As translations flow so spree! 🍀

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimal and off-topic. It only references an external benchmark PR without providing context, summary, motivation, issue link, or completion of the required template sections. Add a proper summary explaining the changes, link to the associated issue using 'Fixes #', and complete the checklist items from the template.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: unifying i18next mocks into centralized helpers, which is the primary focus of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@web/test/i18n-mock.ts`:
- Around line 6-28: The comment above createTFunction is incorrect about lookup
order: the implementation builds fullKey (ns ? `${ns}.${key}` : key) and checks
translations[fullKey] first then translations[key]; update the comment to state
that the function checks the namespaced key (fullKey) first, then the raw key,
and then returns `${fullKey}` with serialized params as fallback so it matches
the logic around createTFunction, fullKey, translations and params.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17089eb and 4235e98.

📒 Files selected for processing (21)
  • .claude/skills/frontend-testing/assets/component-test.template.tsx
  • .claude/skills/frontend-testing/references/mocking.md
  • web/app/components/app/configuration/config/agent-setting-button.spec.tsx
  • web/app/components/app/configuration/config/config-audio.spec.tsx
  • web/app/components/base/inline-delete-confirm/index.spec.tsx
  • web/app/components/base/input-with-copy/index.spec.tsx
  • web/app/components/base/input/index.spec.tsx
  • web/app/components/billing/pricing/footer.spec.tsx
  • web/app/components/datasets/create/index.spec.tsx
  • web/app/components/datasets/documents/create-from-pipeline/processing/index.spec.tsx
  • web/app/components/plugins/card/index.spec.tsx
  • web/app/components/plugins/install-plugin/install-from-local-package/steps/install.spec.tsx
  • web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.spec.tsx
  • web/app/components/plugins/marketplace/index.spec.tsx
  • web/app/components/plugins/plugin-detail-panel/subscription-list/create/common-modal.spec.tsx
  • web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth-client.spec.tsx
  • web/app/components/plugins/plugin-detail-panel/subscription-list/edit/index.spec.tsx
  • web/app/components/plugins/plugin-mutation-model/index.spec.tsx
  • web/test/i18n-mock.ts
  • web/testing/testing.md
  • web/vitest.setup.ts
💤 Files with no reviewable changes (11)
  • web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth-client.spec.tsx
  • web/app/components/datasets/documents/create-from-pipeline/processing/index.spec.tsx
  • web/app/components/app/configuration/config/config-audio.spec.tsx
  • web/app/components/billing/pricing/footer.spec.tsx
  • web/app/components/plugins/card/index.spec.tsx
  • web/app/components/plugins/plugin-detail-panel/subscription-list/create/common-modal.spec.tsx
  • web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.spec.tsx
  • web/app/components/datasets/create/index.spec.tsx
  • web/app/components/plugins/plugin-detail-panel/subscription-list/edit/index.spec.tsx
  • web/app/components/plugins/plugin-mutation-model/index.spec.tsx
  • web/app/components/app/configuration/config/agent-setting-button.spec.tsx
🧰 Additional context used
🧬 Code graph analysis (5)
web/app/components/base/inline-delete-confirm/index.spec.tsx (1)
web/test/i18n-mock.ts (1)
  • createReactI18nextMock (74-79)
web/app/components/plugins/install-plugin/install-from-local-package/steps/install.spec.tsx (1)
web/test/i18n-mock.ts (1)
  • createReactI18nextMock (74-79)
web/app/components/base/input-with-copy/index.spec.tsx (1)
web/test/i18n-mock.ts (1)
  • createReactI18nextMock (74-79)
web/app/components/base/input/index.spec.tsx (1)
web/test/i18n-mock.ts (1)
  • createReactI18nextMock (74-79)
web/vitest.setup.ts (1)
web/test/i18n-mock.ts (1)
  • createReactI18nextMock (74-79)
🔇 Additional comments (16)
web/app/components/base/inline-delete-confirm/index.spec.tsx (1)

3-12: LGTM - Clean migration to centralized i18n mock.

The synchronous mock factory pattern is correctly used here. Translation keys align with test assertions (Delete?, Yes, No).

Minor observation: 'operation.confirmAction' (Line 11) is defined but doesn't appear to be asserted in any test. If this key isn't used by the component under test, consider removing it to keep the mock minimal.

web/app/components/base/input/index.spec.tsx (1)

3-10: LGTM - Consistent migration pattern.

The mock setup correctly provides the two translation keys used by the Input component's default placeholder and search functionality. Tests properly assert against the translated values.

web/vitest.setup.ts (1)

89-96: LGTM - Proper global mock setup with dynamic import.

The async factory pattern correctly:

  1. Preserves actual module exports via importActual
  2. Dynamically imports the centralized mock helper
  3. Spreads in order so mock exports override actual ones

This allows individual tests to either rely on the global mock or override with custom translations using createReactI18nextMock({...}).

web/app/components/plugins/install-plugin/install-from-local-package/steps/install.spec.tsx (1)

67-80: LGTM - Justified custom Trans override.

This test correctly uses the centralized mock while preserving a custom Trans component. The custom implementation is necessary because:

  1. The test at Line 151 verifies the trust source message renders
  2. The trustSource component prop (Line 76) is part of the test's assertion requirements

The pattern of spreading createReactI18nextMock() then overriding specific exports is the right approach when partial customization is needed.

web/app/components/base/input-with-copy/index.spec.tsx (1)

3-20: LGTM - Migration looks good.

The mock correctly provides translation keys for copy/copied states. The test at Line 94 properly asserts the 'Copied' translation appears.

Note: Both 'operation.*' and 'overview.appInfo.embedded.*' namespaces are provided. If the component only uses one namespace, consider removing the unused keys to keep the mock minimal. This is a minor optimization.

.claude/skills/frontend-testing/references/mocking.md (1)

56-77: LGTM - Clear and helpful documentation update.

The documentation effectively explains:

  1. What the global mock provides out-of-the-box (Lines 58-61)
  2. When to use the default vs. custom translations (Lines 63-65)
  3. Correct usage pattern with code example (Lines 67-74)
  4. Anti-pattern to avoid (Lines 76-77)

This will help developers understand when and how to use the centralized mock.

.claude/skills/frontend-testing/assets/component-test.template.tsx (1)

31-38: i18n guidance aligns with centralized mock usage.
Clear and consistent with the new helper-based approach.

web/testing/testing.md (1)

330-352: Documentation updates are consistent and actionable.

web/test/i18n-mock.ts (3)

39-48: createUseTranslationMock looks good.


54-63: createTransMock looks good.


74-78: createReactI18nextMock composition is clean.

web/app/components/plugins/marketplace/index.spec.tsx (5)

33-40: Mock update is consistent with namespaced key expectations.


617-643: Namespace-prefixed assertions look correct.


2759-2767: Updated labels align with the new mock output.


2797-2799: Click target updated consistently with new labels.


2818-2820: Active-state assertion aligns with updated text output.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +6 to +28
/**
* Create a t function with optional custom translations
* Checks translations[key] first, then translations[ns.key], then returns ns.key as fallback
*/
export function createTFunction(translations: TranslationMap, defaultNs?: string) {
return (key: string, options?: Record<string, unknown>) => {
const ns = (options?.ns as string | undefined) ?? defaultNs
const fullKey = ns ? `${ns}.${key}` : key

// Check custom translations with namespace first
if (translations[fullKey] !== undefined)
return translations[fullKey]

// Check custom translations without namespace
if (translations[key] !== undefined)
return translations[key]

// Serialize params (excluding ns) for test assertions
const params = { ...options }
delete params.ns
const suffix = Object.keys(params).length > 0 ? `:${JSON.stringify(params)}` : ''
return `${fullKey}${suffix}`
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix comment to match lookup order.
The comment says raw key is checked first, but the code checks namespaced key first. Align the comment (or logic) to avoid confusion.

💡 Suggested fix
- * Checks translations[key] first, then translations[ns.key], then returns ns.key as fallback
+ * Checks translations[ns.key] first, then translations[key], then returns ns.key as fallback
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Create a t function with optional custom translations
* Checks translations[key] first, then translations[ns.key], then returns ns.key as fallback
*/
export function createTFunction(translations: TranslationMap, defaultNs?: string) {
return (key: string, options?: Record<string, unknown>) => {
const ns = (options?.ns as string | undefined) ?? defaultNs
const fullKey = ns ? `${ns}.${key}` : key
// Check custom translations with namespace first
if (translations[fullKey] !== undefined)
return translations[fullKey]
// Check custom translations without namespace
if (translations[key] !== undefined)
return translations[key]
// Serialize params (excluding ns) for test assertions
const params = { ...options }
delete params.ns
const suffix = Object.keys(params).length > 0 ? `:${JSON.stringify(params)}` : ''
return `${fullKey}${suffix}`
}
/**
* Create a t function with optional custom translations
* Checks translations[ns.key] first, then translations[key], then returns ns.key as fallback
*/
export function createTFunction(translations: TranslationMap, defaultNs?: string) {
return (key: string, options?: Record<string, unknown>) => {
const ns = (options?.ns as string | undefined) ?? defaultNs
const fullKey = ns ? `${ns}.${key}` : key
// Check custom translations with namespace first
if (translations[fullKey] !== undefined)
return translations[fullKey]
// Check custom translations without namespace
if (translations[key] !== undefined)
return translations[key]
// Serialize params (excluding ns) for test assertions
const params = { ...options }
delete params.ns
const suffix = Object.keys(params).length > 0 ? `:${JSON.stringify(params)}` : ''
return `${fullKey}${suffix}`
}
}
🤖 Prompt for AI Agents
In `@web/test/i18n-mock.ts` around lines 6 - 28, The comment above createTFunction
is incorrect about lookup order: the implementation builds fullKey (ns ?
`${ns}.${key}` : key) and checks translations[fullKey] first then
translations[key]; update the comment to state that the function checks the
namespaced key (fullKey) first, then the raw key, and then returns `${fullKey}`
with serialized params as fallback so it matches the logic around
createTFunction, fullKey, translations and params.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants