api-tests-coverage 1.0.23 → 1.0.24

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 (131) hide show
  1. package/README.md +39 -0
  2. package/config.yaml.example +35 -0
  3. package/dist/dashboard/dist/assets/_basePickBy-D4Hl8chy.js +1 -0
  4. package/dist/dashboard/dist/assets/_baseUniq-BSUUnV_V.js +1 -0
  5. package/dist/dashboard/dist/assets/arc-DhDluTY5.js +1 -0
  6. package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-DGlUU7dC.js +36 -0
  7. package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-CgXi3kEZ.js +122 -0
  8. package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-Cr3xB15y.js +10 -0
  9. package/dist/dashboard/dist/assets/channel-DYAie-7m.js +1 -0
  10. package/dist/dashboard/dist/assets/chunk-4BX2VUAB-BaW3__pI.js +1 -0
  11. package/dist/dashboard/dist/assets/chunk-55IACEB6-DyYevfEQ.js +1 -0
  12. package/dist/dashboard/dist/assets/chunk-B4BG7PRW-C2bwZFec.js +165 -0
  13. package/dist/dashboard/dist/assets/chunk-DI55MBZ5-DO0T2xne.js +220 -0
  14. package/dist/dashboard/dist/assets/chunk-FMBD7UC4-CCYA4j_f.js +15 -0
  15. package/dist/dashboard/dist/assets/chunk-QN33PNHL-Cdhqs7xo.js +1 -0
  16. package/dist/dashboard/dist/assets/chunk-QZHKN3VN-BzHw38Ki.js +1 -0
  17. package/dist/dashboard/dist/assets/chunk-TZMSLE5B-dkJ0rsgF.js +1 -0
  18. package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-DiIv5Pho.js +1 -0
  19. package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-DiIv5Pho.js +1 -0
  20. package/dist/dashboard/dist/assets/clone-B4LorrSy.js +1 -0
  21. package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-jzGbyPIS.js +1 -0
  22. package/dist/dashboard/dist/assets/dagre-6UL2VRFP-D7rgvBx1.js +4 -0
  23. package/dist/dashboard/dist/assets/diagram-PSM6KHXK-2rYklqon.js +24 -0
  24. package/dist/dashboard/dist/assets/diagram-QEK2KX5R-CGrvALqm.js +43 -0
  25. package/dist/dashboard/dist/assets/diagram-S2PKOQOG-DA3c-QP4.js +24 -0
  26. package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-BsYH8cLH.js +60 -0
  27. package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-Da_JhBCy.js +162 -0
  28. package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-D8FTswNn.js +267 -0
  29. package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-BFJR-ITH.js +65 -0
  30. package/dist/dashboard/dist/assets/graph-CIvnjOQQ.js +1 -0
  31. package/dist/dashboard/dist/assets/index-BWX0sSZn.css +1 -0
  32. package/dist/dashboard/dist/assets/index-CbAFWEor.js +777 -0
  33. package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-OcK0Lxgi.js +2 -0
  34. package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-DTJukVOY.js +139 -0
  35. package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-Di65fNuD.js +89 -0
  36. package/dist/dashboard/dist/assets/layout-DAt24RVX.js +1 -0
  37. package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-DxI8MXCF.js +68 -0
  38. package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-BafKx3_Y.js +30 -0
  39. package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-BcZsArkk.js +7 -0
  40. package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-CqFAO2t6.js +64 -0
  41. package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-CqSaCg-3.js +10 -0
  42. package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-6IXD1uqW.js +145 -0
  43. package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-DvSVQAfp.js +1 -0
  44. package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-BMFdt0QQ.js +1 -0
  45. package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-Cll7Nvth.js +61 -0
  46. package/dist/dashboard/dist/assets/treemap-GDKQZRPO-DtqX8zNC.js +162 -0
  47. package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-zxwS9i0A.js +7 -0
  48. package/dist/dashboard/dist/index.html +2 -2
  49. package/dist/dashboard/dist/reports/coverage-summary.json +75 -1
  50. package/dist/dashboard/dist/reports/security-full.json +157 -0
  51. package/dist/src/compatibilityCoverage.d.ts +34 -15
  52. package/dist/src/compatibilityCoverage.d.ts.map +1 -1
  53. package/dist/src/compatibilityCoverage.js +387 -85
  54. package/dist/src/config/defaultConfig.d.ts.map +1 -1
  55. package/dist/src/config/defaultConfig.js +62 -0
  56. package/dist/src/config/schema.d.ts.map +1 -1
  57. package/dist/src/config/schema.js +1 -1
  58. package/dist/src/config/types.d.ts +81 -1
  59. package/dist/src/config/types.d.ts.map +1 -1
  60. package/dist/src/config/validateConfig.d.ts.map +1 -1
  61. package/dist/src/config/validateConfig.js +126 -0
  62. package/dist/src/contracts/compatibilityMatrix.d.ts +20 -0
  63. package/dist/src/contracts/compatibilityMatrix.d.ts.map +1 -0
  64. package/dist/src/contracts/compatibilityMatrix.js +198 -0
  65. package/dist/src/contracts/pactBrokerClient.d.ts +10 -0
  66. package/dist/src/contracts/pactBrokerClient.d.ts.map +1 -0
  67. package/dist/src/contracts/pactBrokerClient.js +117 -0
  68. package/dist/src/contracts/schemaEvolutionChecker.d.ts +17 -0
  69. package/dist/src/contracts/schemaEvolutionChecker.d.ts.map +1 -0
  70. package/dist/src/contracts/schemaEvolutionChecker.js +95 -0
  71. package/dist/src/contracts/springCloudContractParser.d.ts +10 -0
  72. package/dist/src/contracts/springCloudContractParser.d.ts.map +1 -0
  73. package/dist/src/contracts/springCloudContractParser.js +144 -0
  74. package/dist/src/discovery/fileClassifier.d.ts.map +1 -1
  75. package/dist/src/discovery/fileClassifier.js +25 -0
  76. package/dist/src/discovery/projectDiscovery.d.ts +2 -0
  77. package/dist/src/discovery/projectDiscovery.d.ts.map +1 -1
  78. package/dist/src/discovery/projectDiscovery.js +25 -25
  79. package/dist/src/index.js +233 -16
  80. package/dist/src/inference/routeInference.d.ts +10 -2
  81. package/dist/src/inference/routeInference.d.ts.map +1 -1
  82. package/dist/src/inference/routeInference.js +363 -62
  83. package/dist/src/languageDetection.d.ts.map +1 -1
  84. package/dist/src/languageDetection.js +21 -4
  85. package/dist/src/lib/index.d.ts +3 -0
  86. package/dist/src/lib/index.d.ts.map +1 -1
  87. package/dist/src/lib/index.js +3 -1
  88. package/dist/src/pipeline/stages/tia/parameterizedTestExpander.js +152 -79
  89. package/dist/src/pipeline/stages/tia/testEndpointMapper.d.ts +5 -1
  90. package/dist/src/pipeline/stages/tia/testEndpointMapper.d.ts.map +1 -1
  91. package/dist/src/pipeline/stages/tia/testEndpointMapper.js +356 -42
  92. package/dist/src/pipeline/stages/tia/testLayerClassifier.d.ts.map +1 -1
  93. package/dist/src/pipeline/stages/tia/testLayerClassifier.js +20 -5
  94. package/dist/src/pipeline/stages/tia/tiaStage.d.ts.map +1 -1
  95. package/dist/src/pipeline/stages/tia/tiaStage.js +3 -1
  96. package/dist/src/pipeline/stages/tia/types.d.ts +11 -2
  97. package/dist/src/pipeline/stages/tia/types.d.ts.map +1 -1
  98. package/dist/src/projectDefaults.d.ts +6 -0
  99. package/dist/src/projectDefaults.d.ts.map +1 -0
  100. package/dist/src/projectDefaults.js +43 -0
  101. package/dist/src/security/hub.d.ts +81 -0
  102. package/dist/src/security/hub.d.ts.map +1 -0
  103. package/dist/src/security/hub.js +420 -0
  104. package/dist/src/security/index.d.ts +1 -0
  105. package/dist/src/security/index.d.ts.map +1 -1
  106. package/dist/src/security/index.js +8 -2
  107. package/dist/src/security/normalizers/gitleaks.d.ts +7 -0
  108. package/dist/src/security/normalizers/gitleaks.d.ts.map +1 -0
  109. package/dist/src/security/normalizers/gitleaks.js +32 -0
  110. package/dist/src/security/scanners/gitleaks.d.ts +3 -0
  111. package/dist/src/security/scanners/gitleaks.d.ts.map +1 -0
  112. package/dist/src/security/scanners/gitleaks.js +105 -0
  113. package/dist/src/security/scanners/semgrep.d.ts.map +1 -1
  114. package/dist/src/security/scanners/semgrep.js +24 -2
  115. package/dist/src/security/scanners/trivy.d.ts.map +1 -1
  116. package/dist/src/security/scanners/trivy.js +24 -2
  117. package/dist/src/security/scanners/zap.d.ts.map +1 -1
  118. package/dist/src/security/scanners/zap.js +27 -2
  119. package/dist/src/security/types.d.ts +15 -1
  120. package/dist/src/security/types.d.ts.map +1 -1
  121. package/dist/src/streaming/schema/index.d.ts +23 -0
  122. package/dist/src/streaming/schema/index.d.ts.map +1 -0
  123. package/dist/src/streaming/schema/index.js +196 -0
  124. package/dist/src/summary/markdownRenderer.d.ts.map +1 -1
  125. package/dist/src/summary/markdownRenderer.js +15 -1
  126. package/dist/src/summary/summaryTypes.d.ts.map +1 -1
  127. package/dist/src/summary/summaryTypes.js +1 -0
  128. package/dist/src/unitAnalysis.d.ts +145 -0
  129. package/dist/src/unitAnalysis.d.ts.map +1 -0
  130. package/dist/src/unitAnalysis.js +1392 -0
  131. package/package.json +1 -1
