test(04-04): the BA7/BA8 drift gates + the search-tree GEO3 pin + the destination-preload capture leg
- BA7: the shipped JS must carry EVERY committed gazetteer id (the web half of bot/web id-set parity, T-04-39) — RED against the pre-gazetteer bundle, green after the resolver lands in the build - BA8: the shipped JS carries NO deep-link crypto (JS assets only — the official Telegram SDK is external, D-11/T-04-40) - no-storage: explicit web/src/search memory-only + no-crypto pin - capture.mjs: the ARAHARAH-DEST signal race + the 'dest' wait mode (state=resolved asserted, then the rendered card's text is waited on — the card mounts at live, T-04-42) + the shell-dest-preload leg; 8/8 expected captures
This commit is contained in:
+39
-5
@@ -26,6 +26,7 @@
|
||||
* shell-live-dark.png LIVE state, Telegram dark theme (PX-02)
|
||||
* shell-denied.png denied card + ASK VIA CHAT (GEO-02 entry point)
|
||||
* shell-chat-pin.png LIVE via the chat-pin relay (?pin=1, stubbed /api/location)
|
||||
* shell-dest-preload.png the Mini App booted WITH a preloaded destination (?dest=<id>)
|
||||
* gallery-compare.png DSGN-02 side-by-side vs navigate_map_overview/screen.png
|
||||
*
|
||||
* Also runs the GEO-03 runtime probe in-page after boot-to-live and fails
|
||||
@@ -162,7 +163,7 @@ log.push(`serving web/dist-harness/ → ${base}/`);
|
||||
|
||||
const browser = await chromium.launch();
|
||||
|
||||
const SIGNALS = ['RAMS-BASEMAP-READY', 'ARAHARAH-LIVE'];
|
||||
const SIGNALS = ['RAMS-BASEMAP-READY', 'ARAHARAH-LIVE', 'ARAHARAH-DEST'];
|
||||
|
||||
/*
|
||||
* One capture leg = one context + one screenshot. The Phase-1 READY-race
|
||||
@@ -186,7 +187,7 @@ async function captureLeg({ name, query, colorScheme, grantGeo, waitMode }) {
|
||||
await context.setGeolocation({ latitude: 3.1513, longitude: 101.6958, accuracy: 12 });
|
||||
}
|
||||
const page = await context.newPage();
|
||||
const seen = { 'RAMS-BASEMAP-READY': false, 'ARAHARAH-LIVE': false, live: 'no' };
|
||||
const seen = { 'RAMS-BASEMAP-READY': false, 'ARAHARAH-LIVE': false, 'ARAHARAH-DEST': false, live: 'no' };
|
||||
const consoleLines = [];
|
||||
page.on('console', (m) => {
|
||||
for (const s of SIGNALS) if (m.text().startsWith(s)) seen[s] = true;
|
||||
@@ -194,7 +195,7 @@ async function captureLeg({ name, query, colorScheme, grantGeo, waitMode }) {
|
||||
if (consoleLines.length > 20) consoleLines.shift();
|
||||
});
|
||||
const signalDiagnostics = () =>
|
||||
`${seen['RAMS-BASEMAP-READY'] ? 'RAMS-BASEMAP-READY yes' : 'RAMS-BASEMAP-READY no'}; ${seen['ARAHARAH-LIVE'] ? 'ARAHARAH-LIVE yes' : 'ARAHARAH-LIVE no'}; last console: ${JSON.stringify(consoleLines.slice(-5))}`;
|
||||
`${seen['RAMS-BASEMAP-READY'] ? 'RAMS-BASEMAP-READY yes' : 'RAMS-BASEMAP-READY no'}; ${seen['ARAHARAH-LIVE'] ? 'ARAHARAH-LIVE yes' : 'ARAHARAH-LIVE no'}; ${seen['ARAHARAH-DEST'] ? 'ARAHARAH-DEST yes' : 'ARAHARAH-DEST no'}; last console: ${JSON.stringify(consoleLines.slice(-5))}`;
|
||||
try {
|
||||
await page.goto(`${base}/?${query}`, { waitUntil: 'domcontentloaded', timeout: 60000 });
|
||||
|
||||
@@ -216,6 +217,33 @@ async function captureLeg({ name, query, colorScheme, grantGeo, waitMode }) {
|
||||
throw new Error(`theme slot mismatch: expected ${colorScheme}, documentElement[data-tg-theme]=${String(themed)}`);
|
||||
}
|
||||
await page.waitForTimeout(2000); // tile render settle (plan: first render + 2s)
|
||||
} else if (waitMode === 'dest') {
|
||||
const signal = await Promise.race([
|
||||
page.waitForEvent('console', {
|
||||
predicate: (m) => m.text().startsWith('ARAHARAH-DEST'),
|
||||
timeout: SIGNAL_TIMEOUT_MS,
|
||||
}).then(() => 'signal'),
|
||||
new Promise((r) => setTimeout(() => r('timeout'), SIGNAL_TIMEOUT_MS)),
|
||||
]);
|
||||
if (signal === 'timeout') {
|
||||
throw new Error(`ARAHARAH-DEST race timed out after ${SIGNAL_TIMEOUT_MS}ms — ${signalDiagnostics()}`);
|
||||
}
|
||||
/* The destination must actually be the RESOLVED one — a signal that fired
|
||||
* with state=absent means the payload never reached the resolver (T-04-42).
|
||||
* The signal is a STATE TOKEN (no id — D-15 hygiene), so the leg then
|
||||
* proves WHICH destination resolved via the rendered card's text. The card
|
||||
* mounts when the chain reaches live (the boot stages replace the stack
|
||||
* transiently), so the DOM check waits rather than sampling once. */
|
||||
const destLine = consoleLines.filter((l) => l.startsWith('ARAHARAH-DEST')).pop() ?? '';
|
||||
if (!destLine.includes('state=resolved')) {
|
||||
throw new Error(`destination did not resolve: "${destLine}" — expected state=resolved`);
|
||||
}
|
||||
await page.waitForFunction(
|
||||
() => (document.body.textContent ?? '').includes('Suria KLCC'),
|
||||
undefined,
|
||||
{ timeout: 15000, polling: 250 },
|
||||
);
|
||||
await page.waitForTimeout(500);
|
||||
} else if (waitMode === 'denied') {
|
||||
// Wait on the denied strip lamp specifically — the awaiting-pin variant of
|
||||
// the card also carries a CTA during LINK 3's 60s poll, so the CARD alone
|
||||
@@ -268,6 +296,11 @@ try {
|
||||
* a pin; the chain reaches LIVE offline — the automated Desktop-leg counterpart. */
|
||||
await captureLeg({ name: 'shell-chat-pin.png', query: 'mock=tdesktop&pin=1', colorScheme: 'light', grantGeo: false, waitMode: 'live' });
|
||||
|
||||
/* 7 — ONBD-02: the destination-preload boot. ?dest=<id> carries the plain
|
||||
* gazetteer id in the URL's own query string (the inline-button carrier —
|
||||
* RESEARCH Pitfall 1). The ARAHARAH-DEST signal resolves the race. */
|
||||
await captureLeg({ name: 'shell-dest-preload.png', query: 'mock=android&dest=suria-klcc', colorScheme: 'light', grantGeo: true, waitMode: 'dest' });
|
||||
|
||||
/* GEO-03 runtime probe (its own live session) — GEO-03's "spot-checkable at
|
||||
* phase exit" criterion made mechanical. Counts and key names only (T-03-24). */
|
||||
{
|
||||
@@ -316,7 +349,7 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
/* 7 — DSGN-02 fidelity artifact: the live-light capture beside the committed
|
||||
/* 8 — DSGN-02 fidelity artifact: the live-light capture beside the committed
|
||||
* navigate_map_overview mockup, each column labeled with its source path. */
|
||||
{
|
||||
const target = join(SHOTS, 'gallery-compare.png');
|
||||
@@ -365,6 +398,7 @@ const expected = [
|
||||
'shell-live-dark.png',
|
||||
'shell-denied.png',
|
||||
'shell-chat-pin.png',
|
||||
'shell-dest-preload.png',
|
||||
'gallery-compare.png',
|
||||
];
|
||||
const missing = expected.filter((f) => !existsSync(join(SHOTS, f)));
|
||||
@@ -378,5 +412,5 @@ if (missing.length || undersized.length || failures.length) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`CAPTURE OK — 7/7 non-blank captures under web/screenshots/`);
|
||||
console.log(`CAPTURE OK — 8/8 non-blank captures under web/screenshots/`);
|
||||
process.exit(0);
|
||||
|
||||
Reference in New Issue
Block a user