feat: release design system engine, studio and component contracts
This commit is contained in:
1 parent
ff1065fb27
commit
3943b946d6
693 files changed
+175546
-3894
No files matched your search
@@ -11,22 +11,43 @@ const code = new Bun.Transpiler({ loader: "ts" })
|
||||
|
||||
test("partial registration failure cleans the backend and live region on mount and refresh", () => {
|
||||
for (const failingMount of [1, 2]) {
|
||||
const window = new Window(), root = window.document.createElement("div");
|
||||
const window = new Window(),
|
||||
root = window.document.createElement("div");
|
||||
window.document.body.append(root);
|
||||
root.innerHTML = '<div data-block-id="a" data-block-parent="root" data-block-slot="content"></div><div data-block-id="b" data-block-parent="root" data-block-slot="content"></div>';
|
||||
let mounts = 0, destroyed = 0, cleaned = 0;
|
||||
root.innerHTML =
|
||||
'<div data-block-id="a" data-block-parent="root" data-block-slot="content"></div><div data-block-id="b" data-block-parent="root" data-block-slot="content"></div>';
|
||||
let mounts = 0,
|
||||
destroyed = 0,
|
||||
cleaned = 0;
|
||||
const mount = new Function("createDndManager", code + ";return mountBlockEditor;")(() => {
|
||||
const number = ++mounts; let registrations = 0;
|
||||
return { registerSortable() { if (++registrations === 2 && number === failingMount) throw new Error("registration failed"); return () => { cleaned++; }; }, destroy() { destroyed++; } };
|
||||
const number = ++mounts;
|
||||
let registrations = 0;
|
||||
return {
|
||||
registerSortable() {
|
||||
if (++registrations === 2 && number === failingMount)
|
||||
throw new Error("registration failed");
|
||||
return () => {
|
||||
cleaned++;
|
||||
};
|
||||
},
|
||||
destroy() {
|
||||
destroyed++;
|
||||
},
|
||||
};
|
||||
});
|
||||
let editor: MountedEditor | undefined;
|
||||
if (failingMount === 1) expect(() => mount(root, { onMove() {} })).toThrow("registration failed");
|
||||
else { editor = mount(root, { onMove() {} }); expect(() => editor!.refresh()).toThrow("registration failed"); }
|
||||
if (failingMount === 1)
|
||||
expect(() => mount(root, { onMove() {} })).toThrow("registration failed");
|
||||
else {
|
||||
editor = mount(root, { onMove() {} });
|
||||
expect(() => editor!.refresh()).toThrow("registration failed");
|
||||
}
|
||||
expect(root.querySelector('[role="status"]')).toBeNull();
|
||||
expect(root.querySelectorAll('[data-block-id]')).toHaveLength(2);
|
||||
expect(root.querySelectorAll("[data-block-id]")).toHaveLength(2);
|
||||
expect(destroyed).toBe(failingMount);
|
||||
expect(cleaned).toBe(failingMount === 1 ? 1 : 3);
|
||||
editor?.destroy(); editor?.refresh();
|
||||
editor?.destroy();
|
||||
editor?.refresh();
|
||||
expect(destroyed).toBe(failingMount);
|
||||
}
|
||||
});
|
||||
@@ -46,7 +67,12 @@ function fixture(onMove: MountEditorOptions["onMove"] = () => false) {
|
||||
}> = [];
|
||||
const mount = new Function("createDndManager", code + ";return mountBlockEditor;")(
|
||||
(options: DndManagerOptions) => {
|
||||
const backend = { options, registrations: [] as SortableRegistration[], zones: [] as DropZoneRegistration[], destroyed: 0 };
|
||||
const backend = {
|
||||
options,
|
||||
registrations: [] as SortableRegistration[],
|
||||
zones: [] as DropZoneRegistration[],
|
||||
destroyed: 0,
|
||||
};
|
||||
backends.push(backend);
|
||||
return {
|
||||
registerDropZone: (registration: DropZoneRegistration) => {
|
||||
@@ -100,9 +126,15 @@ test("large canvas registration scans blocks once and preserves interleaved slot
|
||||
const backend = f.backends.at(-1)!;
|
||||
expect(scans).toBe(1);
|
||||
expect(backend.registrations.map(({ id, group, index }) => ({ id, group, index }))).toEqual(
|
||||
Array.from({ length: 300 }, (_, i) => ({ id: String(i), group: JSON.stringify([`parent:${i % 3}`, "content"]), index: Math.floor(i / 3) })),
|
||||
Array.from({ length: 300 }, (_, i) => ({
|
||||
id: String(i),
|
||||
group: JSON.stringify([`parent:${i % 3}`, "content"]),
|
||||
index: Math.floor(i / 3),
|
||||
})),
|
||||
);
|
||||
expect(backend.zones.map(zone => zone.group)).toEqual([JSON.stringify(["parent:3", "content"])]);
|
||||
expect(backend.zones.map((zone) => zone.group)).toEqual([
|
||||
JSON.stringify(["parent:3", "content"]),
|
||||
]);
|
||||
f.editor.destroy();
|
||||
});
|
||||
|
||||
@@ -127,7 +159,10 @@ test("cancelled optimistic moves restore original DOM nodes across containers",
|
||||
|
||||
test("empty named slot targets produce validated editor move intents and refresh away when populated", async () => {
|
||||
const moves: unknown[] = [];
|
||||
const f = fixture(intent => { moves.push(intent); return true; });
|
||||
const f = fixture((intent) => {
|
||||
moves.push(intent);
|
||||
return true;
|
||||
});
|
||||
const target = f.document.createElement("div");
|
||||
target.dataset.blockParent = "parent:empty";
|
||||
target.dataset.blockSlotTarget = "content:empty";
|
||||
@@ -138,9 +173,12 @@ test("empty named slot targets produce validated editor move intents and refresh
|
||||
const zone = backend.zones[0]!;
|
||||
expect(backend.options.accept!(["a"], { group: zone.group, index: 0 })).toBe(true);
|
||||
await backend.options.onMoveIntent({ ids: ["a"], from: [], to: { group: zone.group, index: 0 } });
|
||||
expect(moves).toEqual([{ nodeIds: ["a"], to: { parentId: "parent:empty", slot: "content:empty", index: 0 } }]);
|
||||
expect(moves).toEqual([
|
||||
{ nodeIds: ["a"], to: { parentId: "parent:empty", slot: "content:empty", index: 0 } },
|
||||
]);
|
||||
const child = f.root.querySelector('[data-block-id="a"]')! as any;
|
||||
child.dataset.blockParent = "parent:empty"; child.dataset.blockSlot = "content:empty";
|
||||
child.dataset.blockParent = "parent:empty";
|
||||
child.dataset.blockSlot = "content:empty";
|
||||
target.append(child);
|
||||
f.editor.refresh();
|
||||
expect(f.backends.at(-1)!.zones).toHaveLength(0);
|
||||
|
||||
Reference in new issue
Block a user