@mohantn/gate-keeper 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/instructions/dotnet-api-integration.instructions.md +416 -0
- package/.github/instructions/dotnet-development.instructions.md +353 -0
- package/.github/instructions/dotnet-testing.instructions.md +406 -0
- package/.github/instructions/gate-keeper.instructions.md +91 -0
- package/.github/instructions/react-development.instructions.md +315 -0
- package/.github/instructions/react-testing-optimization.instructions.md +373 -0
- package/.github/instructions/uiux.instructions.md +261 -0
- package/LICENSE +21 -0
- package/README.md +181 -0
- package/dist/analyzer/coverage-analyzer.d.ts +126 -0
- package/dist/analyzer/coverage-analyzer.d.ts.map +1 -0
- package/dist/analyzer/coverage-analyzer.js +633 -0
- package/dist/analyzer/coverage-analyzer.js.map +1 -0
- package/dist/analyzer/csharp-analyzer.d.ts +28 -0
- package/dist/analyzer/csharp-analyzer.d.ts.map +1 -0
- package/dist/analyzer/csharp-analyzer.js +437 -0
- package/dist/analyzer/csharp-analyzer.js.map +1 -0
- package/dist/analyzer/pattern-detector.d.ts +5 -0
- package/dist/analyzer/pattern-detector.d.ts.map +1 -0
- package/dist/analyzer/pattern-detector.js +74 -0
- package/dist/analyzer/pattern-detector.js.map +1 -0
- package/dist/analyzer/refactoring-advisor.d.ts +7 -0
- package/dist/analyzer/refactoring-advisor.d.ts.map +1 -0
- package/dist/analyzer/refactoring-advisor.js +280 -0
- package/dist/analyzer/refactoring-advisor.js.map +1 -0
- package/dist/analyzer/sonar-eslint-runner.d.ts +3 -0
- package/dist/analyzer/sonar-eslint-runner.d.ts.map +1 -0
- package/dist/analyzer/sonar-eslint-runner.js +136 -0
- package/dist/analyzer/sonar-eslint-runner.js.map +1 -0
- package/dist/analyzer/sonar-rule-map.d.ts +19 -0
- package/dist/analyzer/sonar-rule-map.d.ts.map +1 -0
- package/dist/analyzer/sonar-rule-map.js +67 -0
- package/dist/analyzer/sonar-rule-map.js.map +1 -0
- package/dist/analyzer/string-analyzer.d.ts +27 -0
- package/dist/analyzer/string-analyzer.d.ts.map +1 -0
- package/dist/analyzer/string-analyzer.js +274 -0
- package/dist/analyzer/string-analyzer.js.map +1 -0
- package/dist/analyzer/typescript-analyzer.d.ts +27 -0
- package/dist/analyzer/typescript-analyzer.d.ts.map +1 -0
- package/dist/analyzer/typescript-analyzer.js +437 -0
- package/dist/analyzer/typescript-analyzer.js.map +1 -0
- package/dist/analyzer/universal-analyzer.d.ts +10 -0
- package/dist/analyzer/universal-analyzer.d.ts.map +1 -0
- package/dist/analyzer/universal-analyzer.js +155 -0
- package/dist/analyzer/universal-analyzer.js.map +1 -0
- package/dist/cache/quality-cache.d.ts +119 -0
- package/dist/cache/quality-cache.d.ts.map +1 -0
- package/dist/cache/quality-cache.js +130 -0
- package/dist/cache/quality-cache.js.map +1 -0
- package/dist/cache/sqlite-cache.d.ts +43 -0
- package/dist/cache/sqlite-cache.d.ts.map +1 -0
- package/dist/cache/sqlite-cache.js +346 -0
- package/dist/cache/sqlite-cache.js.map +1 -0
- package/dist/cli/query-repl.d.ts +37 -0
- package/dist/cli/query-repl.d.ts.map +1 -0
- package/dist/cli/query-repl.js +298 -0
- package/dist/cli/query-repl.js.map +1 -0
- package/dist/cli/repl-algorithms.d.ts +49 -0
- package/dist/cli/repl-algorithms.d.ts.map +1 -0
- package/dist/cli/repl-algorithms.js +147 -0
- package/dist/cli/repl-algorithms.js.map +1 -0
- package/dist/cli/setup-core.d.ts +38 -0
- package/dist/cli/setup-core.d.ts.map +1 -0
- package/dist/cli/setup-core.js +427 -0
- package/dist/cli/setup-core.js.map +1 -0
- package/dist/cli/setup.d.ts +25 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +159 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli-entry.d.ts +19 -0
- package/dist/cli-entry.d.ts.map +1 -0
- package/dist/cli-entry.js +178 -0
- package/dist/cli-entry.js.map +1 -0
- package/dist/daemon/watch-mode.d.ts +41 -0
- package/dist/daemon/watch-mode.d.ts.map +1 -0
- package/dist/daemon/watch-mode.js +163 -0
- package/dist/daemon/watch-mode.js.map +1 -0
- package/dist/daemon.d.ts +24 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +357 -0
- package/dist/daemon.js.map +1 -0
- package/dist/github/app.d.ts +34 -0
- package/dist/github/app.d.ts.map +1 -0
- package/dist/github/app.js +261 -0
- package/dist/github/app.js.map +1 -0
- package/dist/github/commenter.d.ts +67 -0
- package/dist/github/commenter.d.ts.map +1 -0
- package/dist/github/commenter.js +155 -0
- package/dist/github/commenter.js.map +1 -0
- package/dist/graph/dependency-graph.d.ts +28 -0
- package/dist/graph/dependency-graph.d.ts.map +1 -0
- package/dist/graph/dependency-graph.js +198 -0
- package/dist/graph/dependency-graph.js.map +1 -0
- package/dist/graph/global-graph.d.ts +65 -0
- package/dist/graph/global-graph.d.ts.map +1 -0
- package/dist/graph/global-graph.js +153 -0
- package/dist/graph/global-graph.js.map +1 -0
- package/dist/graph/graph-algorithms.d.ts +90 -0
- package/dist/graph/graph-algorithms.d.ts.map +1 -0
- package/dist/graph/graph-algorithms.js +180 -0
- package/dist/graph/graph-algorithms.js.map +1 -0
- package/dist/graph/graph-export.d.ts +68 -0
- package/dist/graph/graph-export.d.ts.map +1 -0
- package/dist/graph/graph-export.js +264 -0
- package/dist/graph/graph-export.js.map +1 -0
- package/dist/graph/graph-report.d.ts +34 -0
- package/dist/graph/graph-report.d.ts.map +1 -0
- package/dist/graph/graph-report.js +136 -0
- package/dist/graph/graph-report.js.map +1 -0
- package/dist/graph/graph-summary.d.ts +68 -0
- package/dist/graph/graph-summary.d.ts.map +1 -0
- package/dist/graph/graph-summary.js +213 -0
- package/dist/graph/graph-summary.js.map +1 -0
- package/dist/graph/graphify-ignore.d.ts +32 -0
- package/dist/graph/graphify-ignore.d.ts.map +1 -0
- package/dist/graph/graphify-ignore.js +124 -0
- package/dist/graph/graphify-ignore.js.map +1 -0
- package/dist/graph/question-suggester.d.ts +30 -0
- package/dist/graph/question-suggester.d.ts.map +1 -0
- package/dist/graph/question-suggester.js +113 -0
- package/dist/graph/question-suggester.js.map +1 -0
- package/dist/graph/relationship-extractor.d.ts +40 -0
- package/dist/graph/relationship-extractor.d.ts.map +1 -0
- package/dist/graph/relationship-extractor.js +254 -0
- package/dist/graph/relationship-extractor.js.map +1 -0
- package/dist/graph/relationship-types.d.ts +24 -0
- package/dist/graph/relationship-types.d.ts.map +1 -0
- package/dist/graph/relationship-types.js +21 -0
- package/dist/graph/relationship-types.js.map +1 -0
- package/dist/graph/surprising-connections.d.ts +39 -0
- package/dist/graph/surprising-connections.d.ts.map +1 -0
- package/dist/graph/surprising-connections.js +127 -0
- package/dist/graph/surprising-connections.js.map +1 -0
- package/dist/hook-pre-tool-use.d.ts +14 -0
- package/dist/hook-pre-tool-use.d.ts.map +1 -0
- package/dist/hook-pre-tool-use.js +167 -0
- package/dist/hook-pre-tool-use.js.map +1 -0
- package/dist/hook-receiver.d.ts +29 -0
- package/dist/hook-receiver.d.ts.map +1 -0
- package/dist/hook-receiver.js +327 -0
- package/dist/hook-receiver.js.map +1 -0
- package/dist/hooks/git-hooks.d.ts +30 -0
- package/dist/hooks/git-hooks.d.ts.map +1 -0
- package/dist/hooks/git-hooks.js +179 -0
- package/dist/hooks/git-hooks.js.map +1 -0
- package/dist/mcp/cache-preload.d.ts +29 -0
- package/dist/mcp/cache-preload.d.ts.map +1 -0
- package/dist/mcp/cache-preload.js +103 -0
- package/dist/mcp/cache-preload.js.map +1 -0
- package/dist/mcp/handlers/analysis.d.ts +4 -0
- package/dist/mcp/handlers/analysis.d.ts.map +1 -0
- package/dist/mcp/handlers/analysis.js +196 -0
- package/dist/mcp/handlers/analysis.js.map +1 -0
- package/dist/mcp/handlers/context.d.ts +25 -0
- package/dist/mcp/handlers/context.d.ts.map +1 -0
- package/dist/mcp/handlers/context.js +382 -0
- package/dist/mcp/handlers/context.js.map +1 -0
- package/dist/mcp/handlers/graph-intelligence.d.ts +26 -0
- package/dist/mcp/handlers/graph-intelligence.d.ts.map +1 -0
- package/dist/mcp/handlers/graph-intelligence.js +371 -0
- package/dist/mcp/handlers/graph-intelligence.js.map +1 -0
- package/dist/mcp/handlers/graph-query.d.ts +25 -0
- package/dist/mcp/handlers/graph-query.d.ts.map +1 -0
- package/dist/mcp/handlers/graph-query.js +410 -0
- package/dist/mcp/handlers/graph-query.js.map +1 -0
- package/dist/mcp/handlers/graph.d.ts +5 -0
- package/dist/mcp/handlers/graph.d.ts.map +1 -0
- package/dist/mcp/handlers/graph.js +283 -0
- package/dist/mcp/handlers/graph.js.map +1 -0
- package/dist/mcp/handlers/impact-format.d.ts +9 -0
- package/dist/mcp/handlers/impact-format.d.ts.map +1 -0
- package/dist/mcp/handlers/impact-format.js +189 -0
- package/dist/mcp/handlers/impact-format.js.map +1 -0
- package/dist/mcp/handlers/impact.d.ts +4 -0
- package/dist/mcp/handlers/impact.d.ts.map +1 -0
- package/dist/mcp/handlers/impact.js +139 -0
- package/dist/mcp/handlers/impact.js.map +1 -0
- package/dist/mcp/handlers/improvement.d.ts +4 -0
- package/dist/mcp/handlers/improvement.d.ts.map +1 -0
- package/dist/mcp/handlers/improvement.js +136 -0
- package/dist/mcp/handlers/improvement.js.map +1 -0
- package/dist/mcp/handlers/index.d.ts +14 -0
- package/dist/mcp/handlers/index.d.ts.map +1 -0
- package/dist/mcp/handlers/index.js +36 -0
- package/dist/mcp/handlers/index.js.map +1 -0
- package/dist/mcp/handlers/platform-installer.d.ts +10 -0
- package/dist/mcp/handlers/platform-installer.d.ts.map +1 -0
- package/dist/mcp/handlers/platform-installer.js +168 -0
- package/dist/mcp/handlers/platform-installer.js.map +1 -0
- package/dist/mcp/handlers/pr-review.d.ts +33 -0
- package/dist/mcp/handlers/pr-review.d.ts.map +1 -0
- package/dist/mcp/handlers/pr-review.js +170 -0
- package/dist/mcp/handlers/pr-review.js.map +1 -0
- package/dist/mcp/handlers/shared.d.ts +20 -0
- package/dist/mcp/handlers/shared.d.ts.map +1 -0
- package/dist/mcp/handlers/shared.js +27 -0
- package/dist/mcp/handlers/shared.js.map +1 -0
- package/dist/mcp/handlers/types.d.ts +46 -0
- package/dist/mcp/handlers/types.d.ts.map +1 -0
- package/dist/mcp/handlers/types.js +3 -0
- package/dist/mcp/handlers/types.js.map +1 -0
- package/dist/mcp/helpers.d.ts +36 -0
- package/dist/mcp/helpers.d.ts.map +1 -0
- package/dist/mcp/helpers.js +199 -0
- package/dist/mcp/helpers.js.map +1 -0
- package/dist/mcp/installer.d.ts +22 -0
- package/dist/mcp/installer.d.ts.map +1 -0
- package/dist/mcp/installer.js +341 -0
- package/dist/mcp/installer.js.map +1 -0
- package/dist/mcp/server.d.ts +111 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +216 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/token-tracker.d.ts +47 -0
- package/dist/mcp/token-tracker.d.ts.map +1 -0
- package/dist/mcp/token-tracker.js +93 -0
- package/dist/mcp/token-tracker.js.map +1 -0
- package/dist/quality-loop/file-lock.d.ts +12 -0
- package/dist/quality-loop/file-lock.d.ts.map +1 -0
- package/dist/quality-loop/file-lock.js +38 -0
- package/dist/quality-loop/file-lock.js.map +1 -0
- package/dist/quality-loop/fix-worker.d.ts +44 -0
- package/dist/quality-loop/fix-worker.d.ts.map +1 -0
- package/dist/quality-loop/fix-worker.js +414 -0
- package/dist/quality-loop/fix-worker.js.map +1 -0
- package/dist/quality-loop/orchestrator.d.ts +137 -0
- package/dist/quality-loop/orchestrator.d.ts.map +1 -0
- package/dist/quality-loop/orchestrator.js +894 -0
- package/dist/quality-loop/orchestrator.js.map +1 -0
- package/dist/quality-loop/queue-manager.d.ts +45 -0
- package/dist/quality-loop/queue-manager.d.ts.map +1 -0
- package/dist/quality-loop/queue-manager.js +173 -0
- package/dist/quality-loop/queue-manager.js.map +1 -0
- package/dist/rating/rating-calculator.d.ts +15 -0
- package/dist/rating/rating-calculator.d.ts.map +1 -0
- package/dist/rating/rating-calculator.js +136 -0
- package/dist/rating/rating-calculator.js.map +1 -0
- package/dist/types/agent.d.ts +49 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +7 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types.d.ts +156 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/util/fix-text.d.ts +7 -0
- package/dist/util/fix-text.d.ts.map +1 -0
- package/dist/util/fix-text.js +13 -0
- package/dist/util/fix-text.js.map +1 -0
- package/dist/viz/graph-viz.d.ts +40 -0
- package/dist/viz/graph-viz.d.ts.map +1 -0
- package/dist/viz/graph-viz.js +332 -0
- package/dist/viz/graph-viz.js.map +1 -0
- package/dist/viz/viz-helpers.d.ts +13 -0
- package/dist/viz/viz-helpers.d.ts.map +1 -0
- package/dist/viz/viz-helpers.js +134 -0
- package/dist/viz/viz-helpers.js.map +1 -0
- package/dist/viz/viz-routes.d.ts +28 -0
- package/dist/viz/viz-routes.d.ts.map +1 -0
- package/dist/viz/viz-routes.js +333 -0
- package/dist/viz/viz-routes.js.map +1 -0
- package/dist/viz/viz-scanner.d.ts +20 -0
- package/dist/viz/viz-scanner.d.ts.map +1 -0
- package/dist/viz/viz-scanner.js +241 -0
- package/dist/viz/viz-scanner.js.map +1 -0
- package/dist/viz/viz-server.d.ts +38 -0
- package/dist/viz/viz-server.d.ts.map +1 -0
- package/dist/viz/viz-server.js +240 -0
- package/dist/viz/viz-server.js.map +1 -0
- package/package.json +89 -0
- package/scripts/postinstall.js +28 -0
- package/scripts/setup.sh +113 -0
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CoverageAnalyzer = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
const util_1 = require("util");
|
|
41
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
42
|
+
class CoverageAnalyzer {
|
|
43
|
+
/** Per-project cache entry tracking both parsed data and file modification time. */
|
|
44
|
+
coverageCache = new Map();
|
|
45
|
+
/** Max time (ms) to wait for a test runner to produce coverage. */
|
|
46
|
+
static RUNNER_TIMEOUT_MS = 30_000;
|
|
47
|
+
/**
|
|
48
|
+
* Check coverage for a given source file.
|
|
49
|
+
* 1. Uses existing LCOV data when available.
|
|
50
|
+
* 2. If no LCOV exists but a test file is found, runs that test with
|
|
51
|
+
* coverage to generate LCOV on the fly for the file.
|
|
52
|
+
* 3. Falls back to a "no test file" warning when nothing is found.
|
|
53
|
+
*/
|
|
54
|
+
async checkCoverage(filePath) {
|
|
55
|
+
if (this.isTestFile(filePath))
|
|
56
|
+
return null;
|
|
57
|
+
if (this.isConfigFile(filePath))
|
|
58
|
+
return null;
|
|
59
|
+
if (this.isExcludedFromCoverage(filePath))
|
|
60
|
+
return null;
|
|
61
|
+
const projectRoot = this.findProjectRoot(filePath);
|
|
62
|
+
if (!projectRoot)
|
|
63
|
+
return null;
|
|
64
|
+
// 1. Try pre-existing LCOV
|
|
65
|
+
const coverageMap = this.loadCoverageData(projectRoot);
|
|
66
|
+
if (coverageMap) {
|
|
67
|
+
const normalizedPath = path.resolve(filePath);
|
|
68
|
+
const fileCoverage = this.findFileCoverage(coverageMap, normalizedPath);
|
|
69
|
+
if (!fileCoverage) {
|
|
70
|
+
return {
|
|
71
|
+
coveragePercent: 0,
|
|
72
|
+
uncoveredLines: [],
|
|
73
|
+
violations: [
|
|
74
|
+
{
|
|
75
|
+
type: 'no_test_coverage',
|
|
76
|
+
severity: 'warning',
|
|
77
|
+
message: 'File has no unit test coverage — add tests for this file',
|
|
78
|
+
fix: 'Create a corresponding .test.ts or .spec.ts file with unit tests',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return this.buildCoverageResult(fileCoverage);
|
|
84
|
+
}
|
|
85
|
+
// 2. No LCOV — check if a test file exists
|
|
86
|
+
const testFile = this.findTestFile(filePath, projectRoot);
|
|
87
|
+
if (!testFile) {
|
|
88
|
+
return {
|
|
89
|
+
coveragePercent: undefined,
|
|
90
|
+
uncoveredLines: [],
|
|
91
|
+
violations: [
|
|
92
|
+
{
|
|
93
|
+
type: 'no_test_file',
|
|
94
|
+
severity: 'warning',
|
|
95
|
+
message: 'No corresponding test file found — add tests for this file',
|
|
96
|
+
fix: `Create a test file (e.g. ${this.suggestTestFileName(filePath)})`,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// 3. Test file found — verify it contains real tests before running coverage
|
|
102
|
+
if (!this.hasRealTestContent(testFile)) {
|
|
103
|
+
return {
|
|
104
|
+
coveragePercent: undefined,
|
|
105
|
+
uncoveredLines: [],
|
|
106
|
+
violations: [
|
|
107
|
+
{
|
|
108
|
+
type: 'hollow_test_file',
|
|
109
|
+
severity: 'error',
|
|
110
|
+
message: `Test file exists but contains no real test cases — ${path.basename(testFile)} is an empty shell`,
|
|
111
|
+
fix: 'Add at least one it() / test() / describe() block with assertions',
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// 4. Real test file found — run coverage for this file on the fly
|
|
117
|
+
return this.runCoverageForFile(filePath, testFile, projectRoot);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Build a CoverageResult from parsed LCOV file coverage data.
|
|
121
|
+
*/
|
|
122
|
+
buildCoverageResult(fileCoverage) {
|
|
123
|
+
const violations = [];
|
|
124
|
+
const uncoveredLines = [...fileCoverage.lines.entries()]
|
|
125
|
+
.filter(([, count]) => count === 0)
|
|
126
|
+
.map(([line]) => line)
|
|
127
|
+
.sort((a, b) => a - b);
|
|
128
|
+
const pct = fileCoverage.coveragePercent;
|
|
129
|
+
if (pct < 50) {
|
|
130
|
+
violations.push({
|
|
131
|
+
type: 'low_test_coverage',
|
|
132
|
+
severity: 'warning',
|
|
133
|
+
message: `Test coverage is ${pct.toFixed(1)}% — aim for at least 80%`,
|
|
134
|
+
fix: 'Add unit tests covering the uncovered lines/branches',
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
else if (pct < 80) {
|
|
138
|
+
violations.push({
|
|
139
|
+
type: 'moderate_test_coverage',
|
|
140
|
+
severity: 'info',
|
|
141
|
+
message: `Test coverage is ${pct.toFixed(1)}% — consider improving to 80%+`,
|
|
142
|
+
fix: 'Add tests for uncovered edge cases and error paths',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (uncoveredLines.length > 0) {
|
|
146
|
+
const ranges = this.compactLineRanges(uncoveredLines);
|
|
147
|
+
violations.push({
|
|
148
|
+
type: 'uncovered_lines',
|
|
149
|
+
severity: 'info',
|
|
150
|
+
message: `${uncoveredLines.length} lines not covered by tests: ${ranges}`,
|
|
151
|
+
fix: 'Write tests that exercise these code paths',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return { coveragePercent: pct, uncoveredLines, violations };
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Detect which test runner is available in the project.
|
|
158
|
+
* Returns the runner name or null.
|
|
159
|
+
*/
|
|
160
|
+
detectTestRunner(projectRoot) {
|
|
161
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
162
|
+
if (!fs.existsSync(pkgPath))
|
|
163
|
+
return null;
|
|
164
|
+
try {
|
|
165
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
166
|
+
const allDeps = {
|
|
167
|
+
...pkg.dependencies,
|
|
168
|
+
...pkg.devDependencies,
|
|
169
|
+
};
|
|
170
|
+
if (allDeps['vitest'])
|
|
171
|
+
return 'vitest';
|
|
172
|
+
if (allDeps['jest'] || allDeps['ts-jest'])
|
|
173
|
+
return 'jest';
|
|
174
|
+
if (allDeps['nyc'] || allDeps['c8'])
|
|
175
|
+
return 'nyc';
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// Ignore parse errors
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Run the test file with coverage enabled and parse the resulting LCOV
|
|
184
|
+
* to get per-line coverage for the source file.
|
|
185
|
+
*/
|
|
186
|
+
async runCoverageForFile(sourceFile, testFile, projectRoot) {
|
|
187
|
+
const runner = this.detectTestRunner(projectRoot);
|
|
188
|
+
if (!runner)
|
|
189
|
+
return null;
|
|
190
|
+
const resolvedSource = path.resolve(sourceFile);
|
|
191
|
+
const relativeSource = path.relative(projectRoot, resolvedSource);
|
|
192
|
+
const npxBin = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
193
|
+
const tmpDir = path.join(projectRoot, '.gate-keeper-cov');
|
|
194
|
+
const args = this.buildRunnerArgs(runner, testFile, relativeSource, tmpDir);
|
|
195
|
+
if (!args)
|
|
196
|
+
return null;
|
|
197
|
+
try {
|
|
198
|
+
await execFileAsync(npxBin, args, {
|
|
199
|
+
cwd: projectRoot,
|
|
200
|
+
timeout: CoverageAnalyzer.RUNNER_TIMEOUT_MS,
|
|
201
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
202
|
+
env: { ...process.env, NODE_ENV: 'test' },
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// Test failures and timeouts are okay — coverage may still have been generated
|
|
207
|
+
}
|
|
208
|
+
const lcovPath = path.join(tmpDir, 'lcov.info');
|
|
209
|
+
if (!fs.existsSync(lcovPath))
|
|
210
|
+
return null;
|
|
211
|
+
try {
|
|
212
|
+
const lcov = fs.readFileSync(lcovPath, 'utf8');
|
|
213
|
+
const coverageMap = this.parseLcov(lcov, projectRoot);
|
|
214
|
+
const fileCoverage = this.findFileCoverage(coverageMap, resolvedSource);
|
|
215
|
+
// Clean up temp coverage dir
|
|
216
|
+
this.removeDirSync(tmpDir);
|
|
217
|
+
if (!fileCoverage) {
|
|
218
|
+
return {
|
|
219
|
+
coveragePercent: 0,
|
|
220
|
+
uncoveredLines: [],
|
|
221
|
+
violations: [{
|
|
222
|
+
type: 'no_test_coverage',
|
|
223
|
+
severity: 'warning',
|
|
224
|
+
message: 'Test file exists but does not cover this file — update tests',
|
|
225
|
+
fix: 'Ensure the test file imports and exercises the source file',
|
|
226
|
+
}],
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
return this.buildCoverageResult(fileCoverage);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
this.removeDirSync(tmpDir);
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Build CLI arguments for the test runner.
|
|
238
|
+
*/
|
|
239
|
+
buildRunnerArgs(runner, testFile, relativeSource, coverageDir) {
|
|
240
|
+
switch (runner) {
|
|
241
|
+
case 'jest':
|
|
242
|
+
return [
|
|
243
|
+
'jest', '--no-cache', '--coverage',
|
|
244
|
+
'--coverageReporters', 'lcovonly',
|
|
245
|
+
'--coverageDirectory', coverageDir,
|
|
246
|
+
'--collectCoverageFrom', relativeSource,
|
|
247
|
+
'--', testFile,
|
|
248
|
+
];
|
|
249
|
+
case 'vitest':
|
|
250
|
+
return [
|
|
251
|
+
'vitest', 'run', '--coverage',
|
|
252
|
+
'--coverage.reporter', 'lcov',
|
|
253
|
+
'--coverage.reportsDirectory', coverageDir,
|
|
254
|
+
'--coverage.include', relativeSource,
|
|
255
|
+
testFile,
|
|
256
|
+
];
|
|
257
|
+
case 'nyc':
|
|
258
|
+
return null; // nyc wraps other runners — too variable to auto-invoke
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Recursively remove a directory (sync). Safe for temp cleanup.
|
|
263
|
+
*/
|
|
264
|
+
removeDirSync(dirPath) {
|
|
265
|
+
try {
|
|
266
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
// Best-effort cleanup
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Find the project root by searching upward for package.json or .csproj.
|
|
274
|
+
*/
|
|
275
|
+
findProjectRoot(filePath) {
|
|
276
|
+
let dir = path.dirname(path.resolve(filePath));
|
|
277
|
+
const root = path.parse(dir).root;
|
|
278
|
+
while (dir !== root) {
|
|
279
|
+
if (fs.existsSync(path.join(dir, 'package.json')) ||
|
|
280
|
+
fs.readdirSync(dir).some(f => f.endsWith('.csproj') || f.endsWith('.sln'))) {
|
|
281
|
+
return dir;
|
|
282
|
+
}
|
|
283
|
+
dir = path.dirname(dir);
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Load and cache coverage data for a project root.
|
|
289
|
+
* Searches for LCOV files in common locations.
|
|
290
|
+
*/
|
|
291
|
+
loadCoverageData(projectRoot) {
|
|
292
|
+
const cached = this.coverageCache.get(projectRoot);
|
|
293
|
+
if (cached) {
|
|
294
|
+
try {
|
|
295
|
+
const stat = fs.statSync(cached.lcovPath);
|
|
296
|
+
if (stat.mtimeMs === cached.mtimeMs) {
|
|
297
|
+
return cached.data;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
// stat failed (ENOENT, EACCES, etc.) — fall through to re-search
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const lcovPath = this.findLcovFile(projectRoot);
|
|
305
|
+
if (!lcovPath) {
|
|
306
|
+
this.coverageCache.delete(projectRoot);
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
try {
|
|
310
|
+
const content = fs.readFileSync(lcovPath, 'utf8');
|
|
311
|
+
const coverageMap = this.parseLcov(content, projectRoot);
|
|
312
|
+
const stat = fs.statSync(lcovPath);
|
|
313
|
+
this.coverageCache.set(projectRoot, { lcovPath, mtimeMs: stat.mtimeMs, data: coverageMap });
|
|
314
|
+
return coverageMap;
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Search common locations for an LCOV coverage report.
|
|
322
|
+
*/
|
|
323
|
+
findLcovFile(projectRoot) {
|
|
324
|
+
const candidates = [
|
|
325
|
+
path.join(projectRoot, 'coverage', 'lcov.info'),
|
|
326
|
+
path.join(projectRoot, 'coverage', 'lcov-report', 'lcov.info'),
|
|
327
|
+
path.join(projectRoot, 'lcov.info'),
|
|
328
|
+
path.join(projectRoot, '.coverage', 'lcov.info'),
|
|
329
|
+
];
|
|
330
|
+
for (const candidate of candidates) {
|
|
331
|
+
if (fs.existsSync(candidate))
|
|
332
|
+
return candidate;
|
|
333
|
+
}
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Parse LCOV format into a map of file path → coverage data.
|
|
338
|
+
*
|
|
339
|
+
* LCOV records look like:
|
|
340
|
+
* SF:/path/to/file.ts
|
|
341
|
+
* DA:1,5
|
|
342
|
+
* DA:2,0
|
|
343
|
+
* LF:10
|
|
344
|
+
* LH:8
|
|
345
|
+
* end_of_record
|
|
346
|
+
*/
|
|
347
|
+
parseLcov(content, projectRoot) {
|
|
348
|
+
const coverageMap = new Map();
|
|
349
|
+
const records = content.split('end_of_record');
|
|
350
|
+
for (const record of records) {
|
|
351
|
+
const trimmed = record.trim();
|
|
352
|
+
if (!trimmed)
|
|
353
|
+
continue;
|
|
354
|
+
const sfMatch = trimmed.match(/^SF:(.+)$/m);
|
|
355
|
+
if (!sfMatch)
|
|
356
|
+
continue;
|
|
357
|
+
const rawPath = sfMatch[1].trim();
|
|
358
|
+
// Jest/Istanbul emit project-relative SF paths; resolve against projectRoot
|
|
359
|
+
// so they match the absolute paths used elsewhere in the analyzer.
|
|
360
|
+
const filePath = path.isAbsolute(rawPath)
|
|
361
|
+
? rawPath
|
|
362
|
+
: path.resolve(projectRoot ?? process.cwd(), rawPath);
|
|
363
|
+
const lines = new Map();
|
|
364
|
+
let linesFound = 0;
|
|
365
|
+
let linesHit = 0;
|
|
366
|
+
for (const line of trimmed.split('\n')) {
|
|
367
|
+
const daMatch = line.match(/^DA:(\d+),(\d+)/);
|
|
368
|
+
if (daMatch) {
|
|
369
|
+
const lineNum = parseInt(daMatch[1], 10);
|
|
370
|
+
const count = parseInt(daMatch[2], 10);
|
|
371
|
+
lines.set(lineNum, count);
|
|
372
|
+
}
|
|
373
|
+
const lfMatch = line.match(/^LF:(\d+)/);
|
|
374
|
+
if (lfMatch)
|
|
375
|
+
linesFound = parseInt(lfMatch[1], 10);
|
|
376
|
+
const lhMatch = line.match(/^LH:(\d+)/);
|
|
377
|
+
if (lhMatch)
|
|
378
|
+
linesHit = parseInt(lhMatch[1], 10);
|
|
379
|
+
}
|
|
380
|
+
// If LF/LH weren't in the record, compute from DA entries
|
|
381
|
+
if (linesFound === 0 && lines.size > 0) {
|
|
382
|
+
linesFound = lines.size;
|
|
383
|
+
linesHit = [...lines.values()].filter(c => c > 0).length;
|
|
384
|
+
}
|
|
385
|
+
const coveragePercent = linesFound > 0
|
|
386
|
+
? Math.round((linesHit / linesFound) * 1000) / 10
|
|
387
|
+
: 100;
|
|
388
|
+
coverageMap.set(filePath, { filePath, lines, linesFound, linesHit, coveragePercent });
|
|
389
|
+
}
|
|
390
|
+
return coverageMap;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Find coverage for a file, trying both exact match and relative path matching.
|
|
394
|
+
*/
|
|
395
|
+
findFileCoverage(coverageMap, filePath) {
|
|
396
|
+
// Exact match
|
|
397
|
+
if (coverageMap.has(filePath))
|
|
398
|
+
return coverageMap.get(filePath);
|
|
399
|
+
// Try matching by basename + partial path (coverage tools sometimes use relative paths)
|
|
400
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
401
|
+
for (const [covPath, covData] of coverageMap) {
|
|
402
|
+
const normalizedCov = covPath.replace(/\\/g, '/');
|
|
403
|
+
if (normalizedCov.endsWith(normalized) || normalized.endsWith(normalizedCov)) {
|
|
404
|
+
return covData;
|
|
405
|
+
}
|
|
406
|
+
// Match on last N path segments
|
|
407
|
+
const fileParts = normalized.split('/');
|
|
408
|
+
const covParts = normalizedCov.split('/');
|
|
409
|
+
const minLen = Math.min(fileParts.length, covParts.length, 3);
|
|
410
|
+
const fileTail = fileParts.slice(-minLen).join('/');
|
|
411
|
+
const covTail = covParts.slice(-minLen).join('/');
|
|
412
|
+
if (fileTail === covTail)
|
|
413
|
+
return covData;
|
|
414
|
+
}
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Compact line numbers into readable ranges: [1,2,3,5,7,8,9] → "1-3, 5, 7-9"
|
|
419
|
+
*/
|
|
420
|
+
compactLineRanges(lines) {
|
|
421
|
+
if (lines.length === 0)
|
|
422
|
+
return '';
|
|
423
|
+
const ranges = [];
|
|
424
|
+
let start = lines[0];
|
|
425
|
+
let end = lines[0];
|
|
426
|
+
for (let i = 1; i < lines.length; i++) {
|
|
427
|
+
if (lines[i] === end + 1) {
|
|
428
|
+
end = lines[i];
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
ranges.push(start === end ? `${start}` : `${start}-${end}`);
|
|
432
|
+
start = lines[i];
|
|
433
|
+
end = lines[i];
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
ranges.push(start === end ? `${start}` : `${start}-${end}`);
|
|
437
|
+
// Truncate if too many ranges
|
|
438
|
+
if (ranges.length > 10) {
|
|
439
|
+
return ranges.slice(0, 10).join(', ') + ` (+${ranges.length - 10} more)`;
|
|
440
|
+
}
|
|
441
|
+
return ranges.join(', ');
|
|
442
|
+
}
|
|
443
|
+
/** Patterns that identify test/spec files. */
|
|
444
|
+
static TEST_PATTERNS = [
|
|
445
|
+
// JS/TS conventions
|
|
446
|
+
/\.test\.[jt]sx?$/,
|
|
447
|
+
/\.spec\.[jt]sx?$/,
|
|
448
|
+
/__tests__\//,
|
|
449
|
+
/\.tests\.[jt]sx?$/,
|
|
450
|
+
/\.specs\.[jt]sx?$/,
|
|
451
|
+
// C# conventions: *Test.cs, *Tests.cs, *.Test.cs, *.Tests.cs
|
|
452
|
+
/Tests?\.cs$/i,
|
|
453
|
+
/\.Tests?\.cs$/i,
|
|
454
|
+
];
|
|
455
|
+
/**
|
|
456
|
+
* Patterns that identify config / build / tooling files that do not need
|
|
457
|
+
* unit test coverage. Matched against the file basename.
|
|
458
|
+
*/
|
|
459
|
+
static CONFIG_FILE_PATTERNS = [
|
|
460
|
+
/^jest\.config\./,
|
|
461
|
+
/^vitest\.config\./,
|
|
462
|
+
/^vite\.config\./,
|
|
463
|
+
/^next\.config\./,
|
|
464
|
+
/^playwright\.config\./,
|
|
465
|
+
/^cypress\.config\./,
|
|
466
|
+
/^webpack\.config\./,
|
|
467
|
+
/^rollup\.config\./,
|
|
468
|
+
/^rspack\.config\./,
|
|
469
|
+
/^\.eslintrc/,
|
|
470
|
+
/^\.prettierrc/,
|
|
471
|
+
/^prettier\.config\./,
|
|
472
|
+
/^babel\.config\./,
|
|
473
|
+
/^postcss\.config\./,
|
|
474
|
+
/^tailwind\.config\./,
|
|
475
|
+
/^tsconfig/,
|
|
476
|
+
/^typedoc/,
|
|
477
|
+
/^package\.json$/,
|
|
478
|
+
/^\.editorconfig$/,
|
|
479
|
+
/^\.gitattributes$/,
|
|
480
|
+
/^\.gitignore$/,
|
|
481
|
+
/^\.dockerignore$/,
|
|
482
|
+
/^\.nvmrc$/,
|
|
483
|
+
/^\.npmrc$/,
|
|
484
|
+
/^lerna\.json$/,
|
|
485
|
+
/^nx\.json$/,
|
|
486
|
+
/^turbo\.json$/,
|
|
487
|
+
/^commitlint\.config\./,
|
|
488
|
+
/^\.commitlintrc/,
|
|
489
|
+
/^lint-staged\.config\./,
|
|
490
|
+
/^\.lintstagedrc/,
|
|
491
|
+
/^stylelint\.config\./,
|
|
492
|
+
/^\.stylelintrc/,
|
|
493
|
+
/^\.markdownlint/,
|
|
494
|
+
];
|
|
495
|
+
/**
|
|
496
|
+
* Returns true if the file is itself a test/spec file.
|
|
497
|
+
*/
|
|
498
|
+
isTestFile(filePath) {
|
|
499
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
500
|
+
return CoverageAnalyzer.TEST_PATTERNS.some(p => p.test(normalized));
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Returns true if the file is a config/build/tooling file that should not
|
|
504
|
+
* require unit test coverage.
|
|
505
|
+
*/
|
|
506
|
+
isConfigFile(filePath) {
|
|
507
|
+
const basename = path.basename(filePath);
|
|
508
|
+
return CoverageAnalyzer.CONFIG_FILE_PATTERNS.some(p => p.test(basename));
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Returns true when a C# file carries the [ExcludeFromCodeCoverage] attribute,
|
|
512
|
+
* indicating that the author intentionally exempted it from coverage requirements.
|
|
513
|
+
*/
|
|
514
|
+
isExcludedFromCoverage(filePath) {
|
|
515
|
+
if (!filePath.endsWith('.cs'))
|
|
516
|
+
return false;
|
|
517
|
+
try {
|
|
518
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
519
|
+
return /\[ExcludeFromCodeCoverage(?:Attribute)?(?:\s*\([^)]*\))?\]/.test(content);
|
|
520
|
+
}
|
|
521
|
+
catch {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Search for a corresponding test file for the given source file.
|
|
527
|
+
* Checks sibling locations, `__tests__/` directories, and `tests/` folders.
|
|
528
|
+
*/
|
|
529
|
+
findTestFile(filePath, projectRoot) {
|
|
530
|
+
const resolved = path.resolve(filePath);
|
|
531
|
+
const dir = path.dirname(resolved);
|
|
532
|
+
const ext = path.extname(resolved);
|
|
533
|
+
const baseName = path.basename(resolved, ext);
|
|
534
|
+
const testSuffixes = ['.test', '.spec'];
|
|
535
|
+
const testExts = [ext, '.ts', '.tsx', '.js', '.jsx'];
|
|
536
|
+
// 1. Sibling: foo.test.ts next to foo.ts
|
|
537
|
+
for (const suffix of testSuffixes) {
|
|
538
|
+
for (const testExt of testExts) {
|
|
539
|
+
const candidate = path.join(dir, `${baseName}${suffix}${testExt}`);
|
|
540
|
+
if (fs.existsSync(candidate))
|
|
541
|
+
return candidate;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
// 1b. Sibling C# conventions: *Test.cs, *Tests.cs, *.Test.cs, *.Tests.cs
|
|
545
|
+
if (ext === '.cs') {
|
|
546
|
+
for (const suffix of ['Test', 'Tests', '.Test', '.Tests']) {
|
|
547
|
+
const candidate = path.join(dir, `${baseName}${suffix}${ext}`);
|
|
548
|
+
if (fs.existsSync(candidate))
|
|
549
|
+
return candidate;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
// 2. __tests__/ directory at the same level
|
|
553
|
+
const testsDir = path.join(dir, '__tests__');
|
|
554
|
+
if (fs.existsSync(testsDir)) {
|
|
555
|
+
for (const suffix of ['', ...testSuffixes]) {
|
|
556
|
+
for (const testExt of testExts) {
|
|
557
|
+
const candidate = path.join(testsDir, `${baseName}${suffix}${testExt}`);
|
|
558
|
+
if (fs.existsSync(candidate))
|
|
559
|
+
return candidate;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
// 3. Parallel tests/ or test/ folder at project root
|
|
564
|
+
for (const testFolder of ['tests', 'test', '__tests__']) {
|
|
565
|
+
const rootTestDir = path.join(projectRoot, testFolder);
|
|
566
|
+
if (!fs.existsSync(rootTestDir))
|
|
567
|
+
continue;
|
|
568
|
+
const relativePath = path.relative(projectRoot, dir);
|
|
569
|
+
const parallelDir = path.join(rootTestDir, relativePath);
|
|
570
|
+
if (!fs.existsSync(parallelDir))
|
|
571
|
+
continue;
|
|
572
|
+
for (const suffix of ['', ...testSuffixes]) {
|
|
573
|
+
for (const testExt of testExts) {
|
|
574
|
+
const candidate = path.join(parallelDir, `${baseName}${suffix}${testExt}`);
|
|
575
|
+
if (fs.existsSync(candidate))
|
|
576
|
+
return candidate;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Suggest a test file name for the given source file path.
|
|
584
|
+
*/
|
|
585
|
+
suggestTestFileName(filePath) {
|
|
586
|
+
const ext = path.extname(filePath);
|
|
587
|
+
const baseName = path.basename(filePath, ext);
|
|
588
|
+
return `${baseName}.test${ext}`;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Returns true if a test file contains at least one real test assertion or
|
|
592
|
+
* test-framework call. Catches empty/placeholder test files that would
|
|
593
|
+
* otherwise satisfy the "test file exists" check without actually testing anything.
|
|
594
|
+
*/
|
|
595
|
+
hasRealTestContent(testFilePath) {
|
|
596
|
+
try {
|
|
597
|
+
const content = fs.readFileSync(testFilePath, 'utf8');
|
|
598
|
+
// TypeScript / JavaScript test patterns
|
|
599
|
+
const jsTestPatterns = [
|
|
600
|
+
/\bit\s*\(/, // it('...')
|
|
601
|
+
/\btest\s*\(/, // test('...')
|
|
602
|
+
/\bdescribe\s*\(/, // describe('...')
|
|
603
|
+
/\bexpect\s*\(/, // expect(...)
|
|
604
|
+
/\bassert\./, // assert.equal / assert.ok / etc.
|
|
605
|
+
/\bshould\./, // chai .should chains
|
|
606
|
+
/\bsuiteTest\s*\(/,
|
|
607
|
+
/\bspecify\s*\(/,
|
|
608
|
+
];
|
|
609
|
+
// C# xUnit / NUnit / MSTest attributes and Assert calls
|
|
610
|
+
const csharpTestPatterns = [
|
|
611
|
+
/\[Test\]/,
|
|
612
|
+
/\[TestMethod\]/,
|
|
613
|
+
/\[Fact\]/,
|
|
614
|
+
/\[Theory\]/,
|
|
615
|
+
/\[DataTestMethod\]/,
|
|
616
|
+
/\bAssert\./,
|
|
617
|
+
/\bShould\./,
|
|
618
|
+
];
|
|
619
|
+
const allPatterns = [...jsTestPatterns, ...csharpTestPatterns];
|
|
620
|
+
return allPatterns.some(p => p.test(content));
|
|
621
|
+
}
|
|
622
|
+
catch {
|
|
623
|
+
// If we can't read the file, assume it's real to avoid false positives
|
|
624
|
+
return true;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
/** Clear the coverage cache (e.g., when coverage files are regenerated). */
|
|
628
|
+
clearCache() {
|
|
629
|
+
this.coverageCache.clear();
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
exports.CoverageAnalyzer = CoverageAnalyzer;
|
|
633
|
+
//# sourceMappingURL=coverage-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/coverage-analyzer.ts"],"names":[],"mappings":"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"}
|