feat(web-test): M7.4 — testlevel-хуки + 00-hooks индикатор

_hooks.mjs v0.3: добавлены beforeAll/afterAll/beforeEach/afterEach
(counter-only) и shared `_state` (счётчики + events log).

tests/web-test/00-hooks.test.mjs (новый, 4 шага, 0s) — индикатор
порядка вызовов: проверяет beforeAll===1, beforeEach для текущего
теста, доступность ctx.testInfo, afterEach < beforeEach.

Multi-context хуки оставлены one-shot. Разведка beforeAll:
navigateSection не нужен, 1С после входа уже на дефолтной секции.

Регресс 19/19 ✓ (9m 12.7s).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-05-13 14:35:20 +03:00
co-authored by Claude Opus 4.7
parent e0197683e1
commit 588382cec1
2 changed files with 104 additions and 1 deletions
+49 -1
View File
@@ -1,4 +1,4 @@
// _hooks.mjs v0.2 — автономный тестовый стенд для web-test
// _hooks.mjs v0.3 — автономный тестовый стенд для web-test + testlevel-хуки
//
// `prepare()` поднимает изолированный стенд по smart-логике:
// 1) Если нужно пересоздавать БД (config-rebuild или --reload-data) — web-stop
@@ -293,3 +293,51 @@ export async function cleanup({ log }) {
// или следующий запуск с --rebuild-stand.
log('cleanup: stand left running (use /web-stop or run with `-- --rebuild-stand` to reset)');
}
// ── Testlevel hooks (M7.4) ────────────────────────────────────────────────────
//
// Shared mutable state, импортируется индикатором `00-hooks.test.mjs` для
// проверки порядка вызовов. Хуки — counter-only, никакой реальной работы:
// `prepare()` уже подготовил стенд, дефолтное приземление 1С после входа
// уже показывает панель разделов (разведка 2026-05-13: navigateSection
// в beforeAll не нужен).
//
// `events` — последовательность строк, по которой индикатор восстанавливает
// порядок (`beforeAll`, `beforeEach:01-navigation.test.mjs`, ...).
export const _state = {
beforeAll: 0,
afterAll: 0,
beforeEach: 0,
afterEach: 0,
events: [],
lastTestResult: null,
};
export async function beforeAll(_ctx) {
_state.beforeAll++;
_state.events.push('beforeAll');
}
export async function afterAll(_ctx) {
_state.afterAll++;
_state.events.push('afterAll');
}
export async function beforeEach(ctx) {
_state.beforeEach++;
_state.events.push(`beforeEach:${ctx.testInfo?.file || '?'}`);
}
export async function afterEach(ctx) {
_state.afterEach++;
// Снимок testResult без тяжёлого steps[]: индикатор проверяет только
// status/duration/attempts/error.
if (ctx.testResult) {
const { status, duration, attempts, error } = ctx.testResult;
_state.lastTestResult = { status, duration, attempts, error };
} else {
_state.lastTestResult = null;
}
_state.events.push(`afterEach:${ctx.testInfo?.file || '?'}:${ctx.testResult?.status || '?'}`);
}