94 lines
3.0 KiB
TypeScript
94 lines
3.0 KiB
TypeScript
|
|
/**
|
|||
|
|
* Task H4 – i18n-Grundlage: zentrale strings.ts Maps de/en.
|
|||
|
|
*
|
|||
|
|
* strings-Modul: t(key) mit de/en-Maps, getLanguage/setLanguage
|
|||
|
|
* (localStorage-persistiert, Default de), subscribe + useT-Hook.
|
|||
|
|
* Kern-UI-Texte (LayoutBar, Modus-Umschaltung) laufen ueber die
|
|||
|
|
* Maps; vollstaendige mechanische Ersetzung aller Komponenten ist
|
|||
|
|
* teilautomatisierbares Follow-up (Roadmap-Vermerk).
|
|||
|
|
*/
|
|||
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|||
|
|
import { render, screen, cleanup, fireEvent, act } from '@testing-library/react';
|
|||
|
|
import {
|
|||
|
|
t, getLanguage, setLanguage, subscribeLanguage, useT, LANGUAGES,
|
|||
|
|
} from '../src/i18n/strings';
|
|||
|
|
|
|||
|
|
afterEach(cleanup);
|
|||
|
|
|
|||
|
|
// ––– strings-Modul ––––––––––––––––––––––––
|
|||
|
|
|
|||
|
|
describe('H4: i18n strings', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
localStorage.clear();
|
|||
|
|
setLanguage('de');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('Default-Sprache ist de', () => {
|
|||
|
|
expect(getLanguage()).toBe('de');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('t liefert deutsche Kern-UI-Texte', () => {
|
|||
|
|
expect(t('layouts.title')).toBe('Layouts');
|
|||
|
|
expect(t('layouts.add')).toBe('Layout hinzufügen');
|
|||
|
|
expect(t('layouts.empty')).toBe('Keine Layouts');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('setLanguage(en) wechselt auf englische Texte', () => {
|
|||
|
|
setLanguage('en');
|
|||
|
|
expect(t('layouts.title')).toBe('Layouts');
|
|||
|
|
expect(t('layouts.add')).toBe('Add layout');
|
|||
|
|
expect(t('layouts.empty')).toBe('No layouts');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('Sprache persistiert in localStorage und ueberlebt Reload-Semantik', () => {
|
|||
|
|
setLanguage('en');
|
|||
|
|
expect(localStorage.getItem('webcad.language')).toBe('en');
|
|||
|
|
// erneutes Lesen startet aus persistiertem Zustand
|
|||
|
|
expect(getLanguage()).toBe('en');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('LANGUAGES enthaelt genau de und en', () => {
|
|||
|
|
expect(LANGUAGES).toEqual(['de', 'en']);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('t mit unbekanntem Key liefert den Key zurueck (Fallback, lint-bar)', () => {
|
|||
|
|
setLanguage('de');
|
|||
|
|
expect(t('gibts.nicht')).toBe('gibts.nicht');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('subscribeLanguage feuert bei Wechsel und unsubscribed', () => {
|
|||
|
|
const cb = vi.fn();
|
|||
|
|
const off = subscribeLanguage(cb);
|
|||
|
|
setLanguage('en');
|
|||
|
|
expect(cb).toHaveBeenCalledWith('en');
|
|||
|
|
off();
|
|||
|
|
cb.mockClear();
|
|||
|
|
setLanguage('de');
|
|||
|
|
expect(cb).not.toHaveBeenCalled();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// ––– useT-Hook + Komponente ––––––––––––––––––
|
|||
|
|
|
|||
|
|
describe('H4: useT-Hook rendert LayoutBar zweisprachig', () => {
|
|||
|
|
beforeEach(() => {
|
|||
|
|
localStorage.clear();
|
|||
|
|
setLanguage('de');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('LayoutBar zeigt deutsche Texte und wechselt live auf englisch', async () => {
|
|||
|
|
const LayoutBar = (await import('../src/components/LayoutBar')).default;
|
|||
|
|
render(<LayoutBar doc={null} bridge={null} />);
|
|||
|
|
expect(screen.getByText('Layouts')).toBeTruthy();
|
|||
|
|
expect(screen.getByText('Keine Layouts')).toBeTruthy();
|
|||
|
|
expect(screen.getByTitle('Layout hinzufügen')).toBeTruthy();
|
|||
|
|
|
|||
|
|
act(() => {
|
|||
|
|
setLanguage('en');
|
|||
|
|
});
|
|||
|
|
// Live-Update via subscribe (nach act flush)
|
|||
|
|
expect(screen.getByText('No layouts')).toBeTruthy();
|
|||
|
|
expect(screen.getByTitle('Add layout')).toBeTruthy();
|
|||
|
|
});
|
|||
|
|
});
|