@gnapi/cotester 1.2.6 → 1.2.8

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.
Files changed (46) hide show
  1. package/dist/analyzer.d.ts +10 -0
  2. package/dist/analyzer.js +65 -0
  3. package/dist/analyzer.js.map +1 -1
  4. package/dist/astCache.js +1 -1
  5. package/dist/astCache.js.map +1 -1
  6. package/dist/auditLogger.d.ts +2 -0
  7. package/dist/auditLogger.js +38 -0
  8. package/dist/auditLogger.js.map +1 -1
  9. package/dist/branchAnalyzer.d.ts +1 -1
  10. package/dist/branchAnalyzer.js +91 -18
  11. package/dist/branchAnalyzer.js.map +1 -1
  12. package/dist/checker.d.ts +13 -0
  13. package/dist/checker.js +76 -1
  14. package/dist/checker.js.map +1 -1
  15. package/dist/cli.js +26 -4
  16. package/dist/cli.js.map +1 -1
  17. package/dist/configManager.d.ts +6 -0
  18. package/dist/configManager.js +44 -0
  19. package/dist/configManager.js.map +1 -1
  20. package/dist/frameworkAdapter.d.ts +19 -0
  21. package/dist/frameworkAdapter.js +30 -1
  22. package/dist/frameworkAdapter.js.map +1 -1
  23. package/dist/generator.js +149 -37
  24. package/dist/generator.js.map +1 -1
  25. package/dist/ignoreManager.js +10 -1
  26. package/dist/ignoreManager.js.map +1 -1
  27. package/dist/interfaceShapeResolver.js +77 -41
  28. package/dist/interfaceShapeResolver.js.map +1 -1
  29. package/dist/mockDataEngine.js +132 -1
  30. package/dist/mockDataEngine.js.map +1 -1
  31. package/dist/mockGenerator.js +4 -1
  32. package/dist/mockGenerator.js.map +1 -1
  33. package/dist/ormMockGenerator.js +77 -8
  34. package/dist/ormMockGenerator.js.map +1 -1
  35. package/dist/reporter.d.ts +1 -1
  36. package/dist/reporter.js +116 -4
  37. package/dist/reporter.js.map +1 -1
  38. package/dist/scenarioEngine.d.ts +3 -0
  39. package/dist/scenarioEngine.js +76 -1
  40. package/dist/scenarioEngine.js.map +1 -1
  41. package/dist/validator.d.ts +25 -0
  42. package/dist/validator.js +171 -0
  43. package/dist/validator.js.map +1 -0
  44. package/dist/watcher.js +30 -1
  45. package/dist/watcher.js.map +1 -1
  46. package/package.json +1 -1
@@ -4,6 +4,8 @@ import { PathAliases } from "./pathAliasResolver";
4
4
  export interface ParameterMeta {
5
5
  name: string;
6
6
  type: string;
7
+ /** true when the parameter is optional (declared with `?` or has a default value) */
8
+ isOptional?: boolean;
7
9
  }
8
10
  /** Per-function return type metadata for a single imported name */
