export class CanvasRenderingContext2DMock { constructor(public readonly canvas = {}) { } clearRect(x: number, y: number, w: number, h: number): void { } fillRect(x: number, y: number, w: number, h: number): void { } strokeRect(x: number, y: number, w: number, h: number): void { } setTransform(transform?: DOMMatrix2DInit): void { } getLineDash(): number[] { return []; } setLineDash(segments: number[]): void { } arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void { } arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void { } bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void { } closePath(): void { } ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void { } lineTo(x: number, y: number): void { } moveTo(x: number, y: number): void { } quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void { } rect(x: number, y: number, w: number, h: number): void { } createImageData(sw: number, sh: number): ImageData; createImageData(imagedata: ImageData): ImageData; createImageData() { return { data: new Uint8ClampedArray(0), width: 0, height: 0 }; } getImageData(sx: number, sy: number, sw: number, sh: number): ImageData { return { data: new Uint8ClampedArray(0), width: 0, height: 0 }; } putImageData(imagedata: ImageData, dx: number, dy: number): void; putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX: number, dirtyY: number, dirtyWidth: number, dirtyHeight: number): void; putImageData() { } createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient { return { addColorStop(offset: number, color: string): void { } }; } createPattern(image: CanvasImageSource, repetition: string): CanvasPattern | null { return null; } createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient { return { addColorStop(offset: number, color: string): void { } }; } beginPath(): void { } clip(fillRule?: CanvasFillRule): void; clip(path: Path2D, fillRule?: CanvasFillRule): void; clip() { } fill(fillRule?: CanvasFillRule): void; fill(path: Path2D, fillRule?: CanvasFillRule): void; fill() { } isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean; isPointInPath(path: Path2D, x: number, y: number, fillRule?: CanvasFillRule): boolean; isPointInPath() { return false; } isPointInStroke(x: number, y: number): boolean; isPointInStroke(path: Path2D, x: number, y: number): boolean; isPointInStroke() { return false; } stroke(): void stroke(path: Path2D): void; stroke() { } drawImage(image: CanvasImageSource, dx: number, dy: number): void; drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void; drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void; drawImage() { } restore() { } save() { } } export function canvasRenderingContext2DSpy(interceptions: any[] = []): CanvasRenderingContext2D { return new Proxy(new CanvasRenderingContext2DMock(), { get(target: any, key: PropertyKey) { const value = target[key]; if (typeof value === 'function') { return function (...args: any[]) { interceptions.push({ apply: key, args }); return Reflect.apply(value, target, args); }; } return value; }, set(target: any, key: PropertyKey, value: any) { interceptions.push({ set: key, value }); return Reflect.set(target, key, value); } }); }