mirror of
https://github.com/Canner/WrenAI.git
synced 2026-10-16 15:07:41 +08:00
test(genbi): make the canvas stub impossible to leave incomplete
The literal version was missing rect, and ECharts calls it — one more unhandled error, one more red run, one more round. Enumerating the methods a charting library happens to use is a game with no end, played at a CI round per move. It is a Proxy now: the handful that must return something are named, everything else answers as a no-op, and a method nobody has thought of yet is already handled. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,29 +15,35 @@ if (!('ResizeObserver' in globalThis)) {
|
||||
// Vitest counts those as unhandled errors and exits non-zero on an otherwise
|
||||
// green run, which is how this first reached CI: every assertion passing, the
|
||||
// job still red. A stub context is enough; nothing here asserts on pixels.
|
||||
//
|
||||
// It is a Proxy rather than a literal so it cannot be incomplete. Enumerating
|
||||
// methods meant a CI round per missing one — the first version shipped without
|
||||
// `rect` and found out that way. Anything not named below answers as a no-op.
|
||||
//
|
||||
// jsdom *defines* getContext and returns null from it, so testing for the
|
||||
// method's absence would never install this.
|
||||
// method's absence would never install this. Ask for a context instead.
|
||||
if (document.createElement('canvas').getContext('2d') === null) {
|
||||
HTMLCanvasElement.prototype.getContext = (() => {
|
||||
const noop = () => {};
|
||||
return {
|
||||
canvas: undefined,
|
||||
clearRect: noop, fillRect: noop, strokeRect: noop,
|
||||
save: noop, restore: noop, scale: noop, translate: noop, rotate: noop, setTransform: noop,
|
||||
beginPath: noop, closePath: noop, moveTo: noop, lineTo: noop, arc: noop, bezierCurveTo: noop,
|
||||
fill: noop, stroke: noop, clip: noop,
|
||||
createLinearGradient: () => ({ addColorStop: noop }),
|
||||
createRadialGradient: () => ({ addColorStop: noop }),
|
||||
createPattern: () => null,
|
||||
measureText: () => ({ width: 0 }),
|
||||
fillText: noop, strokeText: noop,
|
||||
drawImage: noop,
|
||||
getImageData: () => ({ data: new Uint8ClampedArray(4) }),
|
||||
putImageData: noop,
|
||||
createImageData: () => ({ data: new Uint8ClampedArray(4) }),
|
||||
setLineDash: noop, getLineDash: () => [],
|
||||
};
|
||||
}) as unknown as HTMLCanvasElement["getContext"];
|
||||
const noop = () => {};
|
||||
const withReturn: Record<string, unknown> = {
|
||||
measureText: () => ({ width: 0 }),
|
||||
createLinearGradient: () => ({ addColorStop: noop }),
|
||||
createRadialGradient: () => ({ addColorStop: noop }),
|
||||
createPattern: () => null,
|
||||
getLineDash: () => [],
|
||||
getImageData: () => ({ data: new Uint8ClampedArray(4) }),
|
||||
createImageData: () => ({ data: new Uint8ClampedArray(4) }),
|
||||
isPointInPath: () => false,
|
||||
isPointInStroke: () => false,
|
||||
};
|
||||
const context = new Proxy({} as Record<string, unknown>, {
|
||||
get: (target, property: string) =>
|
||||
property in withReturn ? withReturn[property]
|
||||
: property in target ? target[property]
|
||||
: noop,
|
||||
set: (target, property: string, value) => { target[property] = value; return true; },
|
||||
has: () => true,
|
||||
});
|
||||
HTMLCanvasElement.prototype.getContext = (() => context) as unknown as HTMLCanvasElement['getContext'];
|
||||
}
|
||||
|
||||
// jsdom does not implement matchMedia; AntD's responsive + theme code reads it.
|
||||
|
||||
Reference in New Issue
Block a user