diff --git a/demo/serve.mjs b/demo/serve.mjs index 6f92bca8..828629db 100644 --- a/demo/serve.mjs +++ b/demo/serve.mjs @@ -31,6 +31,32 @@ export function checkAll(out, expected = {}) { return out; } +/** + * Тот же вердикт по исключениям в карточке, что у `finish()`, для смоков со + * своей логикой выхода (#407). + * + * Счётчик `_pageErrors` живёт здесь, а читал его только `finish()`. Шесть + * смоков `finish()` не вызывали вовсе — у каждого была своя ручная развязка + * (`if (!ok) process.exit(1)`) либо `throw` из try/finally, и ни одна не + * спрашивала про исключения. То есть необработанное исключение внутри карточки + * во время этих шести проходило незамеченным всегда: в лог печаталось `EXC`, а + * прогон оставался зелёным. + * + * Функция ничего не бросает намеренно. Смок с ручной развязкой продолжает + * решать сам, что печатать и когда выходить; здесь только выставляется код + * возврата, который дальше уже не отнять — `process.exitCode` переживёт любой + * последующий `console.log`. + * + * @returns true, если карточка бросала — чтобы вызывающий мог добавить своё + * сообщение, не считая исключения заново. + */ +export function reportPageErrors() { + if (!_pageErrors) return false; + console.error(`FAILED: ${_pageErrors} uncaught exception(s) inside the card`); + process.exitCode = 1; + return true; +} + /** Print the result, report failures, close the browser, set the exit code. */ export async function finish(browser, out) { if (out !== undefined) console.log(JSON.stringify(out, null, 1)); diff --git a/demo/smoke_deeplink.mjs b/demo/smoke_deeplink.mjs index 1ac33390..9f6fcaa9 100644 --- a/demo/smoke_deeplink.mjs +++ b/demo/smoke_deeplink.mjs @@ -1,5 +1,5 @@ // Smoke: the full houseplan-card honours the #space= deep-link (hashchange). -import { launch } from './serve.mjs'; +import { launch, reportPageErrors } from './serve.mjs'; const { page, browser } = await launch({ width: 820, height: 760 }, 1); const res = await page.evaluate(async () => { const card = window.__card; @@ -22,5 +22,8 @@ const res = await page.evaluate(async () => { await browser.close(); const ok = res.after === res.target && res.afterBad === res.target; console.log(JSON.stringify(res)); +// #407: своя развязка про исключения в карточке не спрашивает. Вердикт обязан +// именно остановить: иначе строка успеха печатается после «FAILED». +if (reportPageErrors()) process.exit(1); if (!ok) { console.error('FAIL deeplink smoke'); process.exit(1); } console.log('OK deep-link: full card switches to #space=, ignores invalid ids'); diff --git a/demo/smoke_entry_stale.mjs b/demo/smoke_entry_stale.mjs index 615bbd06..fcb9daf2 100644 --- a/demo/smoke_entry_stale.mjs +++ b/demo/smoke_entry_stale.mjs @@ -5,7 +5,7 @@ // and `await import(entry)` + `createElement(...).setConfig(...)` stays valid. import { readFileSync } from 'node:fs'; import { chromium } from 'playwright'; -import { check, checkAll } from './serve.mjs'; +import { check, checkAll, finish } from './serve.mjs'; const entry = readFileSync('dist/houseplan-card.js'); const page404 = `