import { describe, expect, it } from 'vitest' import { readFileSync } from 'node:fs' import { join } from 'node:path' /** * Das Skript, das das Thema vor dem ersten Malen setzt, hängt an drei Dingen, * die zusammenpassen müssen. Fällt eines weg, merkt es niemand sofort: * * 1. **Der Nonce.** Ohne ihn blockiert die Inhaltsrichtlinie das Skript, und * beim Laden blitzt das falsche Thema auf. Sichtbar, aber leicht als * Kleinigkeit abgetan. * 2. **`suppressHydrationWarning`.** Der Browser leert das Nonce-Attribut * nach dem Parsen, React vergleicht es beim Hydrieren trotzdem und meldet * einen Unterschied, den es nicht gibt. Die Meldung steht nur in der * Konsole des Entwicklungsservers — im Produktionsbau meldet React sie * nicht, ein e2e-Lauf kann sie also nicht auffangen. Deshalb hier auf der * Ebene der Quelle. * 3. **Der Schlüssel im Speicher**, derselbe wie im Umschalter. Weichen sie * ab, wird die Wahl bei jedem Laden vergessen. */ const layout = readFileSync(join(process.cwd(), 'app/layout.tsx'), 'utf8') describe('Thema vor dem ersten Malen', () => { 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'") }) })