116 lines
3.0 KiB
TypeScript
116 lines
3.0 KiB
TypeScript
|
|
/**
|
|||
|
|
* 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]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
}
|