/** * MockAdapter – Headless-Implementierung des RenderAdapter (Task C1). * Zeichnet nichts; protokolliert alle Aufrufe für assertions in Unit-Tests. */ import type { RenderAdapter, Viewport, GridConfig, BackgroundDrawConfig, RulerConfig, LayerStyle, OverlayPainter, SelectionState, } from '../types'; import type { CADElement, CADLayer } from '../../types/cad.types'; import type { Pt } from '../../tools/modification/geometry'; export interface RecordedCall { method: string; args: unknown[]; } export class MockAdapter implements RenderAdapter { readonly calls: RecordedCall[] = []; private canvas: HTMLCanvasElement | null = null; nextHitTestResult: CADElement | null = null; // ── Recording helper ───────────────────────────────────── private rec(method: string, args: unknown[]): void { this.calls.push({ method, args }); } /** Test-Helfer: alle Aufrufe einer Methode. */ callsOf(method: string): RecordedCall[] { return this.calls.filter((c) => c.method === method); } /** Test-Helfer: Anzahl Aufrufe einer Methode. */ countCalls(method: string): number { return this.callsOf(method).length; } reset(): void { this.calls.length = 0; this.nextHitTestResult = null; } // ── RenderAdapter Implementierung (reines Recording) ───── init(canvas: HTMLCanvasElement): void { this.canvas = canvas; this.rec('init', [canvas]); } resize(width: number, height: number, dpr: number): void { this.rec('resize', [width, height, dpr]); } setViewport(vp: Viewport): void { this.rec('setViewport', [vp]); } destroy(): void { this.rec('destroy', []); } clear(color: string): void { this.rec('clear', [color]); } drawGrid(cfg: GridConfig): void { this.rec('drawGrid', [cfg]); } drawBackground(img: HTMLImageElement | null, cfg: BackgroundDrawConfig): void { this.rec('drawBackground', [img, cfg]); } drawRuler(cfg: RulerConfig): void { this.rec('drawRuler', [cfg]); } drawElement(el: CADElement, layer: CADLayer, style: LayerStyle): void { this.rec('drawElement', [el, layer, style]); } removeElement(id: string): void { this.rec('removeElement', [id]); } clearElements(): void { this.rec('clearElements', []); } drawPreview(el: CADElement | null): void { this.rec('drawPreview', [el]); } setSelection(sel: SelectionState): void { this.rec('setSelection', [sel]); } setSnapPoints(pts: Array<{ x: number; y: number; type: string }>): void { this.rec('setSnapPoints', [pts]); } overlay(draw: (g: OverlayPainter) => void): void { const painter: OverlayPainter = { line(a: Pt, b: Pt, color: string, width?: number) {}, rect(x: number, y: number, w: number, h: number, strokeColor: string) {}, circle(center: Pt, radius: number, strokeColor: string) {}, text(text: string, at: Pt, color: string, fontSize?: number) {}, }; draw(painter); this.rec('overlay', [null]); } hitTest(world: Pt, tolerancePx: number): CADElement | null { this.rec('hitTest', [world, tolerancePx]); return this.nextHitTestResult; } }