@@ -38,56 +38,37 @@ function expandJavaKotlinParameterized(filePath, content) {
38
38
  const lines = content.split('\n');
39
39
  for (let i = 0; i < lines.length; i++) {
40
40
  const line = lines[i].trim();
41
- // @ParameterizedTest must precede the data source annotation
42
41
  if (!line.includes('@ParameterizedTest'))
43
42
  continue;
44
- // Look ahead for data source annotations
45
43
  let testName = 'unknown';
46
44
  let variantCount = 'unresolvable';
47
45
  let pattern = '@ParameterizedTest';
48
- for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
46
+ for (let j = i + 1; j < Math.min(i + 12, lines.length); j++) {
49
47
  const nextLine = lines[j].trim();
50
- // Extract test method name
51
- const methodMatch = /(?:void|fun)\s+(\w+)\s*\(/.exec(nextLine);
52
- if (methodMatch) {
53
- testName = methodMatch[1];
54
- break;
55
- }
56
- // @ValueSource(strings = {"a", "b", "c"})
57
48
  const valueSourceMatch = /@ValueSource\(\s*\w+\s*=\s*\{([^}]+)\}/.exec(nextLine);
58
49
  if (valueSourceMatch) {
59
- variantCount = valueSourceMatch[1].split(',').length;
50
+ variantCount = countTopLevelArguments(valueSourceMatch[1]);
60
51
  pattern = '@ValueSource';
61
- continue;
62
52
  }
63
- // @CsvSource({"a,1", "b,2", "c,3"})
64
53
  const csvSourceMatch = /@CsvSource\(\s*(?:value\s*=\s*)?\{([^}]+)\}/.exec(nextLine);
65
54
  if (csvSourceMatch) {
66
55
  variantCount = csvSourceMatch[1].split(/",\s*"/).length;
67
56
  pattern = '@CsvSource';
68
- continue;
69
57
  }
70
- // @MethodSource("methodName")
71
58
  const methodSourceMatch = /@MethodSource\(\s*"(\w+)"/.exec(nextLine);
72
59
  if (methodSourceMatch) {
73
60
  pattern = `@MethodSource(${methodSourceMatch[1]})`;
74
- // Try to find the method and count Stream.of() arguments
75
- const sourceMethodRegex = new RegExp(`(?:static\\s+)?(?:Stream|List|Collection|Set).*?\\s+${methodSourceMatch[1]}\\s*\\([^)]*\\)\\s*\\{([\\s\\S]*?)\\}`, 'm');
76
- const sourceMethodMatch = sourceMethodRegex.exec(content);
77
- if (sourceMethodMatch) {
78
- const body = sourceMethodMatch[1];
79
- const argsMatch = body.match(/(?:Arguments\.of|of)\s*\(/g);
80
- if (argsMatch) {
81
- variantCount = argsMatch.length;
82
- }
83
- }
84
- continue;
61
+ variantCount = countMethodSourceVariants(content, methodSourceMatch[1]);
85
62
  }
86
- // @EnumSource(MyEnum.class)
87
- if (nextLine.includes('@EnumSource')) {
63
+ const enumSourceMatch = /@EnumSource\(\s*(\w+)(?:\.class|::class)/.exec(nextLine);
64
+ if (enumSourceMatch) {
88
65
  pattern = '@EnumSource';
89
- variantCount = 'unresolvable'; // Would need to find enum declaration
90
- continue;
66
+ variantCount = countEnumValues(content, enumSourceMatch[1]);
67
+ }
68
+ const methodMatch = /(?:void|fun)\s+(\w+)\s*\(/.exec(nextLine);
69
+ if (methodMatch) {
70
+ testName = methodMatch[1];
71
+ break;
91
72
  }
92
73
  }
93
74
  results.push({
@@ -107,29 +88,33 @@ function expandJestParameterized(filePath, content) {
107
88
  const lines = content.split('\n');
108
89
  for (let i = 0; i < lines.length; i++) {
109
90
  const line = lines[i];
110
- // test.each([...])('name', ...)
111
- // it.each([...])('name', ...)
112
- // describe.each([...])('name', ...)
113
- const eachMatch = /(?:test|it|describe)\.each\s*\(\s*\[/.exec(line);
91
+ const lineOffset = content.indexOf(line);
92
+ const inlineEachMatch = /(?:test|it|describe)\.each\s*\(\s*\[/.exec(line);
93
+ const variableEachMatch = /(?:test|it|describe)\.each\s*\(\s*([A-Za-z_]\w*)\s*\)/.exec(line);
94
+ const eachMatch = inlineEachMatch !== null && inlineEachMatch !== void 0 ? inlineEachMatch : variableEachMatch;
114
95
  if (eachMatch) {
115
- // Try to extract the array and count items
116
- const arrayContent = extractBalancedBrackets(content, content.indexOf(eachMatch[0], i > 0 ? content.indexOf(lines[i]) : 0));
117
- const variantCount = arrayContent ? countArrayElements(arrayContent) : 'unresolvable';
118
- // Extract test name from the next argument
119
- const nameMatch = /\)\s*\(\s*['"`]([^'"`]+)['"`]/.exec(content.substring(content.indexOf(eachMatch[0])));
96
+ let variantCount = 'unresolvable';
97
+ if (inlineEachMatch) {
98
+ const bracketIndex = content.indexOf('[', lineOffset);
99
+ const arrayContent = extractBalanced(content, bracketIndex, '[', ']');
100
+ variantCount = arrayContent ? countArrayElements(arrayContent) : 'unresolvable';
101
+ }
102
+ else if (variableEachMatch) {
103
+ variantCount = resolveNamedArrayCount(content, variableEachMatch[1]);
104
+ }
105
+ const nameMatch = /\)\s*\(\s*['"`]([^'"`]+)['"`]/.exec(content.substring(lineOffset));
120
106
  const testName = (_a = nameMatch === null || nameMatch === void 0 ? void 0 : nameMatch[1]) !== null && _a !== void 0 ? _a : 'parameterized test';
107
+ const callsite = eachMatch[0].split('.')[0];
121
108
  results.push({
122
109
  testFilePath: filePath,
123
110
  testName,
124
111
  variantCount,
125
- pattern: 'test.each',
112
+ pattern: inlineEachMatch ? `${callsite}.each` : `${callsite}.each(variable)`,
126
113
  line: i + 1,
127
114
  });
128
115
  }
129
- // test.each`template`('name', ...) — tagged template form
130
116
  const templateMatch = /(?:test|it|describe)\.each\s*`/.exec(line);
131
117
  if (templateMatch && !eachMatch) {
132
- // Count rows in tagged template (lines between backticks, minus header)
133
118
  let rowCount = 0;
134
119
  for (let j = i + 1; j < lines.length; j++) {
135
120
  if (lines[j].includes('`'))
@@ -137,12 +122,11 @@ function expandJestParameterized(filePath, content) {
137
122
  if (lines[j].trim())
138
123
  rowCount++;
139
124
  }
140
- const variantCount = rowCount > 0 ? rowCount : 'unresolvable';
141
125
  results.push({
142
126
  testFilePath: filePath,
143
127
  testName: 'parameterized test',
144
- variantCount,
145
- pattern: 'test.each (template)',
128
+ variantCount: rowCount > 0 ? rowCount : 'unresolvable',
129
+ pattern: `${templateMatch[0].split('.')[0]}.each (template)`,
146
130
  line: i + 1,
147
131
  });
148
132
  }
@@ -155,48 +139,61 @@ function expandPytestParameterized(filePath, content) {
155
139
  const lines = content.split('\n');
156
140
  for (let i = 0; i < lines.length; i++) {
157
141
  const line = lines[i].trim();
158
- // @pytest.mark.parametrize("name", [...])
159
142
  const paramMatch = /@pytest\.mark\.parametrize\s*\(/.exec(line);
160
143
  if (paramMatch) {
161
- // Try to extract array content and count elements
162
144
  let variantCount = 'unresolvable';
163
- // Look for the bracket content
164
145
  const fullContent = lines.slice(i, Math.min(i + 20, lines.length)).join('\n');
165
- const bracketContent = extractBalancedBrackets(fullContent, fullContent.indexOf('['));
146
+ const bracketContent = extractBalanced(fullContent, fullContent.indexOf('['), '[', ']');
166
147
  if (bracketContent) {
167
148
  variantCount = countPytestParams(bracketContent);
168
149
  }
169
- // Extract test name from following def line
170
- let testName = 'unknown';
171
- for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
172
- const defMatch = /def\s+(\w+)\s*\(/.exec(lines[j]);
173
- if (defMatch) {
174
- testName = defMatch[1];
175
- break;
176
- }
177
- }
178
150
  results.push({
179
151
  testFilePath: filePath,
180
- testName,
152
+ testName: findPythonDefinitionName(lines, i),
181
153
  variantCount,
182
154
  pattern: '@pytest.mark.parametrize',
183
155
  line: i + 1,
184
156
  });
185
157
  }
158
+ const fixtureMatch = /@pytest\.fixture\s*\(\s*params\s*=\s*\[/.exec(line);
159
+ if (fixtureMatch) {
160
+ let variantCount = 'unresolvable';
161
+ const fullContent = lines.slice(i, Math.min(i + 20, lines.length)).join('\n');
162
+ const bracketContent = extractBalanced(fullContent, fullContent.indexOf('['), '[', ']');
163
+ if (bracketContent) {
164
+ variantCount = countPytestParams(bracketContent);
165
+ }
166
+ results.push({
167
+ testFilePath: filePath,
168
+ testName: findPythonDefinitionName(lines, i),
169
+ variantCount,
170
+ pattern: '@pytest.fixture(params)',
171
+ line: i + 1,
172
+ });
173
+ }
186
174
  }
187
175
  return results;
188
176
  }
189
177
  // ─── Helpers ─────────────────────────────────────────────────────────────────
190
- function extractBalancedBrackets(content, startIndex) {
191
- if (startIndex < 0 || startIndex >= content.length || content[startIndex] !== '[') {
178
+ function findPythonDefinitionName(lines, startIndex) {
179
+ for (let j = startIndex + 1; j < Math.min(startIndex + 10, lines.length); j++) {
180
+ const defMatch = /def\s+(\w+)\s*\(/.exec(lines[j]);
181
+ if (defMatch) {
182
+ return defMatch[1];
183
+ }
184
+ }
185
+ return 'unknown';
186
+ }
187
+ function extractBalanced(content, startIndex, openChar, closeChar) {
188
+ if (startIndex < 0 || startIndex >= content.length || content[startIndex] !== openChar) {
192
189
  return undefined;
193
190
  }
194
191
  let depth = 0;
195
192
  let i = startIndex;
196
193
  while (i < content.length) {
197
- if (content[i] === '[')
194
+ if (content[i] === openChar)
198
195
  depth++;
199
- else if (content[i] === ']') {
196
+ else if (content[i] === closeChar) {
200
197
  depth--;
201
198
  if (depth === 0) {
202
199
  return content.substring(startIndex + 1, i);
@@ -207,32 +204,108 @@ function extractBalancedBrackets(content, startIndex) {
207
204
  return undefined;
208
205
  }
209
206
  function countArrayElements(arrayContent) {
210
- // Count top-level elements (not nested)
207
+ const trimmed = arrayContent.trim();
208
+ if (trimmed.length === 0)
209
+ return 0;
211
210
  let depth = 0;
212
- let count = 1;
211
+ let count = 0;
212
+ let segmentHasContent = false;
213
213
  for (const char of arrayContent) {
214
- if (char === '[' || char === '(' || char === '{')
214
+ if (char === '[' || char === '(' || char === '{') {
215
215
  depth++;
216
- else if (char === ']' || char === ')' || char === '}')
216
+ segmentHasContent = true;
217
+ }
218
+ else if (char === ']' || char === ')' || char === '}') {
217
219
  depth--;
218
- else if (char === ',' && depth === 0)
219
- count++;
220
+ }
221
+ else if (char === ',' && depth === 0) {
222
+ if (segmentHasContent) {
223
+ count++;
224
+ segmentHasContent = false;
225
+ }
226
+ continue;
227
+ }
228
+ else if (!/\s/.test(char)) {
229
+ segmentHasContent = true;
230
+ }
220
231
  }
221
- // If only whitespace, return 0
222
- if (arrayContent.trim().length === 0)
232
+ return segmentHasContent ? count + 1 : count;
233
+ }
234
+ function countTopLevelArguments(content) {
235
+ const trimmed = content.trim();
236
+ if (!trimmed)
223
237
  return 0;
224
- return count;
238
+ return countArrayElements(trimmed);
225
239
  }
226
240
  function countPytestParams(bracketContent) {
227
- // Each top-level tuple/value is a test case
228
241
  const trimmed = bracketContent.trim();
229
242
  if (!trimmed)
230
243
  return 0;
231
- // Count top-level commas for simple values
232
- // For tuples, count each (...) group
233
- const tupleMatches = trimmed.match(/\([^)]*\)/g);
234
- if (tupleMatches)
235
- return tupleMatches.length;
236
- // Otherwise count comma-separated values
244
+ const tupleCount = countTopLevelTuples(trimmed);
245
+ if (tupleCount > 0)
246
+ return tupleCount;
237
247
  return countArrayElements(trimmed);
238
248
  }
249
+ function countMethodSourceVariants(content, methodName) {
250
+ var _a;
251
+ const sourceMethodRegex = new RegExp(`(?:static\\s+)?(?:[\\w<>,?]+\\s+)+${methodName}\\s*\\([^)]*\\)\\s*\\{([\\s\\S]*?)\\}`, 'm');
252
+ const sourceMethodMatch = sourceMethodRegex.exec(content);
253
+ if (!sourceMethodMatch)
254
+ return 'unresolvable';
255
+ const body = sourceMethodMatch[1];
256
+ const argsMatch = body.match(/Arguments\.of\s*\(/g);
257
+ if (argsMatch) {
258
+ return argsMatch.length;
259
+ }
260
+ const collectionMatch = (_a = body.match(/(?:Stream|List|Sequence|Collection|Set)\.of\s*\(([\s\S]*?)\)/m)) !== null && _a !== void 0 ? _a : body.match(/(?:listOf|arrayOf|sequenceOf|setOf)\s*\(([\s\S]*?)\)/m);
261
+ if (collectionMatch) {
262
+ return countTopLevelArguments(collectionMatch[1]);
263
+ }
264
+ return 'unresolvable';
265
+ }
266
+ function countEnumValues(content, enumName) {
267
+ const enumRegex = new RegExp(`enum(?:\\s+class)?\\s+${enumName}\\s*(?::[^\\{]+)?\\{([\\s\\S]*?)\\}`, 'm');
268
+ const enumMatch = enumRegex.exec(content);
269
+ if (!enumMatch)
270
+ return 'unresolvable';
271
+ const body = enumMatch[1]
272
+ .replace(/\/\*[\s\S]*?\*\//g, '')
273
+ .replace(/\/\/.*$/gm, '');
274
+ const values = body
275
+ .split(',')
276
+ .map((value) => value.trim())
277
+ .filter((value) => value.length > 0)
278
+ .map((value) => value.replace(/\([^)]*\).*/, '').trim())
279
+ .filter((value) => /^[A-Z][A-Za-z0-9_]*$/.test(value));
280
+ return values.length > 0 ? values.length : 'unresolvable';
281
+ }
282
+ function resolveNamedArrayCount(content, variableName) {
283
+ const declarationRegex = new RegExp(`(?:const|let|var)\\s+${variableName}\\s*=\\s*\\[`, 'm');
284
+ const declarationMatch = declarationRegex.exec(content);
285
+ if (!declarationMatch)
286
+ return 'unresolvable';
287
+ const bracketIndex = declarationMatch.index + declarationMatch[0].length - 1;
288
+ const arrayContent = extractBalanced(content, bracketIndex, '[', ']');
289
+ return arrayContent ? countArrayElements(arrayContent) : 'unresolvable';
290
+ }
291
+ function countTopLevelTuples(content) {
292
+ let depth = 0;
293
+ let count = 0;
294
+ let tupleStarted = false;
295
+ for (const char of content) {
296
+ if (char === '(') {
297
+ depth++;
298
+ if (depth === 1) {
299
+ tupleStarted = true;
300
+ }
301
+ }
302
+ else if (char === ')') {
303
+ if (depth === 1 && tupleStarted) {
304
+ count++;
305
+ tupleStarted = false;
306
+ }
307
+ depth = Math.max(0, depth - 1);
308
+ }
309
+ }
310
+ return count;
311
+ }
@@ -9,6 +9,8 @@
9
9
  * 5. Framework metadata: Framework annotations link test to endpoint
10
10
  * 6. Helper traversal: URL resolved through helper function chain
11
11
  * 7. Page object: URL resolved through page object pattern
12
+ * 8. Service call: test covers a service method that is linked to an endpoint via call graph
13
+ * 9. Business rule: test method name implies a business rule covered by the test
12
14
  */
13
15
  import type { TestEndpointMapping } from './types';
14
16
  import type { CoverageKnowledgeGraph } from '../../graph';
@@ -17,6 +19,8 @@ import type { CoverageKnowledgeGraph } from '../../graph';
17
19
  *
18
20
  * @param graph - The coverage knowledge graph (from AST stage)
19
21
  * @param testFiles - List of test file paths
22
+ * @param fileContents - Optional test file contents keyed by file path. When absent,
23
+ * the mapper falls back to graph node metadata and finally to the filesystem.
20
24
  */
21
- export declare function mapTestsToEndpoints(graph: CoverageKnowledgeGraph, testFiles: string[]): TestEndpointMapping[];
25
+ export declare function mapTestsToEndpoints(graph: CoverageKnowledgeGraph, testFiles: string[], fileContents?: Record<string, string>): TestEndpointMapping[];
22
26
  //# sourceMappingURL=testEndpointMapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testEndpointMapper.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/tia/testEndpointMapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAG1D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,sBAAsB,EAC7B,SAAS,EAAE,MAAM,EAAE,GAClB,mBAAmB,EAAE,CAqFvB"}
1
+ {"version":3,"file":"testEndpointMapper.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/tia/testEndpointMapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AA4B1D;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,sBAAsB,EAC7B,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACxC,mBAAmB,EAAE,CAyJvB"}