An object whose receipts-track object reached the relay just before the receipts subscription did never gets it live; after a second its group of the receipts track is fetched (moq-streaming-format §4.1). e2e/package-lock.json pins the automation package by integrity (playwright 1.60.0 and playwright-core, Apache-2.0; fsevents, MIT, optional, its install script never run: npm ci --ignore-scripts). Co-Authored-By: Claude Opus 5.5 <[email protected]>
63 lines
3.3 KiB
HTML
63 lines
3.3 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Composition conformance</title>
|
|
<link rel="icon" href="data:,">
|
|
<style>
|
|
:root { --bg: #f6f7f9; --fg: #15171a; --muted: #5d6470; }
|
|
@media (prefers-color-scheme: dark) { :root { --bg: #111317; --fg: #e8eaee; --muted: #9aa2ae; } }
|
|
body { margin: 0; padding: 16px; background: var(--bg); color: var(--fg); font: 14px/1.45 system-ui, sans-serif; }
|
|
pre { white-space: pre-wrap; overflow-wrap: anywhere; font: 12px ui-monospace, monospace; color: var(--muted); }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1 style="font-size:16px">live-conformance/compose in the browser</h1>
|
|
<pre id="out">running</pre>
|
|
<script type="module">
|
|
// Every case of live-conformance/compose given its outcome by wai-live-web's wasm build:
|
|
// the layout and mix cases through the functions a page lays out and mixes with, the
|
|
// compositions through the room replay a page composes with, and wai-rs's own corpus
|
|
// check run in the page. The corpus states the outcome the native build reaches, so a
|
|
// case that holds here gives the native build's rectangles and samples.
|
|
import init, * as wai from "../pkg/wai_live_web.js";
|
|
const out = document.getElementById("out");
|
|
const differ = (c, got) => Object.keys(got).filter((k) => JSON.stringify(c[k]) !== JSON.stringify(got[k]));
|
|
async function run() {
|
|
await init();
|
|
const text = await (await fetch(new URLSearchParams(location.search).get("corpus") || "../vectors/compose.json")).text();
|
|
const doc = JSON.parse(text);
|
|
const r = { layouts: 0, mixes: 0, compositions: 0, descriptors: 0, failures: [] };
|
|
for (const c of doc.layouts) {
|
|
r.layouts++;
|
|
const got = JSON.parse(wai.layoutCase(JSON.stringify(c.params), JSON.stringify(c.entrants)));
|
|
for (const k of differ(c, got)) r.failures.push(`layout ${c.name}: ${k}`);
|
|
}
|
|
for (const c of doc.mixes) {
|
|
r.mixes++;
|
|
const got = JSON.parse(wai.mixCase(c.channels, c.frames, JSON.stringify(c.inputs)));
|
|
for (const k of differ(c, got)) r.failures.push(`mix ${c.name}: ${k}`);
|
|
}
|
|
const unhex = (h) => new Uint8Array((h.match(/../g) || []).map((x) => parseInt(x, 16)));
|
|
for (const c of doc.compositions) {
|
|
r.compositions++;
|
|
const got = JSON.parse(wai.compositionCase(JSON.stringify(doc.rooms[c.room]), unhex(c.descriptor), JSON.stringify(c.instants)));
|
|
for (const k of differ(c, got)) r.failures.push(`composition ${c.name}: ${k}`);
|
|
}
|
|
for (const c of doc.descriptors) {
|
|
r.descriptors++;
|
|
const got = JSON.parse(wai.composeDescriptor(unhex(c.bytes)));
|
|
const want = c.outcome === "read" ? { outcome: "read", digest: c.digest } : { outcome: "refuse", reason: c.reason };
|
|
const g = c.outcome === "read" ? { outcome: got.outcome, digest: got.digest } : { outcome: got.outcome, reason: got.reason };
|
|
if (JSON.stringify(g) !== JSON.stringify(want)) r.failures.push(`descriptor ${c.name}`);
|
|
}
|
|
r.corpus_verify = wai.corpusVerify(text);
|
|
r.tiles = doc.layouts.reduce((n, c) => n + (c.tiles ? c.tiles.length : 0), 0) + doc.compositions.reduce((n, c) => n + (c.frames || []).reduce((k, f) => k + f.tiles.length, 0), 0);
|
|
window.composeTest = r;
|
|
out.textContent = JSON.stringify(r, null, 2);
|
|
}
|
|
run().catch((e) => { window.composeTest = { error: String(e.stack || e) }; out.textContent = String(e.stack || e); });
|
|
</script>
|
|
</body>
|
|
</html>
|