/** * Task G5 – Browser-Print: @media print Stylesheet + Print-Service. * * printService bereitet den Body auf den Druck vor (print-layout-Klasse, * Print-Modus ohne UI-Chrome), printLayout() triggert window.print nach * Vorbereitung und räumt danach ab. Die CSS-Datei muss einen @media print * Block mit den Kernregeln (UI ausblenden, Canvas füllen, @page) * enthalten — verifiziert als Datei-Assertion (jsdom kann kein print-CSS * rendern). */ import { describe, it, expect, vi, afterEach } from 'vitest'; import { readFileSync } from 'fs'; import { join } from 'path'; import { preparePrintLayout, cleanupPrintLayout, printLayout } from '../src/services/printService'; describe('G5: printService', () => { afterEach(() => { cleanupPrintLayout(); }); it('preparePrintLayout setzt print-layout-Klasse am body', () => { document.body.classList.remove('print-layout'); preparePrintLayout(); expect(document.body.classList.contains('print-layout')).toBe(true); }); it('cleanupPrintLayout entfernt die Klasse wieder', () => { preparePrintLayout(); cleanupPrintLayout(); expect(document.body.classList.contains('print-layout')).toBe(false); }); it('printLayout ruft window.print nach Vorbereitung und räumt ab (async)', async () => { const printSpy = vi.spyOn(window, 'print').mockImplementation(() => {}); await printLayout(); expect(printSpy).toHaveBeenCalledTimes(1); // nach dem Druck ist wieder aufgeräumt expect(document.body.classList.contains('print-layout')).toBe(false); printSpy.mockRestore(); }); }); describe('G5: Print-Stylesheet-Regeln (Datei-Assertion)', () => { const css = readFileSync(join(__dirname, '..', 'src', 'styles.css'), 'utf-8'); const printBlock = css.slice(css.indexOf('@media print')); it('enthält einen @media print Block mit @page A4 landscape', () => { expect(css).toContain('@media print'); expect(printBlock).toMatch(/@page\s*\{[^}]*size:\s*A4 landscape/); }); it('blendet UI-Chrome im Druck aus (screen-only Regel)', () => { expect(printBlock).toContain('.screen-only'); expect(printBlock).toMatch(/\.screen-only\s*\{[^}]*display:\s*none/); }); it('Canvas/Druckbereich füllt die Seite (print-area Regel)', () => { expect(printBlock).toContain('.print-area'); expect(printBlock).toMatch(/\.print-area\s*\{[^}]*width:\s*100%/); }); it('print-layout-Modus erzwingt Farbdruck-Hintergründe (print-color-adjust)', () => { expect(printBlock).toMatch(/-webkit-print-color-adjust:\s*exact/); }); });