Add frontend code coverage via Istanbul instrumentation + Playwright

- Install nyc for Istanbul instrumentation
- Add scripts/instrument-frontend.sh to instrument public/*.js
- Add scripts/collect-frontend-coverage.js to extract window.__coverage__
- Add scripts/combined-coverage.sh for combined server+frontend coverage
- Make server.js serve public-instrumented/ when COVERAGE=1 is set
- Add test:full-coverage npm script
- Add public-instrumented/ and .nyc_output/ to .gitignore
This commit is contained in:
you
2026-03-24 03:11:13 +00:00
parent 2040b36a63
commit d7faa4d978
7 changed files with 1783 additions and 2 deletions

View File

@@ -0,0 +1,46 @@
// After Playwright tests, this script:
// 1. Connects to the running test server
// 2. Extracts window.__coverage__ from the browser
// 3. Writes it to .nyc_output/ for merging
const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');
async function collectCoverage() {
const browser = await chromium.launch({
executablePath: process.env.CHROMIUM_PATH || '/usr/bin/chromium',
args: ['--no-sandbox'],
headless: true
});
const page = await browser.newPage();
const BASE = process.env.BASE_URL || 'http://localhost:13581';
// Visit every major page to exercise the code
const pages = ['#/home', '#/nodes', '#/map', '#/packets', '#/channels', '#/analytics', '#/live', '#/traces', '#/observers'];
for (const hash of pages) {
await page.goto(`${BASE}/${hash}`, { waitUntil: 'networkidle', timeout: 15000 }).catch(() => {});
await page.waitForTimeout(2000);
}
// Exercise some interactions
try {
await page.click('#customizeToggle');
await page.waitForTimeout(1000);
} catch {}
// Extract coverage
const coverage = await page.evaluate(() => window.__coverage__);
await browser.close();
if (coverage) {
const outDir = path.join(__dirname, '..', '.nyc_output');
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
fs.writeFileSync(path.join(outDir, 'frontend-coverage.json'), JSON.stringify(coverage));
console.log('Frontend coverage collected: ' + Object.keys(coverage).length + ' files');
} else {
console.log('WARNING: No __coverage__ object found — instrumentation may have failed');
}
}
collectCoverage().catch(e => { console.error(e); process.exit(1); });

View File

@@ -0,0 +1,26 @@
#!/bin/sh
# Run server-side tests with c8, then frontend coverage with nyc
set -e
# 1. Server-side coverage (existing)
npx c8 --reporter=json --reports-dir=.nyc_output node tools/e2e-test.js
# 2. Instrument frontend
sh scripts/instrument-frontend.sh
# 3. Start instrumented server
COVERAGE=1 PORT=13581 node server.js &
SERVER_PID=$!
sleep 5
# 4. Run Playwright tests (exercises frontend code)
BASE_URL=http://localhost:13581 node test-e2e-playwright.js || true
# 5. Collect browser coverage
BASE_URL=http://localhost:13581 node scripts/collect-frontend-coverage.js
# 6. Kill server
kill $SERVER_PID 2>/dev/null || true
# 7. Generate combined report
npx nyc report --reporter=text-summary --reporter=text

View File

@@ -0,0 +1,10 @@
#!/bin/sh
# Instrument frontend JS for coverage tracking
rm -rf public-instrumented
npx nyc instrument public/ public-instrumented/ --compact=false
# Copy non-JS files (CSS, HTML, images) as-is
cp public/*.css public-instrumented/ 2>/dev/null
cp public/*.html public-instrumented/ 2>/dev/null
cp public/*.svg public-instrumented/ 2>/dev/null
cp public/*.png public-instrumented/ 2>/dev/null
echo "Frontend instrumented successfully"