Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6126a7f85c |
@@ -105,9 +105,9 @@ code lives in `src/main.js` with a class-based architecture:
|
||||
- **UI functions**: `buildUI()` constructs the DOM, `updateHostRow()` /
|
||||
`updateSummary()` / `updateHealthBox()` handle incremental updates
|
||||
- **`tick()`**: Main loop — measures all hosts in parallel, pushing each host's
|
||||
sample and redrawing its row as soon as its check ends, then sorts and redraws
|
||||
the summary and health box once the last check ends. When paused, pushes blank
|
||||
markers (no probes, no false outage)
|
||||
sample and redrawing its row as soon as its check ends, then redraws every
|
||||
row, sorts, and redraws the summary and health box once the last check ends.
|
||||
When paused, pushes blank markers (no probes, no false outage)
|
||||
- **`Reporter`**: Posts collected samples to the backend
|
||||
|
||||
### Reporting
|
||||
|
||||
@@ -25,10 +25,11 @@ latest run passes.
|
||||
|
||||
- 2026-10-03: each target's row shows its result as soon as its check ends
|
||||
(issue #91), where every row waited for the round's slowest check, up to 24
|
||||
seconds at a 30-second interval. Sorting, the summary, the health box and
|
||||
offline detection still run once, when the round's last check ends. A check
|
||||
that ends after the user pauses or after its round is given up shows nothing,
|
||||
and the first round is still discarded as a whole
|
||||
seconds at a 30-second interval. Every row is still redrawn, and sorting, the
|
||||
summary, the health box and offline detection still run, once, when the
|
||||
round's last check ends, so no row reads "paused" after a pause and resume
|
||||
during the round. A check that ends after the user pauses or after its round
|
||||
is given up shows nothing, and the first round is still discarded as a whole
|
||||
- 2026-10-03: the Go tests run with the race detector and coverage (issue #88):
|
||||
`backend/script/test` runs `go test -timeout 30s -race -cover ./...` and, if
|
||||
that fails, runs it again with `-v` and fails. Go's `-timeout` bounds the
|
||||
|
||||
@@ -1156,6 +1156,10 @@ export async function tick(state, signal, onOffline) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Redraw every row: if the user paused and resumed during this round,
|
||||
// rows whose check ended before the resume still read "paused"
|
||||
state.allHosts.forEach((host, i) => updateHostRow(host, i));
|
||||
|
||||
// Sort after the first real check, then every 10 ticks thereafter
|
||||
if (state.tickCount === 2 || state.tickCount % 10 === 1) {
|
||||
sortAndRebuildWAN(state);
|
||||
|
||||
+61
-5
@@ -1,16 +1,20 @@
|
||||
// Unit tests for src/main.js, run by script/frontend-test with Node's
|
||||
// built-in test runner. Importing the module does not start the page.
|
||||
|
||||
import { test } from "node:test";
|
||||
import { beforeEach, test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { AppState, CONFIG, measureLatency, tick } from "../../src/main.js";
|
||||
|
||||
// There is no page here, so the tests stand in for it. The debug log looks
|
||||
// for its panel by id and finds none. Each element of a host's row that
|
||||
// tick draws into is a plain object, made the first time it is looked up
|
||||
// and kept in elements under its selector. Drawing a sparkline does
|
||||
// nothing; it looks for the pixel ratio on window and finds none.
|
||||
const elements = {};
|
||||
// tick draws into is a plain object, made the first time a test looks it
|
||||
// up and kept in elements under its selector until the next test starts.
|
||||
// Drawing a sparkline does nothing; it looks for the pixel ratio on window
|
||||
// and finds none.
|
||||
let elements;
|
||||
beforeEach(() => {
|
||||
elements = {};
|
||||
});
|
||||
const doNothing = () => {};
|
||||
const canvasContext = {
|
||||
clearRect: doNothing,
|
||||
@@ -120,3 +124,55 @@ test("at a 30000ms interval, a target answering after 1000ms shows in its row wh
|
||||
assert.notEqual(await settled(round), "still waiting");
|
||||
assert.equal(state.tickCount, 3);
|
||||
});
|
||||
|
||||
// In the next three tests, the answering target's check is still waiting
|
||||
// when something happens after which its result must not show.
|
||||
|
||||
test("at a 30000ms interval, a check still waiting when its round is given up does not show in its row", async (t) => {
|
||||
CONFIG.updateInterval = 30000;
|
||||
const state = new AppState([
|
||||
{ name: "Answering", url: "https://answering.test" },
|
||||
]);
|
||||
const answering = state.local[0];
|
||||
mockTargets(t, (url) => (url.startsWith(answering.url) ? 1000 : Infinity));
|
||||
state.tickCount = 2;
|
||||
|
||||
const roundChecks = new AbortController();
|
||||
const round = tick(state, roundChecks.signal);
|
||||
t.mock.timers.tick(500);
|
||||
// As a round started early does to the last round's checks.
|
||||
roundChecks.abort();
|
||||
assert.notEqual(await settled(round), "still waiting");
|
||||
assert.equal(latencyFigure(state, answering), undefined);
|
||||
});
|
||||
|
||||
test("at a 30000ms interval, a check still waiting when the user pauses does not show in its row", async (t) => {
|
||||
CONFIG.updateInterval = 30000;
|
||||
const state = new AppState([
|
||||
{ name: "Answering", url: "https://answering.test" },
|
||||
]);
|
||||
const answering = state.local[0];
|
||||
mockTargets(t, (url) => (url.startsWith(answering.url) ? 1000 : Infinity));
|
||||
state.tickCount = 2;
|
||||
|
||||
const round = tick(state, new AbortController().signal);
|
||||
t.mock.timers.tick(500);
|
||||
state.paused = true;
|
||||
t.mock.timers.tick(500);
|
||||
assert.equal(await settled(round), "still waiting");
|
||||
assert.equal(latencyFigure(state, answering), undefined);
|
||||
});
|
||||
|
||||
test("at a 30000ms interval, a check in the first round does not show in its row", async (t) => {
|
||||
CONFIG.updateInterval = 30000;
|
||||
const state = new AppState([
|
||||
{ name: "Answering", url: "https://answering.test" },
|
||||
]);
|
||||
const answering = state.local[0];
|
||||
mockTargets(t, (url) => (url.startsWith(answering.url) ? 1000 : Infinity));
|
||||
|
||||
const round = tick(state, new AbortController().signal);
|
||||
t.mock.timers.tick(1000);
|
||||
assert.equal(await settled(round), "still waiting");
|
||||
assert.equal(latencyFigure(state, answering), undefined);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user