Files
ausboss-ComfyUI-AusBoss/tests/chrome.test.mjs
T
ausboss e7f2bf147a Add live per-node progress badges
Nodes can push a status line to their own badge through the new
push_node_status helper, which is a silent no-op without a live
PromptServer so a status update can never fail the run reporting it.
The LaMa inpainter emits "frame i/N" alongside its progress bar,
threading the node id in through a hidden UNIQUE_ID input -- hidden
entries never become widgets, so its visible inputs and saved
widgets_values are unchanged.

The badge rides its own Chrome setting, on by default: unlike the
runtime badge it only exists while a node is running, and it is
retired when the node moves on or the run ends, fails, or is stopped.
2026-08-13 20:13:58 -05:00

189 lines
7.1 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import {
advanceExecution,
applyStatus,
badgeFor,
clearStatuses,
composeTitle,
createRunState,
createStatusState,
formatDuration,
stripQueuePrefix,
} from "../js/shared/chrome.mjs";
test("composeTitle prefixes the queue depth", () => {
assert.equal(composeTitle("ComfyUI", 3), "(3) ComfyUI");
assert.equal(composeTitle("ComfyUI", 1), "(1) ComfyUI");
assert.equal(composeTitle("ComfyUI", "12"), "(12) ComfyUI");
});
test("composeTitle restores the bare title at zero", () => {
assert.equal(composeTitle("ComfyUI", 0), "ComfyUI");
assert.equal(composeTitle("(4) ComfyUI", 0), "ComfyUI");
});
test("composeTitle never double-prefixes an already-prefixed title", () => {
assert.equal(composeTitle("(2) ComfyUI", 5), "(5) ComfyUI");
assert.equal(composeTitle("(2) (3) ComfyUI", 1), "(1) (3) ComfyUI");
});
test("composeTitle treats junk queue depths as idle", () => {
assert.equal(composeTitle("ComfyUI", -1), "ComfyUI");
assert.equal(composeTitle("ComfyUI", NaN), "ComfyUI");
assert.equal(composeTitle("ComfyUI", undefined), "ComfyUI");
assert.equal(composeTitle("(7) ComfyUI", "junk"), "ComfyUI");
});
test("stripQueuePrefix only removes the exact prefix form", () => {
assert.equal(stripQueuePrefix("(3) ComfyUI"), "ComfyUI");
assert.equal(stripQueuePrefix("(3)ComfyUI"), "(3)ComfyUI");
assert.equal(stripQueuePrefix("(three) ComfyUI"), "(three) ComfyUI");
assert.equal(stripQueuePrefix("My (3) tabs"), "My (3) tabs");
assert.equal(stripQueuePrefix("ComfyUI"), "ComfyUI");
assert.equal(stripQueuePrefix(undefined), "");
});
test("formatDuration picks the unit for the magnitude", () => {
assert.equal(formatDuration(0.049), "49ms");
assert.equal(formatDuration(0), "0ms");
assert.equal(formatDuration(0.9994), "999ms");
assert.equal(formatDuration(1.5), "1.50s");
assert.equal(formatDuration(59.99), "59.99s");
assert.equal(formatDuration(95), "1m35s");
assert.equal(formatDuration(60), "1m0s");
assert.equal(formatDuration(3599), "59m59s");
});
test("formatDuration carries rounded-up boundaries into the next unit", () => {
assert.equal(formatDuration(0.9996), "1.00s");
assert.equal(formatDuration(59.999), "1m0s");
});
test("formatDuration rejects junk", () => {
assert.equal(formatDuration(-1), "");
assert.equal(formatDuration(NaN), "");
assert.equal(formatDuration(Infinity), "");
assert.equal(formatDuration("soon"), "");
});
test("advanceExecution closes out the previous node", () => {
const state = createRunState();
assert.deepEqual(advanceExecution(state, "5", 1000), []);
assert.equal(state.runningId, "5");
const updates = advanceExecution(state, "7", 3500);
assert.deepEqual(updates, [{ id: "5", seconds: 2.5 }]);
assert.equal(state.totals.get("5"), 2.5);
assert.equal(state.runningId, "7");
});
test("advanceExecution accumulates revisits so batched loops sum", () => {
const state = createRunState();
advanceExecution(state, "5", 0);
advanceExecution(state, "7", 1000);
advanceExecution(state, "5", 1500);
const updates = advanceExecution(state, null, 3500);
assert.deepEqual(updates, [{ id: "5", seconds: 3 }]);
assert.equal(state.totals.get("5"), 3);
assert.equal(state.totals.get("7"), 0.5);
assert.equal(state.runningId, null);
});
test("advanceExecution is a no-op while idle", () => {
const state = createRunState();
assert.deepEqual(advanceExecution(state, null, 100), []);
assert.equal(state.runningId, null);
assert.equal(state.totals.size, 0);
});
test("advanceExecution normalizes ids and clamps a backwards clock", () => {
const state = createRunState();
advanceExecution(state, 5, 2000);
assert.equal(state.runningId, "5");
const updates = advanceExecution(state, null, 1000);
assert.deepEqual(updates, [{ id: "5", seconds: 0 }]);
});
test("applyStatus stores a normalized entry per node id", () => {
const state = createStatusState();
assert.equal(applyStatus(state, { node_id: 5, text: "frame 2/9", progress: 0.25 }), "5");
assert.deepEqual(state.entries.get("5"), { text: "frame 2/9", progress: 0.25 });
});
test("applyStatus clamps progress and treats junk as no progress", () => {
const state = createStatusState();
applyStatus(state, { node_id: "1", text: "a", progress: 2 });
assert.equal(state.entries.get("1").progress, 1);
applyStatus(state, { node_id: "1", text: "a", progress: -0.5 });
assert.equal(state.entries.get("1").progress, 0);
for (const progress of [null, undefined, NaN, "soon"]) {
applyStatus(state, { node_id: "1", text: "a", progress });
assert.equal(state.entries.get("1").progress, null);
}
});
test("applyStatus keeps badge text to one capped ASCII line", () => {
const state = createStatusState();
applyStatus(state, { node_id: "1", text: " frame\n3/4 — ok " });
assert.equal(state.entries.get("1").text, "frame 3/4 ok");
applyStatus(state, { node_id: "1", text: "x".repeat(40) });
assert.equal(state.entries.get("1").text, "x".repeat(24));
});
test("applyStatus retracts a badge on empty text", () => {
const state = createStatusState();
applyStatus(state, { node_id: "1", text: "working" });
assert.equal(applyStatus(state, { node_id: "1", text: "" }), "1");
assert.equal(state.entries.has("1"), false);
// Nothing to retract the second time around.
assert.equal(applyStatus(state, { node_id: "1", text: " " }), null);
});
test("applyStatus rejects payloads without a node id", () => {
const state = createStatusState();
for (const detail of [undefined, {}, { node_id: null, text: "a" }, { node_id: "", text: "a" }]) {
assert.equal(applyStatus(state, detail), null);
}
assert.equal(state.entries.size, 0);
});
test("clearStatuses retires everything and reports what it cleared", () => {
const state = createStatusState();
applyStatus(state, { node_id: "1", text: "a" });
applyStatus(state, { node_id: "2", text: "b" });
assert.deepEqual(clearStatuses(state).sort(), ["1", "2"]);
assert.equal(state.entries.size, 0);
assert.deepEqual(clearStatuses(state), []);
});
test("clearStatuses keeps the node still executing", () => {
const state = createStatusState();
applyStatus(state, { node_id: "1", text: "a" });
applyStatus(state, { node_id: "2", text: "b" });
assert.deepEqual(clearStatuses(state, 2), ["1"]);
assert.deepEqual([...state.entries.keys()], ["2"]);
});
test("badgeFor prefers a live status over the runtime badge", () => {
const badge = badgeFor({ text: "frame 2/9", progress: 0.25 }, 12.5);
assert.deepEqual(badge, { kind: "live", text: "frame 2/9", progress: 0.25 });
});
test("badgeFor falls back to the runtime badge once the status is gone", () => {
assert.deepEqual(badgeFor(null, 1.5), { kind: "runtime", text: "1.50s", progress: null });
assert.deepEqual(badgeFor(undefined, 0), { kind: "runtime", text: "0ms", progress: null });
assert.deepEqual(badgeFor({ text: "" }, 1.5), {
kind: "runtime",
text: "1.50s",
progress: null,
});
});
test("badgeFor draws nothing without a status or a runtime", () => {
assert.equal(badgeFor(null, undefined), null);
assert.equal(badgeFor({ text: " " }, null), null);
assert.equal(badgeFor(null, "12"), null);
assert.equal(badgeFor(null, -1), null);
});