mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-23 14:52:18 +10:00
124 lines
4.6 KiB
TypeScript
124 lines
4.6 KiB
TypeScript
import type { ResumeData } from "@reactive-resume/schema/resume/data";
|
|
import { describe, expect, it } from "vitest";
|
|
import { defaultResumeData } from "@reactive-resume/schema/resume/default";
|
|
import { createResumeData, hasRenderDataChanged, preserveServerStylesheet } from "./stylesheet-preservation";
|
|
|
|
const cloneData = (): ResumeData => structuredClone(defaultResumeData);
|
|
|
|
const semanticStylesheet = {
|
|
mode: "semantic",
|
|
source: { languageVersion: 1, text: "@version 1;\nresume { color: red; }\n" },
|
|
applied: { languageVersion: 1, text: "@version 1;\nresume { color: red; }\n" },
|
|
} as const;
|
|
|
|
describe("preserveServerStylesheet", () => {
|
|
it("preserves the server-owned stylesheet when an old client omits it", () => {
|
|
const serverData = cloneData();
|
|
serverData.metadata.stylesheet = semanticStylesheet;
|
|
const clientData = cloneData();
|
|
|
|
const merged = preserveServerStylesheet(serverData, clientData);
|
|
|
|
expect(merged.metadata.stylesheet).toEqual(semanticStylesheet);
|
|
});
|
|
|
|
it("preserves the server-owned stylesheet when a client tries to replace it", () => {
|
|
const serverData = cloneData();
|
|
serverData.metadata.stylesheet = semanticStylesheet;
|
|
const clientData = cloneData();
|
|
clientData.metadata.stylesheet = {
|
|
mode: "legacy",
|
|
source: { languageVersion: 1, text: "@version 1;\n" },
|
|
applied: { languageVersion: 1, text: "@version 1;\n" },
|
|
};
|
|
|
|
expect(preserveServerStylesheet(serverData, clientData).metadata.stylesheet).toEqual(semanticStylesheet);
|
|
});
|
|
|
|
it("does not let a generic update introduce a stylesheet", () => {
|
|
const serverData = cloneData();
|
|
const clientData = cloneData();
|
|
clientData.metadata.stylesheet = semanticStylesheet;
|
|
|
|
expect(preserveServerStylesheet(serverData, clientData).metadata.stylesheet).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe("hasRenderDataChanged", () => {
|
|
it("detects content and base-design changes", () => {
|
|
const before = cloneData();
|
|
const changedContent = cloneData();
|
|
changedContent.basics.name = "Changed";
|
|
const changedDesign = cloneData();
|
|
changedDesign.metadata.design.colors.primary = "#000000";
|
|
|
|
expect(hasRenderDataChanged(before, changedContent)).toBe(true);
|
|
expect(hasRenderDataChanged(before, changedDesign)).toBe(true);
|
|
});
|
|
|
|
it("ignores notes and stylesheet source or applied changes", () => {
|
|
const before = cloneData();
|
|
before.metadata.stylesheet = semanticStylesheet;
|
|
const changedNotes = structuredClone(before);
|
|
changedNotes.metadata.notes = "private note";
|
|
const changedStylesheet = structuredClone(before);
|
|
changedStylesheet.metadata.stylesheet = {
|
|
...semanticStylesheet,
|
|
source: { languageVersion: 1, text: "@version 1;\nresume { color: blue; }\n" },
|
|
applied: { languageVersion: 1, text: "@version 1;\nresume { color: blue; }\n" },
|
|
};
|
|
|
|
expect(hasRenderDataChanged(before, changedNotes)).toBe(false);
|
|
expect(hasRenderDataChanged(before, changedStylesheet)).toBe(false);
|
|
});
|
|
|
|
it("detects active legacy style-rule changes but ignores dormant rules in semantic mode", () => {
|
|
const legacyBefore = cloneData();
|
|
const legacyAfter = cloneData();
|
|
legacyAfter.metadata.styleRules = [
|
|
{
|
|
id: "rule",
|
|
label: "Rule",
|
|
enabled: true,
|
|
target: { scope: "global" },
|
|
slots: { heading: { color: "#000000" } },
|
|
},
|
|
];
|
|
const semanticBefore = cloneData();
|
|
semanticBefore.metadata.stylesheet = semanticStylesheet;
|
|
const semanticAfter = structuredClone(semanticBefore);
|
|
semanticAfter.metadata.styleRules = legacyAfter.metadata.styleRules;
|
|
|
|
expect(hasRenderDataChanged(legacyBefore, legacyAfter)).toBe(true);
|
|
expect(hasRenderDataChanged(semanticBefore, semanticAfter)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("createResumeData", () => {
|
|
it("seeds empty semantic source only for the default-enabled cohort", () => {
|
|
expect(createResumeData({ semanticCssDefault: true }).metadata.stylesheet).toEqual({
|
|
mode: "semantic",
|
|
source: { languageVersion: 1, text: "@version 1;\n" },
|
|
applied: { languageVersion: 1, text: "@version 1;\n" },
|
|
});
|
|
expect(createResumeData({ semanticCssDefault: false }).metadata.stylesheet).toBeUndefined();
|
|
});
|
|
|
|
it("clones normal and sample defaults instead of mutating shared data", () => {
|
|
const normal = createResumeData({ semanticCssDefault: false, locale: "de-DE" });
|
|
const sample = createResumeData({
|
|
semanticCssDefault: true,
|
|
withSampleData: true,
|
|
name: "Sample Person",
|
|
locale: "de-DE",
|
|
});
|
|
|
|
normal.basics.name = "Mutated";
|
|
sample.metadata.page.locale = "en-US";
|
|
|
|
expect(defaultResumeData.basics.name).toBe("");
|
|
expect(defaultResumeData.metadata.page.locale).not.toBe("de-DE");
|
|
expect(sample.basics.name).toBe("Sample Person");
|
|
});
|
|
});
|