api-tests-coverage 1.0.15 → 1.0.17

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 (139) hide show
  1. package/dist/dashboard/dist/assets/_basePickBy-C2jmWITn.js +1 -0
  2. package/dist/dashboard/dist/assets/_baseUniq-DE6cyzJb.js +1 -0
  3. package/dist/dashboard/dist/assets/arc-B-Q4nGPT.js +1 -0
  4. package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-C_5dqWCI.js +36 -0
  5. package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-DbGIO6Kt.js +122 -0
  6. package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-CAFpcejP.js +10 -0
  7. package/dist/dashboard/dist/assets/channel-Di9el3wE.js +1 -0
  8. package/dist/dashboard/dist/assets/chunk-4BX2VUAB-DY1boKsq.js +1 -0
  9. package/dist/dashboard/dist/assets/chunk-55IACEB6-BSL35gyW.js +1 -0
  10. package/dist/dashboard/dist/assets/chunk-B4BG7PRW-eTDXrKrv.js +165 -0
  11. package/dist/dashboard/dist/assets/chunk-DI55MBZ5-M-8I3jEy.js +220 -0
  12. package/dist/dashboard/dist/assets/chunk-FMBD7UC4-bSA0XiS0.js +15 -0
  13. package/dist/dashboard/dist/assets/chunk-QN33PNHL-BrOIYUBs.js +1 -0
  14. package/dist/dashboard/dist/assets/chunk-QZHKN3VN-CliaQGD4.js +1 -0
  15. package/dist/dashboard/dist/assets/chunk-TZMSLE5B-CyhcxGB1.js +1 -0
  16. package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-BkGN4Cpz.js +1 -0
  17. package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-BkGN4Cpz.js +1 -0
  18. package/dist/dashboard/dist/assets/clone-Cvq8JuOb.js +1 -0
  19. package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-BUkL7Wtq.js +1 -0
  20. package/dist/dashboard/dist/assets/dagre-6UL2VRFP-B8oEROJc.js +4 -0
  21. package/dist/dashboard/dist/assets/diagram-PSM6KHXK-5uki9Dw8.js +24 -0
  22. package/dist/dashboard/dist/assets/diagram-QEK2KX5R-BRNhmby2.js +43 -0
  23. package/dist/dashboard/dist/assets/diagram-S2PKOQOG-D-ku_X8U.js +24 -0
  24. package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-DGl6gPe2.js +60 -0
  25. package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-Co89qYBD.js +162 -0
  26. package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-2r3WpWQC.js +267 -0
  27. package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-CuJ5l3TK.js +65 -0
  28. package/dist/dashboard/dist/assets/graph-ZtgwAPQj.js +1 -0
  29. package/dist/dashboard/dist/assets/index-D3sRJga7.js +777 -0
  30. package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-ujnMqVz3.js +2 -0
  31. package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-DQzfeBIo.js +139 -0
  32. package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-ueIaoeks.js +89 -0
  33. package/dist/dashboard/dist/assets/layout-B1fTYUMj.js +1 -0
  34. package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-B7wYeLe1.js +68 -0
  35. package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-Bf8vKEOf.js +30 -0
  36. package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-CM8qiFLR.js +7 -0
  37. package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-DPTtP4Ve.js +64 -0
  38. package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-DEVTdH0h.js +10 -0
  39. package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-Bjr5wgXg.js +145 -0
  40. package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-DDrhZYly.js +1 -0
  41. package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-Im6pH8C-.js +1 -0
  42. package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-DAT3r9va.js +61 -0
  43. package/dist/dashboard/dist/assets/treemap-GDKQZRPO-BlA8rg0m.js +162 -0
  44. package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-7aSkQtVu.js +7 -0
  45. package/dist/src/ast/astTypes.d.ts +86 -0
  46. package/dist/src/ast/astTypes.d.ts.map +1 -1
  47. package/dist/src/discovery/fileClassifier.d.ts.map +1 -1
  48. package/dist/src/discovery/fileClassifier.js +15 -16
  49. package/dist/src/discovery/frameworkDetector.d.ts +28 -0
  50. package/dist/src/discovery/frameworkDetector.d.ts.map +1 -0
  51. package/dist/src/discovery/frameworkDetector.js +189 -0
  52. package/dist/src/discovery/projectDiscovery.d.ts +5 -1
  53. package/dist/src/discovery/projectDiscovery.d.ts.map +1 -1
  54. package/dist/src/discovery/projectDiscovery.js +8 -1
  55. package/dist/src/inference/routeInference.d.ts.map +1 -1
  56. package/dist/src/inference/routeInference.js +224 -1
  57. package/dist/src/languages/java/graphqlSchemaParser.d.ts +65 -0
  58. package/dist/src/languages/java/graphqlSchemaParser.d.ts.map +1 -0
  59. package/dist/src/languages/java/graphqlSchemaParser.js +164 -0
  60. package/dist/src/languages/java/mybatisXmlParser.d.ts +52 -0
  61. package/dist/src/languages/java/mybatisXmlParser.d.ts.map +1 -0
  62. package/dist/src/languages/java/mybatisXmlParser.js +107 -0
  63. package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -1
  64. package/dist/src/languages/java/semanticBuilder.js +69 -12
  65. package/dist/src/languages/javascript/angularDetector.d.ts +74 -0
  66. package/dist/src/languages/javascript/angularDetector.d.ts.map +1 -0
  67. package/dist/src/languages/javascript/angularDetector.js +227 -0
  68. package/dist/src/languages/javascript/assertionResolver.js +6 -4
  69. package/dist/src/languages/javascript/hapiDetector.d.ts +40 -0
  70. package/dist/src/languages/javascript/hapiDetector.d.ts.map +1 -0
  71. package/dist/src/languages/javascript/hapiDetector.js +174 -0
  72. package/dist/src/languages/javascript/mongooseDetector.d.ts +65 -0
  73. package/dist/src/languages/javascript/mongooseDetector.d.ts.map +1 -0
  74. package/dist/src/languages/javascript/mongooseDetector.js +237 -0
  75. package/dist/src/languages/javascript/vueDetector.d.ts +42 -0
  76. package/dist/src/languages/javascript/vueDetector.d.ts.map +1 -0
  77. package/dist/src/languages/javascript/vueDetector.js +109 -0
  78. package/dist/src/languages/python/index.d.ts +6 -2
  79. package/dist/src/languages/python/index.d.ts.map +1 -1
  80. package/dist/src/languages/python/index.js +200 -5
  81. package/dist/src/languages/python/testPatternDetector.d.ts +70 -0
  82. package/dist/src/languages/python/testPatternDetector.d.ts.map +1 -0
  83. package/dist/src/languages/python/testPatternDetector.js +201 -0
  84. package/dist/src/pipeline/confidence.d.ts +6 -1
  85. package/dist/src/pipeline/confidence.d.ts.map +1 -1
  86. package/dist/src/pipeline/confidence.js +8 -3
  87. package/dist/src/pipeline/graph.d.ts.map +1 -1
  88. package/dist/src/pipeline/graph.js +16 -4
  89. package/dist/src/pipeline/stages/ast/astStage.d.ts.map +1 -1
  90. package/dist/src/pipeline/stages/ast/astStage.js +51 -1
  91. package/dist/src/pipeline/stages/ast/baseUrlComposer.d.ts +44 -0
  92. package/dist/src/pipeline/stages/ast/baseUrlComposer.d.ts.map +1 -0
  93. package/dist/src/pipeline/stages/ast/baseUrlComposer.js +97 -0
  94. package/dist/src/pipeline/stages/ast/crossFileResolutionPass.d.ts +54 -0
  95. package/dist/src/pipeline/stages/ast/crossFileResolutionPass.d.ts.map +1 -0
  96. package/dist/src/pipeline/stages/ast/crossFileResolutionPass.js +88 -0
  97. package/dist/src/pipeline/stages/ast/crossFileResolver.d.ts.map +1 -1
  98. package/dist/src/pipeline/stages/ast/crossFileResolver.js +39 -1
  99. package/dist/src/pipeline/stages/ast/graphBuilder.d.ts.map +1 -1
  100. package/dist/src/pipeline/stages/ast/graphBuilder.js +81 -0
  101. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts +41 -0
  102. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts.map +1 -0
  103. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.js +101 -0
  104. package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.d.ts +18 -0
  105. package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.d.ts.map +1 -0
  106. package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.js +96 -0
  107. package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.d.ts +46 -0
  108. package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.d.ts.map +1 -0
  109. package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.js +314 -0
  110. package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.d.ts +17 -0
  111. package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.d.ts.map +1 -0
  112. package/dist/src/pipeline/stages/ast/resolvers/expressRouterResolver.js +65 -0
  113. package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.d.ts +17 -0
  114. package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.d.ts.map +1 -0
  115. package/dist/src/pipeline/stages/ast/resolvers/flaskBlueprintResolver.js +114 -0
  116. package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.d.ts +27 -0
  117. package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.d.ts.map +1 -0
  118. package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.js +130 -0
  119. package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.d.ts +17 -0
  120. package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.d.ts.map +1 -0
  121. package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.js +80 -0
  122. package/dist/src/pipeline/stages/ast/rulesEnforcer.d.ts +24 -0
  123. package/dist/src/pipeline/stages/ast/rulesEnforcer.d.ts.map +1 -0
  124. package/dist/src/pipeline/stages/ast/rulesEnforcer.js +411 -0
  125. package/dist/src/pipeline/stages/ast/types.d.ts +114 -1
  126. package/dist/src/pipeline/stages/ast/types.d.ts.map +1 -1
  127. package/dist/src/pipeline/stages/merge/conflictDetector.d.ts +2 -0
  128. package/dist/src/pipeline/stages/merge/conflictDetector.d.ts.map +1 -1
  129. package/dist/src/pipeline/stages/merge/conflictDetector.js +54 -2
  130. package/dist/src/pipeline/stages/merge/coverageMappingBuilder.d.ts.map +1 -1
  131. package/dist/src/pipeline/stages/merge/coverageMappingBuilder.js +67 -3
  132. package/dist/src/pipeline/stages/tia/mockBoundaryDetector.d.ts.map +1 -1
  133. package/dist/src/pipeline/stages/tia/mockBoundaryDetector.js +8 -1
  134. package/dist/src/pipeline/stages/tia/parameterizedTestExpander.js +8 -4
  135. package/dist/src/pipeline/stages/tia/testLayerClassifier.d.ts.map +1 -1
  136. package/dist/src/pipeline/stages/tia/testLayerClassifier.js +41 -10
  137. package/dist/src/pipeline/types.d.ts +1 -1
  138. package/dist/src/pipeline/types.d.ts.map +1 -1
  139. package/package.json +3 -3
