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.
Changes
@@@ -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);})();@@@ -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());
@@ -6,12 +6,19 @@
@@ -6,12 +6,19 @@
*
*
* npm test # everything
* npm test # everything
* npm test -- core pack # only files whose name contains one of the words
* 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';
'use strict';
const { spawn } = require('child_process');
const { spawn } = require('child_process');
const fs = require('fs');
const fs = require('fs');
const path = require('path');
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 filters = process.argv.slice(2).filter((a) => !a.startsWith('-'));
const files = fs.readdirSync(__dirname)
const files = fs.readdirSync(__dirname)
.filter((f) => f.endsWith('.test.js'))
.filter((f) => f.endsWith('.test.js'))
@@ -19,6 +26,19 @@ const files = fs.readdirSync(__dirname)
@@ -19,6 +26,19 @@ const files = fs.readdirSync(__dirname)
.sort();
.sort();
const TIMEOUT_MS = 120000;
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) {
function runOne(file) {
return new Promise((resolve) => {
return new Promise((resolve) => {
const started = Date.now();
const started = Date.now();
@@ -33,7 +53,9 @@ function runOne(file) {
@@ -33,7 +53,9 @@ function runOne(file) {
const timer = setTimeout(() => { output += `\n[run] timed out after ${TIMEOUT_MS}ms`; child.kill('SIGKILL'); }, TIMEOUT_MS);
const timer = setTimeout(() => { output += `\n[run] timed out after ${TIMEOUT_MS}ms`; child.kill('SIGKILL'); }, TIMEOUT_MS);
child.on('close', (code, signal) => {
child.on('close', (code, signal) => {
clearTimeout(timer);
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) {
@@ -44,13 +66,18 @@ function runOne(file) {
for (const f of files) {
for (const f of files) {
const r = await runOne(f);
const r = await runOne(f);
results.push(r);
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) {
for (const r of failed) {
console.log(`\n── ${r.file} (exit ${r.code}) ──`);
console.log(`\n── ${r.file} (exit ${r.code}) ──`);
console.log(r.output.split('\n').slice(-60).join('\n'));
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);
})();
})();
@@ -50,7 +50,7 @@ run([
@@ -50,7 +50,7 @@ run([
path.join(ROOT, '../OpenVibe.Contracts/generated/typescript/index.d.ts'),
path.join(ROOT, '../OpenVibe.Contracts/generated/typescript/index.d.ts'),
];
];
const source = candidates.find((p) => fs.existsSync(p));
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 theirs = fs.readFileSync(source, 'utf8');
const ours = fs.readFileSync(path.join(ROOT, 'types/contracts.d.ts'), '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());
const blocks = ours.split(/\n(?=\/\*\* [a-z]+\.[a-z-]+@)/).slice(1).map((b) => b.trim());