mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-09-26 05:14:32 +00:00
Make `test-all.sh` the authoritative standalone frontend runner for npm and CI. Restore stale assertions and reject missing, duplicate, removed or undocumented inventory entries. Fixes #1858. Rebased onto `a2f039d4`. Retains release-routing, map scope-state and Scope Audit stylesheet tests, adds `test-packets-local-channels.js` to the sorted runner, and classifies `test-neighbor-map-btn-clip-e2e.js` under browser. Its separate CI browser step is preserved. Inventory: 280 root suites, 167 standalone, 113 requiring separate setup. The icon repair fixes two suites red on master: `test-issue-1648-m2-emoji-scan.js` and `test-issue-1648-m6-final-sweep.js`. Node/live configured-scope confirmations now use the existing accessible Phosphor check sprite. Values, visibility conditions and scanner assertions are preserved. - Red evidence: `89e45a9` inventory assertions; `4e255df` accessible confirmation assertion. The latest rebase also reproduced both unclassified-file failures before adding their entries. This follow-up only changes runner/classification configuration and counts; no test files modified. - Local validation: all 167 standalone suites; 27 M2 browser checks and 16 neighbor geometry checks in Chromium. Syntax, whitespace, PII, CSS-variable and XSS checks passed. - Browser coverage includes populated/empty/null configured scopes in node and live views. - No new dependencies, requests, application settings or Go changes. Workflow outside the unit step matches master. - Windows validation uses process-local UTF-8 settings. Encoding and node-reach confirmation follow-ups remain separate, as requested. ## Preflight override External `run-all.sh` is unavailable; applicable repository checks were run directly.
50 lines
3.2 KiB
JavaScript
50 lines
3.2 KiB
JavaScript
/* Every root test must have one explicit home; adding a file cannot skip CI silently. */
|
|
'use strict';
|
|
|
|
const assert = require('assert');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
function checkInventory(files, groups) {
|
|
const assigned = new Set();
|
|
const available = new Set(files);
|
|
for (const [group, spec] of Object.entries(groups)) {
|
|
assert.ok(spec.reason && spec.reason.trim(), group + ' needs a prerequisite/reason');
|
|
for (const file of spec.files) {
|
|
assert.ok(available.has(file), group + ' lists a missing test: ' + file);
|
|
assert.ok(!assigned.has(file), 'test is listed more than once: ' + file);
|
|
assigned.add(file);
|
|
}
|
|
}
|
|
const missing = files.filter(file => !assigned.has(file));
|
|
assert.deepStrictEqual(missing, [], 'unclassified root tests: ' + missing.join(', '));
|
|
}
|
|
|
|
// Exercise the guard itself: omissions, stale paths, duplicate classifications,
|
|
// and undocumented exclusions must fail, even when the rest of the list is valid.
|
|
const unit = files => ({ reason: 'Standalone Node checks', files });
|
|
assert.doesNotThrow(() => checkInventory(['test-a.js'], { unit: unit(['test-a.js']) }));
|
|
assert.throws(() => checkInventory(['test-a.js', 'test-new.js'], { unit: unit(['test-a.js']) }), /unclassified root tests/);
|
|
assert.throws(() => checkInventory(['test-a.js'], { unit: unit(['test-old.js']) }), /missing test/);
|
|
assert.throws(() => checkInventory(['test-a.js'], { unit: unit(['test-a.js', 'test-a.js']) }), /more than once/);
|
|
assert.throws(() => checkInventory(['test-a.js'], { unit: unit(['test-a.js']), browser: unit(['test-a.js']) }), /more than once/);
|
|
assert.throws(() => checkInventory(['test-a.js'], { browser: { reason: '', files: ['test-a.js'] } }), /prerequisite\/reason/);
|
|
|
|
const runner = fs.readFileSync(path.join(__dirname, 'test-all.sh'), 'utf8');
|
|
const unitTests = Array.from(runner.matchAll(/^node (test-[^\s]+\.js)\s*$/gm), match => match[1]);
|
|
const groups = JSON.parse(fs.readFileSync(path.join(__dirname, 'scripts', 'non-unit-tests.json'), 'utf8'));
|
|
assert.ok(!Object.prototype.hasOwnProperty.call(groups, 'unit'), 'unit tests belong only in test-all.sh');
|
|
const files = fs.readdirSync(__dirname).filter(file => /^test-.*\.js$/.test(file)).sort();
|
|
checkInventory(files, { unit: unit(unitTests), ...groups });
|
|
|
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
|
assert.strictEqual(pkg.scripts['test:unit'], 'sh test-all.sh', 'npm test:unit must use the authoritative runner');
|
|
assert.ok(pkg.scripts.test.includes('sh test-all.sh'), 'npm test must use the authoritative runner');
|
|
assert.ok(pkg.scripts['test:coverage'].includes('sh test-all.sh'), 'coverage must use the authoritative runner');
|
|
const workflow = fs.readFileSync(path.join(__dirname, '.github', 'workflows', 'deploy.yml'), 'utf8');
|
|
const unitStep = workflow.match(/- name: Run JS unit tests[^\n]*\n([\s\S]*?)(?=\n - name:)/);
|
|
assert.ok(unitStep, 'CI must retain its JS unit-test step');
|
|
assert.match(unitStep[1], /\bsh test-all\.sh\b/, 'CI must use the authoritative runner');
|
|
assert.doesNotMatch(unitStep[1], /\bnode test-/, 'CI must not keep a second unit-test list');
|
|
console.log('Test inventory: ' + files.length + ' root suites classified; ' + unitTests.length + ' run by local and CI unit checks.');
|