Files
JasonHoku-ComfyUI-Ultimate-…/tests/js/progress_text.test.js
T
Jason HokuandClaude Fable 5.1 b109ded9e3 feat(distributed): Start At Job, claim-time reject re-check, LTX on the master, live ETA, no lost worker results (Roadmap 30/73/13)
- plan: start_at_job skips the first N-1 plan entries (counted as skipped), LTX entries are never
  skipped as "existing" and are split out of the worker queue (legacy companion: clear error)
- claim filter: _make_reject_recheck re-reads the manifest (throttled, mtime/size keyed, under the
  manifest lock) so a preview rejected mid-run is dropped when a worker claims its full render
- LTX phase: video jobs render on the master (_render_ltx_job, shared with the local loop) while
  workers render the image jobs; Start At Job also skips LTX in the local loop
- progress: ultimate_grid.progress events during distributed runs (phase "distributed", machines
  count), ETA from the manager's rolling per-claimer durations via on_status; format_eta_str
- model sync (73-A): the master's claim loop now waits for workers inside the loop and renders
  reclaimed jobs itself after wait_timeout (max(600, claim_timeout)), so a long worker download
  no longer ends with the worker's image deleted as a duplicate
- tests: 35 python, 5 node; docs (ProjectStructure events + wait_timeout, README parity/model
  sync/troubleshooting, Roadmap 30/73/13)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 18:48:52 -08:00

48 lines
2.1 KiB
JavaScript

// Run: node --test tests/js/progress_text.test.js (ETA bar label for progress events, no browser needed)
const fs = require('fs');
const path = require('path');
const test = require('node:test');
const assert = require('assert');
const src = fs.readFileSync(path.join(__dirname, '..', '..', 'resources', 'logic_events.js'), 'utf8');
function grab(name) {
const i = src.indexOf('function ' + name + '(');
assert.ok(i >= 0, name + ' missing');
let depth = 0, j = src.indexOf('{', i);
for (let k = j; k < src.length; k++) {
if (src[k] === '{') depth++;
if (src[k] === '}') { depth--; if (depth === 0) return src.slice(i, k + 1); }
}
}
const formatProgressText = new Function(grab('formatProgressText') + '\nreturn formatProgressText;')();
const base = { current_job: 3, total_jobs: 6, progress_pct: 50, eta_str: '2m 5s', finish_time: '12:00:00', avg_duration: 10.5 };
test('distributed label shows the machine count', () => {
const t = formatProgressText({ ...base, phase: 'distributed', workers: 2 });
assert.strictEqual(t, 'Job 3/6 (50%) | ETA: 2m 5s | ~12:00:00 | 10.5s/job | 2 machine(s)');
});
test('distributed without workers omits the machine part', () => {
const t = formatProgressText({ ...base, phase: 'distributed', workers: 0 });
assert.strictEqual(t, 'Job 3/6 (50%) | ETA: 2m 5s | ~12:00:00 | 10.5s/job');
});
test('upscaling label is unchanged', () => {
const t = formatProgressText({ ...base, phase: 'upscaling', workers: 3 });
assert.strictEqual(t, 'Upscaling 3/6 (50%) | ETA: 2m 5s | ~12:00:00 | 10.5s/job');
});
test('sweep label keeps errors and paused state', () => {
assert.strictEqual(
formatProgressText({ ...base, phase: 'sweep', errors: 1, state: 'paused', finish_time: '' }),
'Sweep job 3/6 (50%) | ETA: 2m 5s | 10.5s/job | 1 error | paused');
assert.strictEqual(
formatProgressText({ ...base, phase: 'sweep', errors: 2, state: 'cancelled' }),
'Sweep job 3/6 (50%) | ETA: 2m 5s | ~12:00:00 | 10.5s/job | 2 errors | cancelled');
});
test('plain run (no phase) uses the Job label', () => {
assert.strictEqual(formatProgressText(base), 'Job 3/6 (50%) | ETA: 2m 5s | ~12:00:00 | 10.5s/job');
});