Plain HTML, CSS and JavaScript modules, with no build step. Hash routes and relative URLs make it work under any path. The job list is polled: every 2 seconds while a job runs, and less often otherwise.
61 lines
2.0 KiB
JavaScript
61 lines
2.0 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { test } from 'node:test';
|
|
import { install, server, settle } from './flow-helpers.mjs';
|
|
|
|
const ui = install();
|
|
const { startPolling, stopPolling, watchJobs } = await import('../../bindery/static/js/jobs.js');
|
|
|
|
test('polling adapts to work and visibility, retries failures, and stops after an in-flight request', async (t) => {
|
|
t.mock.timers.enable({ apis: ['setTimeout'] });
|
|
const api = server(t);
|
|
const rendered = [];
|
|
const unsubscribe = watchJobs({ render: (jobs) => rendered.push(jobs) });
|
|
t.after(() => { unsubscribe(); stopPolling(); });
|
|
let jobs = [];
|
|
api.on('GET', 'jobs', () => jobs);
|
|
startPolling();
|
|
await settle();
|
|
t.mock.timers.tick(9999);
|
|
assert.equal(api.requests.length, 1);
|
|
jobs = [{ id: 'job', status: 'running' }];
|
|
t.mock.timers.tick(1);
|
|
await settle();
|
|
assert.equal(api.requests.length, 2);
|
|
t.mock.timers.tick(1999);
|
|
assert.equal(api.requests.length, 2);
|
|
t.mock.timers.tick(1);
|
|
await settle();
|
|
assert.equal(api.requests.length, 3);
|
|
document.hidden = true;
|
|
ui.documentEvents.visibilitychange();
|
|
assert.equal(api.requests.length, 3);
|
|
t.mock.timers.tick(2000);
|
|
await settle();
|
|
t.mock.timers.tick(59999);
|
|
assert.equal(api.requests.length, 4);
|
|
t.mock.timers.tick(1);
|
|
await settle();
|
|
assert.equal(api.requests.length, 5);
|
|
document.hidden = false;
|
|
api.on('GET', 'jobs', () => { throw new Error('Connection lost'); });
|
|
const previous = rendered.length;
|
|
ui.documentEvents.visibilitychange();
|
|
await settle();
|
|
assert.equal(rendered.length, previous);
|
|
jobs = [{ id: 'job', status: 'done' }];
|
|
api.on('GET', 'jobs', () => jobs);
|
|
t.mock.timers.tick(2000);
|
|
await settle();
|
|
assert.deepEqual(rendered.at(-1), jobs);
|
|
let resolve;
|
|
api.on('GET', 'jobs', () => new Promise((done) => { resolve = done; }));
|
|
t.mock.timers.tick(10000);
|
|
stopPolling();
|
|
resolve([]);
|
|
await settle();
|
|
const total = api.requests.length;
|
|
t.mock.timers.tick(60000);
|
|
await settle();
|
|
assert.equal(api.requests.length, total);
|
|
});
|