86 lines
3.8 KiB
TypeScript
86 lines
3.8 KiB
TypeScript
import { test, expect } from "bun:test";
|
|
import { CORE_DESIGN_SYSTEMS } from "@wrnexus/design-system";
|
|
import { createDesignPackage, readDesignPackage } from "@wrnexus/design-system/package";
|
|
import { StudioSession } from "../src/session.ts";
|
|
import { planDesignUpgrade, applyDesignUpgrade } from "../src/upgrades.ts";
|
|
|
|
test("shared packages have deterministic pins independent of object key order and reject changed or future content", async () => {
|
|
const system = CORE_DESIGN_SYSTEMS.square;
|
|
const first = await createDesignPackage(system);
|
|
const reordered = {
|
|
...system,
|
|
tokens: Object.fromEntries(Object.entries(system.tokens).reverse()),
|
|
};
|
|
expect((await createDesignPackage(reordered)).integrity.digest).toBe(first.integrity.digest);
|
|
expect((await readDesignPackage(JSON.stringify(first))).package).toEqual(first);
|
|
const changed = structuredClone(first);
|
|
changed.system.tokens["color.primary"]!.value = "#abcdef";
|
|
await expect(readDesignPackage(JSON.stringify(changed))).rejects.toThrow("INTEGRITY");
|
|
await expect(readDesignPackage(JSON.stringify({ ...first, formatVersion: 2 }))).rejects.toThrow(
|
|
"VERSION",
|
|
);
|
|
await expect(createDesignPackage({ ...system, extends: ["company"] })).rejects.toThrow();
|
|
expect((await readDesignPackage(JSON.stringify(system))).migrations).toEqual([
|
|
"canonical-v1-to-package-v1",
|
|
]);
|
|
});
|
|
test("upgrade review and explicit adoption respect identity, pins, locks, stale revisions and recoverable history", async () => {
|
|
const session = new StudioSession();
|
|
const next = structuredClone(session.valid);
|
|
next.version = "1.1.0";
|
|
next.tokens["color.primary"]!.value = "#abcdef";
|
|
const source = JSON.stringify(await createDesignPackage(next));
|
|
const plan = await planDesignUpgrade(session, source);
|
|
expect(plan.canApply).toBe(true);
|
|
expect(session.valid.version).toBe("1.0.0");
|
|
session.setLocks(["/tokens/color.primary"]);
|
|
expect((await planDesignUpgrade(session, source)).canApply).toBe(false);
|
|
await expect(applyDesignUpgrade(session, source, plan.baseRevision)).rejects.toThrow("CONFLICT");
|
|
const locked = await planDesignUpgrade(session, source);
|
|
await expect(applyDesignUpgrade(session, source, locked.baseRevision)).rejects.toThrow("LOCK");
|
|
session.setLocks([]);
|
|
const fresh = await planDesignUpgrade(session, source);
|
|
await applyDesignUpgrade(session, source, fresh.baseRevision);
|
|
expect(session.valid.version).toBe("1.1.0");
|
|
session.undo();
|
|
expect(session.valid.version).toBe("1.0.0");
|
|
session.redo();
|
|
expect(session.valid.version).toBe("1.1.0");
|
|
await expect(
|
|
planDesignUpgrade(
|
|
session,
|
|
JSON.stringify(await createDesignPackage({ ...next, id: "different" })),
|
|
),
|
|
).rejects.toThrow("identity");
|
|
session.edit("{unfinished");
|
|
await expect(planDesignUpgrade(session, source)).rejects.toThrow("source errors");
|
|
});
|
|
test("legacy unversioned drafts migrate losslessly; future drafts remain untouched by autosave", () => {
|
|
let saved = "";
|
|
const storage = {
|
|
getItem: () => saved || null,
|
|
setItem: (_key: string, value: string) => {
|
|
saved = value;
|
|
},
|
|
};
|
|
const old = new StudioSession(undefined, storage);
|
|
old.edit("{unfinished");
|
|
const legacy = JSON.parse(saved);
|
|
delete legacy.storageVersion;
|
|
saved = JSON.stringify(legacy);
|
|
const restored = new StudioSession(undefined, storage);
|
|
expect(restored.restore()).toBe(true);
|
|
expect(restored.source).toBe("{unfinished");
|
|
restored.undo();
|
|
expect(JSON.parse(saved).storageVersion).toBe(1);
|
|
const future = JSON.stringify({ ...legacy, storageVersion: 99 });
|
|
saved = future;
|
|
const older = new StudioSession(undefined, storage);
|
|
expect(older.restore()).toBe(false);
|
|
expect(older.recoverySource).toBe(future);
|
|
older.edit("{another edit");
|
|
older.persist();
|
|
expect(saved).toBe(future);
|
|
expect(older.storageError).toContain("protected");
|
|
});
|