diff --git a/nodes/dashboardAPI b/nodes/dashboardAPI index 2874608..92d7eba 160000 --- a/nodes/dashboardAPI +++ b/nodes/dashboardAPI @@ -1 +1 @@ -Subproject commit 287460837540e6d4af2f11416afc910f3e84070f +Subproject commit 92d7eba0fd18829fd1f8e7bf8a89af7b380c85c8 diff --git a/nodes/diffuser b/nodes/diffuser index 0ec9dd1..15cfb22 160000 --- a/nodes/diffuser +++ b/nodes/diffuser @@ -1 +1 @@ -Subproject commit 0ec9dd15a78351e42cdb0c66aa5a3f7f294a9f45 +Subproject commit 15cfb222b2c116850463a4d91707362cc58f0540 diff --git a/nodes/generalFunctions b/nodes/generalFunctions index 8ebf31d..95c5e68 160000 --- a/nodes/generalFunctions +++ b/nodes/generalFunctions @@ -1 +1 @@ -Subproject commit 8ebf31dd39e87919c1d6beda51e71a3d1a649788 +Subproject commit 95c5e684e463962f5b2999d7de8aac2ac6a9aee5 diff --git a/nodes/pumpingStation b/nodes/pumpingStation index 52d3889..d2384b1 160000 --- a/nodes/pumpingStation +++ b/nodes/pumpingStation @@ -1 +1 @@ -Subproject commit 52d3889fbc29192e05edd8f05a94f5d9123bf42e +Subproject commit d2384b1a2d285206c92be2d82592b5196c95d884 diff --git a/package.json b/package.json index c67a17e..7aba41f 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "test:node": "node --test nodes/valve/test/basic/*.test.js nodes/valve/test/edge/*.test.js nodes/valve/test/integration/*.test.js nodes/valveGroupControl/test/basic/*.test.js nodes/valveGroupControl/test/edge/*.test.js nodes/valveGroupControl/test/integration/*.test.js", "test:legacy": "node nodes/machineGroupControl/src/groupcontrol.test.js && node nodes/generalFunctions/src/nrmse/errorMetric.test.js", "test:all": "npm test && npm run test:node && npm run test:legacy", + "test:platform": "node scripts/test-platform.js", "test:e2e:reactor": "node scripts/e2e-reactor-roundtrip.js", "lint": "eslint nodes/", "lint:fix": "eslint nodes/ --fix", diff --git a/scripts/test-platform.js b/scripts/test-platform.js new file mode 100644 index 0000000..b572fd6 --- /dev/null +++ b/scripts/test-platform.js @@ -0,0 +1,76 @@ +#!/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();