Files
ausboss-ComfyUI-AusBoss/tests/touch_stop_note.test.mjs
ausboss c1b620d448 Mask by Touch: clear a stopped run's message once a run works
A run that stopped at the node left its message on the face until
something else was said there. The face's own runs cleared it, but a
workflow run's result did not, so the message stayed under a good result.
The stop now marks its message, and the next result that comes in
clears it.
2026-11-08 23:44:55 -06:00

65 lines
2.9 KiB
JavaScript

// A stopped run's message on Mask by Touch goes once the next result comes in.
//
// When a run stops at Mask by Touch (nothing picked, picks made on another
// picture), its message goes on the node's face and stays there, so the
// person can read it. It used to stay after the next run from the Run button
// had worked, until something else on the face was said. The face's own
// runs cleared it; a workflow run's result did not.
//
// touch_stage.mjs imports ComfyUI's api, so it cannot be loaded here. This
// file runs its setNote for real and holds the stop and the result to the
// lines that clear the message. The live proof is a stopped run followed by
// a good one on a real canvas.
import assert from "node:assert/strict";
import test from "node:test";
import { readFileSync } from "node:fs";
const SOURCE = readFileSync(new URL("../js/shared/touch_stage.mjs", import.meta.url), "utf-8");
function functionSource(name) {
const start = SOURCE.indexOf(`function ${name}(`);
assert.ok(start >= 0, `touch_stage.mjs has no function ${name}`);
const end = SOURCE.indexOf("\n}\n", start);
return SOURCE.slice(start, end + 2);
}
// The face's note, with setNote as touch_stage.mjs has it.
function noteFace() {
const setNote = new Function(`${functionSource("setNote")}\nreturn setNote;`)();
const classes = new Set();
const face = {
noteTimer: 0,
noteEl: { textContent: "", classList: { toggle: (name, on) => (on ? classes.add(name) : classes.delete(name)) } },
};
return { face, setNote, shown: () => (classes.has("on") ? face.noteEl.textContent : "") };
}
test("a stopped run's message stays up until the next result, then goes", () => {
const { face, setNote, shown } = noteFace();
const stopped = SOURCE.match(/face\.stopped = \(message\) => \{([\s\S]*?)\n {2}\};/)?.[1];
assert.ok(stopped, "touch_stage.mjs has no face.stopped");
assert.match(stopped, /setNote\(face, String\(message \?\? ""\)\);\s*(?:\/\/[^\n]*\n\s*)*face\.stopNote = true;/,
"a stop marks its message as a stop message, after it is set");
// What face.stopped does to the note.
setNote(face, "Mask by Touch: nothing is picked.");
face.stopNote = true;
assert.equal(shown(), "Mask by Touch: nothing is picked.");
// The next result clears it, as the head of show() does.
const head = functionSource("show").split("\n").slice(0, 6).join("\n");
assert.match(head, /if \(face\.stopNote && !interim && !restored\) setNote\(face, ""\);/,
"show() clears a stop message when a result comes in");
if (face.stopNote) setNote(face, "");
assert.equal(shown(), "");
});
test("any other message ends the stop message's hold", () => {
const { face, setNote } = noteFace();
setNote(face, "Mask by Touch: nothing is picked.");
face.stopNote = true;
setNote(face, "Nothing found there.", { life: 1 });
clearTimeout(face.noteTimer);
assert.equal(face.stopNote, false, "a note said since is not cleared by the next result");
});