Files
brain/tools/run-test-json.mjs
T

40 lines
2.1 KiB
JavaScript

#!/usr/bin/env node
/**
* run-test-json (Level B) — прогон одного тест-файла vitest с json-репортером и разбор итога.
* Анти-вакуум (SE-LB-1/11): «прошёл» = allGreen И numPassed>0 (0 собранных тестов НЕ зелёный).
* loadError — модуль не импортировался / json не разобран (ошибка сборки мутанта): НЕ ассерт-провал,
* mutate-runner трактует как inconclusive (не «убит»). Чистый parseVitestJson + I/O runVitestJson.
*/
import { execFileSync } from 'node:child_process';
import { join } from 'node:path';
/** Разобрать stdout vitest --reporter json. Битый/пустой → loadError. */
export function parseVitestJson(jsonText) {
let data;
try { data = JSON.parse(String(jsonText)); }
catch { return { allGreen: false, numTests: 0, numPassed: 0, numFailed: 0, loadError: true }; }
if (!data || typeof data !== 'object') {
return { allGreen: false, numTests: 0, numPassed: 0, numFailed: 0, loadError: true };
}
const numTests = Number(data.numTotalTests || 0);
const numPassed = Number(data.numPassedTests || 0);
const numFailed = Number(data.numFailedTests || 0);
const allGreen = numFailed === 0 && numPassed > 0;
return { allGreen, numTests, numPassed, numFailed, loadError: false };
}
/** I/O: прогнать testFile через vitest json. exit≠0 (упавшие тесты) — это нормально, парсим stdout. */
export function runVitestJson(testFile, gitCwd) {
let stdout = '';
try {
stdout = execFileSync('npx', ['vitest', 'run', testFile,
'--root', join(gitCwd, 'app'),
'--config', join(gitCwd, 'app', 'vitest.config.tools.mjs'),
'--reporter', 'json'], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
} catch (e) {
// Упавшие тесты → execFileSync бросает с ненулевым кодом; stdout всё равно несёт json.
stdout = (e && e.stdout) ? String(e.stdout) : '';
}
return parseVitestJson(stdout);
}