Files
EVOLV/scripts/test-platform.js
znetsixe 3b7acdaa88 P10.7: top-level test:platform runner + bump submodule pointers
scripts/test-platform.js iterates each submodule, runs npm test, shows
a per-node pass/fail summary, exits non-zero if any node fails.

Wired as `npm run test:platform` in the parent package.json.

Submodule pointer bumps:
  dashboardAPI     2874608 → 92d7eba  (Mocha → node:test conversion for edge+integration)
  diffuser         0ec9dd1 → 15cfb22  (P10.7a test script fix)
  generalFunctions 8ebf31d → 95c5e68  (P10.7a test script fix + remove 5 broken Mocha dupes)
  pumpingStation   52d3889 → d2384b1  (P10.7a test script fix)

Current platform-wide gate: 729 pass / 5 fail across 12 submodules
(5 failures are all pre-existing AssertionErrors logged in
OPEN_QUESTIONS.md for Phase 10.5).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:45:06 +02:00

77 lines
2.6 KiB
JavaScript

#!/usr/bin/env node
/**
* Runs `npm test` in every submodule under `nodes/` and prints a
* summary table. Exits non-zero if any submodule's test run failed.
*
* Usage: node scripts/test-platform.js
* (or `npm run test:platform` from the EVOLV root)
*/
'use strict';
const { spawnSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '..');
const NODES_DIR = path.join(ROOT, 'nodes');
const TIMEOUT_MS = 300_000; // 5 minutes per node (mathjs-heavy ones can take ~13s/file)
function listSubmodules() {
return fs.readdirSync(NODES_DIR)
.filter((d) => fs.existsSync(path.join(NODES_DIR, d, 'package.json')))
.sort();
}
function pad(s, w) { s = String(s); return s + ' '.repeat(Math.max(0, w - s.length)); }
function runOne(name) {
const dir = path.join(NODES_DIR, name);
const t0 = Date.now();
const r = spawnSync('npm', ['test', '--silent'], {
cwd: dir, encoding: 'utf8', timeout: TIMEOUT_MS, env: { ...process.env, FORCE_COLOR: '0' },
});
const out = (r.stdout || '') + (r.stderr || '');
const pass = Number((out.match(/^# pass (\d+)/m) || [])[1] || 0);
const fail = Number((out.match(/^# fail (\d+)/m) || [])[1] || 0);
const tests = Number((out.match(/^# tests (\d+)/m) || [])[1] || 0);
const durSec = ((Date.now() - t0) / 1000).toFixed(1);
const ok = r.status === 0 && fail === 0;
return { name, pass, fail, tests, durSec, ok, output: out };
}
function main() {
const nodes = listSubmodules();
console.log(`Running tests across ${nodes.length} submodules...\n`);
const results = [];
for (const node of nodes) {
process.stdout.write(` ${pad(node, 22)}`);
const r = runOne(node);
results.push(r);
const mark = r.ok ? '✓' : '✗';
process.stdout.write(`${mark} ${pad(`${r.pass} pass / ${r.fail} fail`, 22)} ${r.durSec}s\n`);
}
console.log('\n--- Summary ---');
const totalPass = results.reduce((s, r) => s + r.pass, 0);
const totalFail = results.reduce((s, r) => s + r.fail, 0);
const totalDur = results.reduce((s, r) => s + Number(r.durSec), 0).toFixed(1);
const allOk = results.every((r) => r.ok);
console.log(` ${totalPass} pass / ${totalFail} fail across ${results.length} submodules in ${totalDur}s`);
if (!allOk) {
console.log('\n--- Failures ---');
for (const r of results.filter((r) => !r.ok)) {
console.log(`\n[${r.name}]`);
const failingLines = r.output.split('\n').filter((l) =>
/^not ok|AssertionError|Error:/.test(l)
).slice(0, 10);
failingLines.forEach((l) => console.log(` ${l}`));
}
}
process.exit(allOk ? 0 : 1);
}
main();