Files
gods-eye-view/scripts/qa/ledger.mjs
T
German Khokhlov 60f9de8511 Wait for the application, not the clock, in the strict QA set
The probe exposes settled() and the first-frame outcome; scripts/qa/ready.mjs
waits for drawn frames with the camera at rest and for a pick at the click
position, with a deadline and its reason in the error. The strict scenarios
use these instead of fixed pauses and loading-screen polling, and the
hidden-switch scenario checks how the loading screen was lifted instead of
how long it took.

Each switch scenario now records a draw ledger per engine and runs a
contract monitor; both write to the scenario's evidence file only, with an
empty allowlist until browser runs show what differs on purpose.
2026-11-10 15:46:26 +04:00

64 lines
2.0 KiB
JavaScript

/** The five public drawing registries, with no SDK objects or volatile fields. */
export function drawLedger(page) {
return page.evaluate(() => {
const { engine } = window.__godsEyeView;
return ['movers', 'lines', 'ground', 'imagery', 'meshes']
.flatMap((family) =>
engine[family].list().map((row) => ({
id: String(row.id),
family,
...(row.kind === undefined ? {} : { kind: row.kind }),
...(row.count === undefined ? {} : { count: row.count }),
shown: row.shown ?? true,
})),
)
.sort(
(a, b) => a.family.localeCompare(b.family) || a.id.localeCompare(b.id),
);
});
}
/** Allowlisted absences keep their reasons; visibility differences are never hidden. */
export function compareLedgers(before, after, allow = []) {
const key = (row) => `${row.family}:${row.id}`;
const left = new Map(before.map((row) => [key(row), row]));
const right = new Map(after.map((row) => [key(row), row]));
const allowed = [];
const only = (a, b, side) =>
[...a].flatMap(([key, row]) => {
if (b.has(key)) return [];
const exception = allow.find(
(entry) =>
entry.id === row.id && (!entry.family || entry.family === row.family),
);
if (exception) {
allowed.push({
id: row.id,
family: row.family,
side,
reason: exception.reason,
});
return [];
}
return [{ id: row.id, family: row.family }];
});
return {
onlyBefore: only(left, right, 'before'),
onlyAfter: only(right, left, 'after'),
shown: [...left].flatMap(([key, row]) => {
const next = right.get(key);
return next && (row.shown ?? true) !== (next.shown ?? true)
? [
{
id: row.id,
family: row.family,
before: row.shown ?? true,
after: next.shown ?? true,
},
]
: [];
}),
allowed,
};
}