import { describe, expect, it } from 'vitest';
import { Page, Text } from '@react-pdf/renderer';
import { renderPdf } from '@/lib/pdf/render';
import {
Badge,
BarChart,
DataTable,
DocumentShell,
FunnelChart,
KeyValueGrid,
LineChart,
PDF_TOKENS,
PieChart,
Section,
} from '@/lib/pdf/brand-kit';
describe('pdf brand kit', () => {
it('exposes canonical design tokens', () => {
expect(PDF_TOKENS.colors.headerBand).toBe('#0f172a');
expect(PDF_TOKENS.sizes.body).toBe(10);
expect(PDF_TOKENS.spacing.logoMaxWidth).toBe(200);
});
it('renders a kitchen-sink PDF without throwing', async () => {
const tree = (
r.name },
{
header: 'Score',
align: 'right',
render: (r: { score: number }) => String(r.score),
},
]}
rows={[
{ name: 'Alpha', score: 1 },
{ name: 'Beta', score: 2 },
]}
totals={['Total', '3']}
/>
);
const bytes = await renderPdf(tree);
expect(bytes).toBeInstanceOf(Buffer);
expect(bytes.length).toBeGreaterThan(1000);
expect(bytes.subarray(0, 5).toString('utf8')).toBe('%PDF-');
}, 30_000);
it('falls back gracefully when no chart data is provided', async () => {
const tree = (
'' }]} rows={[]} />
);
const bytes = await renderPdf(tree);
expect(bytes.subarray(0, 5).toString('utf8')).toBe('%PDF-');
}, 30_000);
});
// Belt-and-suspenders: a minimal direct Page render to confirm @react-pdf/renderer
// is actually installed and produces a real PDF stream, not just our tree.
describe('react-pdf renderer wiring', () => {
it('renders a bare to bytes', async () => {
const { Document } = await import('@react-pdf/renderer');
const tree = (
hello
);
const bytes = await renderPdf(tree);
expect(bytes.length).toBeGreaterThan(500);
expect(bytes.subarray(0, 5).toString('utf8')).toBe('%PDF-');
}, 30_000);
});