diff --git a/frontend/testing/unit/components/I18nContext.test.tsx b/frontend/testing/unit/components/I18nContext.test.tsx
new file mode 100644
index 00000000..7560d578
--- /dev/null
+++ b/frontend/testing/unit/components/I18nContext.test.tsx
@@ -0,0 +1,126 @@
+import React from 'react';
+import { describe, it, expect, vi } from 'vitest';
+import { render, screen, act } from '@testing-library/react';
+import { I18nProvider, useTranslation } from '../../../src/components/I18nContext';
+
+const LocaleDisplay: React.FC = () => {
+ const { locale } = useTranslation();
+ return
{locale}
;
+};
+
+const TranslationDisplay: React.FC<{ path: string }> = ({ path }) => {
+ const { t } = useTranslation();
+ return {t(path)}
;
+};
+
+const LocaleSwitcher: React.FC<{ targetLocale: string }> = ({ targetLocale }) => {
+ const { locale, setLocale } = useTranslation();
+ return (
+ <>
+ {locale}
+
+ >
+ );
+};
+
+describe('I18nContext', () => {
+
+ it('should default locale to "en"', () => {
+ render(
+
+
+
+ );
+ expect(screen.getByTestId('locale').textContent).toBe('en');
+ });
+
+ it('should return correct translation for a valid nested key', () => {
+ render(
+
+
+
+ );
+ expect(screen.getByTestId('translation').textContent).toBe('Dashboard');
+ });
+
+ it('should return the key itself when translation path is not found', () => {
+ render(
+
+
+
+ );
+ expect(screen.getByTestId('translation').textContent).toBe('common.nonexistent');
+ });
+
+ it('should expose setLocale function in context', () => {
+ render(
+
+
+
+ );
+ expect(screen.getByRole('button', { name: 'Switch' })).toBeDefined();
+ });
+
+ it('should update locale when setLocale is called', async () => {
+ render(
+
+
+
+ );
+ expect(screen.getByTestId('locale').textContent).toBe('en');
+ await act(async () => {
+ screen.getByRole('button', { name: 'Switch' }).click();
+ });
+ expect(screen.getByTestId('locale').textContent).toBe('fr');
+ });
+
+ it('should update locale correctly when switching to Hindi', async () => {
+ render(
+
+
+
+ );
+ await act(async () => {
+ screen.getByRole('button', { name: 'Switch' }).click();
+ });
+ expect(screen.getByTestId('locale').textContent).toBe('hi');
+ });
+
+ it('should fail if provider stops exposing locale as a string', () => {
+ render(
+
+
+
+ );
+ const localeEl = screen.getByTestId('locale');
+ expect(typeof localeEl.textContent).toBe('string');
+ expect(localeEl.textContent).toBeTruthy();
+ });
+
+ it('should fail if provider stops exposing t as a function', () => {
+ let capturedT: ((path: string) => string) | undefined;
+ const Inspector: React.FC = () => {
+ const { t } = useTranslation();
+ capturedT = t;
+ return null;
+ };
+ render(
+
+
+
+ );
+ expect(typeof capturedT).toBe('function');
+ });
+
+ it('should throw error when useTranslation is used outside I18nProvider', () => {
+ const BadComponent: React.FC = () => {
+ useTranslation();
+ return null;
+ };
+ const spy = vi.spyOn(console, 'error').mockImplementation(() => {});
+ expect(() => render()).toThrow(
+ 'useTranslation must be used within an I18nProvider'
+ );
+ spy.mockRestore();
+ });
+});