2026-06-26 16:20:09 +02:00
|
|
|
import '@testing-library/jest-dom';
|
2026-06-26 17:48:24 +02:00
|
|
|
|
|
|
|
|
// Mock Canvas 2D context for jsdom (jsdom doesn't implement CanvasRenderingContext2D)
|
|
|
|
|
const noop = () => {};
|
|
|
|
|
const mockCtx = {
|
|
|
|
|
fillRect: noop,
|
|
|
|
|
strokeRect: noop,
|
|
|
|
|
clearRect: noop,
|
|
|
|
|
beginPath: noop,
|
|
|
|
|
closePath: noop,
|
|
|
|
|
moveTo: noop,
|
|
|
|
|
lineTo: noop,
|
|
|
|
|
arc: noop,
|
|
|
|
|
arcTo: noop,
|
|
|
|
|
rect: noop,
|
|
|
|
|
ellipse: noop,
|
|
|
|
|
quadraticCurveTo: noop,
|
|
|
|
|
bezierCurveTo: noop,
|
|
|
|
|
fill: noop,
|
|
|
|
|
stroke: noop,
|
|
|
|
|
save: noop,
|
|
|
|
|
restore: noop,
|
|
|
|
|
scale: noop,
|
|
|
|
|
translate: noop,
|
|
|
|
|
rotate: noop,
|
|
|
|
|
transform: noop,
|
|
|
|
|
setTransform: noop,
|
|
|
|
|
resetTransform: noop,
|
|
|
|
|
setLineDash: noop,
|
|
|
|
|
getLineDash: () => [] as number[],
|
|
|
|
|
clip: noop,
|
|
|
|
|
fillText: noop,
|
|
|
|
|
strokeText: noop,
|
|
|
|
|
measureText: () => ({ width: 0 }) as TextMetrics,
|
|
|
|
|
drawImage: noop,
|
|
|
|
|
createImageData: () => ({ width: 0, height: 0, data: new Uint8ClampedArray(0) }) as ImageData,
|
|
|
|
|
getImageData: () => ({ width: 0, height: 0, data: new Uint8ClampedArray(0) }) as ImageData,
|
|
|
|
|
putImageData: noop,
|
|
|
|
|
createLinearGradient: () => ({ addColorStop: noop }) as CanvasGradient,
|
|
|
|
|
createRadialGradient: () => ({ addColorStop: noop }) as CanvasGradient,
|
|
|
|
|
createPattern: () => null as unknown as CanvasPattern,
|
|
|
|
|
isPointInPath: () => false,
|
|
|
|
|
isPointInStroke: () => false,
|
|
|
|
|
// Properties
|
|
|
|
|
canvas: null as unknown as HTMLCanvasElement,
|
|
|
|
|
fillStyle: '',
|
|
|
|
|
strokeStyle: '',
|
|
|
|
|
lineWidth: 1,
|
|
|
|
|
lineCap: 'butt' as CanvasLineCap,
|
|
|
|
|
lineJoin: 'miter' as CanvasLineJoin,
|
|
|
|
|
miterLimit: 10,
|
|
|
|
|
lineDashOffset: 0,
|
|
|
|
|
font: '10px sans-serif',
|
|
|
|
|
textAlign: 'start' as CanvasTextAlign,
|
|
|
|
|
textBaseline: 'alphabetic' as CanvasTextBaseline,
|
|
|
|
|
direction: 'ltr' as CanvasTextDirection,
|
|
|
|
|
globalAlpha: 1,
|
|
|
|
|
globalCompositeOperation: 'source-over' as GlobalCompositeOperation,
|
|
|
|
|
imageSmoothingEnabled: true,
|
|
|
|
|
imageSmoothingQuality: 'low' as ImageSmoothingQuality,
|
|
|
|
|
shadowBlur: 0,
|
|
|
|
|
shadowColor: 'rgba(0, 0, 0, 0)',
|
|
|
|
|
shadowOffsetX: 0,
|
|
|
|
|
shadowOffsetY: 0,
|
|
|
|
|
filter: 'none',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Override getContext to return our mock for '2d'
|
|
|
|
|
HTMLCanvasElement.prototype.getContext = function (contextId: string) {
|
|
|
|
|
if (contextId === '2d') {
|
|
|
|
|
return mockCtx as unknown as CanvasRenderingContext2D;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
} as typeof HTMLCanvasElement.prototype.getContext;
|
|
|
|
|
|
|
|
|
|
// Mock getBoundingClientRect for canvas elements
|
|
|
|
|
const origGetBoundingClientRect = HTMLElement.prototype.getBoundingClientRect;
|
|
|
|
|
HTMLElement.prototype.getBoundingClientRect = function () {
|
|
|
|
|
if (this instanceof HTMLCanvasElement) {
|
|
|
|
|
return {
|
|
|
|
|
left: 0,
|
|
|
|
|
top: 0,
|
|
|
|
|
right: this.width,
|
|
|
|
|
bottom: this.height,
|
|
|
|
|
width: this.width,
|
|
|
|
|
height: this.height,
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
toJSON: () => ({}),
|
|
|
|
|
} as DOMRect;
|
|
|
|
|
}
|
|
|
|
|
return origGetBoundingClientRect.call(this);
|
|
|
|
|
};
|