Files

52 lines
3.5 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { keepsSize, qualityLabel, swap, upscale } from "./job.js";
const m = (f, sub = "") => ({ filename: f, subfolder: sub, type: "output" });
test("swap replaces the file under every render and ghost that plays it, and nothing else", () => {
const p = { scene_renders: { a: { media: m("x.mp4"), inSec: 1 }, b: { media: m("x.mp4") }, c: { media: m("y.mp4") } }, scene_ghosts: [{ id: "g", media: m("x.mp4") }] };
assert.equal(swap(p, m("x.mp4"), m("up.mp4", "funui_upscaled")), 3);
assert.equal(p.scene_renders.a.media.filename, "up.mp4"); assert.equal(p.scene_renders.a.inSec, 1);
assert.equal(p.scene_renders.c.media.filename, "y.mp4");
});
test("upscale waits while it runs, then returns the video; an error is thrown in words", async () => {
const seq = [{ state: "running" }, { state: "running" }, { state: "done", media: m("up.mp4", "funui_upscaled") }];
const api = { upscale: async () => ({ job_id: "id" }), upscaleJob: async () => seq.shift() };
assert.equal((await upscale(api, m("x.mp4"), "mdl", async () => {})).filename, "up.mp4");
const bad = { upscale: async () => ({ job_id: "id" }), upscaleJob: async () => ({ state: "error", detail: "out of memory" }) };
await assert.rejects(upscale(bad, m("x.mp4"), "mdl", async () => {}), /out of memory/);
});
test("a restarted ComfyUI is named, a dropped reply is retried longer", async () => {
const gone = { upscale: async () => ({ job_id: "id" }), upscaleJob: async () => { throw Object.assign(new Error("x"), { status: 404 }); } };
await assert.rejects(upscale(gone, m("x.mp4"), "mdl", async () => {}), /restarted/);
let n = 0;
const flaky = { upscale: async () => ({ job_id: "id" }), upscaleJob: async () => { if (++n < 5) throw new Error("net"); return { state: "done", media: m("u.mp4") }; } };
assert.equal((await upscale(flaky, m("x.mp4"), "mdl", async () => {})).filename, "u.mp4");
});
test("a take that plays the old file gets the upscaled one too, so stepping back does not undo it", async () => {
const { swap } = await import("./job.js");
const old = { filename: "a.mp4", subfolder: "", type: "output" }, up = { filename: "funui_upscaled_a.mp4", subfolder: "", type: "output" };
const p = { scene_renders: { s: { media: old } }, scene_variants: { s: [{ media: old, promptId: "p" }, { media: { filename: "other.mp4" }, promptId: "q" }] } };
swap(p, old, up);
assert.equal(p.scene_variants.s[0].media.filename, "funui_upscaled_a.mp4");
assert.equal(p.scene_variants.s[1].media.filename, "other.mp4");
});
test("quality levels read as words, and only denoise and deblur keep the video's size", () => {
assert.deepEqual(["BICUBIC", "ULTRA", "DENOISE_HIGH", "HIGHBITRATE_LOW", "STREAMING_ULTRA"].map(qualityLabel),
["Bicubic (no AI)", "Upscale · Ultra", "Denoise · High", "High bitrate · Low", "Streaming · Ultra"]);
assert.deepEqual(["ULTRA", "DENOISE_LOW", "DEBLUR_ULTRA", "HIGHBITRATE_HIGH"].map(keepsSize), [false, true, true, false]);
});
test("the RTX options reach the node as one JSON input, and a model upscale sends none", async () => {
const seen = [];
const api = { upscale: async (...a) => (seen.push(a), { job_id: "id" }), upscaleJob: async () => ({ state: "done", media: m("u.mp4") }) };
await upscale(api, m("x.mp4"), "NVIDIA RTX Super Resolution", async () => {}, { quality: "ULTRA" });
await upscale(api, m("x.mp4"), "mdl", async () => {});
assert.deepEqual(seen.map((a) => a[2]), [{ quality: "ULTRA" }, undefined]);
});