mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-28 23:51:03 +03:00
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:
co-authored by
Claude Opus 4.7
parent
e0197683e1
commit
588382cec1
@@ -0,0 +1,55 @@
|
||||
// 00-hooks.test.mjs — индикатор покрытия testlevel-хуков (M7.4).
|
||||
//
|
||||
// Тест запускается ПЕРВЫМ (алфавитно), импортирует shared `_state` из
|
||||
// `_hooks.mjs` и проверяет:
|
||||
// - `beforeAll` отработал ровно один раз ДО любого теста.
|
||||
// - `beforeEach` уже отработал для самого 00-hooks (счётчик === 1).
|
||||
// - `testInfo` доступен внутри тела (через ctx).
|
||||
// - `afterEach` для 00-hooks ещё не вызывался — `afterEach < beforeEach`.
|
||||
// - Последнее событие — `beforeEach:00-hooks.test.mjs`.
|
||||
//
|
||||
// `afterAll` проверить из теста невозможно (он зовётся после всех тестов).
|
||||
// Покрывается косвенно: финальный run должен показать `afterAll = 1` в
|
||||
// summary log (см. ctx.log в этом тесте).
|
||||
|
||||
import { _state } from './_hooks.mjs';
|
||||
|
||||
export const name = 'Хуки testlevel — индикатор порядка вызовов';
|
||||
export const tags = ['hooks', 'smoke'];
|
||||
export const timeout = 10000;
|
||||
|
||||
export default async function ({ step, assert, log, testInfo }) {
|
||||
|
||||
await step('beforeAll отработал ровно один раз', () => {
|
||||
assert.equal(_state.beforeAll, 1, `beforeAll=${_state.beforeAll}, ожидался 1`);
|
||||
assert.equal(_state.afterAll, 0, `afterAll=${_state.afterAll}, ожидался 0 (вызывается после всех тестов)`);
|
||||
});
|
||||
|
||||
await step('beforeEach отработал для этого теста', () => {
|
||||
assert.ok(_state.beforeEach >= 1, `beforeEach=${_state.beforeEach}, ожидался >= 1`);
|
||||
const last = _state.events[_state.events.length - 1];
|
||||
assert.ok(typeof last === 'string' && last.startsWith('beforeEach:'),
|
||||
`последнее событие должно быть beforeEach:..., но это "${last}"`);
|
||||
assert.ok(last.includes('00-hooks'),
|
||||
`последнее beforeEach должно ссылаться на 00-hooks, а не "${last}"`);
|
||||
});
|
||||
|
||||
await step('testInfo доступен в теле теста', () => {
|
||||
assert.equal(testInfo.file, '00-hooks.test.mjs', `testInfo.file=${testInfo.file}`);
|
||||
assert.ok(Array.isArray(testInfo.tags), 'testInfo.tags должен быть массивом');
|
||||
assert.includes(testInfo.tags, 'hooks', 'testInfo.tags должен содержать "hooks"');
|
||||
assert.equal(testInfo.attempt, 1, `attempt=${testInfo.attempt}`);
|
||||
assert.equal(typeof testInfo.primaryContext, 'string', 'primaryContext должен быть строкой');
|
||||
});
|
||||
|
||||
await step('afterEach для этого теста ещё не вызывался', () => {
|
||||
// В теле теста afterEach НЕ должен быть вызван ни разу для текущего теста.
|
||||
// Если 00-hooks запущен первым (что и ожидается), afterEach === 0.
|
||||
// Tolerance: проверяем относительное неравенство, чтобы тест не сломался
|
||||
// если кто-то добавит ещё один тест с алфавитно меньшим именем.
|
||||
assert.ok(_state.afterEach < _state.beforeEach,
|
||||
`afterEach (${_state.afterEach}) должен быть строго меньше beforeEach (${_state.beforeEach}) в теле теста`);
|
||||
});
|
||||
|
||||
log(`hooks indicator: beforeAll=${_state.beforeAll}, beforeEach=${_state.beforeEach}, afterEach=${_state.afterEach}, events.length=${_state.events.length}`);
|
||||
}
|
||||
@@ -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 || '?'}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user