import type { ResumeData } from "@reactive-resume/schema/resume/data"; import type { SectionTitleResolver } from "./section-title"; import { Buffer } from "node:buffer"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { sampleResumeData } from "@reactive-resume/schema/resume/sample"; const rendererMock = vi.hoisted(() => ({ renderToBuffer: vi.fn(async () => Buffer.from("%PDF")), })); const createRendererUnsafeResumeData = (): ResumeData => { const data = structuredClone(sampleResumeData); data.customSections = [ { id: "custom-experience", type: "experience", title: "Experience", icon: "", columns: 1, hidden: false, keepTogether: false, startOnNewPage: false, items: [{ id: "summary-shaped-item", hidden: false, content: "
Missing company
" }], } as never, ]; return data; }; const createLegacyRendererSafeResumeData = (): ResumeData => ({ ...structuredClone(sampleResumeData), customSections: [ { id: "custom-experience", type: "experience", title: "Experience", icon: "", columns: 1, hidden: false, keepTogether: false, startOnNewPage: false, items: [ { id: "experience-item", hidden: false, company: "Analytical Engines", position: "Programmer", location: "London", period: "1842–1843", description: "Wrote the first algorithm.
", content: "Compatible overlap
", }, ], }, ], }) as unknown as ResumeData; vi.mock("#react-pdf-renderer", async (importOriginal) => ({ ...(await importOriginalCompatible overlap
", roles: [], website: { url: "", label: "", inlineLink: false }, }), ], }), ], }), }), }), ); }); it("returns semantic diagnostics without rendering an invalid applied source", async () => { const data = structuredClone(sampleResumeData); const invalid = { languageVersion: 1, text: "@version 1; section { color: ; }" }; data.metadata.stylesheet = { mode: "semantic", source: invalid, applied: invalid }; const { createResumePdfFileResult } = await import("./server"); const result = await createResumePdfFileResult({ data, filename: "resume.pdf" }); expect(result).toMatchObject({ ok: false, diagnostics: [expect.objectContaining({ severity: "error" })], }); expect(rendererMock.renderToBuffer).not.toHaveBeenCalled(); }); it("rejects unchecked rendering instead of producing an unstyled PDF for semantic errors", async () => { const data = structuredClone(sampleResumeData); const invalid = { languageVersion: 1, text: "@version 1; section { color: ; }" }; data.metadata.stylesheet = { mode: "semantic", source: invalid, applied: invalid }; const { createResumePdfFile } = await import("./server"); await expect(createResumePdfFile({ data, filename: "resume.pdf" })).rejects.toMatchObject({ cause: [expect.objectContaining({ severity: "error" })], }); expect(rendererMock.renderToBuffer).not.toHaveBeenCalled(); }); it("rejects renderer-unsafe data at the server boundary before React PDF dispatch", async () => { const { createResumePdfFile } = await import("./server"); const error = await createResumePdfFile({ data: createRendererUnsafeResumeData(), filename: "resume.pdf", }).catch((caught: unknown) => caught); expect(error).toHaveProperty("issues.0.path", ["customSections", 0, "items", 0, "company"]); expect(rendererMock.renderToBuffer).not.toHaveBeenCalled(); }); });