Add dashboard report snapshots feature with CRUD operations. Implemented new database migrations for dashboard_report_snapshots, including report type handling. Updated backend routes and models to support snapshot retrieval and upsert functionality. Enhanced frontend components to integrate report snapshot management, including UI for daily and end-cycle reports. Added tests for new functionality to ensure reliability.
CI / lint-and-test (push) Canceled after 0s
CI / lint-and-test (push) Canceled after 0s
This commit is contained in:
1 parent
059087be1d
commit
34336b9bd1
41 files changed
+4824
-178
No files matched your search
@@ -0,0 +1,90 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { choosePdfSliceHeight, pdfBlockBreakOffsets } from '../pdfExport.ts';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
addImage: vi.fn(),
|
||||
save: vi.fn(),
|
||||
jsPDF: vi.fn(),
|
||||
html2canvas: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('jspdf', () => ({
|
||||
jsPDF: mocks.jsPDF,
|
||||
}));
|
||||
|
||||
vi.mock('html2canvas', () => ({
|
||||
default: mocks.html2canvas,
|
||||
}));
|
||||
|
||||
describe('exportCardToPdf compression', () => {
|
||||
beforeEach(() => {
|
||||
mocks.addImage.mockReset();
|
||||
mocks.save.mockReset();
|
||||
mocks.jsPDF.mockReset();
|
||||
mocks.html2canvas.mockReset();
|
||||
mocks.jsPDF.mockImplementation(function JsPDF() {
|
||||
return {
|
||||
internal: { pageSize: { getWidth: () => 210, getHeight: () => 297 } },
|
||||
addPage: vi.fn(),
|
||||
addImage: mocks.addImage,
|
||||
save: mocks.save,
|
||||
};
|
||||
});
|
||||
mocks.html2canvas.mockImplementation(async () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = 800;
|
||||
canvas.height = 400;
|
||||
return canvas;
|
||||
});
|
||||
});
|
||||
|
||||
it('embeds JPEG pages in a compressed jsPDF document', async () => {
|
||||
vi.spyOn(HTMLCanvasElement.prototype, 'getContext').mockReturnValue({
|
||||
fillStyle: '',
|
||||
fillRect: vi.fn(),
|
||||
drawImage: vi.fn(),
|
||||
} as unknown as CanvasRenderingContext2D);
|
||||
const toDataURL = vi
|
||||
.spyOn(HTMLCanvasElement.prototype, 'toDataURL')
|
||||
.mockReturnValue('data:image/jpeg;base64,xx');
|
||||
|
||||
const { exportCardToPdf } = await import('../pdfExport.ts');
|
||||
await exportCardToPdf(document.createElement('div'), 'Laporan.pdf');
|
||||
|
||||
expect(mocks.jsPDF).toHaveBeenCalledWith(expect.objectContaining({ compress: true }));
|
||||
expect(toDataURL).toHaveBeenCalledWith('image/jpeg', expect.any(Number));
|
||||
const quality = toDataURL.mock.calls.find((call) => call[0] === 'image/jpeg')?.[1] as number;
|
||||
expect(quality).toBeGreaterThan(0);
|
||||
expect(quality).toBeLessThan(1);
|
||||
expect(mocks.addImage).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
'JPEG',
|
||||
expect.any(Number),
|
||||
expect.any(Number),
|
||||
expect.any(Number),
|
||||
expect.any(Number)
|
||||
);
|
||||
expect(mocks.save).toHaveBeenCalledWith('Laporan.pdf');
|
||||
|
||||
toDataURL.mockRestore();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
});
|
||||
|
||||
describe('pdf page breaks', () => {
|
||||
it('does not defer an oversized table past the header', () => {
|
||||
const usableHeight = 1200;
|
||||
const breaks = pdfBlockBreakOffsets([{ top: 80, bottom: 5000 }], usableHeight);
|
||||
expect(breaks).not.toContain(80);
|
||||
expect(breaks).toContain(5000);
|
||||
expect(choosePdfSliceHeight(0, 5000, usableHeight, breaks)).toBe(usableHeight);
|
||||
});
|
||||
|
||||
it('keeps a small chart whole by breaking before it when it no longer fits', () => {
|
||||
const usableHeight = 400;
|
||||
const breaks = pdfBlockBreakOffsets([{ top: 350, bottom: 500 }], usableHeight);
|
||||
expect(breaks).toEqual(expect.arrayContaining([350, 500]));
|
||||
expect(choosePdfSliceHeight(0, 900, usableHeight, breaks)).toBe(350);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user