feat: code coverage with c8, npm test runs full suite

npm test: all tests + coverage summary
npm run test:unit: fast unit tests only
npm run test:coverage: full suite + HTML report in coverage/

Baseline: 37% statements, 42% branches, 54% functions
Fixed e2e channels crash (undefined .length on null)
This commit is contained in:
you
2026-03-24 00:51:33 +00:00
parent 75d1ff2f99
commit 7f303ee2d7
5 changed files with 40 additions and 7 deletions
+1
View File
@@ -8,3 +8,4 @@ data-lincomatic/
config-lincomatic.json
theme.json
firmware/
coverage/
+6 -2
View File
@@ -141,12 +141,16 @@ node tools/e2e-test.js # 44 tests — E2E: spins up temp server, inje
node tools/frontend-test.js # 66 tests — frontend smoke: HTML, JS refs, API shapes
```
**ALL existing tests must pass before pushing.** Run at minimum:
**ALL existing tests must pass before pushing.** Run:
```bash
node test-packet-filter.js && node test-aging.js && node test-regional-filter.js && node tools/e2e-test.js && node tools/frontend-test.js
npm test # all tests + coverage summary
npm run test:unit # fast: unit tests only (no server needed)
npm run test:coverage # all tests + HTML coverage report in coverage/
```
If any test fails, fix it before pushing. No exceptions. No "known failures."
**Coverage baseline:** 37% statements, 42% branches, 54% functions. Coverage should only go up.
**Every new feature must add tests.** If you add logic, add tests. If you fix a bug, add a regression test. Test count should only go up, never down.
Tests that hit live data can use `https://analyzer.00id.net` — all API endpoints are public, no auth required.
+4 -2
View File
@@ -4,7 +4,9 @@
"description": "Community-run alternative to the closed-source `analyzer.letsmesh.net`. MQTT packet collection + open-source web analyzer for the Bay Area MeshCore mesh.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "npx c8 --reporter=text --reporter=text-summary sh test-all.sh",
"test:unit": "node test-packet-filter.js && node test-aging.js && node test-regional-filter.js",
"test:coverage": "npx c8 --reporter=text --reporter=html sh test-all.sh"
},
"keywords": [],
"author": "",
@@ -16,4 +18,4 @@
"mqtt": "^5.15.0",
"ws": "^8.19.0"
}
}
}
Executable
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
# Run all tests with coverage
set -e
echo "═══════════════════════════════════════"
echo " MeshCore Analyzer — Test Suite"
echo "═══════════════════════════════════════"
echo ""
# Unit tests (deterministic, fast)
echo "── Unit Tests ──"
node test-packet-filter.js
node test-aging.js
node test-regional-filter.js
# Integration tests (spin up temp servers)
echo ""
echo "── Integration Tests ──"
node tools/e2e-test.js
node tools/frontend-test.js
echo ""
echo "═══════════════════════════════════════"
echo " All tests passed"
echo "═══════════════════════════════════════"
+4 -3
View File
@@ -370,9 +370,10 @@ async function main() {
// 5e. Channels
console.log('── Channels ──');
const chResp = (await get('/api/channels')).data;
assert(Array.isArray(chResp.channels), 'channels response is array');
if (chResp.channels.length > 0) {
const someCh = chResp.channels[0];
const chList = chResp.channels || [];
assert(Array.isArray(chList), 'channels response is array');
if (chList.length > 0) {
const someCh = chList[0];
assert(someCh.messageCount > 0, `channel has messages (${someCh.messageCount})`);
const msgResp = (await get(`/api/channels/${someCh.hash}/messages`)).data;
assert(msgResp.messages.length > 0, 'channel has message list');