diff --git a/web/app/layout.tsx b/web/app/layout.tsx index 3d25c85..0b36e3d 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -35,7 +35,26 @@ export default async function RootLayout({ children }: { children: React.ReactNo return (
- + {/* + `suppressHydrationWarning` wegen des Nonce, nicht wegen des Inhalts. + Der Browser **leert das Nonce-Attribut**, sobald er das Element + geparst hat — so schreibt es die CSP-Spezifikation vor, damit kein + Skript den Wert über `getAttribute` auslesen und sich selbst + nachladen kann. React vergleicht beim Hydrieren aber genau dieses + Attribut, liest clientseitig den leeren Wert und meldet einen + Unterschied, den es nicht gibt: unser Markup ist auf beiden Seiten + dasselbe. + + Es bleibt bei einem einzigen Element mit einer Konstante als Inhalt, + deshalb ist die Unterdrückung hier eng genug. Der Nonce selbst + entfällt nicht: ohne ihn blockiert die Richtlinie das Skript, und + ohne das Skript blitzt beim Laden das falsche Thema auf. + */} + {/* Nur die beiden Schnitte vorladen, die auf jeder Seite vorkommen. */} { + it('gibt dem Skript einen Nonce und nimmt es aus dem Hydrierungsvergleich', () => { + const tag = layout.slice(layout.indexOf('')) + + expect(tag).toContain('nonce={nonce}') + expect(tag).toContain('suppressHydrationWarning') + }) + + it('benutzt denselben Speicherschlüssel wie der Umschalter', () => { + const toggle = readFileSync(join(process.cwd(), 'components/ThemeToggle.tsx'), 'utf8') + + // Der Schlüssel wird importiert, nicht abgeschrieben — genau das prüft das + // hier: eine zweite, abgeschriebene Zeichenkette wäre der Fehler. + expect(toggle).toMatch(/export const THEME_KEY = '([^']+)'/) + expect(layout).toContain("import { THEME_KEY } from '@/components/ThemeToggle'") + expect(layout).toContain('JSON.stringify(THEME_KEY)') + }) + + it('setzt nur die beiden ausdrücklichen Themen, nie „wie das System"', () => { + // "system" darf kein data-theme setzen, sonst gewinnt es über die + // Medienabfrage und der Nutzer sitzt im falschen Thema. + expect(layout).toContain("t==='dark'||t==='light'") + }) +})