Three browser gates stop passing hollow or racing (rega's gates:post run at ded4b3c1)
- check:dashboard-geocoder-provider: 0 search bars on BOTH engines. Its default leaf (research-map) hides
the bar under MapLibre on purpose, and the tokenless Mapbox run could not draw. It now defaults to
doxa-simple-map (a bar on both engines), and the Mapbox run gets a host token: TEST_MAPBOX_TOKEN, or a
well-formed fake whose token-carrying requests are aborted, never sent.
- check:composite-embed-knobs: every tk case SKIPPED (no baked token since the auto engine), so every
provider case went UNMEASURED and the gate still PASSed. It takes TEST_MAPBOX_TOKEN, and a run where no
case measured anything exits 75 NOT MEASURED instead of PASS.
- check:linked-vocabulary: it attached its groups-filtered listener after goto and could miss the grid's
first emit ("the grid never reported a total"). The totals are now recorded from page start
(addInitScript).
Not browser-run here (browsers are rega's): rega's next gates:post pass is the proof.
This commit is contained in:
parent
3dddba0eeb
commit
6c804159c3
3 changed files with 35 additions and 7 deletions
|
|
@ -42,7 +42,8 @@
|
|||
* naming the composite and the knob; both restored, both pass. Removing the zero-request assertion
|
||||
* from the provider case makes it pass on a build that ignores the prop, which is what it is for.
|
||||
*
|
||||
* Exit: 0 pass or SKIP (no built tree, no browser, no baked token to test with) · 1 fail.
|
||||
* Exit: 0 pass (or SKIP: no built tree / no browser) · 1 fail · 75 NOT MEASURED (every case skipped, e.g. no
|
||||
* token: set TEST_MAPBOX_TOKEN).
|
||||
*/
|
||||
import { createServer } from 'node:http'
|
||||
import { spawn } from 'node:child_process'
|
||||
|
|
@ -92,7 +93,10 @@ if (!targets.length) {
|
|||
|
||||
// The token to hand the partner page is the one the tree already bakes into its own leaves: this
|
||||
// gate must not invent a key, and a token that is not this tree's would 401 and look like our bug.
|
||||
const bakedToken = (() => {
|
||||
// The tree bakes no token since the auto engine (the repo ships none), so every tk case SKIPPED and every
|
||||
// provider case went UNMEASURED: a hollow PASS (rega, ded4b3c1). A seat that has a real public token passes
|
||||
// it as TEST_MAPBOX_TOKEN (as rega's checks do); otherwise a baked one is still used if a tree has it.
|
||||
const bakedToken = process.env.TEST_MAPBOX_TOKEN || (() => {
|
||||
for (const b of manifest.bundles || []) {
|
||||
for (const p of b.profiles || []) {
|
||||
if (!p.isMap || !p.iframeUrl) continue
|
||||
|
|
@ -227,4 +231,9 @@ if (fails.length) {
|
|||
console.error(' on a partner page — the case the published embed snippet is written for.')
|
||||
process.exit(1)
|
||||
}
|
||||
// A run in which no case measured anything is NOT MEASURED (exit 75), never a PASS.
|
||||
if (!lines.some((l) => /^\s*ok\b/.test(l))) {
|
||||
console.log(`\nCOMPOSITE-EMBED-KNOBS: NOT MEASURED — every case skipped or went unmeasured${bakedToken ? '' : ' (no token: set TEST_MAPBOX_TOKEN to a public pk. token)'}.`)
|
||||
process.exit(75)
|
||||
}
|
||||
console.log(`\nCOMPOSITE-EMBED-KNOBS: PASS — the host's token and provider reach every nested map.`)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
* maplibre ZERO requests to api.mapbox.com.
|
||||
* both whatever search bars this leaf renders still produce suggestions — a zero bought by
|
||||
* breaking search is not a fix. A leaf with NO bar now FAILS (it used to pass hollow);
|
||||
* the default leaf is doxa-research-map/research-map, which mounts one (--leaf to change).
|
||||
* the default leaf is doxa-simple-map/doxa-simple-map, which mounts one on both engines (--leaf to change).
|
||||
*
|
||||
* Exit: 0 pass or SKIP (no built tree, no browser, no data) · 1 fail.
|
||||
*/
|
||||
|
|
@ -53,7 +53,10 @@ const manifest = JSON.parse(readFileSync(MANIFEST, 'utf8'))
|
|||
// ★ A LEAF THAT MOUNTS THE SEARCH BAR, or the suggestion half proves nothing (2026-09-26: the
|
||||
// research-dashboard leaf renders no bar, so every run passed with "search bars: 0" — a hollow PASS).
|
||||
// Default: the research map, which mounts the library GeocoderComponent. --leaf <bundle>/<profile>.
|
||||
const leafArg = (() => { const i = process.argv.indexOf('--leaf'); return i >= 0 ? process.argv[i + 1] : 'doxa-research-map/research-map' })()
|
||||
// doxa-simple-map mounts the library GeocoderComponent under BOTH engines. research-map hides its bar
|
||||
// under MapLibre on purpose (research-map.vue hasGeocoder), so it cannot test the MapLibre half (rega,
|
||||
// ded4b3c1: 0 bars on both engines, since the tokenless Mapbox run did not draw either).
|
||||
const leafArg = (() => { const i = process.argv.indexOf('--leaf'); return i >= 0 ? process.argv[i + 1] : 'doxa-simple-map/doxa-simple-map' })()
|
||||
const [wantBundle, wantProfile] = leafArg.split('/')
|
||||
const bundle = (manifest.bundles || []).find((b) => b.bundle === wantBundle)
|
||||
const profile = bundle && (bundle.profiles || []).find((p) => p.iframeUrl && (!wantProfile || p.profile === wantProfile))
|
||||
|
|
@ -80,6 +83,14 @@ const lines = []
|
|||
try {
|
||||
for (const engine of ['maplibre', 'mapbox']) {
|
||||
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } })
|
||||
// Mapbox needs a token to draw at all since the repo ships none (the auto engine). Give that run a host
|
||||
// token: TEST_MAPBOX_TOKEN when the seat has one, else a well-formed FAKE (its tile requests are aborted,
|
||||
// never sent; the engine still starts and the bar still mounts). The MapLibre run gets NO token.
|
||||
if (engine === 'mapbox') {
|
||||
const tk = process.env.TEST_MAPBOX_TOKEN || ['pk', Buffer.from(JSON.stringify({ u: 'geocoder-provider-check' })).toString('base64url'), 'c2ln'].join('.')
|
||||
await page.addInitScript((t) => { window.MAP_TOKEN = t }, tk)
|
||||
if (!process.env.TEST_MAPBOX_TOKEN) await page.route((u) => /(^|\.)mapbox\.com$/i.test(u.hostname) && u.searchParams.has('access_token'), (r) => r.abort())
|
||||
}
|
||||
const mapboxCalls = []
|
||||
page.on('request', (r) => { const u = r.url(); if (u.includes('api.mapbox.com')) mapboxCalls.push(u) })
|
||||
await page.goto(`${LEAF}?provider=${engine}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
||||
|
|
|
|||
|
|
@ -99,6 +99,13 @@ try {
|
|||
for (const locale of LOCALES) {
|
||||
for (const engine of PROVIDERS) {
|
||||
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } })
|
||||
// ★ LISTEN BEFORE THE PAGE RUNS. The grid reports its total on its FIRST filter pass, which can happen
|
||||
// before an evaluate() after goto attaches a listener; the gate then read "the grid never reported a
|
||||
// total" while the grid had reported one (rega, ded4b3c1). Every total is recorded from the start.
|
||||
await page.addInitScript(() => {
|
||||
window.__lvTotals = []
|
||||
document.addEventListener('groups-filtered', (e) => { window.__lvTotals.push(e.detail?.total ?? null) }, true)
|
||||
})
|
||||
await page.goto(`${LEAF}?provider=${engine}&lang=${locale}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
||||
|
||||
// Everything below runs in ONE evaluate: the totals have to be read from the same live page, and
|
||||
|
|
@ -129,9 +136,10 @@ try {
|
|||
|
||||
// The grid reports its total on every filter pass. Listening is how a total is read here: the
|
||||
// rendered count line is localized and the DOM shape is not this gate's business.
|
||||
let total = null
|
||||
const seen = []
|
||||
document.addEventListener('groups-filtered', (e) => { total = e.detail?.total ?? null; seen.push(total) }, true)
|
||||
// Totals recorded since the page started (addInitScript above), so an early first pass is not missed.
|
||||
const seen = window.__lvTotals || (window.__lvTotals = [])
|
||||
let total = seen.length ? seen[seen.length - 1] : null
|
||||
document.addEventListener('groups-filtered', (e) => { total = e.detail?.total ?? null }, true)
|
||||
|
||||
// Wait for the first fetch to settle — a total of null means the data never arrived, which is a
|
||||
// SKIP (no network in the sandbox), not a failure of the mapping.
|
||||
|
|
|
|||
Loading…
Reference in a new issue