Files
olivv-cs-ComfyUI-FunPack/app/ui/features/composer/story.test.js
T

79 lines
4.0 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { applyStory, clash, joinStory, match, storyRoots } from "./story.js";
const proj = () => ({ scenes: [{ id: "a", text: "one" }, { id: "b", text: "two" }, { id: "v", text: "", source: { type: "video", media_ref: "m" } }, { id: "c", text: "three" }], scene_renders: {}, scene_ghosts: [] });
const texts = (p) => p.scenes.map((s) => `${s.id}:${s.text}`);
test("the story is the generated roots' texts with the marker between them; video clips and left-out scenes are not in it", () => {
const p = proj(); p.scenes[3].excluded = true;
assert.deepEqual(storyRoots(p).map((s) => s.id), ["a", "b"]);
assert.equal(joinStory(p, "qcut"), "one\nqcut\ntwo");
});
test("match: exact text pins a scene through a reorder; the rest take the leftovers in order", () => {
assert.deepEqual(match(["three", "one", "new"], ["one", "two", "three"]), [2, 0, 1]);
assert.deepEqual(match(["x", "two"], ["one", "two"]), [0, 1]);
assert.deepEqual(match(["a", "b", "c"], ["a"]), [0, -1, -1]);
});
test("editing a scene's words keeps the scene (its id, so its render and anchor)", () => {
const p = proj();
assert.equal(applyStory(p, ["one!", "two", "three"]), true);
assert.deepEqual(texts(p), ["a:one!", "b:two", "v:", "c:three"]);
});
test("a dropped part removes its scene (a rendered one leaves a ghost); the video clip stays", () => {
const p = proj(); p.scene_renders.b = { media: { filename: "b.mp4" } };
assert.equal(applyStory(p, ["one", "three"]), true);
assert.deepEqual(texts(p), ["a:one", "v:", "c:three"]);
assert.deepEqual(p.scene_ghosts.map((g) => g.id), ["b"]);
});
test("a part nothing owns becomes a new scene at the end of the story", () => {
const p = proj();
assert.equal(applyStory(p, ["one", "two", "three", "four"]), true);
assert.deepEqual(p.scenes.map((s) => s.text), ["one", "two", "", "three", "four"]);
});
test("a part with new words takes over the leftover scene in place, so its render and anchor are kept", () => {
const p = proj();
applyStory(p, ["one", "extra", "three"]);
assert.deepEqual(texts(p), ["a:one", "b:extra", "v:", "c:three"]);
});
test("a reordered story reorders the plan; an unchanged story changes nothing", () => {
const p = proj();
assert.equal(applyStory(p, ["three", "one", "two"]), true);
assert.deepEqual(p.scenes.map((s) => s.id), ["c", "a", "v", "b"]); // the video clip keeps its slot
const q = proj();
assert.equal(applyStory(q, ["one", "two", "three"]), false);
});
test("an empty split changes nothing", () => assert.equal(applyStory(proj(), []), false));
test("an emptied box does not delete the scenes", () => {
const p = proj(), before = JSON.stringify(p);
assert.equal(applyStory(p, [""]), false);
assert.equal(JSON.stringify(p), before);
});
test("editing one scene leaves the plan order alone, even with a montage or a cut unit interleaved", () => {
const p = { scenes: [{ id: "A", text: "alpha" }, { id: "B", text: "beta" }, { id: "a1", gen_unit_id: "A", cut_offset_frames: 40, text: "" }, { id: "b1", gen_unit_id: "B", cut_offset_frames: 40, text: "" }, { id: "a2", gen_unit_id: "A", cut_offset_frames: 0, text: "alpha" }], scene_renders: {}, scene_ghosts: [] };
applyStory(p, ["alpha!", "beta"]);
assert.deepEqual(p.scenes.map((s) => s.id), ["A", "B", "a1", "b1", "a2"]);
assert.equal(p.scenes.find((s) => s.id === "a2").text, "alpha!", "the first piece shares the prompt");
});
test("dropping a cut scene's paragraph removes the scene with its cuts instead of promoting a cut", () => {
const p = { scenes: [{ id: "A", text: "alpha" }, { id: "A2", gen_unit_id: "A", cut_offset_frames: 40, text: "" }, { id: "B", text: "beta" }], scene_renders: {}, scene_ghosts: [] };
assert.equal(applyStory(p, ["beta"]), true);
assert.deepEqual(p.scenes.map((s) => s.id), ["B"]);
});
test("clash finds a scene whose own text contains a cut word", () => {
const p = proj(); p.scenes[1].text = "a quick qcut to b";
assert.equal(clash(p, ["qcut"]).id, "b");
assert.equal(clash(p, ["other"]), null);
});