mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-10-09 07:18:33 +00:00
Moves 290 root test-*.js into tests/unit (177, listed in test-all.sh) and tests/e2e (113, classified in scripts/non-unit-tests.json), per #1981 and PR-D of #1385. Root goes from 348 entries to 48. test-all.sh and test-fixtures/ stay put. The inventory guard now fails if a test reappears in the root or sits in the wrong folder.
Verified independently of the diff: the invoked sets are unchanged (test-all.sh 177 before and after, deploy.yml 96 before and after, both identical as sets), and a full local run of test-all.sh on master and on the branch produced 4702 output lines each whose only differences are absolute paths, stack-trace line numbers shifted by the REPO_ROOT line, the inventory wording and two perf ratios. The guard was mutation-checked: a test back in the root, a unit suite in tests/e2e, and a suite dropped from test-all.sh each make it exit 1. CI run 35246304316 ran 97 suites from tests/e2e and is green.
Follow-up 9335c51d finished the instruction files: no bare root test command is left in AGENTS.md, the squad charters, .github or docs, and every tests/ path they name resolves.
Merged by the interim maintainer without a second human reviewer: CI and the local runs above are the independent checks.
Known and deliberately out of scope: 18 of the 113 files in tests/e2e are invoked by no runner at all, and one of them cannot run anywhere because it requires jsdom, which is not a declared dependency. Tracked separately.
113 lines
4.2 KiB
JavaScript
113 lines
4.2 KiB
JavaScript
/* Unit tests for compare.js asymmetric overlap stats — Fixes #671 */
|
|
'use strict';
|
|
const REPO_ROOT = require('path').resolve(__dirname, '..', '..');
|
|
const vm = require('vm');
|
|
const fs = require('fs');
|
|
const assert = require('assert');
|
|
|
|
let passed = 0, failed = 0;
|
|
function test(name, fn) {
|
|
try { fn(); passed++; console.log(` ✅ ${name}`); }
|
|
catch (e) { failed++; console.log(` ❌ ${name}: ${e.message}`); }
|
|
}
|
|
|
|
function makeSandbox() {
|
|
const ctx = {
|
|
window: { addEventListener: () => {}, dispatchEvent: () => {} },
|
|
document: {
|
|
readyState: 'complete',
|
|
createElement: () => ({ id: '', textContent: '', innerHTML: '', addEventListener: () => {} }),
|
|
head: { appendChild: () => {} },
|
|
getElementById: () => null,
|
|
querySelectorAll: () => [],
|
|
addEventListener: () => {},
|
|
},
|
|
console,
|
|
setTimeout, clearTimeout,
|
|
location: { hash: '#/compare', href: '' },
|
|
history: { replaceState: () => {} },
|
|
URLSearchParams,
|
|
Map, Set, Date, Promise,
|
|
escapeHtml: (s) => s,
|
|
api: () => Promise.resolve({ observers: [] }),
|
|
CLIENT_TTL: { observers: 0 },
|
|
registerPage: () => {},
|
|
timeAgo: () => '',
|
|
payloadTypeColor: () => '',
|
|
};
|
|
ctx.self = ctx.window;
|
|
return ctx;
|
|
}
|
|
|
|
const ctx = makeSandbox();
|
|
const sandbox = vm.createContext(ctx);
|
|
const compareSrc = fs.readFileSync(REPO_ROOT + '/public/compare.js', 'utf8');
|
|
vm.runInContext(compareSrc, sandbox);
|
|
|
|
console.log('\ncompare.js asymmetric overlap stats (#671):');
|
|
|
|
test('computeOverlapStats is exposed on window', () => {
|
|
assert.strictEqual(typeof sandbox.window.computeOverlapStats, 'function',
|
|
'computeOverlapStats should be exposed on window');
|
|
});
|
|
|
|
test('basic asymmetric overlap — A sees 8/10 of B\'s, B sees 8/12 of A\'s', () => {
|
|
// A: 12 unique packets total (10 shared with B + 2 unique)
|
|
// B: 10 unique packets total (10 shared with A... wait: 8 shared + 2 unique to B)
|
|
// Let's do: A has packets 1..10 + extras 11,12; B has packets 1..8 + extras 13,14
|
|
// shared = {1..8} = 8
|
|
// onlyA = {9,10,11,12} = 4
|
|
// onlyB = {13,14} = 2
|
|
// A total = 12, B total = 10
|
|
// A sees 8/10 = 80% of B's packets
|
|
// B sees 8/12 = 66.7% of A's packets
|
|
const setA = new Set(['1','2','3','4','5','6','7','8','9','10','11','12']);
|
|
const setB = new Set(['1','2','3','4','5','6','7','8','13','14']);
|
|
const cmp = sandbox.window.comparePacketSets(setA, setB);
|
|
const stats = sandbox.window.computeOverlapStats(cmp);
|
|
assert.strictEqual(stats.totalA, 12, 'totalA');
|
|
assert.strictEqual(stats.totalB, 10, 'totalB');
|
|
assert.strictEqual(stats.shared, 8, 'shared');
|
|
assert.strictEqual(stats.onlyA, 4, 'onlyA');
|
|
assert.strictEqual(stats.onlyB, 2, 'onlyB');
|
|
assert.strictEqual(stats.aSeesOfB, 80.0, 'A sees 80% of B\'s');
|
|
assert.strictEqual(stats.bSeesOfA, Math.round(8/12*1000)/10, 'B sees 66.7% of A\'s');
|
|
});
|
|
|
|
test('zero packets — no division by zero', () => {
|
|
const cmp = sandbox.window.comparePacketSets(new Set(), new Set());
|
|
const stats = sandbox.window.computeOverlapStats(cmp);
|
|
assert.strictEqual(stats.aSeesOfB, 0);
|
|
assert.strictEqual(stats.bSeesOfA, 0);
|
|
assert.strictEqual(stats.shared, 0);
|
|
});
|
|
|
|
test('one observer empty — other gets 0% mutual coverage', () => {
|
|
const cmp = sandbox.window.comparePacketSets(new Set(['x','y']), new Set());
|
|
const stats = sandbox.window.computeOverlapStats(cmp);
|
|
assert.strictEqual(stats.totalA, 2);
|
|
assert.strictEqual(stats.totalB, 0);
|
|
assert.strictEqual(stats.aSeesOfB, 0, 'no B packets to see');
|
|
assert.strictEqual(stats.bSeesOfA, 0, 'B saw 0 of A\'s');
|
|
});
|
|
|
|
test('perfect overlap — 100% both ways', () => {
|
|
const s = new Set(['a','b','c']);
|
|
const cmp = sandbox.window.comparePacketSets(s, new Set(s));
|
|
const stats = sandbox.window.computeOverlapStats(cmp);
|
|
assert.strictEqual(stats.aSeesOfB, 100);
|
|
assert.strictEqual(stats.bSeesOfA, 100);
|
|
assert.strictEqual(stats.shared, 3);
|
|
});
|
|
|
|
test('disjoint observers — 0% both ways', () => {
|
|
const cmp = sandbox.window.comparePacketSets(new Set(['a','b']), new Set(['c','d']));
|
|
const stats = sandbox.window.computeOverlapStats(cmp);
|
|
assert.strictEqual(stats.aSeesOfB, 0);
|
|
assert.strictEqual(stats.bSeesOfA, 0);
|
|
assert.strictEqual(stats.shared, 0);
|
|
});
|
|
|
|
console.log(`\n ${passed} passed, ${failed} failed`);
|
|
process.exit(failed > 0 ? 1 : 0);
|