@machina.ai/openapi-contract-tester 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/.env.example +91 -0
  2. package/README.md +472 -0
  3. package/dist/ai-engine/assertion-generator.d.ts +48 -0
  4. package/dist/ai-engine/assertion-generator.d.ts.map +1 -0
  5. package/dist/ai-engine/assertion-generator.js +166 -0
  6. package/dist/ai-engine/assertion-generator.js.map +1 -0
  7. package/dist/ai-engine/context-data-generator.d.ts +38 -0
  8. package/dist/ai-engine/context-data-generator.d.ts.map +1 -0
  9. package/dist/ai-engine/context-data-generator.js +146 -0
  10. package/dist/ai-engine/context-data-generator.js.map +1 -0
  11. package/dist/ai-engine/dataflow-detector.d.ts +53 -0
  12. package/dist/ai-engine/dataflow-detector.d.ts.map +1 -0
  13. package/dist/ai-engine/dataflow-detector.js +217 -0
  14. package/dist/ai-engine/dataflow-detector.js.map +1 -0
  15. package/dist/ai-engine/dependency-detector.d.ts +52 -0
  16. package/dist/ai-engine/dependency-detector.d.ts.map +1 -0
  17. package/dist/ai-engine/dependency-detector.js +241 -0
  18. package/dist/ai-engine/dependency-detector.js.map +1 -0
  19. package/dist/ai-engine/edge-case-suggester.d.ts +63 -0
  20. package/dist/ai-engine/edge-case-suggester.d.ts.map +1 -0
  21. package/dist/ai-engine/edge-case-suggester.js +177 -0
  22. package/dist/ai-engine/edge-case-suggester.js.map +1 -0
  23. package/dist/ai-engine/index.d.ts +13 -0
  24. package/dist/ai-engine/index.d.ts.map +1 -0
  25. package/dist/ai-engine/index.js +13 -0
  26. package/dist/ai-engine/index.js.map +1 -0
  27. package/dist/analyzers/ai-failure-analyzer.d.ts +41 -0
  28. package/dist/analyzers/ai-failure-analyzer.d.ts.map +1 -0
  29. package/dist/analyzers/ai-failure-analyzer.js +220 -0
  30. package/dist/analyzers/ai-failure-analyzer.js.map +1 -0
  31. package/dist/analyzers/comparison-utils.d.ts +31 -0
  32. package/dist/analyzers/comparison-utils.d.ts.map +1 -0
  33. package/dist/analyzers/comparison-utils.js +85 -0
  34. package/dist/analyzers/comparison-utils.js.map +1 -0
  35. package/dist/analyzers/context-analyzer.d.ts +49 -0
  36. package/dist/analyzers/context-analyzer.d.ts.map +1 -0
  37. package/dist/analyzers/context-analyzer.js +292 -0
  38. package/dist/analyzers/context-analyzer.js.map +1 -0
  39. package/dist/analyzers/dependency-analyzer.d.ts +44 -0
  40. package/dist/analyzers/dependency-analyzer.d.ts.map +1 -0
  41. package/dist/analyzers/dependency-analyzer.js +313 -0
  42. package/dist/analyzers/dependency-analyzer.js.map +1 -0
  43. package/dist/analyzers/failure-analyzer.d.ts +122 -0
  44. package/dist/analyzers/failure-analyzer.d.ts.map +1 -0
  45. package/dist/analyzers/failure-analyzer.js +140 -0
  46. package/dist/analyzers/failure-analyzer.js.map +1 -0
  47. package/dist/analyzers/failure-detectors/index.d.ts +33 -0
  48. package/dist/analyzers/failure-detectors/index.d.ts.map +1 -0
  49. package/dist/analyzers/failure-detectors/index.js +164 -0
  50. package/dist/analyzers/failure-detectors/index.js.map +1 -0
  51. package/dist/analyzers/failure-discrepancy-correlator.d.ts +111 -0
  52. package/dist/analyzers/failure-discrepancy-correlator.d.ts.map +1 -0
  53. package/dist/analyzers/failure-discrepancy-correlator.js +202 -0
  54. package/dist/analyzers/failure-discrepancy-correlator.js.map +1 -0
  55. package/dist/analyzers/index.d.ts +10 -0
  56. package/dist/analyzers/index.d.ts.map +1 -0
  57. package/dist/analyzers/index.js +10 -0
  58. package/dist/analyzers/index.js.map +1 -0
  59. package/dist/analyzers/semantic-matcher.d.ts +123 -0
  60. package/dist/analyzers/semantic-matcher.d.ts.map +1 -0
  61. package/dist/analyzers/semantic-matcher.js +297 -0
  62. package/dist/analyzers/semantic-matcher.js.map +1 -0
  63. package/dist/analyzers/source-comparator.d.ts +177 -0
  64. package/dist/analyzers/source-comparator.d.ts.map +1 -0
  65. package/dist/analyzers/source-comparator.js +225 -0
  66. package/dist/analyzers/source-comparator.js.map +1 -0
  67. package/dist/business-rules/business-rules-analyzer.d.ts +44 -0
  68. package/dist/business-rules/business-rules-analyzer.d.ts.map +1 -0
  69. package/dist/business-rules/business-rules-analyzer.js +363 -0
  70. package/dist/business-rules/business-rules-analyzer.js.map +1 -0
  71. package/dist/business-rules/business-rules-generator.d.ts +78 -0
  72. package/dist/business-rules/business-rules-generator.d.ts.map +1 -0
  73. package/dist/business-rules/business-rules-generator.js +357 -0
  74. package/dist/business-rules/business-rules-generator.js.map +1 -0
  75. package/dist/business-rules/extractors/rule-extractors.d.ts +50 -0
  76. package/dist/business-rules/extractors/rule-extractors.d.ts.map +1 -0
  77. package/dist/business-rules/extractors/rule-extractors.js +189 -0
  78. package/dist/business-rules/extractors/rule-extractors.js.map +1 -0
  79. package/dist/business-rules/value-generators.d.ts +70 -0
  80. package/dist/business-rules/value-generators.d.ts.map +1 -0
  81. package/dist/business-rules/value-generators.js +142 -0
  82. package/dist/business-rules/value-generators.js.map +1 -0
  83. package/dist/executor/auth-providers/auth-header-builder.d.ts +16 -0
  84. package/dist/executor/auth-providers/auth-header-builder.d.ts.map +1 -0
  85. package/dist/executor/auth-providers/auth-header-builder.js +47 -0
  86. package/dist/executor/auth-providers/auth-header-builder.js.map +1 -0
  87. package/dist/executor/auth-providers/oauth2-provider.d.ts +19 -0
  88. package/dist/executor/auth-providers/oauth2-provider.d.ts.map +1 -0
  89. package/dist/executor/auth-providers/oauth2-provider.js +114 -0
  90. package/dist/executor/auth-providers/oauth2-provider.js.map +1 -0
  91. package/dist/executor/http-client.d.ts +133 -0
  92. package/dist/executor/http-client.d.ts.map +1 -0
  93. package/dist/executor/http-client.js +172 -0
  94. package/dist/executor/http-client.js.map +1 -0
  95. package/dist/executor/http-request-builder.d.ts +69 -0
  96. package/dist/executor/http-request-builder.d.ts.map +1 -0
  97. package/dist/executor/http-request-builder.js +140 -0
  98. package/dist/executor/http-request-builder.js.map +1 -0
  99. package/dist/executor/http-response-parser.d.ts +28 -0
  100. package/dist/executor/http-response-parser.d.ts.map +1 -0
  101. package/dist/executor/http-response-parser.js +74 -0
  102. package/dist/executor/http-response-parser.js.map +1 -0
  103. package/dist/executor/response-handler.d.ts +66 -0
  104. package/dist/executor/response-handler.d.ts.map +1 -0
  105. package/dist/executor/response-handler.js +135 -0
  106. package/dist/executor/response-handler.js.map +1 -0
  107. package/dist/executor/result-processor.d.ts +27 -0
  108. package/dist/executor/result-processor.d.ts.map +1 -0
  109. package/dist/executor/result-processor.js +140 -0
  110. package/dist/executor/result-processor.js.map +1 -0
  111. package/dist/executor/result-utils.d.ts +21 -0
  112. package/dist/executor/result-utils.d.ts.map +1 -0
  113. package/dist/executor/result-utils.js +29 -0
  114. package/dist/executor/result-utils.js.map +1 -0
  115. package/dist/executor/test-executor.d.ts +49 -0
  116. package/dist/executor/test-executor.d.ts.map +1 -0
  117. package/dist/executor/test-executor.js +226 -0
  118. package/dist/executor/test-executor.js.map +1 -0
  119. package/dist/executor/test-runner.d.ts +85 -0
  120. package/dist/executor/test-runner.d.ts.map +1 -0
  121. package/dist/executor/test-runner.js +177 -0
  122. package/dist/executor/test-runner.js.map +1 -0
  123. package/dist/executor/token-detector/index.d.ts +7 -0
  124. package/dist/executor/token-detector/index.d.ts.map +1 -0
  125. package/dist/executor/token-detector/index.js +7 -0
  126. package/dist/executor/token-detector/index.js.map +1 -0
  127. package/dist/executor/token-detector/token-detector.d.ts +64 -0
  128. package/dist/executor/token-detector/token-detector.d.ts.map +1 -0
  129. package/dist/executor/token-detector/token-detector.js +140 -0
  130. package/dist/executor/token-detector/token-detector.js.map +1 -0
  131. package/dist/generators/business-rule-from-stories-generator.d.ts +30 -0
  132. package/dist/generators/business-rule-from-stories-generator.d.ts.map +1 -0
  133. package/dist/generators/business-rule-from-stories-generator.js +227 -0
  134. package/dist/generators/business-rule-from-stories-generator.js.map +1 -0
  135. package/dist/generators/data/ai-data-generator.d.ts +23 -0
  136. package/dist/generators/data/ai-data-generator.d.ts.map +1 -0
  137. package/dist/generators/data/ai-data-generator.js +41 -0
  138. package/dist/generators/data/ai-data-generator.js.map +1 -0
  139. package/dist/generators/data/base-generator.d.ts +121 -0
  140. package/dist/generators/data/base-generator.d.ts.map +1 -0
  141. package/dist/generators/data/base-generator.js +200 -0
  142. package/dist/generators/data/base-generator.js.map +1 -0
  143. package/dist/generators/data/heuristic-data-generator.d.ts +28 -0
  144. package/dist/generators/data/heuristic-data-generator.d.ts.map +1 -0
  145. package/dist/generators/data/heuristic-data-generator.js +49 -0
  146. package/dist/generators/data/heuristic-data-generator.js.map +1 -0
  147. package/dist/generators/data/index.d.ts +48 -0
  148. package/dist/generators/data/index.d.ts.map +1 -0
  149. package/dist/generators/data/index.js +201 -0
  150. package/dist/generators/data/index.js.map +1 -0
  151. package/dist/generators/data/schema-walker.d.ts +45 -0
  152. package/dist/generators/data/schema-walker.d.ts.map +1 -0
  153. package/dist/generators/data/schema-walker.js +103 -0
  154. package/dist/generators/data/schema-walker.js.map +1 -0
  155. package/dist/generators/data/type-strategies.d.ts +79 -0
  156. package/dist/generators/data/type-strategies.d.ts.map +1 -0
  157. package/dist/generators/data/type-strategies.js +394 -0
  158. package/dist/generators/data/type-strategies.js.map +1 -0
  159. package/dist/generators/data-generator.d.ts +11 -0
  160. package/dist/generators/data-generator.d.ts.map +1 -0
  161. package/dist/generators/data-generator.js +11 -0
  162. package/dist/generators/data-generator.js.map +1 -0
  163. package/dist/generators/edge-case-generator.d.ts +55 -0
  164. package/dist/generators/edge-case-generator.d.ts.map +1 -0
  165. package/dist/generators/edge-case-generator.js +327 -0
  166. package/dist/generators/edge-case-generator.js.map +1 -0
  167. package/dist/generators/edge-cases/boundary-analyzer.d.ts +26 -0
  168. package/dist/generators/edge-cases/boundary-analyzer.d.ts.map +1 -0
  169. package/dist/generators/edge-cases/boundary-analyzer.js +95 -0
  170. package/dist/generators/edge-cases/boundary-analyzer.js.map +1 -0
  171. package/dist/generators/error-case-generator.d.ts +11 -0
  172. package/dist/generators/error-case-generator.d.ts.map +1 -0
  173. package/dist/generators/error-case-generator.js +11 -0
  174. package/dist/generators/error-case-generator.js.map +1 -0
  175. package/dist/generators/errors/auth-error-strategy.d.ts +36 -0
  176. package/dist/generators/errors/auth-error-strategy.d.ts.map +1 -0
  177. package/dist/generators/errors/auth-error-strategy.js +118 -0
  178. package/dist/generators/errors/auth-error-strategy.js.map +1 -0
  179. package/dist/generators/errors/business-error-strategy.d.ts +44 -0
  180. package/dist/generators/errors/business-error-strategy.d.ts.map +1 -0
  181. package/dist/generators/errors/business-error-strategy.js +152 -0
  182. package/dist/generators/errors/business-error-strategy.js.map +1 -0
  183. package/dist/generators/errors/error-strategy-factory.d.ts +27 -0
  184. package/dist/generators/errors/error-strategy-factory.d.ts.map +1 -0
  185. package/dist/generators/errors/error-strategy-factory.js +47 -0
  186. package/dist/generators/errors/error-strategy-factory.js.map +1 -0
  187. package/dist/generators/errors/error-strategy.d.ts +62 -0
  188. package/dist/generators/errors/error-strategy.d.ts.map +1 -0
  189. package/dist/generators/errors/error-strategy.js +69 -0
  190. package/dist/generators/errors/error-strategy.js.map +1 -0
  191. package/dist/generators/errors/index.d.ts +23 -0
  192. package/dist/generators/errors/index.d.ts.map +1 -0
  193. package/dist/generators/errors/index.js +73 -0
  194. package/dist/generators/errors/index.js.map +1 -0
  195. package/dist/generators/errors/validation-error-strategy.d.ts +25 -0
  196. package/dist/generators/errors/validation-error-strategy.d.ts.map +1 -0
  197. package/dist/generators/errors/validation-error-strategy.js +214 -0
  198. package/dist/generators/errors/validation-error-strategy.js.map +1 -0
  199. package/dist/generators/happy-path-generator.d.ts +93 -0
  200. package/dist/generators/happy-path-generator.d.ts.map +1 -0
  201. package/dist/generators/happy-path-generator.js +275 -0
  202. package/dist/generators/happy-path-generator.js.map +1 -0
  203. package/dist/generators/test-enricher.d.ts +44 -0
  204. package/dist/generators/test-enricher.d.ts.map +1 -0
  205. package/dist/generators/test-enricher.js +109 -0
  206. package/dist/generators/test-enricher.js.map +1 -0
  207. package/dist/index.d.ts +9 -0
  208. package/dist/index.d.ts.map +1 -0
  209. package/dist/index.js +14 -0
  210. package/dist/index.js.map +1 -0
  211. package/dist/llm/ai-cache.d.ts +123 -0
  212. package/dist/llm/ai-cache.d.ts.map +1 -0
  213. package/dist/llm/ai-cache.js +220 -0
  214. package/dist/llm/ai-cache.js.map +1 -0
  215. package/dist/llm/ai-client.d.ts +92 -0
  216. package/dist/llm/ai-client.d.ts.map +1 -0
  217. package/dist/llm/ai-client.js +386 -0
  218. package/dist/llm/ai-client.js.map +1 -0
  219. package/dist/llm/data-generator-ai.d.ts +84 -0
  220. package/dist/llm/data-generator-ai.d.ts.map +1 -0
  221. package/dist/llm/data-generator-ai.js +284 -0
  222. package/dist/llm/data-generator-ai.js.map +1 -0
  223. package/dist/llm/index.d.ts +7 -0
  224. package/dist/llm/index.d.ts.map +1 -0
  225. package/dist/llm/index.js +7 -0
  226. package/dist/llm/index.js.map +1 -0
  227. package/dist/mcp/handlers/base-handler.d.ts +72 -0
  228. package/dist/mcp/handlers/base-handler.d.ts.map +1 -0
  229. package/dist/mcp/handlers/base-handler.js +86 -0
  230. package/dist/mcp/handlers/base-handler.js.map +1 -0
  231. package/dist/mcp/handlers/compare-sources.d.ts +91 -0
  232. package/dist/mcp/handlers/compare-sources.d.ts.map +1 -0
  233. package/dist/mcp/handlers/compare-sources.js +182 -0
  234. package/dist/mcp/handlers/compare-sources.js.map +1 -0
  235. package/dist/mcp/handlers/export-results.d.ts +53 -0
  236. package/dist/mcp/handlers/export-results.d.ts.map +1 -0
  237. package/dist/mcp/handlers/export-results.js +132 -0
  238. package/dist/mcp/handlers/export-results.js.map +1 -0
  239. package/dist/mcp/handlers/export-to-postman.d.ts +65 -0
  240. package/dist/mcp/handlers/export-to-postman.d.ts.map +1 -0
  241. package/dist/mcp/handlers/export-to-postman.js +128 -0
  242. package/dist/mcp/handlers/export-to-postman.js.map +1 -0
  243. package/dist/mcp/handlers/generate-tests.d.ts +74 -0
  244. package/dist/mcp/handlers/generate-tests.d.ts.map +1 -0
  245. package/dist/mcp/handlers/generate-tests.js +519 -0
  246. package/dist/mcp/handlers/generate-tests.js.map +1 -0
  247. package/dist/mcp/handlers/index.d.ts +13 -0
  248. package/dist/mcp/handlers/index.d.ts.map +1 -0
  249. package/dist/mcp/handlers/index.js +12 -0
  250. package/dist/mcp/handlers/index.js.map +1 -0
  251. package/dist/mcp/handlers/run-tests.d.ts +89 -0
  252. package/dist/mcp/handlers/run-tests.d.ts.map +1 -0
  253. package/dist/mcp/handlers/run-tests.js +233 -0
  254. package/dist/mcp/handlers/run-tests.js.map +1 -0
  255. package/dist/mcp/handlers/types.d.ts +61 -0
  256. package/dist/mcp/handlers/types.d.ts.map +1 -0
  257. package/dist/mcp/handlers/types.js +9 -0
  258. package/dist/mcp/handlers/types.js.map +1 -0
  259. package/dist/mcp/server.d.ts +64 -0
  260. package/dist/mcp/server.d.ts.map +1 -0
  261. package/dist/mcp/server.js +200 -0
  262. package/dist/mcp/server.js.map +1 -0
  263. package/dist/mcp/services/file-service.d.ts +66 -0
  264. package/dist/mcp/services/file-service.d.ts.map +1 -0
  265. package/dist/mcp/services/file-service.js +143 -0
  266. package/dist/mcp/services/file-service.js.map +1 -0
  267. package/dist/mcp/services/llm-service.d.ts +70 -0
  268. package/dist/mcp/services/llm-service.d.ts.map +1 -0
  269. package/dist/mcp/services/llm-service.js +189 -0
  270. package/dist/mcp/services/llm-service.js.map +1 -0
  271. package/dist/mcp/services/postman-service.d.ts +128 -0
  272. package/dist/mcp/services/postman-service.d.ts.map +1 -0
  273. package/dist/mcp/services/postman-service.js +266 -0
  274. package/dist/mcp/services/postman-service.js.map +1 -0
  275. package/dist/mcp/services/report-service.d.ts +81 -0
  276. package/dist/mcp/services/report-service.d.ts.map +1 -0
  277. package/dist/mcp/services/report-service.js +210 -0
  278. package/dist/mcp/services/report-service.js.map +1 -0
  279. package/dist/mcp/services/spec-service.d.ts +58 -0
  280. package/dist/mcp/services/spec-service.d.ts.map +1 -0
  281. package/dist/mcp/services/spec-service.js +140 -0
  282. package/dist/mcp/services/spec-service.js.map +1 -0
  283. package/dist/parsers/endpoint-extractor.d.ts +32 -0
  284. package/dist/parsers/endpoint-extractor.d.ts.map +1 -0
  285. package/dist/parsers/endpoint-extractor.js +160 -0
  286. package/dist/parsers/endpoint-extractor.js.map +1 -0
  287. package/dist/parsers/openapi-parser.d.ts +120 -0
  288. package/dist/parsers/openapi-parser.d.ts.map +1 -0
  289. package/dist/parsers/openapi-parser.js +257 -0
  290. package/dist/parsers/openapi-parser.js.map +1 -0
  291. package/dist/parsers/visitors/auth-visitor.d.ts +28 -0
  292. package/dist/parsers/visitors/auth-visitor.d.ts.map +1 -0
  293. package/dist/parsers/visitors/auth-visitor.js +116 -0
  294. package/dist/parsers/visitors/auth-visitor.js.map +1 -0
  295. package/dist/prd/index.d.ts +10 -0
  296. package/dist/prd/index.d.ts.map +1 -0
  297. package/dist/prd/index.js +10 -0
  298. package/dist/prd/index.js.map +1 -0
  299. package/dist/prd/prd-reader.d.ts +124 -0
  300. package/dist/prd/prd-reader.d.ts.map +1 -0
  301. package/dist/prd/prd-reader.js +308 -0
  302. package/dist/prd/prd-reader.js.map +1 -0
  303. package/dist/prd/prd-storage.d.ts +232 -0
  304. package/dist/prd/prd-storage.d.ts.map +1 -0
  305. package/dist/prd/prd-storage.js +129 -0
  306. package/dist/prd/prd-storage.js.map +1 -0
  307. package/dist/repairers/test-auto-repairer.d.ts +61 -0
  308. package/dist/repairers/test-auto-repairer.d.ts.map +1 -0
  309. package/dist/repairers/test-auto-repairer.js +213 -0
  310. package/dist/repairers/test-auto-repairer.js.map +1 -0
  311. package/dist/reporters/comparison-report-generator.d.ts +58 -0
  312. package/dist/reporters/comparison-report-generator.d.ts.map +1 -0
  313. package/dist/reporters/comparison-report-generator.js +369 -0
  314. package/dist/reporters/comparison-report-generator.js.map +1 -0
  315. package/dist/reporters/gherkin-formatter.d.ts +34 -0
  316. package/dist/reporters/gherkin-formatter.d.ts.map +1 -0
  317. package/dist/reporters/gherkin-formatter.js +231 -0
  318. package/dist/reporters/gherkin-formatter.js.map +1 -0
  319. package/dist/reporters/html-report-generator.d.ts +174 -0
  320. package/dist/reporters/html-report-generator.d.ts.map +1 -0
  321. package/dist/reporters/html-report-generator.js +194 -0
  322. package/dist/reporters/html-report-generator.js.map +1 -0
  323. package/dist/reporters/report-charts.d.ts +23 -0
  324. package/dist/reporters/report-charts.d.ts.map +1 -0
  325. package/dist/reporters/report-charts.js +182 -0
  326. package/dist/reporters/report-charts.js.map +1 -0
  327. package/dist/reporters/report-sections.d.ts +34 -0
  328. package/dist/reporters/report-sections.d.ts.map +1 -0
  329. package/dist/reporters/report-sections.js +481 -0
  330. package/dist/reporters/report-sections.js.map +1 -0
  331. package/dist/reporters/report-styles.d.ts +12 -0
  332. package/dist/reporters/report-styles.d.ts.map +1 -0
  333. package/dist/reporters/report-styles.js +412 -0
  334. package/dist/reporters/report-styles.js.map +1 -0
  335. package/dist/reporters/report-test-details.d.ts +56 -0
  336. package/dist/reporters/report-test-details.d.ts.map +1 -0
  337. package/dist/reporters/report-test-details.js +328 -0
  338. package/dist/reporters/report-test-details.js.map +1 -0
  339. package/dist/reporters/report-utils.d.ts +40 -0
  340. package/dist/reporters/report-utils.d.ts.map +1 -0
  341. package/dist/reporters/report-utils.js +163 -0
  342. package/dist/reporters/report-utils.js.map +1 -0
  343. package/dist/types/ai-config.d.ts +63 -0
  344. package/dist/types/ai-config.d.ts.map +1 -0
  345. package/dist/types/ai-config.js +79 -0
  346. package/dist/types/ai-config.js.map +1 -0
  347. package/dist/types/business-rules.d.ts +235 -0
  348. package/dist/types/business-rules.d.ts.map +1 -0
  349. package/dist/types/business-rules.js +6 -0
  350. package/dist/types/business-rules.js.map +1 -0
  351. package/dist/types/config.d.ts +106 -0
  352. package/dist/types/config.d.ts.map +1 -0
  353. package/dist/types/config.js +6 -0
  354. package/dist/types/config.js.map +1 -0
  355. package/dist/types/core.d.ts +72 -0
  356. package/dist/types/core.d.ts.map +1 -0
  357. package/dist/types/core.js +6 -0
  358. package/dist/types/core.js.map +1 -0
  359. package/dist/types/index.d.ts +17 -0
  360. package/dist/types/index.d.ts.map +1 -0
  361. package/dist/types/index.js +10 -0
  362. package/dist/types/index.js.map +1 -0
  363. package/dist/types/openapi.d.ts +139 -0
  364. package/dist/types/openapi.d.ts.map +1 -0
  365. package/dist/types/openapi.js +6 -0
  366. package/dist/types/openapi.js.map +1 -0
  367. package/dist/types/pact.d.ts +101 -0
  368. package/dist/types/pact.d.ts.map +1 -0
  369. package/dist/types/pact.js +6 -0
  370. package/dist/types/pact.js.map +1 -0
  371. package/dist/types/reporting.d.ts +93 -0
  372. package/dist/types/reporting.d.ts.map +1 -0
  373. package/dist/types/reporting.js +6 -0
  374. package/dist/types/reporting.js.map +1 -0
  375. package/dist/types/test-case.d.ts +233 -0
  376. package/dist/types/test-case.d.ts.map +1 -0
  377. package/dist/types/test-case.js +6 -0
  378. package/dist/types/test-case.js.map +1 -0
  379. package/dist/types/test-execution.d.ts +80 -0
  380. package/dist/types/test-execution.d.ts.map +1 -0
  381. package/dist/types/test-execution.js +6 -0
  382. package/dist/types/test-execution.js.map +1 -0
  383. package/dist/utils/auth-generator.d.ts +30 -0
  384. package/dist/utils/auth-generator.d.ts.map +1 -0
  385. package/dist/utils/auth-generator.js +68 -0
  386. package/dist/utils/auth-generator.js.map +1 -0
  387. package/dist/utils/config.d.ts +181 -0
  388. package/dist/utils/config.d.ts.map +1 -0
  389. package/dist/utils/config.js +141 -0
  390. package/dist/utils/config.js.map +1 -0
  391. package/dist/utils/coverage-calculator.d.ts +81 -0
  392. package/dist/utils/coverage-calculator.d.ts.map +1 -0
  393. package/dist/utils/coverage-calculator.js +134 -0
  394. package/dist/utils/coverage-calculator.js.map +1 -0
  395. package/dist/utils/data-loader.d.ts +52 -0
  396. package/dist/utils/data-loader.d.ts.map +1 -0
  397. package/dist/utils/data-loader.js +192 -0
  398. package/dist/utils/data-loader.js.map +1 -0
  399. package/dist/utils/errors.d.ts +167 -0
  400. package/dist/utils/errors.d.ts.map +1 -0
  401. package/dist/utils/errors.js +257 -0
  402. package/dist/utils/errors.js.map +1 -0
  403. package/dist/utils/logger.d.ts +220 -0
  404. package/dist/utils/logger.d.ts.map +1 -0
  405. package/dist/utils/logger.js +325 -0
  406. package/dist/utils/logger.js.map +1 -0
  407. package/dist/utils/openapi-discovery.d.ts +31 -0
  408. package/dist/utils/openapi-discovery.d.ts.map +1 -0
  409. package/dist/utils/openapi-discovery.js +322 -0
  410. package/dist/utils/openapi-discovery.js.map +1 -0
  411. package/dist/utils/path-resolver.d.ts +101 -0
  412. package/dist/utils/path-resolver.d.ts.map +1 -0
  413. package/dist/utils/path-resolver.js +167 -0
  414. package/dist/utils/path-resolver.js.map +1 -0
  415. package/dist/utils/resilience.d.ts +181 -0
  416. package/dist/utils/resilience.d.ts.map +1 -0
  417. package/dist/utils/resilience.js +269 -0
  418. package/dist/utils/resilience.js.map +1 -0
  419. package/dist/validators/openapi-validator.d.ts +198 -0
  420. package/dist/validators/openapi-validator.d.ts.map +1 -0
  421. package/dist/validators/openapi-validator.js +349 -0
  422. package/dist/validators/openapi-validator.js.map +1 -0
  423. package/dist/validators/response-matcher.d.ts +84 -0
  424. package/dist/validators/response-matcher.d.ts.map +1 -0
  425. package/dist/validators/response-matcher.js +234 -0
  426. package/dist/validators/response-matcher.js.map +1 -0
  427. package/dist/validators/schema-validator.d.ts +174 -0
  428. package/dist/validators/schema-validator.d.ts.map +1 -0
  429. package/dist/validators/schema-validator.js +340 -0
  430. package/dist/validators/schema-validator.js.map +1 -0
  431. package/package.json +76 -0
