Files
bitvid/test-audit/run-static-analysis.mjs
T
google-labs-jules[bot]andPR0M3TH3AN 82dc581145 docs: add daily test audit report and artifacts
- Run unit tests with coverage (c8)
- Generate test audit report (test-audit-report-2026-02-15.md)
- Add static analysis of suspicious tests
- Add flakiness check script and results (timed out)
- Create daily completion log

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-15 22:24:28 +00:00

90 lines
2.5 KiB
JavaScript

import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
const rootDir = process.cwd();
const testsDir = path.join(rootDir, "tests");
const resultsFile = path.join(rootDir, "test-audit/suspicious-tests.json");
const checks = {
zeroAssertions: {
regex: /(expect\(|assert\.|t\.is|chai\.expect|should\.)/,
message: "No obvious assertions found",
inverted: true // fails if NOT found
},
focusedOrSkipped: {
regex: /\.(only|skip)\(/,
message: "Test is focused (.only) or skipped (.skip)"
},
sleeps: {
regex: /(setTimeout\(|sleep\(|await delay\(|new Promise\(r => setTimeout)/,
message: "Uses setTimeout/sleep (brittle)"
},
network: {
regex: /(fetch\(|axios\.|new WebSocket|WebSocket\()/,
message: "Direct network usage found"
},
mocking: {
regex: /(jest\.mock|sinon\.stub|proxyquire|rewire|vi\.mock|vi\.spy)/,
message: "Heavy mocking detected"
},
console: {
regex: /console\.(log|warn|error)/,
message: "Console usage inside test"
}
};
async function collectTests(dir, testFiles = []) {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.name.startsWith(".")) continue;
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
if (entry.name === "visual") continue; // Skip visual tests if needed?
await collectTests(fullPath, testFiles);
continue;
}
if (entry.isFile() && (entry.name.endsWith(".test.mjs") || entry.name.endsWith(".test.js"))) {
testFiles.push(fullPath);
}
}
return testFiles;
}
async function analyzeFile(filepath) {
const content = await fs.readFile(filepath, "utf8");
const issues = [];
for (const [key, check] of Object.entries(checks)) {
const match = check.regex.test(content);
if (check.inverted) {
if (!match) issues.push(check.message);
} else {
if (match) issues.push(check.message);
}
}
return issues;
}
async function run() {
const testFiles = await collectTests(testsDir);
const suspiciousTests = {};
for (const file of testFiles) {
const issues = await analyzeFile(file);
if (issues.length > 0) {
const relativePath = path.relative(rootDir, file);
suspiciousTests[relativePath] = issues;
}
}
await fs.writeFile(resultsFile, JSON.stringify(suspiciousTests, null, 2));
console.log(`Static analysis complete. Found issues in ${Object.keys(suspiciousTests).length} files.`);
}
run().catch(console.error);