Compare commits
1
Commits
next
...
60fc08706f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60fc08706f |
@@ -23,6 +23,11 @@ latest run passes.
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- 2026-10-03: the tap-target check in `make frontend-viewport-test` expects one
|
||||
visible pin button per WAN host row (issue #46), where it expected at least 10
|
||||
of the 26, so pin buttons missing from only some rows now fail it. The host
|
||||
row count the harness gathers, which the `app-rendered` check also reads, now
|
||||
counts only the WAN host rows: the local host rows have no pin button
|
||||
- 2026-10-03: `backend/script/lint` says what went wrong with its
|
||||
`.golangci.yml` check (issue #34). On a hash mismatch it says to compare the
|
||||
file with the org standard: if they differ, restore the org standard; if they
|
||||
@@ -211,9 +216,11 @@ latest run passes.
|
||||
- 2026-08-09: automated responsive-layout harness
|
||||
(`make frontend-viewport-test`): digest-pinned headless Chrome driven over CDP
|
||||
against the built `dist/`, viewport widths derived from the breakpoints in
|
||||
`src/styles.css` ([#13](https://git.eeqj.de/sneak/netwatch/issues/13)). Every
|
||||
check carries a presence guard so none of them can pass against a page it is
|
||||
not actually measuring. Found two real layout defects, filed as
|
||||
`src/styles.css` ([#13](https://git.eeqj.de/sneak/netwatch/issues/13)). The
|
||||
tap-target and host-row checks each fail when they measured nothing; the
|
||||
overflow, viewport-edge and clipped-text checks have no such guard of their
|
||||
own and rely on the `app-rendered` check, which fails the run when the app did
|
||||
not render. Found two real layout defects, filed as
|
||||
[#42](https://git.eeqj.de/sneak/netwatch/issues/42) and
|
||||
[#43](https://git.eeqj.de/sneak/netwatch/issues/43)
|
||||
- 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints, Makefile
|
||||
|
||||
@@ -49,10 +49,11 @@ sizes straddling the breakpoint for the rotation case.
|
||||
excluded: it is a design choice, not breakage.
|
||||
- **tap-targets-44px** — every interactive control is at least 44x44 CSS px on
|
||||
touch viewports, _and_ each selector in the control list matched at least the
|
||||
number of visible elements it declares. The second half is what stops the
|
||||
check passing vacuously: with size alone, a renamed class would take its
|
||||
controls out of the measured set and the check would report "all 0 controls
|
||||
are at least 44x44" and pass. See below.
|
||||
number of visible elements it declares: one of each single control, and one
|
||||
pin button per WAN host row. The second half is what stops the check passing
|
||||
vacuously: with size alone, a renamed class would take its controls out of the
|
||||
measured set and the check would report "all 0 controls are at least 44x44"
|
||||
and pass. See below.
|
||||
- **host-rows-stacked / host-rows-side-by-side** — the rows genuinely reflow.
|
||||
Computed `flex-direction` _and_ the actual geometry are checked, and in the
|
||||
narrow layout the info block and the sparkline must each occupy essentially
|
||||
|
||||
+13
-12
@@ -15,7 +15,8 @@ export const MIN_TAP_TARGET_PX = 44;
|
||||
|
||||
// The controls named in the definition of done, plus the pause button.
|
||||
// Each carries the smallest number of *visible* instances the page has to
|
||||
// contain for the tap-target oracle to be measuring anything at all.
|
||||
// contain, worked out from the facts gathered from that page, for the
|
||||
// tap-target oracle to be measuring every control it should.
|
||||
//
|
||||
// Without those floors the check is inert: `undersized` is empty both when
|
||||
// every control is large enough and when the selectors have gone stale and
|
||||
@@ -24,13 +25,12 @@ export const MIN_TAP_TARGET_PX = 44;
|
||||
// for all three singleton controls vanishing at once — so the floor is per
|
||||
// selector, and one stale selector out of four fails the check.
|
||||
export const INTERACTIVE_CONTROLS = [
|
||||
{ selector: "#pause-btn", minCount: 1 },
|
||||
{ selector: "#interval-select", minCount: 1 },
|
||||
// One per pinnable host row. `app-rendered` already requires at least
|
||||
// 10 host rows, so a count below that means the pin buttons stopped
|
||||
// being rendered per row rather than that there were fewer hosts.
|
||||
{ selector: ".pin-btn", minCount: 10 },
|
||||
{ selector: "#debug-toggle", minCount: 1 },
|
||||
{ selector: "#pause-btn", minCount: () => 1 },
|
||||
{ selector: "#interval-select", minCount: () => 1 },
|
||||
// One per WAN host row, so pin buttons missing from even one row fail
|
||||
// the check rather than only a drop below some fixed number.
|
||||
{ selector: ".pin-btn", minCount: (facts) => facts.rowCount },
|
||||
{ selector: "#debug-toggle", minCount: () => 1 },
|
||||
];
|
||||
|
||||
export const INTERACTIVE_SELECTORS = INTERACTIVE_CONTROLS.map(
|
||||
@@ -106,7 +106,7 @@ export function evaluateChecks(facts, viewport, probes) {
|
||||
check(
|
||||
"app-rendered",
|
||||
facts.rowCount >= 10 && facts.numericLatencies >= 5,
|
||||
`${facts.rowCount} host rows, ${facts.numericLatencies} showing a numeric latency`,
|
||||
`${facts.rowCount} WAN host rows, ${facts.numericLatencies} showing a numeric latency`,
|
||||
);
|
||||
|
||||
const viewportWidth = Math.min(facts.innerWidth, facts.documentClientWidth);
|
||||
@@ -162,7 +162,8 @@ export function evaluateChecks(facts, viewport, probes) {
|
||||
seen.set(target.selector, (seen.get(target.selector) ?? 0) + 1);
|
||||
}
|
||||
const missing = INTERACTIVE_CONTROLS.filter(
|
||||
(control) => (seen.get(control.selector) ?? 0) < control.minCount,
|
||||
(control) =>
|
||||
(seen.get(control.selector) ?? 0) < control.minCount(facts),
|
||||
);
|
||||
|
||||
const undersized = facts.tapTargets.filter(
|
||||
@@ -184,11 +185,11 @@ export function evaluateChecks(facts, viewport, probes) {
|
||||
const detail = [];
|
||||
if (missing.length > 0) {
|
||||
detail.push(
|
||||
"oracle is not measuring the page: " +
|
||||
"oracle is not measuring every control: " +
|
||||
summarise(
|
||||
missing,
|
||||
(c) =>
|
||||
`${c.selector} matched ${seen.get(c.selector) ?? 0} visible element(s), expected at least ${c.minCount}`,
|
||||
`${c.selector} matched ${seen.get(c.selector) ?? 0} visible element(s), expected at least ${c.minCount(facts)}`,
|
||||
4,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -173,7 +173,9 @@ export function collectLayoutFacts(options) {
|
||||
clipped,
|
||||
tapTargets,
|
||||
rows,
|
||||
rowCount: document.querySelectorAll(".host-row").length,
|
||||
// WAN host rows only: each has a pin button, and the tap-target
|
||||
// check expects one per row. The local host rows have none.
|
||||
rowCount: document.querySelectorAll("#wan-hosts .host-row").length,
|
||||
numericLatencies: Array.from(
|
||||
document.querySelectorAll(".latency-value"),
|
||||
).filter((el) => /\d/.test(el.textContent)).length,
|
||||
|
||||
Reference in New Issue
Block a user