/// import { expect } from 'vitest'; import { Chart, ChartConfiguration, defaults, ChartType, DefaultDataPoint } from 'chart.js'; import { toMatchImageSnapshot, MatchImageSnapshotOptions } from 'jest-image-snapshot'; import 'canvas-5-polyfill'; expect.extend({ toMatchImageSnapshot }); function toBuffer(canvas: HTMLCanvasElement) { return new Promise((resolve) => { canvas.toBlob((b) => { const file = new FileReader(); file.onload = () => resolve(Buffer.from(file.result as ArrayBuffer)); file.readAsArrayBuffer(b!); }); }); } export async function expectMatchSnapshot(canvas: HTMLCanvasElement): Promise { const image = await toBuffer(canvas); expect(image).toMatchImageSnapshot(); } export interface ChartHelper, LABEL = string> { chart: Chart; canvas: HTMLCanvasElement; ctx: CanvasRenderingContext2D; toMatchImageSnapshot(options?: MatchImageSnapshotOptions): Promise; } export default function createChart< TYPE extends ChartType, DATA extends unknown[] = DefaultDataPoint, LABEL = string, >(config: ChartConfiguration, width = 800, height = 600): ChartHelper { const canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; Object.assign(defaults.font, { family: 'Courier New' }); // defaults.color = 'transparent'; config.options = { responsive: false, animation: { duration: 1, }, plugins: { legend: { display: false, }, title: { display: false, }, }, ...(config.options || {}), } as any; const ctx = canvas.getContext('2d')!; // remove Path2D since not properly working (window as any).Path2D = null; const t = new Chart(ctx, config); return { chart: t, canvas, ctx, async toMatchImageSnapshot(options?: MatchImageSnapshotOptions) { await new Promise((resolve) => setTimeout(resolve, 100)); const image = await toBuffer(canvas); expect(image).toMatchImageSnapshot(options); }, }; }