// @vitest-environment happy-dom import type { CustomSection, ResumeData, SectionType } from "@reactive-resume/schema/resume/data"; import { describe, expect, it } from "vitest"; import { getDefaultSectionIconName } from "@reactive-resume/schema/resume/section-icons"; import { renderBuiltInSection, renderCustomSection, renderSummary, setRenderConfig } from "./section-renderers"; const baseConfig = { headingFont: "Inter", headingSizeHalfPt: 28, bodyFont: "Inter", bodySizeHalfPt: 20, textColorHex: "111111", primaryColorHex: "0563C1", }; setRenderConfig(baseConfig); const HEX = "#0563C1"; describe("renderSummary", () => { it("returns [] when the section is hidden", () => { const summary: ResumeData["summary"] = { title: "Summary", icon: getDefaultSectionIconName("summary"), content: "
Hello
", hidden: true, columns: 1, keepTogether: false, startOnNewPage: false, }; expect(renderSummary(summary, HEX)).toEqual([]); }); it("returns [] when content is empty", () => { const summary: ResumeData["summary"] = { title: "Summary", icon: getDefaultSectionIconName("summary"), content: "", hidden: false, columns: 1, keepTogether: false, startOnNewPage: false, }; expect(renderSummary(summary, HEX)).toEqual([]); }); it("includes a heading paragraph when both title and content are present", () => { const summary: ResumeData["summary"] = { title: "Summary", icon: getDefaultSectionIconName("summary"), content: "Hello world
", hidden: false, columns: 1, keepTogether: false, startOnNewPage: false, }; const paragraphs = renderSummary(summary, HEX); // One heading + the htmlToParagraphs output for one. expect(paragraphs.length).toBeGreaterThanOrEqual(2); }); it("omits the heading when title is empty but still renders content", () => { const summary: ResumeData["summary"] = { title: "", icon: getDefaultSectionIconName("summary"), content: "
Hello world
", hidden: false, columns: 1, keepTogether: false, startOnNewPage: false, }; const paragraphs = renderSummary(summary, HEX); expect(paragraphs.length).toBeGreaterThanOrEqual(1); }); }); const emptySection =x
" } as never], }; expect(renderCustomSection(section, HEX)).toEqual([]); }); it("renders content for a summary-type custom section", () => { const section: CustomSection = { ...baseCustom, type: "summary", items: [{ id: "x", hidden: false, content: "Hello
" } as never], }; const paragraphs = renderCustomSection(section, HEX); // 1 heading + at least one paragraph for the HTML expect(paragraphs.length).toBeGreaterThanOrEqual(2); }); it("renders recipient + content for a cover-letter custom section", () => { const section: CustomSection = { ...baseCustom, type: "cover-letter", title: "Cover Letter", items: [ { id: "x", hidden: false, recipient: "Dear Jane,
", content: "Body
", } as never, ], }; const paragraphs = renderCustomSection(section, HEX); expect(paragraphs).toHaveLength(2); }); }); describe("setRenderConfig", () => { it("can be called repeatedly with a different config (no throw)", () => { expect(() => setRenderConfig({ ...baseConfig, headingFont: "Roboto", primaryColorHex: "ff0000" })).not.toThrow(); // Restore for any later tests in the file setRenderConfig(baseConfig); }); });