Health box and summary update as each WAN check ends (closes #206)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
The health box and the summary were drawn only once every check in a round had ended, so a target that never answers held them back until its timeout, after the rows already showed the network was back. tick now redraws both with each WAN host's row. The "Health:" debug log line moved from updateHealthBox to the end of the round, so it is still written once per round, and still only once a WAN host's check is recorded. Model: opus-5-5
This commit was merged in pull request #217.
This commit is contained in:
1 parent
cdabf019bb
commit
7d1f4c6b13
3 files changed
+108
-12
No files matched your search
@@ -868,6 +868,88 @@ test("once every WAN target's check has failed, the summary's Reachable slot rea
|
||||
assert.equal(elements["#summary-reachable"].className, "text-red-400");
|
||||
});
|
||||
|
||||
// The network has just come back: every WAN target's last check failed, so
|
||||
// the health box reads OFFLINE. In this round every WAN target but one
|
||||
// answers after 10ms, and the one never answers. Each element of the summary
|
||||
// and the health box is a plain object, as in the tests above; the debug
|
||||
// log's panel is not there.
|
||||
test("at a 30000ms interval, the summary and the health box take in each WAN target's answer while another WAN target's check is still waiting", async (t) => {
|
||||
CONFIG.updateInterval = 30000;
|
||||
t.mock.method(globalThis.document, "getElementById", (id) =>
|
||||
id.startsWith("summary-") || id.startsWith("health-")
|
||||
? (elements[`#${id}`] ??= {})
|
||||
: null,
|
||||
);
|
||||
const state = new AppState([]);
|
||||
for (const host of state.wan) {
|
||||
host.pushSample(Date.now(), { latency: null, error: "timeout" });
|
||||
}
|
||||
const silent = state.wan[0];
|
||||
mockTargets(t, (url) => (url === silent.url ? Infinity : 10));
|
||||
// The third tick, as in the tests above.
|
||||
state.tickCount = 2;
|
||||
|
||||
const round = tick(state, new AbortController().signal);
|
||||
t.mock.timers.tick(10);
|
||||
assert.equal(await settled(round), "still waiting");
|
||||
assert.equal(elements["#health-text"].textContent, "HEALTHY");
|
||||
assert.equal(
|
||||
elements["#summary-reachable"].textContent,
|
||||
`${state.wan.length - 1}/${state.wan.length}`,
|
||||
);
|
||||
assert.equal(elements["#summary-max"].textContent, "10");
|
||||
// Checks counts finished rounds only.
|
||||
assert.equal(elements["#summary-checks"].textContent, 2);
|
||||
|
||||
t.mock.timers.tick(CONFIG.requestTimeout - 10);
|
||||
assert.notEqual(await settled(round), "still waiting");
|
||||
assert.equal(elements["#summary-checks"].textContent, 3);
|
||||
});
|
||||
|
||||
// The user pauses during the first recorded round after the page loads.
|
||||
// Every WAN target's check ends during the pause. Silent never answers, and
|
||||
// the user resumes before its check times out. Every element the page looks
|
||||
// up by id is a plain object, except the debug log's panel, which is not
|
||||
// there.
|
||||
test(`at a 30000ms interval, after the user pauses and resumes during a round that records no WAN target's check, the debug log has no "Health:" line`, async (t) => {
|
||||
CONFIG.updateInterval = 30000;
|
||||
t.mock.method(globalThis.document, "getElementById", (id) =>
|
||||
id === "debug-panel" ? null : (elements[`#${id}`] ??= {}),
|
||||
);
|
||||
t.mock.method(log, "notice");
|
||||
t.mock.method(log, "warning");
|
||||
const state = new AppState([
|
||||
{ name: "Silent", url: "https://silent.test" },
|
||||
]);
|
||||
const silent = state.local[0];
|
||||
mockTargets(t, (url) => (url === silent.url ? Infinity : 10));
|
||||
// The second tick: the first that is recorded.
|
||||
state.tickCount = 1;
|
||||
|
||||
const round = tick(state, new AbortController().signal);
|
||||
// The user pauses, which greys out the summary and the health box, as
|
||||
// togglePause does.
|
||||
state.paused = true;
|
||||
greyOutUI(state);
|
||||
t.mock.timers.tick(10);
|
||||
assert.equal(await settled(round), "still waiting");
|
||||
// The user resumes, which leaves the page as it is.
|
||||
state.paused = false;
|
||||
|
||||
t.mock.timers.tick(CONFIG.requestTimeout - 10);
|
||||
assert.notEqual(await settled(round), "still waiting");
|
||||
assert.equal(state.tickCount, 2);
|
||||
const lines = [...log.notice.mock.calls, ...log.warning.mock.calls].map(
|
||||
(call) => call.arguments[0],
|
||||
);
|
||||
assert.deepEqual(
|
||||
lines.filter((line) => line.startsWith("Health:")),
|
||||
[],
|
||||
);
|
||||
assert.equal(elements["#health-text"].textContent, "---");
|
||||
assert.equal(elements["#summary-reachable"].textContent, "--/--");
|
||||
});
|
||||
|
||||
// In the next two tests each of the header's clocks is a plain object, made
|
||||
// the first time updateClocks looks it up and kept in elements under "#" and
|
||||
// its id.
|
||||
|
||||
Reference in new issue
Block a user