@@ -0,0 +1,292 @@
1
+ /**
2
+ * API Context Analyzer
3
+ *
4
+ * Analyzes OpenAPI specifications to determine the type of API
5
+ * (banking, ecommerce, blog, internal, etc.) for contextual test generation.
6
+ *
7
+ * @module analyzers/context-analyzer
8
+ */
9
+ import { callLLM } from '../llm/ai-client.js';
10
+ import { createLogger } from '../utils/logger.js';
11
+ const log = createLogger('context-analyzer');
12
+ /**
13
+ * Detects the type of API from the OpenAPI specification
14
+ *
15
+ * @param spec - OpenAPI specification document
16
+ * @returns API context with detected type and settings
17
+ */
18
+ export async function detectAPIContext(spec) {
19
+ // Check if AI context detection is disabled
20
+ const useAI = process.env.USE_AI_CONTEXT !== 'false';
21
+ if (!useAI) {
22
+ log.info('AI context detection disabled (USE_AI_CONTEXT=false), using heuristics');
23
+ return detectAPIContextHeuristic(spec);
24
+ }
25
+ try {
26
+ // Gather information from the spec
27
+ const title = spec.info.title || 'Unknown API';
28
+ const description = spec.info.description || '';
29
+ const endpoints = Object.keys(spec.paths).slice(0, 15); // Sample first 15 endpoints
30
+ const version = spec.info.version || '';
31
+ log.info('Analyzing API context with AI', {
32
+ title,
33
+ endpointCount: Object.keys(spec.paths).length
34
+ });
35
+ // Build prompt for LLM
36
+ const prompt = buildAPIContextPrompt(title, description, endpoints, version);
37
+ // Call LLM
38
+ const result = await callLLM(prompt, {
39
+ maxTokens: 128,
40
+ temperature: 0.1, // Low temperature for consistent classification
41
+ timeout: 10000 // 10 seconds is reasonable for this simple classification
42
+ });
43
+ if (!result.success || !result.text) {
44
+ log.warn('AI context detection failed, using heuristic fallback');
45
+ return detectAPIContextHeuristic(spec);
46
+ }
47
+ // Parse AI response
48
+ const detectedType = result.text.trim().toLowerCase();
49
+ const apiContext = buildAPIContext(detectedType);
50
+ log.info('API context detected with AI', apiContext);
51
+ return apiContext;
52
+ }
53
+ catch (error) {
54
+ log.error('Error detecting API context with AI, using heuristic fallback', {
55
+ error: error instanceof Error ? error.message : String(error)
56
+ });
57
+ return detectAPIContextHeuristic(spec);
58
+ }
59
+ }
60
+ /**
61
+ * Enriches APIContext with entity types inferred from endpoints
62
+ *
63
+ * Extracts entity names from endpoint paths (e.g., /api/users/{id} → 'users')
64
+ * to help the AI engine understand what domain entities the API deals with.
65
+ *
66
+ * @param context - Base API context to enrich
67
+ * @param endpoints - Array of parsed endpoints
68
+ * @returns Enriched API context with entityTypes populated
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const baseContext = { type: 'banking', domain: 'banking', industry: 'financial', entityTypes: [] };
73
+ * const endpoints = [{ path: '/api/accounts/{id}' }, { path: '/api/transactions' }];
74
+ * const enriched = enrichAPIContext(baseContext, endpoints);
75
+ * // enriched.entityTypes = ['accounts', 'transactions']
76
+ * ```
77
+ */
78
+ export function enrichAPIContext(context, endpoints) {
79
+ const entityTypes = new Set();
80
+ for (const endpoint of endpoints) {
81
+ // Extract path segments, filter out params and common prefixes
82
+ const pathParts = endpoint.path
83
+ .split('/')
84
+ .filter(p => p && !p.startsWith('{'))
85
+ .map(p => p.toLowerCase());
86
+ if (pathParts.length > 0) {
87
+ // Take the last significant segment (usually the entity name)
88
+ const entity = pathParts[pathParts.length - 1];
89
+ // Skip common API prefixes/versions
90
+ if (!['api', 'v1', 'v2', 'v3', 'v4', 'rest'].includes(entity)) {
91
+ entityTypes.add(entity);
92
+ }
93
+ }
94
+ }
95
+ const enrichedContext = {
96
+ ...context,
97
+ entityTypes: Array.from(entityTypes).slice(0, 10) // Limit to 10 most common
98
+ };
99
+ log.debug('Enriched API context', {
100
+ entityTypesFound: enrichedContext.entityTypes.length,
101
+ entities: enrichedContext.entityTypes
102
+ });
103
+ return enrichedContext;
104
+ }
105
+ /**
106
+ * Builds the prompt for API context detection
107
+ *
108
+ * @param title - API title
109
+ * @param description - API description
110
+ * @param endpoints - Sample of endpoint paths
111
+ * @param version - API version
112
+ * @returns Prompt string
113
+ */
114
+ function buildAPIContextPrompt(title, description, endpoints, version) {
115
+ return `Analyze this API and classify it into ONE category.
116
+
117
+ API Title: ${title}
118
+ Version: ${version}
119
+ Description: ${description}
120
+
121
+ Sample Endpoints (${endpoints.length}):
122
+ ${endpoints.join('\n')}
123
+
124
+ Classify as ONE of these types:
125
+ - banking: Financial APIs with strict validation (IBANs, amounts, transactions, accounts, transfers)
126
+ - ecommerce: Shopping APIs (products, cart, orders, checkout, payments, inventory)
127
+ - blog: Content management APIs (posts, comments, articles, authors, categories)
128
+ - healthcare: Medical/health APIs (patients, appointments, records, prescriptions)
129
+ - education: Learning platforms (courses, students, assignments, grades)
130
+ - social: Social networks (users, posts, likes, friends, messaging)
131
+ - internal: Corporate/internal APIs (flexible, business-specific)
132
+ - other: General purpose API
133
+
134
+ Respond with ONLY the category name, nothing else.`;
135
+ }
136
+ /**
137
+ * Builds API context object from detected type
138
+ *
139
+ * @param type - Detected API type
140
+ * @returns API context object
141
+ */
142
+ function buildAPIContext(type) {
143
+ // Validate type
144
+ const validTypes = [
145
+ 'banking',
146
+ 'ecommerce',
147
+ 'blog',
148
+ 'healthcare',
149
+ 'education',
150
+ 'social',
151
+ 'internal',
152
+ 'other'
153
+ ];
154
+ const normalizedType = validTypes.includes(type) ? type : 'other';
155
+ // Configure settings based on type
156
+ const strictTypes = ['banking', 'healthcare'];
157
+ const realFormatTypes = ['banking', 'ecommerce', 'healthcare'];
158
+ // Map type to industry
159
+ const industryMap = {
160
+ 'banking': 'financial',
161
+ 'ecommerce': 'retail',
162
+ 'healthcare': 'medical',
163
+ 'education': 'academic',
164
+ 'social': 'social_network',
165
+ 'blog': 'content_management',
166
+ 'internal': 'enterprise',
167
+ 'other': 'general'
168
+ };
169
+ return {
170
+ type: normalizedType,
171
+ validationLevel: strictTypes.includes(normalizedType) ? 'strict' : 'relaxed',
172
+ useRealFormats: realFormatTypes.includes(normalizedType),
173
+ domain: normalizedType,
174
+ industry: industryMap[normalizedType] || 'general',
175
+ entityTypes: [] // Will be populated by enrichAPIContext
176
+ };
177
+ }
178
+ /**
179
+ * Heuristic-based API context detection (fallback when AI fails)
180
+ *
181
+ * @param spec - OpenAPI specification
182
+ * @returns API context based on heuristics
183
+ */
184
+ function detectAPIContextHeuristic(spec) {
185
+ const title = (spec.info.title || '').toLowerCase();
186
+ const description = (spec.info.description || '').toLowerCase();
187
+ const endpointPaths = Object.keys(spec.paths).map(p => p.toLowerCase()).join(' ');
188
+ const combined = `${title} ${description} ${endpointPaths}`;
189
+ // Banking keywords
190
+ if (hasKeywords(combined, ['bank', 'account', 'transfer', 'transaction', 'iban', 'payment', 'balance'])) {
191
+ log.info('Heuristic detected: banking');
192
+ return buildAPIContext('banking');
193
+ }
194
+ // E-commerce keywords
195
+ if (hasKeywords(combined, ['product', 'cart', 'order', 'checkout', 'shop', 'store', 'inventory'])) {
196
+ log.info('Heuristic detected: ecommerce');
197
+ return buildAPIContext('ecommerce');
198
+ }
199
+ // Blog/CMS keywords
200
+ if (hasKeywords(combined, ['post', 'article', 'comment', 'blog', 'author', 'category', 'tag'])) {
201
+ log.info('Heuristic detected: blog');
202
+ return buildAPIContext('blog');
203
+ }
204
+ // Healthcare keywords
205
+ if (hasKeywords(combined, ['patient', 'doctor', 'appointment', 'medical', 'health', 'prescription', 'diagnosis'])) {
206
+ log.info('Heuristic detected: healthcare');
207
+ return buildAPIContext('healthcare');
208
+ }
209
+ // Education keywords
210
+ if (hasKeywords(combined, ['course', 'student', 'teacher', 'assignment', 'grade', 'lesson', 'education'])) {
211
+ log.info('Heuristic detected: education');
212
+ return buildAPIContext('education');
213
+ }
214
+ // Social keywords
215
+ if (hasKeywords(combined, ['user', 'friend', 'follow', 'like', 'post', 'message', 'social', 'profile'])) {
216
+ log.info('Heuristic detected: social');
217
+ return buildAPIContext('social');
218
+ }
219
+ // Default to 'other'
220
+ log.info('Heuristic detected: other (default)');
221
+ return buildAPIContext('other');
222
+ }
223
+ /**
224
+ * Checks if text contains at least 2 keywords from the list
225
+ *
226
+ * @param text - Text to search
227
+ * @param keywords - List of keywords
228
+ * @returns true if at least 2 keywords found
229
+ */
230
+ function hasKeywords(text, keywords) {
231
+ const count = keywords.filter(keyword => text.includes(keyword)).length;
232
+ return count >= 2;
233
+ }
234
+ /**
235
+ * Infers the purpose of a specific endpoint
236
+ *
237
+ * @param path - Endpoint path
238
+ * @param method - HTTP method
239
+ * @param operation - OpenAPI operation object
240
+ * @returns Inferred purpose
241
+ */
242
+ export function inferEndpointPurpose(path, method, operation) {
243
+ const pathLower = path.toLowerCase();
244
+ const methodUpper = method.toUpperCase();
245
+ // Check operation summary/description for hints
246
+ const summary = (operation?.summary || '').toLowerCase();
247
+ const description = (operation?.description || '').toLowerCase();
248
+ const combined = `${pathLower} ${summary} ${description}`;
249
+ // Authentication
250
+ if (combined.includes('login') || combined.includes('signin'))
251
+ return 'login';
252
+ if (combined.includes('logout') || combined.includes('signout'))
253
+ return 'logout';
254
+ if (combined.includes('register') || combined.includes('signup'))
255
+ return 'register';
256
+ if (combined.includes('auth') || combined.includes('token'))
257
+ return 'authentication';
258
+ // Payment & Financial
259
+ if (combined.includes('payment') || combined.includes('pay'))
260
+ return 'payment';
261
+ if (combined.includes('transfer'))
262
+ return 'transfer';
263
+ if (combined.includes('transaction'))
264
+ return 'transaction';
265
+ if (combined.includes('balance'))
266
+ return 'balance_check';
267
+ if (combined.includes('wallet'))
268
+ return 'wallet_management';
269
+ if (combined.includes('invoice'))
270
+ return 'invoice';
271
+ // User management
272
+ if (combined.includes('user') || combined.includes('profile')) {
273
+ if (methodUpper === 'POST')
274
+ return 'create_user';
275
+ if (methodUpper === 'PUT' || methodUpper === 'PATCH')
276
+ return 'update_user';
277
+ if (methodUpper === 'DELETE')
278
+ return 'delete_user';
279
+ return 'get_user';
280
+ }
281
+ // Generic CRUD
282
+ if (methodUpper === 'POST')
283
+ return 'create';
284
+ if (methodUpper === 'PUT' || methodUpper === 'PATCH')
285
+ return 'update';
286
+ if (methodUpper === 'DELETE')
287
+ return 'delete';
288
+ if (methodUpper === 'GET')
289
+ return 'retrieve';
290
+ return 'general';
291
+ }
292
+ //# sourceMappingURL=context-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/context-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Dependency Analyzer
3
+ *
4
+ * Automatically detects dependencies between test cases based on:
5
+ * - Path parameter injection (GET /users/{id} depends on POST /users)
6
+ * - Authentication requirements
7
+ * - Resource hierarchies
8
+ *
9
+ * @module analyzers/dependency-analyzer
10
+ */
11
+ import type { TestCase, ParsedEndpoint } from '../types/index.js';
12
+ /**
13
+ * Detected dependency information
14
+ */
15
+ export interface DetectedDependency {
16
+ testId: string;
17
+ dependsOn: string[];
18
+ reason: string;
19
+ confidence: 'high' | 'medium' | 'low';
20
+ }
21
+ /**
22
+ * Detects dependencies between test cases automatically
23
+ *
24
+ * @param tests - Array of test cases
25
+ * @param endpoints - Array of parsed endpoints
26
+ * @returns Dependency map (testId => array of dependency test IDs)
27
+ */
28
+ export declare function detectDependencies(tests: TestCase[], endpoints: ParsedEndpoint[]): Record<string, string[]>;
29
+ /**
30
+ * Merges auto-detected dependencies with user-provided dependencies
31
+ *
32
+ * @param autoDeps - Auto-detected dependencies
33
+ * @param userDeps - User-provided dependencies
34
+ * @returns Merged dependencies (user deps take precedence)
35
+ */
36
+ export declare function mergeDependencies(autoDeps: Record<string, string[]>, userDeps: Record<string, string[]>): Record<string, string[]>;
37
+ /**
38
+ * Validates dependencies to avoid circular references
39
+ *
40
+ * @param dependencies - Dependency map
41
+ * @returns Array of circular dependency errors
42
+ */
43
+ export declare function validateDependencies(dependencies: Record<string, string[]>): string[];
44
+ //# sourceMappingURL=dependency-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/dependency-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAKlE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,EAAE,EACjB,SAAS,EAAE,cAAc,EAAE,GAC1B,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAwC1B;AA+PD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACjC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAkB1B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,MAAM,EAAE,CAkCV"}
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Dependency Analyzer
3
+ *
4
+ * Automatically detects dependencies between test cases based on:
5
+ * - Path parameter injection (GET /users/{id} depends on POST /users)
6
+ * - Authentication requirements
7
+ * - Resource hierarchies
8
+ *
9
+ * @module analyzers/dependency-analyzer
10
+ */
11
+ import { createLogger } from '../utils/logger.js';
12
+ const log = createLogger('dependency-analyzer');
13
+ /**
14
+ * Detects dependencies between test cases automatically
15
+ *
16
+ * @param tests - Array of test cases
17
+ * @param endpoints - Array of parsed endpoints
18
+ * @returns Dependency map (testId => array of dependency test IDs)
19
+ */
20
+ export function detectDependencies(tests, endpoints) {
21
+ log.info('Analyzing test dependencies', { testCount: tests.length });
22
+ const dependencies = {};
23
+ const detectedDeps = [];
24
+ // Pattern 1: Path parameter dependencies
25
+ const pathDeps = detectPathParameterDependencies(tests);
26
+ detectedDeps.push(...pathDeps);
27
+ // Pattern 2: Authentication dependencies
28
+ const authDeps = detectAuthenticationDependencies(tests, endpoints);
29
+ detectedDeps.push(...authDeps);
30
+ // Pattern 3: Resource hierarchy dependencies
31
+ const hierarchyDeps = detectResourceHierarchyDependencies(tests);
32
+ detectedDeps.push(...hierarchyDeps);
33
+ // Convert to dependency map
34
+ for (const dep of detectedDeps) {
35
+ if (!dependencies[dep.testId]) {
36
+ dependencies[dep.testId] = [];
37
+ }
38
+ for (const depTestId of dep.dependsOn) {
39
+ if (!dependencies[dep.testId].includes(depTestId)) {
40
+ dependencies[dep.testId].push(depTestId);
41
+ }
42
+ }
43
+ }
44
+ log.info('Dependencies detected', {
45
+ totalDependencies: Object.keys(dependencies).length,
46
+ byPattern: {
47
+ pathParams: pathDeps.length,
48
+ auth: authDeps.length,
49
+ hierarchy: hierarchyDeps.length
50
+ }
51
+ });
52
+ return dependencies;
53
+ }
54
+ /**
55
+ * Detects dependencies based on path parameters
56
+ * Example: GET /users/{id} depends on POST /users
57
+ *
58
+ * @param tests - Array of test cases
59
+ * @returns Array of detected dependencies
60
+ */
61
+ function detectPathParameterDependencies(tests) {
62
+ const dependencies = [];
63
+ for (const test of tests) {
64
+ // Skip if test doesn't have path parameters
65
+ if (!test.path.includes('{')) {
66
+ continue;
67
+ }
68
+ // Skip if test is a creation endpoint (POST)
69
+ if (test.method === 'POST') {
70
+ continue;
71
+ }
72
+ // Extract base path (without parameters)
73
+ const basePath = extractBasePath(test.path);
74
+ // Find corresponding creation test (POST to base path)
75
+ const createTests = tests.filter(t => t.method === 'POST' &&
76
+ t.path === basePath &&
77
+ t.id !== test.id &&
78
+ t.category === 'happy-path' // Only depend on successful creation
79
+ );
80
+ if (createTests.length > 0) {
81
+ dependencies.push({
82
+ testId: test.id,
83
+ dependsOn: createTests.map(t => t.id),
84
+ reason: `Requires resource to exist (path parameter dependency: ${test.path})`,
85
+ confidence: 'high'
86
+ });
87
+ log.debug('Path parameter dependency detected', {
88
+ test: test.id,
89
+ dependsOn: createTests.map(t => t.id),
90
+ path: test.path,
91
+ basePath
92
+ });
93
+ }
94
+ }
95
+ return dependencies;
96
+ }
97
+ /**
98
+ * Detects authentication dependencies
99
+ * Tests that require auth depend on login/auth tests
100
+ *
101
+ * @param tests - Array of test cases
102
+ * @param endpoints - Array of parsed endpoints
103
+ * @returns Array of detected dependencies
104
+ */
105
+ function detectAuthenticationDependencies(tests, endpoints) {
106
+ const dependencies = [];
107
+ // Find authentication tests (login, signin, token, auth endpoints)
108
+ const authTests = tests.filter(t => isAuthenticationTest(t) && t.category === 'happy-path');
109
+ if (authTests.length === 0) {
110
+ log.debug('No authentication tests found');
111
+ return dependencies;
112
+ }
113
+ // Use the first auth test as the dependency
114
+ const primaryAuthTest = authTests[0];
115
+ for (const test of tests) {
116
+ // Skip if test IS the auth test
117
+ if (test.id === primaryAuthTest.id) {
118
+ continue;
119
+ }
120
+ // Skip if test explicitly requires NO auth
121
+ if (test.requiresAuth === false) {
122
+ continue;
123
+ }
124
+ // Skip if test expects auth failure (401, 403)
125
+ if (test.expectedStatus === 401 || test.expectedStatus === 403) {
126
+ continue;
127
+ }
128
+ // Skip if test is also an auth test
129
+ if (isAuthenticationTest(test)) {
130
+ continue;
131
+ }
132
+ // Find endpoint info
133
+ const endpoint = endpoints.find(e => e.path === test.path && e.method === test.method);
134
+ // Check if endpoint requires auth
135
+ const requiresAuth = test.requiresAuth ?? endpoint?.requiresAuth ?? true;
136
+ if (requiresAuth && test.expectedStatus >= 200 && test.expectedStatus < 300) {
137
+ dependencies.push({
138
+ testId: test.id,
139
+ dependsOn: [primaryAuthTest.id],
140
+ reason: 'Requires authentication token',
141
+ confidence: 'high'
142
+ });
143
+ log.debug('Authentication dependency detected', {
144
+ test: test.id,
145
+ dependsOn: primaryAuthTest.id,
146
+ path: test.path
147
+ });
148
+ }
149
+ }
150
+ return dependencies;
151
+ }
152
+ /**
153
+ * Detects resource hierarchy dependencies
154
+ * Example: POST /users/{userId}/orders depends on POST /users
155
+ *
156
+ * @param tests - Array of test cases
157
+ * @returns Array of detected dependencies
158
+ */
159
+ function detectResourceHierarchyDependencies(tests) {
160
+ const dependencies = [];
161
+ for (const test of tests) {
162
+ // Check if path has nested resources (multiple parameters or deep nesting)
163
+ const paramCount = (test.path.match(/\{[^}]+\}/g) || []).length;
164
+ if (paramCount === 0) {
165
+ continue;
166
+ }
167
+ // Extract parent path
168
+ const parentPath = extractParentResourcePath(test.path);
169
+ if (!parentPath) {
170
+ continue;
171
+ }
172
+ // Find parent resource creation tests
173
+ const parentCreateTests = tests.filter(t => t.method === 'POST' &&
174
+ matchesPath(t.path, parentPath) &&
175
+ t.id !== test.id &&
176
+ t.category === 'happy-path');
177
+ if (parentCreateTests.length > 0) {
178
+ dependencies.push({
179
+ testId: test.id,
180
+ dependsOn: parentCreateTests.map(t => t.id),
181
+ reason: `Requires parent resource to exist (${parentPath})`,
182
+ confidence: 'medium'
183
+ });
184
+ log.debug('Resource hierarchy dependency detected', {
185
+ test: test.id,
186
+ dependsOn: parentCreateTests.map(t => t.id),
187
+ path: test.path,
188
+ parentPath
189
+ });
190
+ }
191
+ }
192
+ return dependencies;
193
+ }
194
+ /**
195
+ * Checks if a test is an authentication test
196
+ *
197
+ * @param test - Test case
198
+ * @returns true if test is auth-related
199
+ */
200
+ function isAuthenticationTest(test) {
201
+ const pathLower = test.path.toLowerCase();
202
+ const nameLower = test.name.toLowerCase();
203
+ return (pathLower.includes('/login') ||
204
+ pathLower.includes('/signin') ||
205
+ pathLower.includes('/auth') ||
206
+ pathLower.includes('/token') ||
207
+ pathLower.includes('/oauth') ||
208
+ nameLower.includes('login') ||
209
+ nameLower.includes('auth'));
210
+ }
211
+ /**
212
+ * Extracts base path by removing path parameters
213
+ * Example: /users/{id}/orders => /users
214
+ *
215
+ * @param path - Path with parameters
216
+ * @returns Base path without parameters
217
+ */
218
+ function extractBasePath(path) {
219
+ // Remove the last segment if it contains a parameter
220
+ const segments = path.split('/').filter(s => s.length > 0);
221
+ const baseSegments = segments.slice(0, segments.findIndex(s => s.includes('{')));
222
+ if (baseSegments.length === 0) {
223
+ return '/';
224
+ }
225
+ return '/' + baseSegments.join('/');
226
+ }
227
+ /**
228
+ * Extracts parent resource path from nested path
229
+ * Example: /users/{userId}/orders/{orderId} => /users
230
+ *
231
+ * @param path - Nested path
232
+ * @returns Parent resource path or null
233
+ */
234
+ function extractParentResourcePath(path) {
235
+ const segments = path.split('/').filter(s => s.length > 0);
236
+ // Find the first parameter
237
+ const firstParamIndex = segments.findIndex(s => s.includes('{'));
238
+ if (firstParamIndex === -1 || firstParamIndex === 0) {
239
+ return null;
240
+ }
241
+ // Return path up to first parameter
242
+ return '/' + segments.slice(0, firstParamIndex).join('/');
243
+ }
244
+ /**
245
+ * Checks if two paths match (ignoring parameters)
246
+ *
247
+ * @param path1 - First path
248
+ * @param path2 - Second path
249
+ * @returns true if paths match
250
+ */
251
+ function matchesPath(path1, path2) {
252
+ // Normalize paths
253
+ const normalize = (p) => p.split('/').filter(s => s.length > 0).join('/');
254
+ return normalize(path1) === normalize(path2);
255
+ }
256
+ /**
257
+ * Merges auto-detected dependencies with user-provided dependencies
258
+ *
259
+ * @param autoDeps - Auto-detected dependencies
260
+ * @param userDeps - User-provided dependencies
261
+ * @returns Merged dependencies (user deps take precedence)
262
+ */
263
+ export function mergeDependencies(autoDeps, userDeps) {
264
+ const merged = { ...autoDeps };
265
+ // Add or override with user dependencies
266
+ for (const [testId, deps] of Object.entries(userDeps)) {
267
+ if (!merged[testId]) {
268
+ merged[testId] = [];
269
+ }
270
+ // Add user deps, avoiding duplicates
271
+ for (const dep of deps) {
272
+ if (!merged[testId].includes(dep)) {
273
+ merged[testId].push(dep);
274
+ }
275
+ }
276
+ }
277
+ return merged;
278
+ }
279
+ /**
280
+ * Validates dependencies to avoid circular references
281
+ *
282
+ * @param dependencies - Dependency map
283
+ * @returns Array of circular dependency errors
284
+ */
285
+ export function validateDependencies(dependencies) {
286
+ const errors = [];
287
+ const visited = new Set();
288
+ const recursionStack = new Set();
289
+ function detectCycle(testId, path = []) {
290
+ if (recursionStack.has(testId)) {
291
+ errors.push(`Circular dependency detected: ${path.join(' -> ')} -> ${testId}`);
292
+ return true;
293
+ }
294
+ if (visited.has(testId)) {
295
+ return false;
296
+ }
297
+ visited.add(testId);
298
+ recursionStack.add(testId);
299
+ const deps = dependencies[testId] || [];
300
+ for (const dep of deps) {
301
+ if (detectCycle(dep, [...path, testId])) {
302
+ return true;
303
+ }
304
+ }
305
+ recursionStack.delete(testId);
306
+ return false;
307
+ }
308
+ for (const testId of Object.keys(dependencies)) {
309
+ detectCycle(testId);
310
+ }
311
+ return errors;
312
+ }
313
+ //# sourceMappingURL=dependency-analyzer.js.map