test(web-test): обвязка check.mjs для фикстуры _hang + не ограничивать prepare

check.mjs спавнит раннер дочерним процессом и превращает «читать глазами
два условия» в 0/1. Проверяет шесть вещей: раннер завершился за 90с (а не
завис — это и есть суть), вердикт hang, контекст прерван с успешным logout,
следующий тест зелёный (лицензия вернулась), результат зависшего теста попал
в отчёт (инкрементальная запись), код выхода 1. Отдельный код 2 — стенд не
поднят: у фикстуры нет своих хуков, и «нет стенда» не должно выглядеть как
поломка механики.

Заодно фикс собственной регрессии: hooks.prepare был обёрнут в bounded(),
который ГЛОТАЕТ ошибку — упавшая пересборка стенда молча пропускалась бы, и
вместо одной внятной ошибки прогон вываливал бы экран непонятных падений.
Плюс бюджет 120с обрезал бы легитимно долгую пересборку большой базы.
Возвращено к голому await: prepare честно долгий, а его падение обязано быть
фатальным.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-15 17:50:08 +03:00
parent dc8afb402b
commit 9352d28008
2 changed files with 135 additions and 2 deletions
@@ -33,7 +33,7 @@ export async function cmdTest(rawArgs) {
stopRecording: 40000, // ffmpeg has its own 30s inside
closeContext: 20000,
disconnect: 30000,
hooks: 120000, // prepare/cleanup/beforeAll/afterAll do real work (db rebuilds)
hooks: 120000, // afterAll/cleanup only — prepare/beforeAll stay unbounded (see below)
abortAll: 30000, // whole abort+cleanup sequence for one hung test
probe: 2000,
};
@@ -294,7 +294,11 @@ export async function cmdTest(rawArgs) {
const hookLog = (...a) => W.write(`[hooks] ${a.map(String).join(' ')}\n`);
const hookEnv = { hookArgs, log: hookLog, config };
if (hooks.prepare) await bounded(hooks.prepare(hookEnv), D.hooks, 'hooks.prepare');
// Deliberately unbounded and allowed to throw: prepare() rebuilds the stand (db-create +
// load + update), whose honest duration depends on the application's size — a deadline here
// would cut a legitimate rebuild. And its failure must stay fatal: proceeding into a run
// without a stand turns one clear error into a screenful of confusing ones.
if (hooks.prepare) await hooks.prepare(hookEnv);
/** Force-release every open context (frees 1C licenses), then drop the browser. */
async function shutdownAll() {