///
///
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));
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
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 = 300, height = 300): ChartHelper {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
Object.assign(defaults.font, { family: 'Courier New' });
defaults.color = 'transparent';
// eslint-disable-next-line no-param-reassign
config.options = {
responsive: false,
animation: {
duration: 1,
},
plugins: {
legend: {
display: false,
},
title: {
display: false,
},
},
...(config.options || {}),
} as any;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const ctx = canvas.getContext('2d')!;
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);
},
};
}