Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0d1315f7b |
No files matched your search
+1
-4
@@ -98,10 +98,7 @@ COPY --from=frontend-test /app/yarn.lock /dev/null
|
|||||||
FROM frontend-test AS frontend-build
|
FROM frontend-test AS frontend-build
|
||||||
COPY --from=lint /src/go.sum /dev/null
|
COPY --from=lint /src/go.sum /dev/null
|
||||||
COPY --from=test /src/go.sum /dev/null
|
COPY --from=test /src/go.sum /dev/null
|
||||||
# vite.config.js reads the commit for the page's footer with git. git is
|
# vite.config.js reads the commit for the page's footer with git.
|
||||||
# installed again on every image build, although it comes above
|
|
||||||
# ARG CACHEBUST, because this stage starts from frontend-test, whose
|
|
||||||
# steps run again on every build.
|
|
||||||
RUN apk add --no-cache git
|
RUN apk add --no-cache git
|
||||||
ARG CACHEBUST
|
ARG CACHEBUST
|
||||||
RUN yarn build
|
RUN yarn build
|
||||||
|
|||||||
@@ -101,13 +101,10 @@ either one is broken. We provide:
|
|||||||
new `CACHEBUST` value, so every step in `Dockerfile` that lints, tests or
|
new `CACHEBUST` value, so every step in `Dockerfile` that lints, tests or
|
||||||
compiles runs again even when nothing has changed. Docker keeps the system
|
compiles runs again even when nothing has changed. Docker keeps the system
|
||||||
packages and the Go modules from earlier builds until the base image, the step
|
packages and the Go modules from earlier builds until the base image, the step
|
||||||
that installs them, or `go.mod` and `go.sum` change. The `frontend-build` stage
|
that installs them, or `go.mod` and `go.sum` change. Go's build cache and
|
||||||
is the exception: it installs git again on every image build, because it starts
|
golangci-lint's are kept as well, and each reuses a result only when everything
|
||||||
from the `frontend-test` stage, whose steps run again on every build. Go's build
|
it was made from is unchanged. Both `go test` runs carry `-count=1`, so no test
|
||||||
cache and golangci-lint's are kept as well, and each reuses a result only when
|
result is reused. The yarn packages are installed again on every build.
|
||||||
everything it was made from is unchanged. Both `go test` runs carry `-count=1`,
|
|
||||||
so no test result is reused. The yarn packages are installed again on every
|
|
||||||
build.
|
|
||||||
|
|
||||||
## Responsive layout
|
## Responsive layout
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,6 @@ Run `make frontend-viewport-test` in CI as its own step; it is not part of
|
|||||||
cache and golangci-lint's are cache mounts, and both `go test` runs carry
|
cache and golangci-lint's are cache mounts, and both `go test` runs carry
|
||||||
`-count=1`. The test phase's Go caches used to be in memory, empty on every
|
`-count=1`. The test phase's Go caches used to be in memory, empty on every
|
||||||
build
|
build
|
||||||
- 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
|
- 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
|
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
|
error naming `DATA_DIR` and its value, as the other settings' errors do
|
||||||
|
|||||||
+9
-22
@@ -83,11 +83,6 @@ function statusText(state, host) {
|
|||||||
return elements[`.status-text[data-host="${index}"]`]?.innerHTML;
|
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
|
// 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
|
// time, and replaces fetch with targets that each answer after
|
||||||
// answerAfter(url) milliseconds of that clock, or never when that is
|
// answerAfter(url) milliseconds of that clock, or never when that is
|
||||||
@@ -207,10 +202,9 @@ 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
|
// In the next three tests, the answering target's check is still waiting
|
||||||
// when something happens after which its result must not be recorded or
|
// when something happens after which its result must not show.
|
||||||
// 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 is not recorded and does not show in its row", async (t) => {
|
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;
|
CONFIG.updateInterval = 30000;
|
||||||
const state = new AppState([
|
const state = new AppState([
|
||||||
{ name: "Answering", url: "https://answering.test" },
|
{ name: "Answering", url: "https://answering.test" },
|
||||||
@@ -226,13 +220,9 @@ test("at a 30000ms interval, a check still waiting when its round is given up is
|
|||||||
roundChecks.abort();
|
roundChecks.abort();
|
||||||
assert.notEqual(await settled(round), "still waiting");
|
assert.notEqual(await settled(round), "still waiting");
|
||||||
assert.equal(latencyFigure(state, answering), undefined);
|
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 is not recorded and does not show in its row", async (t) => {
|
test("at a 30000ms interval, a check still waiting when the user pauses does not show in its row", async (t) => {
|
||||||
CONFIG.updateInterval = 30000;
|
CONFIG.updateInterval = 30000;
|
||||||
const state = new AppState([
|
const state = new AppState([
|
||||||
{ name: "Answering", url: "https://answering.test" },
|
{ name: "Answering", url: "https://answering.test" },
|
||||||
@@ -247,13 +237,9 @@ test("at a 30000ms interval, a check still waiting when the user pauses is not r
|
|||||||
t.mock.timers.tick(500);
|
t.mock.timers.tick(500);
|
||||||
assert.equal(await settled(round), "still waiting");
|
assert.equal(await settled(round), "still waiting");
|
||||||
assert.equal(latencyFigure(state, answering), undefined);
|
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 is not recorded and does not show in its row", async (t) => {
|
test("at a 30000ms interval, a check in the first round does not show in its row", async (t) => {
|
||||||
CONFIG.updateInterval = 30000;
|
CONFIG.updateInterval = 30000;
|
||||||
const state = new AppState([
|
const state = new AppState([
|
||||||
{ name: "Answering", url: "https://answering.test" },
|
{ name: "Answering", url: "https://answering.test" },
|
||||||
@@ -265,10 +251,6 @@ test("at a 30000ms interval, a check in the first round is not recorded and does
|
|||||||
t.mock.timers.tick(1000);
|
t.mock.timers.tick(1000);
|
||||||
assert.equal(await settled(round), "still waiting");
|
assert.equal(await settled(round), "still waiting");
|
||||||
assert.equal(latencyFigure(state, answering), undefined);
|
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) => {
|
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) => {
|
||||||
@@ -318,6 +300,11 @@ function stateWithOneTarget() {
|
|||||||
return { state, target: state.local[0] };
|
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) => {
|
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();
|
const { state, target } = stateWithOneTarget();
|
||||||
mockTargets(t, () => 23, target.url);
|
mockTargets(t, () => 23, target.url);
|
||||||
|
|||||||
Reference in new issue
Block a user