feat: release design system engine, studio and component contracts

This commit is contained in:
Clintchiz committed 2026-10-19 13:09:03 +05:30
1 parent ff1065fb27
commit 3943b946d6
693 files changed
+175546 -3894

No files matched your search

+152
View File
@@ -0,0 +1,152 @@
import { test, expect } from "bun:test";
import { StudioSession, importDesign, exportDesign, diffDesign } from "../src/index.ts";
import { CORE_DESIGN_SYSTEMS, validateDesignSystem } from "../../design-system/src/index.ts";
test("invalid edits preserve a valid preview, raw input, undo/redo and reload", () => {
const data = new Map<string, string>();
const storage = {
getItem: (k: string) => data.get(k) ?? null,
setItem: (k: string, v: string) => {
data.set(k, v);
},
};
const session = new StudioSession(CORE_DESIGN_SYSTEMS.soft, storage);
session.mutate((s) => {
s.tokens["shape.control"]!.value = "13px";
}, "Changed radius");
session.edit('{"tokens":', "Incomplete JSON");
expect(session.diagnostics[0]!.code).toBe("WRN-STUDIO-IMPORT");
expect(session.valid.tokens["shape.control"]!.value).toBe("13px");
session.undo();
expect(session.diagnostics).toEqual([]);
session.redo();
expect(session.source).toBe('{"tokens":');
const restored = new StudioSession(undefined, storage);
expect(restored.restore()).toBe(true);
expect(restored.source).toBe(session.source);
expect(restored.valid.tokens["shape.control"]!.value).toBe("13px");
expect(() => restored.markApplied()).toThrow();
expect(() => restored.mutate(() => {}, "x")).toThrow();
});
test("history stays bounded, branches after undo, and realistic full-preset history reloads", () => {
const data = new Map<string, string>();
const storage = {
getItem: (k: string) => data.get(k) ?? null,
setItem: (k: string, v: string) => {
data.set(k, v);
},
};
const session = new StudioSession(undefined, storage);
for (let i = 0; i < 30; i++)
session.mutate((s) => {
s.name = "Revision " + i;
}, "Name");
expect(session.history).toHaveLength(25);
const restored = new StudioSession(undefined, storage);
expect(restored.restore()).toBe(true);
restored.undo();
restored.mutate((s) => {
s.name = "Branch";
}, "Branched");
restored.redo();
expect(restored.valid.name).toBe("Branch");
expect(restored.history.at(-1)!.label).toBe("Branched");
});
test("corrupted storage and quota failures do not destroy in-memory drafts", () => {
const broken = new StudioSession(undefined, {
getItem: () => "{",
setItem: () => {
throw Error("quota");
},
});
expect(broken.restore()).toBe(false);
expect(broken.storageError).toContain("could not be restored");
broken.mutate((s) => {
s.name = "Kept";
}, "Edit");
expect(broken.valid.name).toBe("Kept");
expect(broken.storageError).toContain("Autosave unavailable");
});
test("canonical import/export round trips all recipes, modes, aliases and metadata", () => {
for (const system of Object.values(CORE_DESIGN_SYSTEMS)) {
const artifact = exportDesign(system);
const report = importDesign(artifact.canonical);
expect(report.diagnostics).toEqual([]);
expect(report.system).toEqual(system);
expect(artifact.css).toContain("data-wrn-owner");
expect(JSON.parse(artifact.theme).designSystem.system).toEqual(system);
}
});
test("legacy import reports unsupported fields and preserves literal semantic bindings", () => {
const report = importDesign(
JSON.stringify({
default: "light",
palette: "violet",
themes: { light: { "color-primary": "#112233", unknown: "4px" } },
}),
"legacy",
);
expect(report.diagnostics).toEqual([]);
expect(report.unsupported).toContain("palette");
expect(report.unsupported).toContain("themes.light.unknown");
expect(report.system!.modes!.light!["color.primary"]).toEqual({
type: "color",
value: "#112233",
legacy: "color-primary",
});
});
test("exchange subset preserves aliases and reports ambiguous semantic mapping and unsupported composites", () => {
const report = importDesign(
JSON.stringify({
brand: {
$type: "color",
base: { $value: "#112233" },
action: { $value: "{brand.base}" },
complex: { $value: { colorSpace: "srgb", components: [0, 0, 0] } },
},
$extensions: { x: 1 },
}),
"tokens",
);
expect(report.diagnostics).toEqual([]);
expect(report.system!.tokens["brand.action"]!.value).toEqual({ ref: "brand.base" });
expect(report.unsupported).toContain("brand.complex");
expect(report.unsupported).toContain("$extensions");
expect(report.ambiguous).toHaveLength(2);
});
test("imports reject oversized, cyclic, executable, polluted and missing-reference documents", () => {
expect(importDesign(" ".repeat(2_000_001)).diagnostics).not.toEqual([]);
expect(
importDesign('{"__proto__":{"$type":"color","$value":"#000"}}', "tokens").diagnostics,
).not.toEqual([]);
for (const tokens of [
{ a: { type: "color", value: { ref: "missing" } } },
{ a: { type: "color", value: { ref: "b" } }, b: { type: "color", value: { ref: "a" } } },
{ a: { type: "color", value: "red;}body{display:none" } },
]) {
const system = { schemaVersion: 1, id: "bad", name: "Bad", version: "1", tokens };
expect(importDesign(JSON.stringify(system)).diagnostics).not.toEqual([]);
}
});
test("review diffs identify affected paths and applied snapshots are detached", () => {
const session = new StudioSession();
session.mutate((s) => {
s.tokens["shape.control"]!.value = "6px";
}, "Radius");
expect(session.changes()).toContain("$.tokens.shape.control.value");
session.markApplied();
expect(session.changes()).toEqual([]);
session.mutate((s) => {
s.name = "Other";
}, "Name");
expect(session.applied.name).not.toBe("Other");
expect(diffDesign({ a: 1 }, { a: 2, b: 3 })).toEqual(["$.a", "$.b"]);
expect(validateDesignSystem(session.valid)).toEqual([]);
});