[test](trx-frontend-http): watch the history progress from inside the page
CI / lint (push) Successful in 2m16s
CI / test (push) Successful in 8m18s
CI / frontend (push) Successful in 3m38s
CI / reuse (push) Successful in 2s

The replay-progress check polled the overlay from the test every 100ms.
A replay that starts and finishes between two polls is never sampled, and
the test then reports that no progress was shown at all -- the source of
the intermittent "no progress was shown while the history loaded" failure.

Record the samples from a MutationObserver installed before the page's own
scripts run, so a fast replay is observed rather than missed.

Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
sjg
2026-08-05 07:10:57 +02:00
parent 39f551c914
commit d31b6f545f
@@ -11,7 +11,7 @@ import assert from "node:assert/strict";
import { chromium } from "playwright-core";
import { startBrowser, startWebFixture } from "./web-fixture.mjs";
/* global document, getComputedStyle, window, location */
/* global document, getComputedStyle, window, location, requestAnimationFrame, MutationObserver */
const VESSEL = {
type: "ais", mmsi: 244660000, lat: 52.37, lon: 4.89, vessel_name: "NEDERLAND",
@@ -121,6 +121,27 @@ const historyFixture = await startWebFixture({
});
const replay = await startBrowser(chromium);
// Installed before the page's own scripts, so nothing can be missed: every
// time the progress element becomes visible, its geometry is recorded.
await replay.page.addInitScript(() => {
window.__historyProgressSamples = [];
const watch = () => {
const element = document.getElementById("decode-history-overlay");
if (!element) { requestAnimationFrame(watch); return; }
const sample = () => {
if (element.classList.contains("is-hidden")) return;
const rect = element.getBoundingClientRect();
window.__historyProgressSamples.push({
width: Math.round(rect.width),
coversCentre: document.elementFromPoint(700, 450)?.id === "decode-history-overlay",
});
};
new MutationObserver(sample).observe(element, { attributes: true, attributeFilter: ["class"] });
sample();
};
watch();
});
try {
await replay.page.setViewportSize({ width: 1400, height: 900 });
await replay.page.goto(`${historyFixture.origin}/digital-modes`, { waitUntil: "domcontentloaded" });
@@ -128,20 +149,11 @@ try {
// While it loads, the operator can still see the radio. This used to be a
// full-screen scrim over everything for as long as the replay ran.
const samples = [];
for (let attempt = 0; attempt < 30; attempt++) {
samples.push(await replay.page.evaluate(() => {
const element = document.getElementById("decode-history-overlay");
if (!element || element.classList.contains("is-hidden")) return null;
const rect = element.getBoundingClientRect();
return {
width: Math.round(rect.width),
coversCentre: document.elementFromPoint(700, 450)?.id === "decode-history-overlay",
};
}));
await replay.page.waitForTimeout(100);
}
const shown = samples.filter(Boolean);
//
// Watched from inside the page rather than polled from here: a fast replay
// can start and finish between two polls, and then the test reports that no
// progress was ever shown when what happened is that it blinked.
const shown = await replay.page.evaluate(() => window.__historyProgressSamples ?? []);
assert.ok(shown.length > 0, "no progress was shown while the history loaded");
for (const sample of shown) {
assert.ok(sample.width < 700, `the progress covers ${sample.width}px of a 1400px page`);