@@ -97,6 +97,8 @@ function extractJavaFunctions(root, constants) {
97
97
  continue;
98
98
  const annotations = extractAnnotationNames(method);
99
99
  const block = (_e = (_d = method.childForFieldName) === null || _d === void 0 ? void 0 : _d.call(method, 'body')) !== null && _e !== void 0 ? _e : (0, treeSitterUtils_1.firstChildOfType)(method, 'block');
100
+ // Extract method parameters
101
+ const parameters = extractMethodParameters(method);
100
102
  const bodyHttpCalls = [];
101
103
  const calledFunctions = [];
102
104
  let returnValue;
@@ -109,7 +111,7 @@ function extractJavaFunctions(root, constants) {
109
111
  const cucumberPattern = extractCucumberPattern(annotations, method);
110
112
  graph.set(name, {
111
113
  name,
112
- parameters: [],
114
+ parameters,
113
115
  bodyHttpCalls,
114
116
  calledFunctions,
115
117
  returnValue,
@@ -121,14 +123,44 @@ function extractJavaFunctions(root, constants) {
121
123
  }
122
124
  // ─── HTTP call extraction ─────────────────────────────────────────────────────
123
125
  function extractJavaHttpCalls(block, constants, out) {
124
- var _a, _b, _c, _d, _e, _f, _g;
126
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
125
127
  const methodInvocations = (0, treeSitterUtils_1.findNodes)(block, ['method_invocation']);
126
128
  for (const invoc of methodInvocations) {
127
129
  const methodName = (_e = (_c = (_b = (_a = invoc.childForFieldName) === null || _a === void 0 ? void 0 : _a.call(invoc, 'name')) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : (_d = firstChildNamed(invoc, 'identifier')) === null || _d === void 0 ? void 0 : _d.text) !== null && _e !== void 0 ? _e : '';
128
130
  const lowerMethod = methodName.toLowerCase();
131
+ // MockMvc: perform(get("/path")) — extract the inner HTTP method call
132
+ if (lowerMethod === 'perform') {
133
+ const argList = (_g = (_f = invoc.childForFieldName) === null || _f === void 0 ? void 0 : _f.call(invoc, 'arguments')) !== null && _g !== void 0 ? _g : (0, treeSitterUtils_1.firstChildOfType)(invoc, 'argument_list');
134
+ if (!argList)
135
+ continue;
136
+ // The argument to perform() is a method invocation like get("/path") or post("/path")
137
+ const innerInvocations = (0, treeSitterUtils_1.findNodes)(argList, ['method_invocation']);
138
+ for (const innerInvoc of innerInvocations) {
139
+ const innerMethodName = (_m = (_k = (_j = (_h = innerInvoc.childForFieldName) === null || _h === void 0 ? void 0 : _h.call(innerInvoc, 'name')) === null || _j === void 0 ? void 0 : _j.text) !== null && _k !== void 0 ? _k : (_l = firstChildNamed(innerInvoc, 'identifier')) === null || _l === void 0 ? void 0 : _l.text) !== null && _m !== void 0 ? _m : '';
140
+ const innerLower = innerMethodName.toLowerCase();
141
+ if (!HTTP_METHODS.has(innerLower))
142
+ continue;
143
+ const innerArgList = (_p = (_o = innerInvoc.childForFieldName) === null || _o === void 0 ? void 0 : _o.call(innerInvoc, 'arguments')) !== null && _p !== void 0 ? _p : (0, treeSitterUtils_1.firstChildOfType)(innerInvoc, 'argument_list');
144
+ if (!innerArgList)
145
+ continue;
146
+ const innerStringArg = findFirstStringInArgList(innerArgList, constants);
147
+ if (!innerStringArg)
148
+ continue;
149
+ const normalizedPath = innerStringArg.value.startsWith('/') ? (0, resolvePaths_1.normalizePathToTemplate)(innerStringArg.value) : undefined;
150
+ out.push({
151
+ method: innerLower.toUpperCase(),
152
+ rawPathArg: (_q = innerStringArg.varName) !== null && _q !== void 0 ? _q : innerStringArg.value,
153
+ resolvedPath: innerStringArg.value,
154
+ normalizedPath,
155
+ resolutionType: innerStringArg.isDirect ? 'direct' : 'constant',
156
+ confidence: innerStringArg.isDirect ? 'high' : 'medium',
157
+ });
158
+ }
159
+ continue;
160
+ }
129
161
  if (!HTTP_METHODS.has(lowerMethod))
130
162
  continue;
131
- const argList = (_g = (_f = invoc.childForFieldName) === null || _f === void 0 ? void 0 : _f.call(invoc, 'arguments')) !== null && _g !== void 0 ? _g : (0, treeSitterUtils_1.firstChildOfType)(invoc, 'argument_list');
163
+ const argList = (_s = (_r = invoc.childForFieldName) === null || _r === void 0 ? void 0 : _r.call(invoc, 'arguments')) !== null && _s !== void 0 ? _s : (0, treeSitterUtils_1.firstChildOfType)(invoc, 'argument_list');
132
164
  if (!argList)
133
165
  continue;
134
166
  // Extract the first string argument (path)
@@ -138,15 +170,6 @@ function extractJavaHttpCalls(block, constants, out) {
138
170
  const { value: path, isDirect, varName } = firstStringArg;
139
171
  // Try to detect the HTTP method from context
140
172
  let httpMethod = lowerMethod.toUpperCase();
141
- // RestAssured: .when().get("/path") or .given().get("/path")
142
- // The method name IS the HTTP method in RestAssured style
143
- if (!HTTP_METHODS.has(lowerMethod))
144
- continue;
145
- // MockMvc: perform(get("/path")) — perform wraps a method call
146
- if (lowerMethod === 'perform') {
147
- // The arg is another method invocation
148
- continue; // Handled when we process the inner get/post
149
- }
150
173
  if (lowerMethod === 'request') {
151
174
  // generic request(method, path) — try to get HTTP method from first arg
152
175
  const stringArgs = findAllStringsInArgList(argList, constants);
@@ -224,6 +247,40 @@ function extractJavaFlowRefs(root) {
224
247
  return refs;
225
248
  }
226
249
  // ─── Helpers ──────────────────────────────────────────────────────────────────
250
+ /**
251
+ * Extract method parameters with their annotations (e.g. @RequestParam, @PathVariable, @RequestBody).
252
+ */
253
+ function extractMethodParameters(method) {
254
+ var _a;
255
+ const params = [];
256
+ const formalParams = (0, treeSitterUtils_1.firstChildOfType)(method, 'formal_parameters');
257
+ if (!formalParams)
258
+ return params;
259
+ const paramNodes = (0, treeSitterUtils_1.findNodes)(formalParams, ['formal_parameter', 'spread_parameter']);
260
+ for (const paramNode of paramNodes) {
261
+ const paramAnnotations = [];
262
+ (0, treeSitterUtils_1.walkTree)(paramNode, (n) => {
263
+ var _a;
264
+ if (n.type === 'annotation' || n.type === 'marker_annotation') {
265
+ const nameNode = (0, treeSitterUtils_1.firstChildOfType)(n, 'identifier');
266
+ if (nameNode)
267
+ paramAnnotations.push('@' + ((_a = nameNode.text) !== null && _a !== void 0 ? _a : ''));
268
+ }
269
+ });
270
+ const nameNode = firstChildNamed(paramNode, 'identifier');
271
+ const name = (_a = nameNode === null || nameNode === void 0 ? void 0 : nameNode.text) !== null && _a !== void 0 ? _a : '';
272
+ if (!name)
273
+ continue;
274
+ // Include annotation prefix for annotated params (Spring @RequestParam, @PathVariable, etc.)
275
+ if (paramAnnotations.length > 0) {
276
+ params.push(`${paramAnnotations.join(' ')} ${name}`);
277
+ }
278
+ else {
279
+ params.push(name);
280
+ }
281
+ }
282
+ return params;
283
+ }
227
284
  function extractModifierTexts(node) {
228
285
  const modifiers = [];
229
286
  (0, treeSitterUtils_1.walkTree)(node, (n) => {
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Angular pattern detector (Feature 27, Sub-PR 7)
3
+ *
4
+ * Detects:
5
+ * 1. @Injectable services with HttpClient injection
6
+ * 2. this.http.get/post/put/delete/patch() API calls
7
+ * 3. inject(HttpClient) functional style
8
+ * 4. environment.api_url usage
9
+ * 5. CanActivateFn / CanActivateChildFn / CanDeactivateFn / ResolveFn guards
10
+ * 6. implements HttpInterceptor / HttpInterceptorFn interceptors
11
+ * 7. TestBed.configureTestingModule with HttpClientTestingModule
12
+ * 8. httpMock.expectOne(url) assertion nodes
13
+ * 9. signal<T>(), toSignal() patterns
14
+ */
15
+ export interface AngularHttpCall {
16
+ method: string;
17
+ urlPattern: string;
18
+ usesEnvironmentUrl: boolean;
19
+ sourceFile: string;
20
+ line?: number;
21
+ }
22
+ export interface AngularInjection {
23
+ /** Class that receives the injection */
24
+ consumerClass: string;
25
+ /** Service class being injected */
26
+ serviceClass: string;
27
+ /** Injection style: constructor, inject function, decorator */
28
+ style: 'constructor' | 'inject-fn';
29
+ sourceFile: string;
30
+ line?: number;
31
+ }
32
+ export interface AngularGuard {
33
+ name: string;
34
+ type: 'functional' | 'class-based';
35
+ guardType: 'CanActivate' | 'CanActivateChild' | 'CanDeactivate' | 'Resolve' | 'CanMatch';
36
+ sourceFile: string;
37
+ line?: number;
38
+ }
39
+ export interface AngularInterceptor {
40
+ name: string;
41
+ type: 'class-based' | 'functional';
42
+ sourceFile: string;
43
+ line?: number;
44
+ }
45
+ export interface AngularTestSetup {
46
+ usesHttpClientTestingModule: boolean;
47
+ httpMockExpectations: string[];
48
+ sourceFile: string;
49
+ }
50
+ /**
51
+ * Detect Angular HttpClient API calls from source text.
52
+ */
53
+ export declare function detectAngularHttpCalls(sourceText: string, filePath: string): AngularHttpCall[];
54
+ /**
55
+ * Detect Angular constructor injections and inject() calls.
56
+ */
57
+ export declare function detectAngularInjections(sourceText: string, filePath: string): AngularInjection[];
58
+ /**
59
+ * Detect Angular guards (functional and class-based).
60
+ */
61
+ export declare function detectAngularGuards(sourceText: string, filePath: string): AngularGuard[];
62
+ /**
63
+ * Detect Angular HTTP interceptors.
64
+ */
65
+ export declare function detectAngularInterceptors(sourceText: string, filePath: string): AngularInterceptor[];
66
+ /**
67
+ * Detect Angular test setup patterns (HttpClientTestingModule, httpMock).
68
+ */
69
+ export declare function detectAngularTestSetup(sourceText: string, filePath: string): AngularTestSetup;
70
+ /**
71
+ * Check if source text contains Angular HttpClient usage.
72
+ */
73
+ export declare function hasAngularHttpClient(sourceText: string): boolean;
74
+ //# sourceMappingURL=angularDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angularDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/javascript/angularDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,KAAK,EAAE,aAAa,GAAG,WAAW,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC;IACnC,SAAS,EAAE,aAAa,GAAG,kBAAkB,GAAG,eAAe,GAAG,SAAS,GAAG,UAAU,CAAC;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B,EAAE,OAAO,CAAC;IACrC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAyC9F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA2EhG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAyCxF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAgCpG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAY7F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEhE"}
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ /**
3
+ * Angular pattern detector (Feature 27, Sub-PR 7)
4
+ *
5
+ * Detects:
6
+ * 1. @Injectable services with HttpClient injection
7
+ * 2. this.http.get/post/put/delete/patch() API calls
8
+ * 3. inject(HttpClient) functional style
9
+ * 4. environment.api_url usage
10
+ * 5. CanActivateFn / CanActivateChildFn / CanDeactivateFn / ResolveFn guards
11
+ * 6. implements HttpInterceptor / HttpInterceptorFn interceptors
12
+ * 7. TestBed.configureTestingModule with HttpClientTestingModule
13
+ * 8. httpMock.expectOne(url) assertion nodes
14
+ * 9. signal<T>(), toSignal() patterns
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.detectAngularHttpCalls = detectAngularHttpCalls;
18
+ exports.detectAngularInjections = detectAngularInjections;
19
+ exports.detectAngularGuards = detectAngularGuards;
20
+ exports.detectAngularInterceptors = detectAngularInterceptors;
21
+ exports.detectAngularTestSetup = detectAngularTestSetup;
22
+ exports.hasAngularHttpClient = hasAngularHttpClient;
23
+ /**
24
+ * Detect Angular HttpClient API calls from source text.
25
+ */
26
+ function detectAngularHttpCalls(sourceText, filePath) {
27
+ const calls = [];
28
+ const lines = sourceText.split('\n');
29
+ // this.http.METHOD<Type>('url') or this.httpClient.METHOD('url')
30
+ const httpCallPattern = /this\.(?:http|httpClient)\.(get|post|put|patch|delete|head|options)(?:<[^>]+>)?\s*\(\s*[`'"]([^`'"]+)[`'"]/;
31
+ for (let i = 0; i < lines.length; i++) {
32
+ const line = lines[i];
33
+ const match = line.match(httpCallPattern);
34
+ if (match) {
35
+ const usesEnvironmentUrl = match[2].includes('environment') || match[2].includes('${');
36
+ calls.push({
37
+ method: match[1].toUpperCase(),
38
+ urlPattern: match[2],
39
+ usesEnvironmentUrl,
40
+ sourceFile: filePath,
41
+ line: i + 1,
42
+ });
43
+ }
44
+ }
45
+ // Also detect template literal calls: this.http.get(`${this.apiUrl}/articles`)
46
+ const templatePattern = /this\.(?:http|httpClient)\.(get|post|put|patch|delete)(?:<[^>]+>)?\s*\(\s*`([^`]+)`/g;
47
+ let tmatch;
48
+ while ((tmatch = templatePattern.exec(sourceText)) !== null) {
49
+ const url = tmatch[2];
50
+ // Avoid duplicates
51
+ if (!calls.some((c) => c.urlPattern === url)) {
52
+ const lineNum = sourceText.substring(0, tmatch.index).split('\n').length;
53
+ calls.push({
54
+ method: tmatch[1].toUpperCase(),
55
+ urlPattern: url,
56
+ usesEnvironmentUrl: url.includes('environment') || url.includes('${'),
57
+ sourceFile: filePath,
58
+ line: lineNum,
59
+ });
60
+ }
61
+ }
62
+ return calls;
63
+ }
64
+ /**
65
+ * Detect Angular constructor injections and inject() calls.
66
+ */
67
+ function detectAngularInjections(sourceText, filePath) {
68
+ const injections = [];
69
+ const lines = sourceText.split('\n');
70
+ let currentClass = '';
71
+ let currentConstHost = '';
72
+ let inConstructorParams = false;
73
+ for (let i = 0; i < lines.length; i++) {
74
+ const line = lines[i];
75
+ // Track current class
76
+ const classMatch = line.match(/class\s+(\w+)/);
77
+ if (classMatch)
78
+ currentClass = classMatch[1];
79
+ // Track current const/export const assignment as potential host for inject() outside class.
80
+ // Only update when the line is NOT itself an inject() call (e.g. skip `const x = inject(Y)`).
81
+ if (!currentClass) {
82
+ const constHostMatch = line.match(/(?:export\s+)?(?:const|let)\s+(\w+)\s*(?::\s*\S+)?\s*=/);
83
+ if (constHostMatch && !line.match(/=\s*inject\s*\(/)) {
84
+ currentConstHost = constHostMatch[1];
85
+ }
86
+ }
87
+ // Track constructor parameter block boundaries
88
+ if (/\bconstructor\s*\(/.test(line)) {
89
+ inConstructorParams = true;
90
+ }
91
+ if (inConstructorParams && line.includes(')')) {
92
+ // Process this line (it's still inside the constructor params), then close
93
+ // We'll close after checking for injections below
94
+ }
95
+ // Constructor injection: constructor(private http: HttpClient)
96
+ // Only match visibility-modified parameters when inside a constructor(...) block
97
+ if (inConstructorParams) {
98
+ const ctorParamPattern = /(?:private|protected|public|readonly)\s+(\w+)\s*:\s*(\w+)/g;
99
+ let ctorMatch;
100
+ while ((ctorMatch = ctorParamPattern.exec(line)) !== null) {
101
+ if (currentClass) {
102
+ injections.push({
103
+ consumerClass: currentClass,
104
+ serviceClass: ctorMatch[2],
105
+ style: 'constructor',
106
+ sourceFile: filePath,
107
+ line: i + 1,
108
+ });
109
+ }
110
+ }
111
+ }
112
+ // Close the constructor param block after processing (handles closing paren on same line)
113
+ if (inConstructorParams && line.includes(')')) {
114
+ inConstructorParams = false;
115
+ }
116
+ // Functional inject: inject(HttpClient)
117
+ const injectMatch = line.match(/(\w+)\s*=\s*inject\s*\(\s*(\w+)\s*\)/);
118
+ if (injectMatch) {
119
+ // Use the enclosing class, or fall back to the enclosing const/export const host
120
+ // (e.g. functional guards/interceptors: `export const authGuard: CanActivateFn = ...`)
121
+ const hostName = currentClass || currentConstHost;
122
+ if (hostName) {
123
+ injections.push({
124
+ consumerClass: hostName,
125
+ serviceClass: injectMatch[2],
126
+ style: 'inject-fn',
127
+ sourceFile: filePath,
128
+ line: i + 1,
129
+ });
130
+ }
131
+ }
132
+ }
133
+ return injections;
134
+ }
135
+ /**
136
+ * Detect Angular guards (functional and class-based).
137
+ */
138
+ function detectAngularGuards(sourceText, filePath) {
139
+ var _a;
140
+ const guards = [];
141
+ const lines = sourceText.split('\n');
142
+ for (let i = 0; i < lines.length; i++) {
143
+ const line = lines[i];
144
+ // Functional guard: export const authGuard: CanActivateFn = ...
145
+ const functionalMatch = line.match(/(?:export\s+)?(?:const|let)\s+(\w+)\s*:\s*(CanActivateFn|CanActivateChildFn|CanDeactivateFn|ResolveFn|CanMatchFn)/);
146
+ if (functionalMatch) {
147
+ const guardTypeMap = {
148
+ CanActivateFn: 'CanActivate',
149
+ CanActivateChildFn: 'CanActivateChild',
150
+ CanDeactivateFn: 'CanDeactivate',
151
+ ResolveFn: 'Resolve',
152
+ CanMatchFn: 'CanMatch',
153
+ };
154
+ guards.push({
155
+ name: functionalMatch[1],
156
+ type: 'functional',
157
+ guardType: (_a = guardTypeMap[functionalMatch[2]]) !== null && _a !== void 0 ? _a : 'CanActivate',
158
+ sourceFile: filePath,
159
+ line: i + 1,
160
+ });
161
+ continue;
162
+ }
163
+ // Class-based guard: implements CanActivate
164
+ const classMatch = line.match(/class\s+(\w+).*implements\s+(?:.*,\s*)?(CanActivate|CanActivateChild|CanDeactivate|Resolve|CanMatch)/);
165
+ if (classMatch) {
166
+ guards.push({
167
+ name: classMatch[1],
168
+ type: 'class-based',
169
+ guardType: classMatch[2],
170
+ sourceFile: filePath,
171
+ line: i + 1,
172
+ });
173
+ }
174
+ }
175
+ return guards;
176
+ }
177
+ /**
178
+ * Detect Angular HTTP interceptors.
179
+ */
180
+ function detectAngularInterceptors(sourceText, filePath) {
181
+ const interceptors = [];
182
+ const lines = sourceText.split('\n');
183
+ for (let i = 0; i < lines.length; i++) {
184
+ const line = lines[i];
185
+ // Class-based: implements HttpInterceptor
186
+ const classMatch = line.match(/class\s+(\w+).*implements\s+(?:.*,\s*)?HttpInterceptor/);
187
+ if (classMatch) {
188
+ interceptors.push({
189
+ name: classMatch[1],
190
+ type: 'class-based',
191
+ sourceFile: filePath,
192
+ line: i + 1,
193
+ });
194
+ continue;
195
+ }
196
+ // Functional: HttpInterceptorFn
197
+ const fnMatch = line.match(/(?:export\s+)?(?:const|let)\s+(\w+)\s*:\s*HttpInterceptorFn/);
198
+ if (fnMatch) {
199
+ interceptors.push({
200
+ name: fnMatch[1],
201
+ type: 'functional',
202
+ sourceFile: filePath,
203
+ line: i + 1,
204
+ });
205
+ }
206
+ }
207
+ return interceptors;
208
+ }
209
+ /**
210
+ * Detect Angular test setup patterns (HttpClientTestingModule, httpMock).
211
+ */
212
+ function detectAngularTestSetup(sourceText, filePath) {
213
+ const usesHttpClientTestingModule = /HttpClientTestingModule|provideHttpClientTesting/.test(sourceText);
214
+ const httpMockExpectations = [];
215
+ const expectOnePattern = /httpMock\.expectOne\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
216
+ let match;
217
+ while ((match = expectOnePattern.exec(sourceText)) !== null) {
218
+ httpMockExpectations.push(match[1]);
219
+ }
220
+ return { usesHttpClientTestingModule, httpMockExpectations, sourceFile: filePath };
221
+ }
222
+ /**
223
+ * Check if source text contains Angular HttpClient usage.
224
+ */
225
+ function hasAngularHttpClient(sourceText) {
226
+ return /HttpClient|this\.http\.(get|post|put|patch|delete)/.test(sourceText);
227
+ }
@@ -66,8 +66,8 @@ function tryExtractAssertion(callNode) {
66
66
  if (!subject)
67
67
  return null;
68
68
  const methodName = (_j = (_h = (_g = callee.property) === null || _g === void 0 ? void 0 : _g.name) === null || _h === void 0 ? void 0 : _h.toLowerCase()) !== null && _j !== void 0 ? _j : '';
69
- const assertionType = classifyAssertionMethod(methodName);
70
- const { variable } = classifyExpectSubject(subject);
69
+ const { variable, assertionType: subjectType } = classifyExpectSubject(subject);
70
+ const assertionType = classifyAssertionMethod(methodName, subjectType);
71
71
  return { assertionType, subjectVariable: variable, line: (_l = (_k = callNode.loc) === null || _k === void 0 ? void 0 : _k.start) === null || _l === void 0 ? void 0 : _l.line };
72
72
  }
73
73
  }
@@ -132,13 +132,15 @@ function classifyExpectSubject(subject) {
132
132
  }
133
133
  return { variable: undefined, assertionType: 'body-field' };
134
134
  }
135
- function classifyAssertionMethod(methodName) {
135
+ function classifyAssertionMethod(methodName, subjectType) {
136
136
  if (methodName === 'tobe' ||
137
137
  methodName === 'toequal' ||
138
138
  methodName === 'tostrictequal' ||
139
139
  methodName === 'tobetruthy' ||
140
140
  methodName === 'tobefalsy') {
141
- return 'status-code'; // Could be either, default to status-code
141
+ // These methods are ambiguous use subject context to decide.
142
+ // Only classify as status-code when the subject involves status.
143
+ return subjectType === 'status-code' ? 'status-code' : 'body-field';
142
144
  }
143
145
  if (methodName === 'tohaveproperty' || methodName === 'tocontain' || methodName === 'tomatch') {
144
146
  return 'body-field';
@@ -0,0 +1,40 @@
1
+ /**
2
+ * HapiJS pattern detector (Feature 27, Sub-PR 8)
3
+ *
4
+ * Detects:
5
+ * 1. server.route({ method, path, options: { auth, validate, handler } })
6
+ * 2. Joi validator chains: Joi.string().required(), Joi.number().min().max().default()
7
+ * 3. auth: 'jwt' = required, auth: { mode: 'try' } = optional
8
+ * 4. Boom error responses: Boom.notFound(), Boom.unauthorized()
9
+ */
10
+ export interface HapiRoute {
11
+ method: string;
12
+ path: string;
13
+ auth?: HapiAuth;
14
+ validation?: HapiValidation;
15
+ sourceFile: string;
16
+ line?: number;
17
+ }
18
+ export interface HapiAuth {
19
+ strategy?: string;
20
+ mode: 'required' | 'optional' | 'try';
21
+ }
22
+ export interface HapiValidation {
23
+ queryParams: string[];
24
+ payloadParams: string[];
25
+ }
26
+ export interface HapiBoomError {
27
+ errorType: string;
28
+ statusCode?: number;
29
+ sourceFile: string;
30
+ line?: number;
31
+ }
32
+ /**
33
+ * Detect HapiJS route definitions from source text.
34
+ */
35
+ export declare function detectHapiRoutes(sourceText: string, filePath: string): HapiRoute[];
36
+ /**
37
+ * Detect Boom error responses.
38
+ */
39
+ export declare function detectBoomErrors(sourceText: string, filePath: string): HapiBoomError[];
40
+ //# sourceMappingURL=hapiDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hapiDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/javascript/hapiDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,KAAK,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAkBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,CA6HlF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAmBtF"}