From 56fef58ca4241e21a1db2a73db923a1ae0e1beb5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 04:59:29 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A7=AA=20[testing]=20add=20unit=20tes?= =?UTF-8?q?ts=20for=20i18n=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎯 What: Added a missing test file `src/__tests__/i18n.test.ts` for `src/i18n.ts` to ensure proper functioning of translation features. πŸ“Š Coverage: Tested `setLocale`, `getLocale`, `t` (including fallback and string interpolation logic), `addTranslations`, and the singleton export. ✨ Result: Improved test coverage and ensured reliability of translation utility and interpolation functions. Co-authored-by: sunnylqm <615282+sunnylqm@users.noreply.github.com> --- src/__tests__/i18n.test.ts | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/__tests__/i18n.test.ts diff --git a/src/__tests__/i18n.test.ts b/src/__tests__/i18n.test.ts new file mode 100644 index 00000000..eb86ed79 --- /dev/null +++ b/src/__tests__/i18n.test.ts @@ -0,0 +1,90 @@ +import { describe, expect, test } from 'bun:test'; + +describe('I18n', () => { + // Use a helper function to import the real implementation + // since `../i18n` is globally mocked in `setup.ts` + const getRealI18n = async () => { + // Generate a random cache-buster so we get a fresh instance if needed, + // although singleton is usually fine, the `setup.ts` mock needs to be bypassed. + const module = await import('../i18n?real'); + return { I18n: module.I18n, i18nSingleton: module.default }; + }; + + test('setLocale and getLocale', async () => { + const { I18n } = await getRealI18n(); + const i18n = new I18n(); + + expect(i18n.getLocale()).toBe('en'); // Default is 'en' + + i18n.setLocale('zh'); + expect(i18n.getLocale()).toBe('zh'); + + i18n.setLocale('en'); + expect(i18n.getLocale()).toBe('en'); + }); + + test('basic translations and fallback', async () => { + const { I18n } = await getRealI18n(); + const i18n = new I18n(); + + // English translation + i18n.setLocale('en'); + expect(i18n.t('checking_update')).toBe('Checking for updates...'); + + // Chinese translation + i18n.setLocale('zh'); + expect(i18n.t('checking_update')).toBe('ζ­£εœ¨ζ£€ζŸ₯ζ›΄ζ–°...'); + + // Fallback logic + // Add translation only to 'zh', check if 'en' falls back to 'zh' + i18n.addTranslations('zh', { 'only_in_zh': 'δΈ­ζ–‡δΈ“ε±ž' }); + i18n.setLocale('en'); + expect(i18n.t('only_in_zh' as any)).toBe('δΈ­ζ–‡δΈ“ε±ž'); + + // Add translation only to 'en', check if 'zh' falls back to 'en' + i18n.addTranslations('en', { 'only_in_en': 'English Only' }); + i18n.setLocale('zh'); + expect(i18n.t('only_in_en' as any)).toBe('English Only'); + + // Key missing in both locales + expect(i18n.t('missing_key' as any)).toBe('missing_key'); + }); + + test('string interpolation', async () => { + const { I18n } = await getRealI18n(); + const i18n = new I18n(); + + i18n.setLocale('en'); + + // Normal interpolation + expect(i18n.t('download_progress', { progress: 50 })).toBe('Download progress: 50%'); + + // Multiple interpolations + expect(i18n.t('retry_count', { count: 1, max: 3 })).toBe('Retry attempt: 1/3'); + + // Interpolation with missing values (should leave placeholder as is) + expect(i18n.t('download_progress')).toBe('Download progress: {{progress}}%'); + + // Invalid interpolation syntax (spaces) are ignored + i18n.addTranslations('en', { 'invalid_syntax': 'Test {{ key }} here' }); + expect(i18n.t('invalid_syntax' as any, { key: 'value' })).toBe('Test {{ key }} here'); + }); + + test('addTranslations', async () => { + const { I18n } = await getRealI18n(); + const i18n = new I18n(); + + i18n.addTranslations('en', { 'new_key': 'New Value' }); + i18n.setLocale('en'); + + expect(i18n.t('new_key' as any)).toBe('New Value'); + }); + + test('singleton export', async () => { + const { i18nSingleton } = await getRealI18n(); + + // Verify it works + expect(i18nSingleton.getLocale()).toBeDefined(); + expect(i18nSingleton.t('checking_update')).toBeDefined(); + }); +}); From aa7b99129843e4d107121bd39da160f80c70ffbf Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 05:09:41 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A7=AA=20fix(test):=20resolve=20TS=20?= =?UTF-8?q?compiler=20error=20with=20dynamic=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎯 What: Modified the dynamic import in `src/__tests__/i18n.test.ts` to use a string interpolation variable instead of a raw query parameter string. πŸ“Š Coverage: Ensures the codebase passes `tsc --noEmit` while retaining the ability to bypass bun:test's global module cache to test the genuine implementation. ✨ Result: CI lint/TS validation check now passes properly. Co-authored-by: sunnylqm <615282+sunnylqm@users.noreply.github.com> --- src/__tests__/i18n.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/__tests__/i18n.test.ts b/src/__tests__/i18n.test.ts index eb86ed79..84d05157 100644 --- a/src/__tests__/i18n.test.ts +++ b/src/__tests__/i18n.test.ts @@ -6,7 +6,8 @@ describe('I18n', () => { const getRealI18n = async () => { // Generate a random cache-buster so we get a fresh instance if needed, // although singleton is usually fine, the `setup.ts` mock needs to be bypassed. - const module = await import('../i18n?real'); + const cacheKey = 'real'; + const module = await import(`../i18n?${cacheKey}`); return { I18n: module.I18n, i18nSingleton: module.default }; };