Files
Artificial-Sweetener-Simple…/web/tests/orderedMediaPreviewTransaction.test.ts
T

91 lines
2.7 KiB
TypeScript

// SimpleSyrup - workflow-focused ComfyUI extensions for image generation
// Copyright (C) 2026 Artificial Sweetener and contributors
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, expect, it, vi } from "vitest";
import {
OrderedMediaPreviewTransaction,
type OrderedMediaPreviewItem
} from "../src/orderedMediaPreviewTransaction";
import type { NativePreviewSlot } from "../src/orderedMediaPreviewAffordances";
describe("OrderedMediaPreviewTransaction", () => {
it("reorders the captured native surface without creating DOM elements", async () => {
let ready = false;
let rendered = items("one.png", "two.png");
const apply = vi.fn((next: OrderedMediaPreviewItem[]) => {
rendered = [...next];
});
const release = vi.fn();
const transaction = new OrderedMediaPreviewTransaction({
captureSurface: () => ({
items: rendered,
slots: [() => slot(0), () => slot(100)],
apply,
release
}),
authoritativeReady: () => ready,
stateChanged: vi.fn()
});
const childCount = document.body.childElementCount;
expect(transaction.move(0, 1)).toBe(true);
expect(rendered.map((item) => file(item.sourceUrl))).toEqual([
"two.png",
"one.png"
]);
expect(document.body.childElementCount).toBe(childCount);
transaction.authoritativePublished();
await new Promise((resolve) => setTimeout(resolve, 30));
expect(release).not.toHaveBeenCalled();
ready = true;
await vi.waitFor(() => {
expect(release).toHaveBeenCalledOnce();
});
transaction.dispose();
});
it("compacts removals through the same native surface", () => {
let rendered = items("one.png", "two.png", "three.png");
const transaction = new OrderedMediaPreviewTransaction({
captureSurface: () => ({
items: rendered,
slots: [() => slot(0), () => slot(100), () => slot(200)],
apply: (next) => {
rendered = [...next];
},
release: vi.fn()
}),
authoritativeReady: () => false,
stateChanged: vi.fn()
});
expect(transaction.remove(1)).toBe(true);
expect(rendered.map((item) => file(item.sourceUrl))).toEqual([
"one.png",
"three.png"
]);
expect(transaction.activeSlots()).toEqual([slot(0), slot(100)]);
transaction.dispose();
});
});
function items(...files: string[]): OrderedMediaPreviewItem[] {
return files.map((name) => {
const image = document.createElement("img");
image.src = `http://localhost/${name}`;
return { sourceUrl: image.src, image };
});
}
function slot(left: number): NativePreviewSlot {
return { left, top: 20, width: 80, height: 90 };
}
function file(sourceUrl: string): string {
return new URL(sourceUrl).pathname.slice(1);
}