import { act, cleanup, render } from '@testing-library/react'; import { NextIntlClientProvider, useTranslations } from 'next-intl'; import { useState } from 'react'; import { afterEach, describe, expect, it } from 'vitest'; /** * translations-identity.test.tsx (Restposten 4, quick-260921-jt4) * * Prueft am ECHTEN `NextIntlClientProvider` — nicht behauptet, sondern * gemessen —, ob `t` aus `useTranslations` bei einem Zustandswechsel EINER * Komponente seine Identitaet behaelt. Der Quelltext der eingesetzten * `use-intl`-Fassung (4.13.0, `react.js`) zeigt: `translate` entsteht in * einem `useMemo`, dessen Abhaengigkeiten ausschliesslich aus dem * Intl-Kontext stammen (`cache, formatters, getMessageFallback, allMessages, * namespace, onError, globalFormats, locale, timeZone`) — keine davon haengt * vom lokalen Zustand einer Komponente ab. Der Anbieter (`NextIntlClientProvider`) * steht in `app/layout.tsx`, also oberhalb aller Komponenten dieses Projekts; * ein Zustandswechsel in einer Kindkomponente rendert den Anbieter nicht neu. * * Dieser eine Test entscheidet die Annahme aus quick-260921-gof * ("`t` ist bei jedem Render eine frische Funktion") an der Wurzel statt an * vier einzelnen Symptomstellen. */ const messages = { widgets: { calendar: { name: 'Kalender', }, }, }; function ProbeComponent({ onRender }: { onRender: (t: unknown) => void }) { const t = useTranslations('widgets'); const [, forceRerender] = useState(0); onRender(t); return ( ); } afterEach(() => { cleanup(); }); describe('t aus useTranslations — Identitaet ueber einen Zustandswechsel (Restposten 4)', () => { it('bleibt beim erneuten Render derselben Komponente dasselbe Funktionsobjekt, wenn NUR lokaler Zustand wechselt', () => { const seenTranslators: unknown[] = []; const { getByRole } = render( seenTranslators.push(t)} /> , ); expect(seenTranslators).toHaveLength(1); const tBeforeRerender = seenTranslators[0]; act(() => { getByRole('button').click(); }); expect(seenTranslators).toHaveLength(2); const tAfterRerender = seenTranslators[1]; // Der gemessene Kern der Annahme: dasselbe Objekt, nicht nur denselben // Rueckgabewert bei Aufruf — ein `toBe` (Referenzgleichheit), kein `toEqual`. expect(tAfterRerender).toBe(tBeforeRerender); }); });