openvibers/openvibe.sdk Commits

npm test no longer counts a skipped test as passed (roadmap WS-Q task 7, the rule of openvibe-shared/test-runner). test/run.js counted every file that exited 0 as passed, so a file that printed that it skipped its work and checked nothing still read as green. A test now prints "<label>: skipped (<why>)" for what it could not run, and the runner lists that file with ○ and its reasons and does not count it as passed: the summary reads "32/33 test files passed, 1 skipped (…)", and only a run with nothing skipped says N/N; --strict (or OV_TEST_STRICT=1) makes a skip fail the run. The SDK does not depend on openvibe-shared, so the runner keeps its own loop (one file at a time, 120 s timeout) with SKIP_RE and skipsIn copied from the module. types.test.js printed "skipped: no openvibe-contracts checkout next to this repository" when it had no contract types to compare with and now prints "copied contract types: skipped (…)". npm test (Node 22) 33/33.

OP OpenVibers committed 28 Sept 2026 · adda89e45a · 2 files, +33 −6


Changes

ddiff --git a/test/run.js b/test/run.js
iindex 5dbf53e..03325bc 100644
---- a/test/run.js
++++ b/test/run.js
@@@ -6,12 +6,19 @@
*
* npm test # everything
* npm test -- core pack # only files whose name contains one of the words
++ * npm test -- --strict # a skipped test fails the run too (or OV_TEST_STRICT=1)
++ *
++ * A test that cannot run something here prints `<label>: skipped (<why>)`: that file is listed with
++ * ○ and its reasons and not counted as passed, so the summary reads `9/10 test files passed,
++ * 1 skipped (…)`; only a run with nothing skipped says `N/N test files passed`. This is the rule of
++ * openvibe-shared/test-runner, copied here because the SDK does not depend on openvibe-shared.
*/
'use strict';
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
++const strict = process.argv.includes('--strict') || process.env.OV_TEST_STRICT === '1';
const filters = process.argv.slice(2).filter((a) => !a.startsWith('-'));
const files = fs.readdirSync(__dirname)
.filter((f) => f.endsWith('.test.js'))
@@@ -19,6 +26,19 @@ const files = fs.readdirSync(__dirname)
.sort();
const TIMEOUT_MS = 120000;
++/** `<label>: skipped (<why>)` on a line of its own (SKIP_RE from openvibe-shared/test-runner). */
++const SKIP_RE = /^[ \t]*[\w .,'()/+#-]{1,120}: skipped \((.+)\)[ \t]*$/gm;
++
++/** The skip lines in a test's output, in order, without repeats (skipsIn from openvibe-shared/test-runner). */
++function skipsIn(output) {
++ const out = [];
++ for (const m of String(output || '').matchAll(SKIP_RE)) {
++ const line = m[0].trim();
++ if (!out.includes(line)) out.push(line);
++ }
++ return out;
++}
++
function runOne(file) {
return new Promise((resolve) => {
const started = Date.now();
@@@ -33,7 +53,9 @@ function runOne(file) {
const timer = setTimeout(() => { output += `\n[run] timed out after ${TIMEOUT_MS}ms`; child.kill('SIGKILL'); }, TIMEOUT_MS);
child.on('close', (code, signal) => {
clearTimeout(timer);
-- resolve({ file, ok: code === 0, code: code ?? signal, ms: Date.now() - started, output });
++ const ok = code === 0;
++ const skips = ok ? skipsIn(output) : [];
++ resolve({ file, ok, state: !ok ? 'fail' : skips.length ? 'skip' : 'pass', skips, code: code ?? signal, ms: Date.now() - started, output });
});
});
}
@@@ -44,13 +66,18 @@ function runOne(file) {
for (const f of files) {
const r = await runOne(f);
results.push(r);
-- console.log(`${r.ok ? '✓' : '✗'} ${r.file.padEnd(32)} ${String(r.ms).padStart(6)}ms`);
++ const mark = r.state === 'pass' ? '✓' : r.state === 'skip' ? '○' : '✗';
++ console.log(`${mark} ${r.file.padEnd(32)} ${String(r.ms).padStart(6)}ms${r.state === 'skip' ? ` ${r.skips.join('; ')}` : ''}`);
}
-- const failed = results.filter((r) => !r.ok);
++ const failed = results.filter((r) => r.state === 'fail');
++ const skipped = results.filter((r) => r.state === 'skip');
for (const r of failed) {
console.log(`\n── ${r.file} (exit ${r.code}) ──`);
console.log(r.output.split('\n').slice(-60).join('\n'));
}
-- console.log(`\n${results.length - failed.length}/${results.length} test files passed`);
-- process.exit(failed.length ? 1 : 0);
++ const passed = results.length - failed.length - skipped.length;
++ console.log(skipped.length
++ ? `\n${passed}/${results.length} test files passed, ${skipped.length} skipped (${skipped.map((r) => `${r.file}: ${r.skips.join('; ')}`).join(' | ')})${strict ? ' — strict: skips fail the run' : ''}`
++ : `\n${passed}/${results.length} test files passed`);
++ process.exit(failed.length || (strict && skipped.length) ? 1 : 0);
})();
ddiff --git a/test/types.test.js b/test/types.test.js
iindex 8b2b927..ccc6db5 100644
---- a/test/types.test.js
++++ b/test/types.test.js
@@@ -50,7 +50,7 @@ run([
path.join(ROOT, '../OpenVibe.Contracts/generated/typescript/index.d.ts'),
];
const source = candidates.find((p) => fs.existsSync(p));
-- if (!source) { console.log(' skipped: no openvibe-contracts checkout next to this repository'); return; }
++ if (!source) { console.log('copied contract types: skipped (no openvibe-contracts checkout next to this repository)'); return; }
const theirs = fs.readFileSync(source, 'utf8');
const ours = fs.readFileSync(path.join(ROOT, 'types/contracts.d.ts'), 'utf8');
const blocks = ours.split(/\n(?=\/\*\* [a-z]+\.[a-z-]+@)/).slice(1).map((b) => b.trim());