api-tests-coverage 1.0.23 → 1.0.25
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/README.md +39 -0
- package/config.yaml.example +35 -0
- package/dist/dashboard/dist/assets/_basePickBy-BHjg34fk.js +1 -0
- package/dist/dashboard/dist/assets/_basePickBy-D4Hl8chy.js +1 -0
- package/dist/dashboard/dist/assets/_baseUniq-BSUUnV_V.js +1 -0
- package/dist/dashboard/dist/assets/_baseUniq-DxJYHd7T.js +1 -0
- package/dist/dashboard/dist/assets/arc-DcXkmNi0.js +1 -0
- package/dist/dashboard/dist/assets/arc-DhDluTY5.js +1 -0
- package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-ChMY32ql.js +36 -0
- package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-DGlUU7dC.js +36 -0
- package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-CgXi3kEZ.js +122 -0
- package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-DVhWtRxG.js +122 -0
- package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-B6esYq70.js +10 -0
- package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-Cr3xB15y.js +10 -0
- package/dist/dashboard/dist/assets/channel-DYAie-7m.js +1 -0
- package/dist/dashboard/dist/assets/channel-Df6s6dhy.js +1 -0
- package/dist/dashboard/dist/assets/chunk-4BX2VUAB-B7Pkx3C3.js +1 -0
- package/dist/dashboard/dist/assets/chunk-4BX2VUAB-BaW3__pI.js +1 -0
- package/dist/dashboard/dist/assets/chunk-55IACEB6-8ClDkPsD.js +1 -0
- package/dist/dashboard/dist/assets/chunk-55IACEB6-DyYevfEQ.js +1 -0
- package/dist/dashboard/dist/assets/chunk-B4BG7PRW--cjprmFF.js +165 -0
- package/dist/dashboard/dist/assets/chunk-B4BG7PRW-C2bwZFec.js +165 -0
- package/dist/dashboard/dist/assets/chunk-DI55MBZ5-D9bxNSnS.js +220 -0
- package/dist/dashboard/dist/assets/chunk-DI55MBZ5-DO0T2xne.js +220 -0
- package/dist/dashboard/dist/assets/chunk-FMBD7UC4-CCYA4j_f.js +15 -0
- package/dist/dashboard/dist/assets/chunk-FMBD7UC4-CSek7h3u.js +15 -0
- package/dist/dashboard/dist/assets/chunk-QN33PNHL-BRCzcTtl.js +1 -0
- package/dist/dashboard/dist/assets/chunk-QN33PNHL-Cdhqs7xo.js +1 -0
- package/dist/dashboard/dist/assets/chunk-QZHKN3VN-BzHw38Ki.js +1 -0
- package/dist/dashboard/dist/assets/chunk-QZHKN3VN-TFdw1-iS.js +1 -0
- package/dist/dashboard/dist/assets/chunk-TZMSLE5B-CWotsEVz.js +1 -0
- package/dist/dashboard/dist/assets/chunk-TZMSLE5B-dkJ0rsgF.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-DiIv5Pho.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-Dr8j2BkV.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-DiIv5Pho.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-Dr8j2BkV.js +1 -0
- package/dist/dashboard/dist/assets/clone-B4LorrSy.js +1 -0
- package/dist/dashboard/dist/assets/clone-D-A0zWrx.js +1 -0
- package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-L06bC_vI.js +1 -0
- package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-jzGbyPIS.js +1 -0
- package/dist/dashboard/dist/assets/dagre-6UL2VRFP-D7rgvBx1.js +4 -0
- package/dist/dashboard/dist/assets/dagre-6UL2VRFP-LQJxsDjp.js +4 -0
- package/dist/dashboard/dist/assets/diagram-PSM6KHXK-2rYklqon.js +24 -0
- package/dist/dashboard/dist/assets/diagram-PSM6KHXK-Bguvtjhb.js +24 -0
- package/dist/dashboard/dist/assets/diagram-QEK2KX5R-CDM-bAUc.js +43 -0
- package/dist/dashboard/dist/assets/diagram-QEK2KX5R-CGrvALqm.js +43 -0
- package/dist/dashboard/dist/assets/diagram-S2PKOQOG-DA3c-QP4.js +24 -0
- package/dist/dashboard/dist/assets/diagram-S2PKOQOG-DNQuKOCA.js +24 -0
- package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-BsYH8cLH.js +60 -0
- package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-CgAEujxC.js +60 -0
- package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-C8juupCT.js +162 -0
- package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-Da_JhBCy.js +162 -0
- package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-BzXOAiOm.js +267 -0
- package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-D8FTswNn.js +267 -0
- package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-6Rn0oWgA.js +65 -0
- package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-BFJR-ITH.js +65 -0
- package/dist/dashboard/dist/assets/graph-CIvnjOQQ.js +1 -0
- package/dist/dashboard/dist/assets/graph-VO6A5Zyb.js +1 -0
- package/dist/dashboard/dist/assets/index-BD_Ue7zI.js +777 -0
- package/dist/dashboard/dist/assets/index-BWX0sSZn.css +1 -0
- package/dist/dashboard/dist/assets/index-CbAFWEor.js +777 -0
- package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-BEOgUULT.js +2 -0
- package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-OcK0Lxgi.js +2 -0
- package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-CBFUW_L2.js +139 -0
- package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-DTJukVOY.js +139 -0
- package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-BXpodEnf.js +89 -0
- package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-Di65fNuD.js +89 -0
- package/dist/dashboard/dist/assets/layout-Cpj8l95P.js +1 -0
- package/dist/dashboard/dist/assets/layout-DAt24RVX.js +1 -0
- package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-DxI8MXCF.js +68 -0
- package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-_3DZbNEl.js +68 -0
- package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-B--OM1Gs.js +30 -0
- package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-BafKx3_Y.js +30 -0
- package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-BcZsArkk.js +7 -0
- package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-CDx0v76p.js +7 -0
- package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-CbvZ1a-7.js +64 -0
- package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-CqFAO2t6.js +64 -0
- package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-CqSaCg-3.js +10 -0
- package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-D-fji9s3.js +10 -0
- package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-6IXD1uqW.js +145 -0
- package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-CWB1Ub2x.js +145 -0
- package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-DvSVQAfp.js +1 -0
- package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-J-c1KNJ7.js +1 -0
- package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-BMFdt0QQ.js +1 -0
- package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-DRL2jF9p.js +1 -0
- package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-Cll7Nvth.js +61 -0
- package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-LOxOovzx.js +61 -0
- package/dist/dashboard/dist/assets/treemap-GDKQZRPO-C6DntuKu.js +162 -0
- package/dist/dashboard/dist/assets/treemap-GDKQZRPO-DtqX8zNC.js +162 -0
- package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-BKisDUaz.js +7 -0
- package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-zxwS9i0A.js +7 -0
- package/dist/dashboard/dist/index.html +2 -2
- package/dist/dashboard/dist/reports/coverage-summary.json +75 -1
- package/dist/dashboard/dist/reports/security-full.json +157 -0
- package/dist/src/compatibilityCoverage.d.ts +34 -15
- package/dist/src/compatibilityCoverage.d.ts.map +1 -1
- package/dist/src/compatibilityCoverage.js +387 -85
- package/dist/src/config/defaultConfig.d.ts.map +1 -1
- package/dist/src/config/defaultConfig.js +62 -0
- package/dist/src/config/schema.d.ts.map +1 -1
- package/dist/src/config/schema.js +1 -1
- package/dist/src/config/types.d.ts +81 -1
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/config/validateConfig.d.ts.map +1 -1
- package/dist/src/config/validateConfig.js +126 -0
- package/dist/src/contracts/compatibilityMatrix.d.ts +20 -0
- package/dist/src/contracts/compatibilityMatrix.d.ts.map +1 -0
- package/dist/src/contracts/compatibilityMatrix.js +198 -0
- package/dist/src/contracts/pactBrokerClient.d.ts +10 -0
- package/dist/src/contracts/pactBrokerClient.d.ts.map +1 -0
- package/dist/src/contracts/pactBrokerClient.js +117 -0
- package/dist/src/contracts/schemaEvolutionChecker.d.ts +17 -0
- package/dist/src/contracts/schemaEvolutionChecker.d.ts.map +1 -0
- package/dist/src/contracts/schemaEvolutionChecker.js +95 -0
- package/dist/src/contracts/springCloudContractParser.d.ts +10 -0
- package/dist/src/contracts/springCloudContractParser.d.ts.map +1 -0
- package/dist/src/contracts/springCloudContractParser.js +144 -0
- package/dist/src/discovery/fileClassifier.d.ts.map +1 -1
- package/dist/src/discovery/fileClassifier.js +25 -0
- package/dist/src/discovery/projectDiscovery.d.ts +2 -0
- package/dist/src/discovery/projectDiscovery.d.ts.map +1 -1
- package/dist/src/discovery/projectDiscovery.js +25 -25
- package/dist/src/index.js +233 -16
- package/dist/src/inference/routeInference.d.ts +10 -2
- package/dist/src/inference/routeInference.d.ts.map +1 -1
- package/dist/src/inference/routeInference.js +363 -62
- package/dist/src/languageDetection.d.ts.map +1 -1
- package/dist/src/languageDetection.js +21 -4
- package/dist/src/lib/index.d.ts +3 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +3 -1
- package/dist/src/pipeline/stages/tia/parameterizedTestExpander.js +152 -79
- package/dist/src/pipeline/stages/tia/testEndpointMapper.d.ts +5 -1
- package/dist/src/pipeline/stages/tia/testEndpointMapper.d.ts.map +1 -1
- package/dist/src/pipeline/stages/tia/testEndpointMapper.js +356 -42
- package/dist/src/pipeline/stages/tia/testLayerClassifier.d.ts.map +1 -1
- package/dist/src/pipeline/stages/tia/testLayerClassifier.js +20 -5
- package/dist/src/pipeline/stages/tia/tiaStage.d.ts.map +1 -1
- package/dist/src/pipeline/stages/tia/tiaStage.js +3 -1
- package/dist/src/pipeline/stages/tia/types.d.ts +11 -2
- package/dist/src/pipeline/stages/tia/types.d.ts.map +1 -1
- package/dist/src/projectDefaults.d.ts +6 -0
- package/dist/src/projectDefaults.d.ts.map +1 -0
- package/dist/src/projectDefaults.js +43 -0
- package/dist/src/security/hub.d.ts +81 -0
- package/dist/src/security/hub.d.ts.map +1 -0
- package/dist/src/security/hub.js +420 -0
- package/dist/src/security/index.d.ts +1 -0
- package/dist/src/security/index.d.ts.map +1 -1
- package/dist/src/security/index.js +8 -2
- package/dist/src/security/normalizers/gitleaks.d.ts +7 -0
- package/dist/src/security/normalizers/gitleaks.d.ts.map +1 -0
- package/dist/src/security/normalizers/gitleaks.js +32 -0
- package/dist/src/security/scanners/gitleaks.d.ts +3 -0
- package/dist/src/security/scanners/gitleaks.d.ts.map +1 -0
- package/dist/src/security/scanners/gitleaks.js +105 -0
- package/dist/src/security/scanners/semgrep.d.ts.map +1 -1
- package/dist/src/security/scanners/semgrep.js +24 -2
- package/dist/src/security/scanners/trivy.d.ts.map +1 -1
- package/dist/src/security/scanners/trivy.js +24 -2
- package/dist/src/security/scanners/zap.d.ts.map +1 -1
- package/dist/src/security/scanners/zap.js +27 -2
- package/dist/src/security/types.d.ts +15 -1
- package/dist/src/security/types.d.ts.map +1 -1
- package/dist/src/streaming/schema/index.d.ts +23 -0
- package/dist/src/streaming/schema/index.d.ts.map +1 -0
- package/dist/src/streaming/schema/index.js +196 -0
- package/dist/src/summary/markdownRenderer.d.ts.map +1 -1
- package/dist/src/summary/markdownRenderer.js +15 -1
- package/dist/src/summary/summaryTypes.d.ts.map +1 -1
- package/dist/src/summary/summaryTypes.js +1 -0
- package/dist/src/unitAnalysis.d.ts +145 -0
- package/dist/src/unitAnalysis.d.ts.map +1 -0
- package/dist/src/unitAnalysis.js +1392 -0
- 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 +
|
|
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]
|
|
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
|
-
|
|
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
|
-
|
|
87
|
-
if (
|
|
63
|
+
const enumSourceMatch = /@EnumSource\(\s*(\w+)(?:\.class|::class)/.exec(nextLine);
|
|
64
|
+
if (enumSourceMatch) {
|
|
88
65
|
pattern = '@EnumSource';
|
|
89
|
-
variantCount =
|
|
90
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const eachMatch =
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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:
|
|
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: '
|
|
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 =
|
|
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
|
|
191
|
-
|
|
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
|
-
|
|
207
|
+
const trimmed = arrayContent.trim();
|
|
208
|
+
if (trimmed.length === 0)
|
|
209
|
+
return 0;
|
|
211
210
|
let depth = 0;
|
|
212
|
-
let count =
|
|
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
|
-
|
|
216
|
+
segmentHasContent = true;
|
|
217
|
+
}
|
|
218
|
+
else if (char === ']' || char === ')' || char === '}') {
|
|
217
219
|
depth--;
|
|
218
|
-
|
|
219
|
-
|
|
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
|
-
|
|
222
|
-
|
|
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
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
|
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"}
|