Release vehicle for Image Conveyor v1.6.0. Adds backend-authoritative main/reference output toggles, a dedicated queue-driven last_frame output, deterministic queue-role snapshots, disabled-branch prompt pruning, append-only saved-node migration, and v1.6.0 release metadata. Validated in live ComfyUI and by the complete GitHub Actions suite.
150 lines
4.2 KiB
JavaScript
150 lines
4.2 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
|
|
import {
|
|
normalizeQueueOutputSlots,
|
|
serializeToggleQueueSnapshot,
|
|
serializeToggleRuntimeState
|
|
} from '../web/image_conveyor_toggle_state_math.mjs'
|
|
|
|
test('toggle runtime state embeds reference, main, and last-frame switches', () => {
|
|
const raw = JSON.stringify({
|
|
version: 2,
|
|
output_mode: 'persistent_refs',
|
|
items: [{ id: 'A' }]
|
|
})
|
|
const next = JSON.parse(serializeToggleRuntimeState(
|
|
raw,
|
|
[false, true, false, true, true, true, true, false],
|
|
false,
|
|
8,
|
|
false
|
|
))
|
|
|
|
assert.deepEqual(next.reference_output_enabled, [
|
|
false, true, false, true, true, true, true, false
|
|
])
|
|
assert.equal(next.main_output_enabled, false)
|
|
assert.equal(next.last_frame_output_enabled, false)
|
|
assert.deepEqual(next.items, [{ id: 'A' }])
|
|
})
|
|
|
|
test('queue-output roles normalize to image and last_frame only', () => {
|
|
assert.deepEqual(normalizeQueueOutputSlots([1, 0, 1, -1, 2, true]), [0, 1])
|
|
})
|
|
|
|
test('toggle runtime state changes when only the visual switch state changes', () => {
|
|
const raw = JSON.stringify({ version: 2, output_mode: 'persistent_refs' })
|
|
const enabled = serializeToggleRuntimeState(raw, Array(8).fill(true), true, 8, true)
|
|
const disabled = serializeToggleRuntimeState(raw, Array(8).fill(true), true, 8, false)
|
|
assert.notEqual(enabled, disabled)
|
|
})
|
|
|
|
test('malformed state is left unchanged instead of inventing a backend state', () => {
|
|
assert.equal(serializeToggleRuntimeState('{bad', [false], false), '{bad')
|
|
})
|
|
|
|
test('reference-only emits explicit empty queue topology and filtered references', () => {
|
|
const next = JSON.parse(serializeToggleQueueSnapshot(
|
|
'',
|
|
'persistent_refs',
|
|
[1, 2, 3, 4],
|
|
[false, true, false, true, true, true, true, true],
|
|
false,
|
|
8,
|
|
[],
|
|
false
|
|
))
|
|
|
|
assert.deepEqual(next.reference_output_slots, [2, 4])
|
|
assert.deepEqual(next.queue_output_slots, [])
|
|
assert.equal(next.main_output_enabled, false)
|
|
assert.equal(next.last_frame_output_enabled, false)
|
|
assert.equal(Object.hasOwn(next, 'id'), false)
|
|
})
|
|
|
|
test('image-only keeps one reservation and emits queue role 0', () => {
|
|
const raw = JSON.stringify({ id: 'A', annotated: 'a.png [input]' })
|
|
const next = JSON.parse(serializeToggleQueueSnapshot(
|
|
raw,
|
|
'persistent_refs',
|
|
[1, 2],
|
|
[true, false, true, true, true, true, true, true],
|
|
true,
|
|
8,
|
|
[0],
|
|
true
|
|
))
|
|
|
|
assert.equal(next.id, 'A')
|
|
assert.deepEqual(next.queue_output_slots, [0])
|
|
assert.deepEqual(next.reference_output_slots, [1])
|
|
})
|
|
|
|
test('last-frame-only keeps its reservation even though main is disabled', () => {
|
|
const raw = JSON.stringify({ id: 'A', annotated: 'a.png [input]' })
|
|
const next = JSON.parse(serializeToggleQueueSnapshot(
|
|
raw,
|
|
'persistent_refs',
|
|
[],
|
|
Array(8).fill(true),
|
|
false,
|
|
8,
|
|
[1],
|
|
true
|
|
))
|
|
|
|
assert.equal(next.id, 'A')
|
|
assert.equal(next.annotated, 'a.png [input]')
|
|
assert.deepEqual(next.queue_output_slots, [1])
|
|
assert.equal(next.main_output_enabled, false)
|
|
assert.equal(next.last_frame_output_enabled, true)
|
|
})
|
|
|
|
test('image plus last_frame preserves a two-member reservation', () => {
|
|
const raw = JSON.stringify({
|
|
id: 'A',
|
|
annotated: 'a.png [input]',
|
|
items: [
|
|
{ id: 'A', annotated: 'a.png [input]' },
|
|
{ id: 'B', annotated: 'b.png [input]' }
|
|
]
|
|
})
|
|
const next = JSON.parse(serializeToggleQueueSnapshot(
|
|
raw,
|
|
'persistent_refs',
|
|
[],
|
|
Array(8).fill(true),
|
|
true,
|
|
8,
|
|
[0, 1],
|
|
true
|
|
))
|
|
|
|
assert.deepEqual(next.queue_output_slots, [0, 1])
|
|
assert.equal(next.items.length, 2)
|
|
})
|
|
|
|
test('disabled last_frame filters role 1 out of a connected queue topology', () => {
|
|
const raw = JSON.stringify({ id: 'A', annotated: 'a.png [input]' })
|
|
const next = JSON.parse(serializeToggleQueueSnapshot(
|
|
raw,
|
|
'persistent_refs',
|
|
[],
|
|
Array(8).fill(true),
|
|
true,
|
|
8,
|
|
[0, 1],
|
|
false
|
|
))
|
|
assert.deepEqual(next.queue_output_slots, [0])
|
|
})
|
|
|
|
test('queue-group mode is untouched by persistent-reference toggle serialization', () => {
|
|
const raw = JSON.stringify({ id: 'A', annotated: 'a.png [input]' })
|
|
assert.equal(
|
|
serializeToggleQueueSnapshot(raw, 'queue_group', [1], [false], false, 8, [1], true),
|
|
raw
|
|
)
|
|
})
|