Discarded-check unit tests check nothing was recorded (closes #151)
check / check (push) Waiting to run

The three unit tests of a check whose result is discarded (its round
given up, the user paused, or the first round) checked only that the
row showed nothing. Each now also checks that the host's history is
still empty, its status still pending, and nothing was written to the
console, so a change that recorded the result and skipped only the row
fails them. The console helper moves above its first use.

Model: opus-5-5
This commit was merged in pull request #173.
This commit is contained in:
2026-10-19 03:44:13 +02:00
parent be6dc93eaa
commit 648c225919
2 changed files with 29 additions and 9 deletions
+7
View File
@@ -21,6 +21,13 @@ Run `make frontend-viewport-test` in CI as its own step; it is not part of
# Completed Steps
- 2026-10-19: the three unit tests of a check whose result is discarded (its
round given up, the user paused, or the first round) also check that the
host's history is still empty, its status still `pending`, and nothing was
written to the console
([#151](https://git.eeqj.de/sneak/netwatch/issues/151)). They checked only the
row, so a change that recorded the result and skipped only the row would have
kept them passing
- 2026-10-18: when the backend runs on its own, a `DATA_DIR` that cannot be
created or read, or where no file can be created, stops the start with an
error naming `DATA_DIR` and its value, as the other settings' errors do
+22 -9
View File
@@ -83,6 +83,11 @@ function statusText(state, host) {
return elements[`.status-text[data-host="${index}"]`]?.innerHTML;
}
// What this test wrote to the browser console with console[method].
function consoleLines(method) {
return console[method].mock.calls.map((call) => call.arguments[0]);
}
// Mocks the clock for test t, so that a check lasting seconds takes no real
// time, and replaces fetch with targets that each answer after
// answerAfter(url) milliseconds of that clock, or never when that is
@@ -202,9 +207,10 @@ test("at a 30000ms interval, a target answering after 1000ms shows in its row wh
});
// In the next three tests, the answering target's check is still waiting
// when something happens after which its result must not show.
// when something happens after which its result must not be recorded or
// show in its row, and the check must write nothing to the console.
test("at a 30000ms interval, a check still waiting when its round is given up does not show in its row", async (t) => {
test("at a 30000ms interval, a check still waiting when its round is given up is not recorded and does not show in its row", async (t) => {
CONFIG.updateInterval = 30000;
const state = new AppState([
{ name: "Answering", url: "https://answering.test" },
@@ -220,9 +226,13 @@ test("at a 30000ms interval, a check still waiting when its round is given up do
roundChecks.abort();
assert.notEqual(await settled(round), "still waiting");
assert.equal(latencyFigure(state, answering), undefined);
assert.deepEqual(answering.history, []);
assert.equal(answering.status, "pending");
assert.deepEqual(consoleLines("error"), []);
assert.deepEqual(consoleLines("info"), []);
});
test("at a 30000ms interval, a check still waiting when the user pauses does not show in its row", async (t) => {
test("at a 30000ms interval, a check still waiting when the user pauses is not recorded and does not show in its row", async (t) => {
CONFIG.updateInterval = 30000;
const state = new AppState([
{ name: "Answering", url: "https://answering.test" },
@@ -237,9 +247,13 @@ test("at a 30000ms interval, a check still waiting when the user pauses does not
t.mock.timers.tick(500);
assert.equal(await settled(round), "still waiting");
assert.equal(latencyFigure(state, answering), undefined);
assert.deepEqual(answering.history, []);
assert.equal(answering.status, "pending");
assert.deepEqual(consoleLines("error"), []);
assert.deepEqual(consoleLines("info"), []);
});
test("at a 30000ms interval, a check in the first round does not show in its row", async (t) => {
test("at a 30000ms interval, a check in the first round is not recorded and does not show in its row", async (t) => {
CONFIG.updateInterval = 30000;
const state = new AppState([
{ name: "Answering", url: "https://answering.test" },
@@ -251,6 +265,10 @@ test("at a 30000ms interval, a check in the first round does not show in its row
t.mock.timers.tick(1000);
assert.equal(await settled(round), "still waiting");
assert.equal(latencyFigure(state, answering), undefined);
assert.deepEqual(answering.history, []);
assert.equal(answering.status, "pending");
assert.deepEqual(consoleLines("error"), []);
assert.deepEqual(consoleLines("info"), []);
});
test("at a 30000ms interval, after the user pauses and resumes during a round, no row reads paused once its last check ends", async (t) => {
@@ -300,11 +318,6 @@ function stateWithOneTarget() {
return { state, target: state.local[0] };
}
// What this test wrote to the browser console with console[method].
function consoleLines(method) {
return console[method].mock.calls.map((call) => call.arguments[0]);
}
test("a check that fails with a network error writes one console line with the target, the time, the error and how long the request took", async (t) => {
const { state, target } = stateWithOneTarget();
mockTargets(t, () => 23, target.url);