9
11
  export interface ImportedFunctionMeta {
@@ -33,6 +35,8 @@ export interface DependencyMeta {
33
35
  export interface FunctionMeta {
34
36
  name: string;
35
37
  className?: string;
38
+ /** true when this is a static class method */
39
+ isStatic?: boolean;
36
40
  parameters: ParameterMeta[];
37
41
  returnType: string;
38
42
  /** Function uses async/await or returns a Promise */
@@ -51,6 +55,12 @@ export interface FunctionMeta {
51
55
  ormUsage: OrmUsage | null;
52
56
  /** Absolute path of the source file containing this function (for interface shape resolution) */
53
57
  sourceFilePath: string;
58
+ /** 1-based line number where this function starts (for LCOV FN: records) */
59
+ lineNumber?: number;
60
+ /** true when the containing class is decorated with a NestJS @Injectable / @Controller / @Resolver */
61
+ isNestInjectable?: boolean;
62
+ /** Decorator names found on the containing class (e.g. ['Injectable', 'Controller']) */
63
+ classDecorators?: string[];
54
64
  }
55
65
  /** Detected structural file type */
56
66
  export type FileType = "controller" | "service" | "repository" | "unknown";
package/dist/analyzer.js CHANGED
@@ -62,12 +62,16 @@ function analyzeFile(filePath, aliases) {
62
62
  for (const fn of functions) {
63
63
  if (!fn.isExported())
64
64
  continue;
65
+ // Skip overload signatures (they have no body)
66
+ if (fn.getBody() === undefined)
67
+ continue;
65
68
  const name = fn.getName();
66
69
  if (!name)
67
70
  continue;
68
71
  const parameters = fn.getParameters().map((p) => ({
69
72
  name: p.getName(),
70
73
  type: p.getType().getText(p) || "unknown",
74
+ isOptional: p.isOptional(),
71
75
  }));
72
76
  const returnType = fn.getReturnType().getText(fn) || "void";
73
77
  const isAsync = fn.isAsync() || returnType.toLowerCase().startsWith("promise");
@@ -86,14 +90,63 @@ function analyzeFile(filePath, aliases) {
86
90
  fileType,
87
91
  ormUsage,
88
92
  sourceFilePath: filePath,
93
+ lineNumber: fn.getStartLineNumber(),
89
94
  });
90
95
  }
96
+ // ── Exported arrow functions / function expressions (variable statements) ──
97
+ const NEST_DECORATORS = ["Injectable", "Controller", "Resolver", "Module", "Guard", "Interceptor", "Pipe", "Middleware"];
98
+ for (const stmt of sourceFile.getVariableStatements()) {
99
+ if (!stmt.isExported())
100
+ continue;
101
+ for (const decl of stmt.getDeclarations()) {
102
+ const init = decl.getInitializer();
103
+ if (!init)
104
+ continue;
105
+ const kind = init.getKind();
106
+ if (kind !== ts_morph_1.SyntaxKind.ArrowFunction && kind !== ts_morph_1.SyntaxKind.FunctionExpression)
107
+ continue;
108
+ const name = decl.getName();
109
+ if (!name)
110
+ continue;
111
+ const fnNode = init;
112
+ const parameters = fnNode.getParameters().map((p) => ({
113
+ name: p.getName(),
114
+ type: p.getType().getText(p) || "unknown",
115
+ isOptional: p.isOptional(),
116
+ }));
117
+ const returnType = fnNode.getReturnType().getText(fnNode) || "void";
118
+ const isAsync = fnNode.isAsync?.() || returnType.toLowerCase().startsWith("promise");
119
+ const throwsErrors = bodyContainsThrow(fnNode);
120
+ const dependencies = findUsedDependencies(fnNode, fileImports, sourceFile);
121
+ const branches = (0, branchAnalyzer_1.analyzeBranches)(fnNode);
122
+ const ormUsage = (0, ormMockGenerator_1.detectOrmUsage)(fnNode);
123
+ results.push({
124
+ name,
125
+ parameters,
126
+ returnType,
127
+ isAsync,
128
+ throwsErrors,
129
+ dependencies,
130
+ branches,
131
+ fileType,
132
+ ormUsage,
133
+ sourceFilePath: filePath,
134
+ lineNumber: decl.getStartLineNumber(),
135
+ });
136
+ }
137
+ }
91
138
  // ── Exported class declarations → public methods ────────────────────
92
139
  const classes = sourceFile.getClasses();
93
140
  for (const cls of classes) {
94
141
  if (!cls.isExported())
95
142
  continue;
143
+ // Skip abstract classes — they can't be instantiated directly
144
+ if (cls.isAbstract())
145
+ continue;
96
146
  const className = cls.getName() ?? "AnonymousClass";
147
+ // Detect NestJS DI decorators for specialized mock generation
148
+ const classDecoratorNames = cls.getDecorators().map((d) => d.getName());
149
+ const isNestInjectable = classDecoratorNames.some((n) => NEST_DECORATORS.includes(n));
97
150
  // Extract constructor params for DI
98
151
  const constructorParams = extractConstructorParams(cls);
99
152
  const methods = cls.getMethods();
@@ -103,13 +156,21 @@ function analyzeFile(filePath, aliases) {
103
156
  method.hasModifier(ts_morph_1.SyntaxKind.ProtectedKeyword)) {
104
157
  continue;
105
158
  }
159
+ // Skip abstract methods — no implementation to test
160
+ if (method.isAbstract())
161
+ continue;
162
+ // Skip overload signatures (no body)
163
+ if (method.getBody() === undefined)
164
+ continue;
106
165
  const name = method.getName();
107
166
  const parameters = method.getParameters().map((p) => ({
108
167
  name: p.getName(),
109
168
  type: p.getType().getText(p) || "unknown",
169
+ isOptional: p.isOptional(),
110
170
  }));
111
171
  const returnType = method.getReturnType().getText(method) || "void";
112
172
  const isAsync = method.isAsync() || returnType.toLowerCase().startsWith("promise");
173
+ const isStatic = method.hasModifier(ts_morph_1.SyntaxKind.StaticKeyword);
113
174
  const throwsErrors = bodyContainsThrow(method);
114
175
  const dependencies = findUsedDependencies(method, fileImports, sourceFile);
115
176
  const branches = (0, branchAnalyzer_1.analyzeBranches)(method);
@@ -117,6 +178,7 @@ function analyzeFile(filePath, aliases) {
117
178
  results.push({
118
179
  name,
119
180
  className,
181
+ isStatic,
120
182
  parameters,
121
183
  returnType,
122
184
  isAsync,
@@ -127,6 +189,9 @@ function analyzeFile(filePath, aliases) {
127
189
  fileType,
128
190
  ormUsage,
129
191
  sourceFilePath: filePath,
192
+ lineNumber: method.getStartLineNumber(),
193
+ isNestInjectable,
194
+ classDecorators: classDecoratorNames,
130
195
  });
131
196
  }
132
197
  }
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
package/dist/astCache.js CHANGED
@@ -63,7 +63,7 @@ const pathAliasResolver_1 = require("./pathAliasResolver");
63
63
  * Increment when FunctionMeta or any nested type (BranchInfo, OrmUsage, …)
64
64
  * changes shape. Old on-disk entries with a different version are discarded.
65
65
  */
66
- const CACHE_VERSION = "2";
66
+ const CACHE_VERSION = "3"; // bumped: added lineNumber, classDecorators, isNestInjectable to FunctionMeta
67
67
  /**
68
68
  * In-process cache. Shared within a single watcher/worker process lifetime.
69
69
  * Prevents redundant disk reads on rapid successive saves of the same file.
@@ -1 +1 @@
1
- {"version":3,"file":"astCache.js","sourceRoot":"","sources":["../src/astCache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"astCache.js","sourceRoot":"","sources":["../src/astCache.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,8 @@
17
17
  export interface AuditEntry {
18
18
  /** ISO-8601 UTC timestamp of the generation run */
19
19
  timestamp: string;
20
+ /** L-4: IANA timezone name so compliance tools can distinguish UTC vs local time */
21
+ timezone: string;
20
22
  /** Source file path relative to projectRoot, forward-slash separated */
21
23
  file: string;
22
24
  /** Function/method names for which a new describe block was written */
@@ -56,6 +56,9 @@ const path = __importStar(require("path"));
56
56
  const utils_1 = require("./utils");
57
57
  // ─── Constants ────────────────────────────────────────────────────────────────
58
58
  const AUDIT_FILE = path.join("cotester", ".audit.jsonl");
59
+ /** H-6: rotate the log when it exceeds 50 MB or 10 000 entries */
60
+ const MAX_AUDIT_BYTES = 50 * 1024 * 1024; // 50 MB
61
+ const MAX_AUDIT_LINES = 10000;
59
62
  // ─── Public API ───────────────────────────────────────────────────────────────
60
63
  /**
61
64
  * Append one audit entry to `cotester/.audit.jsonl`.
@@ -79,6 +82,8 @@ function writeAuditEntry(entry, projectRoot, dryRun = false) {
79
82
  const auditPath = path.join(projectRoot, AUDIT_FILE);
80
83
  (0, utils_1.ensureDir)(path.dirname(auditPath));
81
84
  try {
85
+ // H-6: rotate log when it exceeds size or line count limits
86
+ rotateAuditLogIfNeeded(auditPath);
82
87
  fs.appendFileSync(auditPath, line + "\n", "utf-8");
83
88
  }
84
89
  catch (err) {
@@ -96,12 +101,45 @@ function writeAuditEntry(entry, projectRoot, dryRun = false) {
96
101
  * @param skipped Function names already covered with no changes.
97
102
  */
98
103
  function buildAuditEntry(srcFilePath, projectRoot, added, merged, skipped) {
104
+ // L-4: include IANA timezone so compliance tools can distinguish UTC vs local
105
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? "UTC";
99
106
  return {
100
107
  timestamp: new Date().toISOString(),
108
+ timezone,
101
109
  file: path.relative(projectRoot, srcFilePath).replace(/\\/g, "/"),
102
110
  added,
103
111
  merged,
104
112
  skipped,
105
113
  };
106
114
  }
115
+ // ─── H-6: Log rotation ────────────────────────────────────────────────────────
116
+ /**
117
+ * Rotate `auditPath` to `auditPath.1` when it exceeds MAX_AUDIT_BYTES or
118
+ * MAX_AUDIT_LINES. Keeps at most one rotated archive (`.audit.jsonl.1`).
119
+ */
120
+ function rotateAuditLogIfNeeded(auditPath) {
121
+ try {
122
+ if (!fs.existsSync(auditPath))
123
+ return;
124
+ const stat = fs.statSync(auditPath);
125
+ let needsRotation = stat.size >= MAX_AUDIT_BYTES;
126
+ if (!needsRotation) {
127
+ // Check line count without reading the whole file — count newlines
128
+ const content = fs.readFileSync(auditPath, "utf-8");
129
+ const lineCount = (content.match(/\n/g) ?? []).length;
130
+ needsRotation = lineCount >= MAX_AUDIT_LINES;
131
+ }
132
+ if (needsRotation) {
133
+ const archivePath = auditPath + ".1";
134
+ // Overwrite previous archive if it exists
135
+ if (fs.existsSync(archivePath))
136
+ fs.unlinkSync(archivePath);
137
+ fs.renameSync(auditPath, archivePath);
138
+ (0, utils_1.log)(`Audit log rotated → ${path.basename(archivePath)}`, "info");
139
+ }
140
+ }
141
+ catch {
142
+ // Non-fatal — rotation failure should not block writes
143
+ }
144
+ }
107
145
  //# sourceMappingURL=auditLogger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auditLogger.js","sourceRoot":"","sources":["../src/auditLogger.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCH,0CA8BC;AAWD,0CAcC;AAvFD,uCAAyB;AACzB,2CAA6B;AAC7B,mCAAyC;AAiBzC,iFAAiF;AAEjF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;AAEzD,iFAAiF;AAEjF;;;;;;GAMG;AACH,SAAgB,eAAe,CAC3B,KAAiB,EACjB,WAAmB,EACnB,MAAM,GAAG,KAAK;IAEd,+DAA+D;IAC/D,IACI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QACxB,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAC5B,CAAC;QACC,OAAO;IACX,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEnC,IAAI,MAAM,EAAE,CAAC;QACT,IAAA,WAAG,EAAC,WAAW,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO;IACX,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACrD,IAAA,iBAAS,EAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAEnC,IAAI,CAAC;QACD,EAAE,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,gEAAgE;QAChE,IAAA,WAAG,EAAC,yCAAyC,GAAG,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;IACxE,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,eAAe,CAC3B,WAAmB,EACnB,WAAmB,EACnB,KAAe,EACf,MAAgB,EAChB,OAAiB;IAEjB,OAAO;QACH,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;QACjE,KAAK;QACL,MAAM;QACN,OAAO;KACV,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"auditLogger.js","sourceRoot":"","sources":["../src/auditLogger.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ export interface BranchInfo {
7
7
  /** Suggested test label for the "false" path */
8
8
  falseLabel: string;
9
9
  /** Type of branch */
10
- kind: "if" | "ternary" | "guard" | "nullcheck" | "logical";
10
+ kind: "if" | "ternary" | "guard" | "nullcheck" | "logical" | "optionalchain" | "nullish" | "switch" | "trycatch";
11
11
  }
12
12
  /**
13
13
  * Analyze a function/method body for conditional branches.
@@ -44,26 +44,97 @@ function analyzeBranches(fnNode) {
44
44
  const binaryExpressions = fnNode.getDescendantsOfKind(ts_morph_1.SyntaxKind.BinaryExpression);
45
45
  for (const bin of binaryExpressions) {
46
46
  const opToken = bin.getOperatorToken().getText();
47
- if (opToken !== "&&" && opToken !== "||")
47
+ if (opToken === "&&" || opToken === "||") {
48
+ // skip if already captured as part of an if condition
49
+ const parent = bin.getParent();
50
+ if (parent?.getKind() === ts_morph_1.SyntaxKind.IfStatement)
51
+ continue;
52
+ if (parent?.getKind() === ts_morph_1.SyntaxKind.ParenthesizedExpression) {
53
+ const grandparent = parent.getParent();
54
+ if (grandparent?.getKind() === ts_morph_1.SyntaxKind.IfStatement)
55
+ continue;
56
+ }
57
+ const condText = bin.getText().trim();
58
+ if (seen.has(condText) || condText.length > 80)
59
+ continue;
60
+ seen.add(condText);
61
+ branches.push({
62
+ condition: condText,
63
+ trueLabel: `handles case when ${simplifyCondition(condText)}`,
64
+ falseLabel: `handles case when ${negateSimple(condText)}`,
65
+ kind: "logical",
66
+ });
67
+ }
68
+ else if (opToken === "??") {
69
+ // Nullish coalescing — two paths: left is null/undefined, left has value
70
+ const leftText = bin.getLeft().getText().trim();
71
+ const key = `??:${leftText}`;
72
+ if (seen.has(key))
73
+ continue;
74
+ seen.add(key);
75
+ branches.push({
76
+ condition: `${leftText} ?? ...`,
77
+ trueLabel: `uses fallback when ${simplifyCondition(leftText)} is null/undefined`,
78
+ falseLabel: `uses ${simplifyCondition(leftText)} value when defined`,
79
+ kind: "nullish",
80
+ });
81
+ }
82
+ }
83
+ // ── Optional chaining (?.) ────────────────────────────────────────────
84
+ // Use PropertyAccessExpression and check for question-dot token via getText
85
+ const propAccesses = fnNode.getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertyAccessExpression);
86
+ for (const pa of propAccesses) {
87
+ // ts-morph: hasQuestionDotToken() available on PropertyAccessExpression
88
+ const hasQD = pa.hasQuestionDotToken?.();
89
+ if (!hasQD)
48
90
  continue;
49
- // skip if already captured as part of an if condition
50
- const parent = bin.getParent();
51
- if (parent?.getKind() === ts_morph_1.SyntaxKind.IfStatement)
91
+ const exprText = pa.getExpression().getText().trim();
92
+ const key = `?.:${exprText}`;
93
+ if (seen.has(key))
52
94
  continue;
53
- if (parent?.getKind() === ts_morph_1.SyntaxKind.ParenthesizedExpression) {
54
- const grandparent = parent.getParent();
55
- if (grandparent?.getKind() === ts_morph_1.SyntaxKind.IfStatement)
56
- continue;
95
+ seen.add(key);
96
+ branches.push({
97
+ condition: `${exprText}?.`,
98
+ trueLabel: `handles when ${simplifyCondition(exprText)} is defined`,
99
+ falseLabel: `handles when ${simplifyCondition(exprText)} is null/undefined (optional chain short-circuits)`,
100
+ kind: "optionalchain",
101
+ });
102
+ }
103
+ // ── Switch statements ─────────────────────────────────────────────────
104
+ const switchStatements = fnNode.getDescendantsOfKind(ts_morph_1.SyntaxKind.SwitchStatement);
105
+ for (const sw of switchStatements) {
106
+ const exprText = sw.getExpression().getText().trim();
107
+ const clauses = sw.getCaseBlock().getClauses();
108
+ const labels = [];
109
+ for (const clause of clauses) {
110
+ if (clause.getKind() === ts_morph_1.SyntaxKind.CaseClause) {
111
+ labels.push(clause.getExpression().getText().trim());
112
+ }
57
113
  }
58
- const condText = bin.getText().trim();
59
- if (seen.has(condText) || condText.length > 80)
114
+ const key = `switch:${exprText}`;
115
+ if (seen.has(key))
60
116
  continue;
61
- seen.add(condText);
117
+ seen.add(key);
118
+ const caseList = labels.slice(0, 3).join(", ") + (labels.length > 3 ? ", ..." : "");
62
119
  branches.push({
63
- condition: condText,
64
- trueLabel: `handles case when ${simplifyCondition(condText)}`,
65
- falseLabel: `handles case when ${negateSimple(condText)}`,
66
- kind: "logical",
120
+ condition: `switch (${exprText})`,
121
+ trueLabel: `handles case ${labels[0] ?? "matching"}`,
122
+ falseLabel: `handles default/unmatched case${caseList ? ` (cases: ${caseList})` : ""}`,
123
+ kind: "switch",
124
+ });
125
+ }
126
+ // ── Try/catch blocks ──────────────────────────────────────────────────
127
+ const tryBlocks = fnNode.getDescendantsOfKind(ts_morph_1.SyntaxKind.TryStatement);
128
+ for (const tryStmt of tryBlocks) {
129
+ const key = `try:${tryStmt.getStartLineNumber()}`;
130
+ if (seen.has(key))
131
+ continue;
132
+ seen.add(key);
133
+ branches.push({
134
+ condition: `try/catch at line ${tryStmt.getStartLineNumber()}`,
135
+ trueLabel: `succeeds without throwing`,
136
+ falseLabel: `handles error thrown inside try block`,
137
+ kind: "trycatch",
67
138
  });
68
139
  }
69
140
  return branches;
@@ -134,10 +205,12 @@ function simplifyCondition(cond) {
134
205
  return `${cond} is truthy`;
135
206
  }
136
207
  // "a > b" → keep as is
137
- if (cond.length < 40)
208
+ if (cond.length < 60)
138
209
  return cond;
139
- // Truncate long conditions
140
- return cond.substring(0, 35) + "...";
210
+ // Truncate long conditions at a word boundary to preserve semantic meaning
211
+ const truncated = cond.substring(0, 57);
212
+ const lastSpace = truncated.lastIndexOf(" ");
213
+ return (lastSpace > 20 ? truncated.substring(0, lastSpace) : truncated) + "...";
141
214
  }
142
215
  /**
143
216
  * Create a negative version of a condition description.
@@ -1 +1 @@
1
- {"version":3,"file":"branchAnalyzer.js","sourceRoot":"","sources":["../src/branchAnalyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"branchAnalyzer.js","sourceRoot":"","sources":["../src/branchAnalyzer.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;;AAuBnE,0CAsIC;AA3JD,uCAA4C;AAe5C,gFAAgF;AAEhF;;;GAGG;AACH,SAAgB,eAAe,CAAC,MAAY;IACxC,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,uEAAuE;IACvE,MAAM,YAAY,GAAG,MAAM,CAAC,oBAAoB,CAAC,qBAAU,CAAC,WAAW,CAAC,CAAC;IACzE,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;QAEhD,uDAAuD;QACvD,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEnB,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,wEAAwE;IACxE,MAAM,YAAY,GAAG,MAAM,CAAC,oBAAoB,CAAC,qBAAU,CAAC,qBAAqB,CAAC,CAAC;IACnF,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;QACtD,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEnB,QAAQ,CAAC,IAAI,CAAC;YACV,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,0BAA0B,iBAAiB,CAAC,QAAQ,CAAC,EAAE;YAClE,UAAU,EAAE,yBAAyB,YAAY,CAAC,QAAQ,CAAC,EAAE;YAC7D,IAAI,EAAE,SAAS;SAClB,CAAC,CAAC;IACP,CAAC;IAED,wEAAwE;IACxE,MAAM,iBAAiB,GAAG,MAAM,CAAC,oBAAoB,CAAC,qBAAU,CAAC,gBAAgB,CAAC,CAAC;IACnF,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,GAAG,CAAC,gBAAgB,EAAE,CAAC,OAAO,EAAE,CAAC;QAEjD,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACvC,sDAAsD;YACtD,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;YAC/B,IAAI,MAAM,EAAE,OAAO,EAAE,KAAK,qBAAU,CAAC,WAAW;gBAAE,SAAS;YAC3D,IAAI,MAAM,EAAE,OAAO,EAAE,KAAK,qBAAU,CAAC,uBAAuB,EAAE,CAAC;gBAC3D,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;gBACvC,IAAI,WAAW,EAAE,OAAO,EAAE,KAAK,qBAAU,CAAC,WAAW;oBAAE,SAAS;YACpE,CAAC;YAED,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE;gBAAE,SAAS;YACzD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAEnB,QAAQ,CAAC,IAAI,CAAC;gBACV,SAAS,EAAE,QAAQ;gBACnB,SAAS,EAAE,qBAAqB,iBAAiB,CAAC,QAAQ,CAAC,EAAE;gBAC7D,UAAU,EAAE,qBAAqB,YAAY,CAAC,QAAQ,CAAC,EAAE;gBACzD,IAAI,EAAE,SAAS;aAClB,CAAC,CAAC;QACP,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1B,yEAAyE;YACzE,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,MAAM,QAAQ,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEd,QAAQ,CAAC,IAAI,CAAC;gBACV,SAAS,EAAE,GAAG,QAAQ,SAAS;gBAC/B,SAAS,EAAE,sBAAsB,iBAAiB,CAAC,QAAQ,CAAC,oBAAoB;gBAChF,UAAU,EAAE,QAAQ,iBAAiB,CAAC,QAAQ,CAAC,qBAAqB;gBACpE,IAAI,EAAE,SAAS;aAClB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,yEAAyE;IACzE,4EAA4E;IAC5E,MAAM,YAAY,GAAG,MAAM,CAAC,oBAAoB,CAAC,qBAAU,CAAC,wBAAwB,CAAC,CAAC;IACtF,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;QAC5B,wEAAwE;QACxE,MAAM,KAAK,GAAI,EAAU,CAAC,mBAAmB,EAAE,EAAE,CAAC;QAClD,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,QAAQ,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEd,QAAQ,CAAC,IAAI,CAAC;YACV,SAAS,EAAE,GAAG,QAAQ,IAAI;YAC1B,SAAS,EAAE,gBAAgB,iBAAiB,CAAC,QAAQ,CAAC,aAAa;YACnE,UAAU,EAAE,gBAAgB,iBAAiB,CAAC,QAAQ,CAAC,oDAAoD;YAC3G,IAAI,EAAE,eAAe;SACxB,CAAC,CAAC;IACP,CAAC;IAED,yEAAyE;IACzE,MAAM,gBAAgB,GAAG,MAAM,CAAC,oBAAoB,CAAC,qBAAU,CAAC,eAAe,CAAC,CAAC;IACjF,KAAK,MAAM,EAAE,IAAI,gBAAgB,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;QACrD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,MAAM,CAAC,OAAO,EAAE,KAAK,qBAAU,CAAC,UAAU,EAAE,CAAC;gBAC7C,MAAM,CAAC,IAAI,CAAE,MAAwC,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5F,CAAC;QACL,CAAC;QACD,MAAM,GAAG,GAAG,UAAU,QAAQ,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEd,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpF,QAAQ,CAAC,IAAI,CAAC;YACV,SAAS,EAAE,WAAW,QAAQ,GAAG;YACjC,SAAS,EAAE,gBAAgB,MAAM,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE;YACpD,UAAU,EAAE,iCAAiC,QAAQ,CAAC,CAAC,CAAC,YAAY,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACtF,IAAI,EAAE,QAAQ;SACjB,CAAC,CAAC;IACP,CAAC;IAED,yEAAyE;IACzE,MAAM,SAAS,GAAG,MAAM,CAAC,oBAAoB,CAAC,qBAAU,CAAC,YAAY,CAAC,CAAC;IACvE,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;QAClD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEd,QAAQ,CAAC,IAAI,CAAC;YACV,SAAS,EAAE,qBAAqB,OAAO,CAAC,kBAAkB,EAAE,EAAE;YAC9D,SAAS,EAAE,2BAA2B;YACtC,UAAU,EAAE,uCAAuC;YACnD,IAAI,EAAE,UAAU;SACnB,CAAC,CAAC;IACP,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,gFAAgF;AAEhF,SAAS,iBAAiB,CAAC,QAAgB,EAAE,MAAY;IACrD,+CAA+C;IAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC;IACrE,MAAM,QAAQ,GAAG,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC5C,MAAM,OAAO,GAAG,yBAAyB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAEhE,uBAAuB;IACvB,MAAM,WAAW,GAAG,yBAAyB,CAAC,IAAI,CAAC,QAAQ,CAAC;WACrD,yBAAyB,CAAC,IAAI,CAAC,QAAQ,CAAC;WACxC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAElC,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;QACzB,OAAO;YACH,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,2BAA2B,iBAAiB,CAAC,QAAQ,CAAC,GAAG;YACpE,UAAU,EAAE,4BAA4B;YACxC,IAAI,EAAE,OAAO;SAChB,CAAC;IACN,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACV,OAAO;YACH,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,iCAAiC,iBAAiB,CAAC,QAAQ,CAAC,GAAG;YAC1E,UAAU,EAAE,2BAA2B;YACvC,IAAI,EAAE,OAAO;SAChB,CAAC;IACN,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QACd,OAAO;YACH,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,gBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE;YACxD,UAAU,EAAE,gBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE;YACpD,IAAI,EAAE,WAAW;SACpB,CAAC;IACN,CAAC;IAED,mBAAmB;IACnB,OAAO;QACH,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,gBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE;QACxD,UAAU,EAAE,gBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE;QACpD,IAAI,EAAE,IAAI;KACb,CAAC;AACN,CAAC;AAED,gFAAgF;AAEhF;;GAEG;AACH,SAAS,iBAAiB,CAAC,IAAY;IACnC,4BAA4B;IAC5B,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;IACvC,CAAC;IAED,mCAAmC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACtF,IAAI,OAAO,EAAE,CAAC;QACV,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,CAAC;IAED,uCAAuC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACvF,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,CAAC;IAED,4CAA4C;IAC5C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,IAAI,YAAY,CAAC;IAC/B,CAAC;IAED,uBAAuB;IACvB,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IAElC,2EAA2E;IAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;AACpF,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,IAAY;IAC9B,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;IACxC,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACtF,IAAI,OAAO,EAAE,CAAC;QACV,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,WAAW,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACvF,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9C,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,IAAI,WAAW,CAAC;IAC9B,CAAC;IAED,OAAO,sBAAsB,CAAC;AAClC,CAAC"}
package/dist/checker.d.ts CHANGED
@@ -4,6 +4,8 @@ interface FunctionCoverage {
4
4
  name: string;
5
5
  /** Whether a describe block for this name was found in the test file */
6
6
  covered: boolean;
7
+ /** 1-based source line number (from FunctionMeta.lineNumber — for LCOV FN: records) */
8
+ lineNumber?: number;
7
9
  }
8
10
  export interface FileCoverage {
9
11
  /** Absolute source file path */
@@ -21,6 +23,17 @@ export interface FileCoverage {
21
23
  totalCount: number;
22
24
  /** Number of functions whose @testgen-sig fingerprint no longer matches current source */
23
25
  staleCount: number;
26
+ /** Total `expect(` calls found in the test file */
27
+ assertionCount: number;
28
+ /** Total `it(` / `test(` calls found in the test file */
29
+ testCaseCount: number;
30
+ /**
31
+ * Heuristic quality score (0–100):
32
+ * - 0 when no test file exists
33
+ * - Based on assertion density (assertions per test case) and test case count
34
+ * - A = 80+, B = 60–79, C = 40–59, D = <40
35
+ */
36
+ qualityScore: number;
24
37
  }
25
38
  export interface CheckResult {
26
39
  fileCoverages: FileCoverage[];
package/dist/checker.js CHANGED
@@ -104,17 +104,39 @@ function computeCoverage(scanRoot, projectRoot, config) {
104
104
  const absSrcRoot = path.resolve(projectRoot, config.srcDir);
105
105
  for (const srcPath of sourceFiles) {
106
106
  const rawFunctions = safeAnalyze(srcPath, projectRoot);
107
- if (rawFunctions.length === 0)
107
+ // R-2: track empty files (types-only) don't silently skip them
108
+ if (rawFunctions.length === 0) {
109
+ fileCoverages.push({
110
+ srcPath,
111
+ relPath: path.relative(projectRoot, srcPath).replace(/\\/g, "/"),
112
+ testPath: (0, utils_1.mirrorPath)(srcPath, absSrcRoot, path.join(projectRoot, config.testDir), ".test.ts"),
113
+ testFileExists: false,
114
+ functions: [],
115
+ coveredCount: 0,
116
+ totalCount: 0,
117
+ staleCount: 0,
118
+ assertionCount: 0,
119
+ testCaseCount: 0,
120
+ qualityScore: 0,
121
+ });
108
122
  continue;
123
+ }
109
124
  const testPath = (0, utils_1.mirrorPath)(srcPath, absSrcRoot, path.join(projectRoot, config.testDir), ".test.ts");
110
125
  const testFileExists = fs.existsSync(testPath);
111
126
  const testContent = readTestContent(testPath);
112
127
  const functionCoverages = rawFunctions.map((fn) => ({
113
128
  name: fn.name,
114
129
  covered: isCovered(fn.name, testContent),
130
+ lineNumber: fn.lineNumber,
115
131
  }));
116
132
  const fileCoveredCount = functionCoverages.filter((f) => f.covered).length;
117
133
  const fileStaleCount = detectStaleCount(testContent, rawFunctions);
134
+ // H-2: strip comments before counting to avoid false positives
135
+ const strippedContent = stripComments(testContent);
136
+ const assertionCount = countOccurrences(strippedContent, "expect(");
137
+ // H-2: exclude it.skip / it.todo / xit / test.skip / test.todo from active test count
138
+ const testCaseCount = countActiveTestCases(strippedContent);
139
+ const qualityScore = computeQualityScore(assertionCount, testCaseCount, testFileExists);
118
140
  totalFunctions += functionCoverages.length;
119
141
  coveredFunctions += fileCoveredCount;
120
142
  totalStale += fileStaleCount;
@@ -127,8 +149,13 @@ function computeCoverage(scanRoot, projectRoot, config) {
127
149
  coveredCount: fileCoveredCount,
128
150
  totalCount: functionCoverages.length,
129
151
  staleCount: fileStaleCount,
152
+ assertionCount,
153
+ testCaseCount,
154
+ qualityScore,
130
155
  });
131
156
  }
157
+ // L-1: sort by relPath for reproducible output across Windows/Linux
158
+ fileCoverages.sort((a, b) => a.relPath.localeCompare(b.relPath));
132
159
  const coveragePercent = totalFunctions === 0 ? 100 : Math.round((coveredFunctions / totalFunctions) * 100);
133
160
  return {
134
161
  fileCoverages,
@@ -337,6 +364,54 @@ function isCovered(fnName, testContent) {
337
364
  const pattern = new RegExp(`describe\\s*\\(\\s*['"\`]${escaped}['"\`]`);
338
365
  return pattern.test(testContent);
339
366
  }
367
+ /**
368
+ * Strip single-line (//) and multi-line (/* *\/) comments from source text.
369
+ * This prevents expect( or it( inside comments from inflating quality scores (H-2).
370
+ */
371
+ function stripComments(src) {
372
+ // Remove block comments first, then line comments
373
+ return src
374
+ .replace(/\/\*[\s\S]*?\*\//g, " ")
375
+ .replace(/\/\/[^\n]*/g, " ");
376
+ }
377
+ /**
378
+ * Count active (non-skipped) test cases: it(, test( — excluding
379
+ * it.skip(, it.todo(, xit(, xtest(, test.skip(, test.todo( (H-2).
380
+ */
381
+ function countActiveTestCases(src) {
382
+ // Match standalone it( and test( but not the .skip/.todo variants
383
+ const itMatches = (src.match(/(?<![.\w])it\s*\(/g) ?? []).length;
384
+ const testMatches = (src.match(/(?<![.\w])test\s*\(/g) ?? []).length;
385
+ const skipMatches = (src.match(/(?:it|test)\.(?:skip|todo)\s*\(/g) ?? []).length;
386
+ const xMatches = (src.match(/(?:xit|xtest)\s*\(/g) ?? []).length;
387
+ return Math.max(0, itMatches + testMatches - skipMatches - xMatches);
388
+ }
389
+ /** Count non-overlapping occurrences of `needle` in `haystack`. */
390
+ function countOccurrences(haystack, needle) {
391
+ if (!haystack || !needle)
392
+ return 0;
393
+ let count = 0;
394
+ let idx = 0;
395
+ while ((idx = haystack.indexOf(needle, idx)) !== -1) {
396
+ count++;
397
+ idx += needle.length;
398
+ }
399
+ return count;
400
+ }
401
+ /**
402
+ * Heuristic quality score (0–100).
403
+ * - 0 when no test file exists
404
+ * - Rewards assertion density and number of test cases
405
+ * - A = 80+, B = 60–79, C = 40–59, D = <40
406
+ */
407
+ function computeQualityScore(assertionCount, testCaseCount, testFileExists) {
408
+ if (!testFileExists || testCaseCount === 0)
409
+ return 0;
410
+ const density = assertionCount / testCaseCount; // avg assertions per test
411
+ const densityScore = Math.min(50, density * 25); // up to 50 pts for ≥2 asserts/test
412
+ const caseScore = Math.min(50, testCaseCount * 5); // up to 50 pts for ≥10 test cases
413
+ return Math.round(densityScore + caseScore);
414
+ }
340
415
  /** Safely analyse a file, returning [] on any error. */
341
416
  function safeAnalyze(filePath, projectRoot) {
342
417
  try {