@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.
- package/.env.example +91 -0
- package/README.md +472 -0
- package/dist/ai-engine/assertion-generator.d.ts +48 -0
- package/dist/ai-engine/assertion-generator.d.ts.map +1 -0
- package/dist/ai-engine/assertion-generator.js +166 -0
- package/dist/ai-engine/assertion-generator.js.map +1 -0
- package/dist/ai-engine/context-data-generator.d.ts +38 -0
- package/dist/ai-engine/context-data-generator.d.ts.map +1 -0
- package/dist/ai-engine/context-data-generator.js +146 -0
- package/dist/ai-engine/context-data-generator.js.map +1 -0
- package/dist/ai-engine/dataflow-detector.d.ts +53 -0
- package/dist/ai-engine/dataflow-detector.d.ts.map +1 -0
- package/dist/ai-engine/dataflow-detector.js +217 -0
- package/dist/ai-engine/dataflow-detector.js.map +1 -0
- package/dist/ai-engine/dependency-detector.d.ts +52 -0
- package/dist/ai-engine/dependency-detector.d.ts.map +1 -0
- package/dist/ai-engine/dependency-detector.js +241 -0
- package/dist/ai-engine/dependency-detector.js.map +1 -0
- package/dist/ai-engine/edge-case-suggester.d.ts +63 -0
- package/dist/ai-engine/edge-case-suggester.d.ts.map +1 -0
- package/dist/ai-engine/edge-case-suggester.js +177 -0
- package/dist/ai-engine/edge-case-suggester.js.map +1 -0
- package/dist/ai-engine/index.d.ts +13 -0
- package/dist/ai-engine/index.d.ts.map +1 -0
- package/dist/ai-engine/index.js +13 -0
- package/dist/ai-engine/index.js.map +1 -0
- package/dist/analyzers/ai-failure-analyzer.d.ts +41 -0
- package/dist/analyzers/ai-failure-analyzer.d.ts.map +1 -0
- package/dist/analyzers/ai-failure-analyzer.js +220 -0
- package/dist/analyzers/ai-failure-analyzer.js.map +1 -0
- package/dist/analyzers/comparison-utils.d.ts +31 -0
- package/dist/analyzers/comparison-utils.d.ts.map +1 -0
- package/dist/analyzers/comparison-utils.js +85 -0
- package/dist/analyzers/comparison-utils.js.map +1 -0
- package/dist/analyzers/context-analyzer.d.ts +49 -0
- package/dist/analyzers/context-analyzer.d.ts.map +1 -0
- package/dist/analyzers/context-analyzer.js +292 -0
- package/dist/analyzers/context-analyzer.js.map +1 -0
- package/dist/analyzers/dependency-analyzer.d.ts +44 -0
- package/dist/analyzers/dependency-analyzer.d.ts.map +1 -0
- package/dist/analyzers/dependency-analyzer.js +313 -0
- package/dist/analyzers/dependency-analyzer.js.map +1 -0
- package/dist/analyzers/failure-analyzer.d.ts +122 -0
- package/dist/analyzers/failure-analyzer.d.ts.map +1 -0
- package/dist/analyzers/failure-analyzer.js +140 -0
- package/dist/analyzers/failure-analyzer.js.map +1 -0
- package/dist/analyzers/failure-detectors/index.d.ts +33 -0
- package/dist/analyzers/failure-detectors/index.d.ts.map +1 -0
- package/dist/analyzers/failure-detectors/index.js +164 -0
- package/dist/analyzers/failure-detectors/index.js.map +1 -0
- package/dist/analyzers/failure-discrepancy-correlator.d.ts +111 -0
- package/dist/analyzers/failure-discrepancy-correlator.d.ts.map +1 -0
- package/dist/analyzers/failure-discrepancy-correlator.js +202 -0
- package/dist/analyzers/failure-discrepancy-correlator.js.map +1 -0
- package/dist/analyzers/index.d.ts +10 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +10 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/semantic-matcher.d.ts +123 -0
- package/dist/analyzers/semantic-matcher.d.ts.map +1 -0
- package/dist/analyzers/semantic-matcher.js +297 -0
- package/dist/analyzers/semantic-matcher.js.map +1 -0
- package/dist/analyzers/source-comparator.d.ts +177 -0
- package/dist/analyzers/source-comparator.d.ts.map +1 -0
- package/dist/analyzers/source-comparator.js +225 -0
- package/dist/analyzers/source-comparator.js.map +1 -0
- package/dist/business-rules/business-rules-analyzer.d.ts +44 -0
- package/dist/business-rules/business-rules-analyzer.d.ts.map +1 -0
- package/dist/business-rules/business-rules-analyzer.js +363 -0
- package/dist/business-rules/business-rules-analyzer.js.map +1 -0
- package/dist/business-rules/business-rules-generator.d.ts +78 -0
- package/dist/business-rules/business-rules-generator.d.ts.map +1 -0
- package/dist/business-rules/business-rules-generator.js +357 -0
- package/dist/business-rules/business-rules-generator.js.map +1 -0
- package/dist/business-rules/extractors/rule-extractors.d.ts +50 -0
- package/dist/business-rules/extractors/rule-extractors.d.ts.map +1 -0
- package/dist/business-rules/extractors/rule-extractors.js +189 -0
- package/dist/business-rules/extractors/rule-extractors.js.map +1 -0
- package/dist/business-rules/value-generators.d.ts +70 -0
- package/dist/business-rules/value-generators.d.ts.map +1 -0
- package/dist/business-rules/value-generators.js +142 -0
- package/dist/business-rules/value-generators.js.map +1 -0
- package/dist/executor/auth-providers/auth-header-builder.d.ts +16 -0
- package/dist/executor/auth-providers/auth-header-builder.d.ts.map +1 -0
- package/dist/executor/auth-providers/auth-header-builder.js +47 -0
- package/dist/executor/auth-providers/auth-header-builder.js.map +1 -0
- package/dist/executor/auth-providers/oauth2-provider.d.ts +19 -0
- package/dist/executor/auth-providers/oauth2-provider.d.ts.map +1 -0
- package/dist/executor/auth-providers/oauth2-provider.js +114 -0
- package/dist/executor/auth-providers/oauth2-provider.js.map +1 -0
- package/dist/executor/http-client.d.ts +133 -0
- package/dist/executor/http-client.d.ts.map +1 -0
- package/dist/executor/http-client.js +172 -0
- package/dist/executor/http-client.js.map +1 -0
- package/dist/executor/http-request-builder.d.ts +69 -0
- package/dist/executor/http-request-builder.d.ts.map +1 -0
- package/dist/executor/http-request-builder.js +140 -0
- package/dist/executor/http-request-builder.js.map +1 -0
- package/dist/executor/http-response-parser.d.ts +28 -0
- package/dist/executor/http-response-parser.d.ts.map +1 -0
- package/dist/executor/http-response-parser.js +74 -0
- package/dist/executor/http-response-parser.js.map +1 -0
- package/dist/executor/response-handler.d.ts +66 -0
- package/dist/executor/response-handler.d.ts.map +1 -0
- package/dist/executor/response-handler.js +135 -0
- package/dist/executor/response-handler.js.map +1 -0
- package/dist/executor/result-processor.d.ts +27 -0
- package/dist/executor/result-processor.d.ts.map +1 -0
- package/dist/executor/result-processor.js +140 -0
- package/dist/executor/result-processor.js.map +1 -0
- package/dist/executor/result-utils.d.ts +21 -0
- package/dist/executor/result-utils.d.ts.map +1 -0
- package/dist/executor/result-utils.js +29 -0
- package/dist/executor/result-utils.js.map +1 -0
- package/dist/executor/test-executor.d.ts +49 -0
- package/dist/executor/test-executor.d.ts.map +1 -0
- package/dist/executor/test-executor.js +226 -0
- package/dist/executor/test-executor.js.map +1 -0
- package/dist/executor/test-runner.d.ts +85 -0
- package/dist/executor/test-runner.d.ts.map +1 -0
- package/dist/executor/test-runner.js +177 -0
- package/dist/executor/test-runner.js.map +1 -0
- package/dist/executor/token-detector/index.d.ts +7 -0
- package/dist/executor/token-detector/index.d.ts.map +1 -0
- package/dist/executor/token-detector/index.js +7 -0
- package/dist/executor/token-detector/index.js.map +1 -0
- package/dist/executor/token-detector/token-detector.d.ts +64 -0
- package/dist/executor/token-detector/token-detector.d.ts.map +1 -0
- package/dist/executor/token-detector/token-detector.js +140 -0
- package/dist/executor/token-detector/token-detector.js.map +1 -0
- package/dist/generators/business-rule-from-stories-generator.d.ts +30 -0
- package/dist/generators/business-rule-from-stories-generator.d.ts.map +1 -0
- package/dist/generators/business-rule-from-stories-generator.js +227 -0
- package/dist/generators/business-rule-from-stories-generator.js.map +1 -0
- package/dist/generators/data/ai-data-generator.d.ts +23 -0
- package/dist/generators/data/ai-data-generator.d.ts.map +1 -0
- package/dist/generators/data/ai-data-generator.js +41 -0
- package/dist/generators/data/ai-data-generator.js.map +1 -0
- package/dist/generators/data/base-generator.d.ts +121 -0
- package/dist/generators/data/base-generator.d.ts.map +1 -0
- package/dist/generators/data/base-generator.js +200 -0
- package/dist/generators/data/base-generator.js.map +1 -0
- package/dist/generators/data/heuristic-data-generator.d.ts +28 -0
- package/dist/generators/data/heuristic-data-generator.d.ts.map +1 -0
- package/dist/generators/data/heuristic-data-generator.js +49 -0
- package/dist/generators/data/heuristic-data-generator.js.map +1 -0
- package/dist/generators/data/index.d.ts +48 -0
- package/dist/generators/data/index.d.ts.map +1 -0
- package/dist/generators/data/index.js +201 -0
- package/dist/generators/data/index.js.map +1 -0
- package/dist/generators/data/schema-walker.d.ts +45 -0
- package/dist/generators/data/schema-walker.d.ts.map +1 -0
- package/dist/generators/data/schema-walker.js +103 -0
- package/dist/generators/data/schema-walker.js.map +1 -0
- package/dist/generators/data/type-strategies.d.ts +79 -0
- package/dist/generators/data/type-strategies.d.ts.map +1 -0
- package/dist/generators/data/type-strategies.js +394 -0
- package/dist/generators/data/type-strategies.js.map +1 -0
- package/dist/generators/data-generator.d.ts +11 -0
- package/dist/generators/data-generator.d.ts.map +1 -0
- package/dist/generators/data-generator.js +11 -0
- package/dist/generators/data-generator.js.map +1 -0
- package/dist/generators/edge-case-generator.d.ts +55 -0
- package/dist/generators/edge-case-generator.d.ts.map +1 -0
- package/dist/generators/edge-case-generator.js +327 -0
- package/dist/generators/edge-case-generator.js.map +1 -0
- package/dist/generators/edge-cases/boundary-analyzer.d.ts +26 -0
- package/dist/generators/edge-cases/boundary-analyzer.d.ts.map +1 -0
- package/dist/generators/edge-cases/boundary-analyzer.js +95 -0
- package/dist/generators/edge-cases/boundary-analyzer.js.map +1 -0
- package/dist/generators/error-case-generator.d.ts +11 -0
- package/dist/generators/error-case-generator.d.ts.map +1 -0
- package/dist/generators/error-case-generator.js +11 -0
- package/dist/generators/error-case-generator.js.map +1 -0
- package/dist/generators/errors/auth-error-strategy.d.ts +36 -0
- package/dist/generators/errors/auth-error-strategy.d.ts.map +1 -0
- package/dist/generators/errors/auth-error-strategy.js +118 -0
- package/dist/generators/errors/auth-error-strategy.js.map +1 -0
- package/dist/generators/errors/business-error-strategy.d.ts +44 -0
- package/dist/generators/errors/business-error-strategy.d.ts.map +1 -0
- package/dist/generators/errors/business-error-strategy.js +152 -0
- package/dist/generators/errors/business-error-strategy.js.map +1 -0
- package/dist/generators/errors/error-strategy-factory.d.ts +27 -0
- package/dist/generators/errors/error-strategy-factory.d.ts.map +1 -0
- package/dist/generators/errors/error-strategy-factory.js +47 -0
- package/dist/generators/errors/error-strategy-factory.js.map +1 -0
- package/dist/generators/errors/error-strategy.d.ts +62 -0
- package/dist/generators/errors/error-strategy.d.ts.map +1 -0
- package/dist/generators/errors/error-strategy.js +69 -0
- package/dist/generators/errors/error-strategy.js.map +1 -0
- package/dist/generators/errors/index.d.ts +23 -0
- package/dist/generators/errors/index.d.ts.map +1 -0
- package/dist/generators/errors/index.js +73 -0
- package/dist/generators/errors/index.js.map +1 -0
- package/dist/generators/errors/validation-error-strategy.d.ts +25 -0
- package/dist/generators/errors/validation-error-strategy.d.ts.map +1 -0
- package/dist/generators/errors/validation-error-strategy.js +214 -0
- package/dist/generators/errors/validation-error-strategy.js.map +1 -0
- package/dist/generators/happy-path-generator.d.ts +93 -0
- package/dist/generators/happy-path-generator.d.ts.map +1 -0
- package/dist/generators/happy-path-generator.js +275 -0
- package/dist/generators/happy-path-generator.js.map +1 -0
- package/dist/generators/test-enricher.d.ts +44 -0
- package/dist/generators/test-enricher.d.ts.map +1 -0
- package/dist/generators/test-enricher.js +109 -0
- package/dist/generators/test-enricher.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/ai-cache.d.ts +123 -0
- package/dist/llm/ai-cache.d.ts.map +1 -0
- package/dist/llm/ai-cache.js +220 -0
- package/dist/llm/ai-cache.js.map +1 -0
- package/dist/llm/ai-client.d.ts +92 -0
- package/dist/llm/ai-client.d.ts.map +1 -0
- package/dist/llm/ai-client.js +386 -0
- package/dist/llm/ai-client.js.map +1 -0
- package/dist/llm/data-generator-ai.d.ts +84 -0
- package/dist/llm/data-generator-ai.d.ts.map +1 -0
- package/dist/llm/data-generator-ai.js +284 -0
- package/dist/llm/data-generator-ai.js.map +1 -0
- package/dist/llm/index.d.ts +7 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +7 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/mcp/handlers/base-handler.d.ts +72 -0
- package/dist/mcp/handlers/base-handler.d.ts.map +1 -0
- package/dist/mcp/handlers/base-handler.js +86 -0
- package/dist/mcp/handlers/base-handler.js.map +1 -0
- package/dist/mcp/handlers/compare-sources.d.ts +91 -0
- package/dist/mcp/handlers/compare-sources.d.ts.map +1 -0
- package/dist/mcp/handlers/compare-sources.js +182 -0
- package/dist/mcp/handlers/compare-sources.js.map +1 -0
- package/dist/mcp/handlers/export-results.d.ts +53 -0
- package/dist/mcp/handlers/export-results.d.ts.map +1 -0
- package/dist/mcp/handlers/export-results.js +132 -0
- package/dist/mcp/handlers/export-results.js.map +1 -0
- package/dist/mcp/handlers/export-to-postman.d.ts +65 -0
- package/dist/mcp/handlers/export-to-postman.d.ts.map +1 -0
- package/dist/mcp/handlers/export-to-postman.js +128 -0
- package/dist/mcp/handlers/export-to-postman.js.map +1 -0
- package/dist/mcp/handlers/generate-tests.d.ts +74 -0
- package/dist/mcp/handlers/generate-tests.d.ts.map +1 -0
- package/dist/mcp/handlers/generate-tests.js +519 -0
- package/dist/mcp/handlers/generate-tests.js.map +1 -0
- package/dist/mcp/handlers/index.d.ts +13 -0
- package/dist/mcp/handlers/index.d.ts.map +1 -0
- package/dist/mcp/handlers/index.js +12 -0
- package/dist/mcp/handlers/index.js.map +1 -0
- package/dist/mcp/handlers/run-tests.d.ts +89 -0
- package/dist/mcp/handlers/run-tests.d.ts.map +1 -0
- package/dist/mcp/handlers/run-tests.js +233 -0
- package/dist/mcp/handlers/run-tests.js.map +1 -0
- package/dist/mcp/handlers/types.d.ts +61 -0
- package/dist/mcp/handlers/types.d.ts.map +1 -0
- package/dist/mcp/handlers/types.js +9 -0
- package/dist/mcp/handlers/types.js.map +1 -0
- package/dist/mcp/server.d.ts +64 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +200 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/services/file-service.d.ts +66 -0
- package/dist/mcp/services/file-service.d.ts.map +1 -0
- package/dist/mcp/services/file-service.js +143 -0
- package/dist/mcp/services/file-service.js.map +1 -0
- package/dist/mcp/services/llm-service.d.ts +70 -0
- package/dist/mcp/services/llm-service.d.ts.map +1 -0
- package/dist/mcp/services/llm-service.js +189 -0
- package/dist/mcp/services/llm-service.js.map +1 -0
- package/dist/mcp/services/postman-service.d.ts +128 -0
- package/dist/mcp/services/postman-service.d.ts.map +1 -0
- package/dist/mcp/services/postman-service.js +266 -0
- package/dist/mcp/services/postman-service.js.map +1 -0
- package/dist/mcp/services/report-service.d.ts +81 -0
- package/dist/mcp/services/report-service.d.ts.map +1 -0
- package/dist/mcp/services/report-service.js +210 -0
- package/dist/mcp/services/report-service.js.map +1 -0
- package/dist/mcp/services/spec-service.d.ts +58 -0
- package/dist/mcp/services/spec-service.d.ts.map +1 -0
- package/dist/mcp/services/spec-service.js +140 -0
- package/dist/mcp/services/spec-service.js.map +1 -0
- package/dist/parsers/endpoint-extractor.d.ts +32 -0
- package/dist/parsers/endpoint-extractor.d.ts.map +1 -0
- package/dist/parsers/endpoint-extractor.js +160 -0
- package/dist/parsers/endpoint-extractor.js.map +1 -0
- package/dist/parsers/openapi-parser.d.ts +120 -0
- package/dist/parsers/openapi-parser.d.ts.map +1 -0
- package/dist/parsers/openapi-parser.js +257 -0
- package/dist/parsers/openapi-parser.js.map +1 -0
- package/dist/parsers/visitors/auth-visitor.d.ts +28 -0
- package/dist/parsers/visitors/auth-visitor.d.ts.map +1 -0
- package/dist/parsers/visitors/auth-visitor.js +116 -0
- package/dist/parsers/visitors/auth-visitor.js.map +1 -0
- package/dist/prd/index.d.ts +10 -0
- package/dist/prd/index.d.ts.map +1 -0
- package/dist/prd/index.js +10 -0
- package/dist/prd/index.js.map +1 -0
- package/dist/prd/prd-reader.d.ts +124 -0
- package/dist/prd/prd-reader.d.ts.map +1 -0
- package/dist/prd/prd-reader.js +308 -0
- package/dist/prd/prd-reader.js.map +1 -0
- package/dist/prd/prd-storage.d.ts +232 -0
- package/dist/prd/prd-storage.d.ts.map +1 -0
- package/dist/prd/prd-storage.js +129 -0
- package/dist/prd/prd-storage.js.map +1 -0
- package/dist/repairers/test-auto-repairer.d.ts +61 -0
- package/dist/repairers/test-auto-repairer.d.ts.map +1 -0
- package/dist/repairers/test-auto-repairer.js +213 -0
- package/dist/repairers/test-auto-repairer.js.map +1 -0
- package/dist/reporters/comparison-report-generator.d.ts +58 -0
- package/dist/reporters/comparison-report-generator.d.ts.map +1 -0
- package/dist/reporters/comparison-report-generator.js +369 -0
- package/dist/reporters/comparison-report-generator.js.map +1 -0
- package/dist/reporters/gherkin-formatter.d.ts +34 -0
- package/dist/reporters/gherkin-formatter.d.ts.map +1 -0
- package/dist/reporters/gherkin-formatter.js +231 -0
- package/dist/reporters/gherkin-formatter.js.map +1 -0
- package/dist/reporters/html-report-generator.d.ts +174 -0
- package/dist/reporters/html-report-generator.d.ts.map +1 -0
- package/dist/reporters/html-report-generator.js +194 -0
- package/dist/reporters/html-report-generator.js.map +1 -0
- package/dist/reporters/report-charts.d.ts +23 -0
- package/dist/reporters/report-charts.d.ts.map +1 -0
- package/dist/reporters/report-charts.js +182 -0
- package/dist/reporters/report-charts.js.map +1 -0
- package/dist/reporters/report-sections.d.ts +34 -0
- package/dist/reporters/report-sections.d.ts.map +1 -0
- package/dist/reporters/report-sections.js +481 -0
- package/dist/reporters/report-sections.js.map +1 -0
- package/dist/reporters/report-styles.d.ts +12 -0
- package/dist/reporters/report-styles.d.ts.map +1 -0
- package/dist/reporters/report-styles.js +412 -0
- package/dist/reporters/report-styles.js.map +1 -0
- package/dist/reporters/report-test-details.d.ts +56 -0
- package/dist/reporters/report-test-details.d.ts.map +1 -0
- package/dist/reporters/report-test-details.js +328 -0
- package/dist/reporters/report-test-details.js.map +1 -0
- package/dist/reporters/report-utils.d.ts +40 -0
- package/dist/reporters/report-utils.d.ts.map +1 -0
- package/dist/reporters/report-utils.js +163 -0
- package/dist/reporters/report-utils.js.map +1 -0
- package/dist/types/ai-config.d.ts +63 -0
- package/dist/types/ai-config.d.ts.map +1 -0
- package/dist/types/ai-config.js +79 -0
- package/dist/types/ai-config.js.map +1 -0
- package/dist/types/business-rules.d.ts +235 -0
- package/dist/types/business-rules.d.ts.map +1 -0
- package/dist/types/business-rules.js +6 -0
- package/dist/types/business-rules.js.map +1 -0
- package/dist/types/config.d.ts +106 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +6 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/core.d.ts +72 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +6 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/openapi.d.ts +139 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +6 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/types/pact.d.ts +101 -0
- package/dist/types/pact.d.ts.map +1 -0
- package/dist/types/pact.js +6 -0
- package/dist/types/pact.js.map +1 -0
- package/dist/types/reporting.d.ts +93 -0
- package/dist/types/reporting.d.ts.map +1 -0
- package/dist/types/reporting.js +6 -0
- package/dist/types/reporting.js.map +1 -0
- package/dist/types/test-case.d.ts +233 -0
- package/dist/types/test-case.d.ts.map +1 -0
- package/dist/types/test-case.js +6 -0
- package/dist/types/test-case.js.map +1 -0
- package/dist/types/test-execution.d.ts +80 -0
- package/dist/types/test-execution.d.ts.map +1 -0
- package/dist/types/test-execution.js +6 -0
- package/dist/types/test-execution.js.map +1 -0
- package/dist/utils/auth-generator.d.ts +30 -0
- package/dist/utils/auth-generator.d.ts.map +1 -0
- package/dist/utils/auth-generator.js +68 -0
- package/dist/utils/auth-generator.js.map +1 -0
- package/dist/utils/config.d.ts +181 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +141 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/coverage-calculator.d.ts +81 -0
- package/dist/utils/coverage-calculator.d.ts.map +1 -0
- package/dist/utils/coverage-calculator.js +134 -0
- package/dist/utils/coverage-calculator.js.map +1 -0
- package/dist/utils/data-loader.d.ts +52 -0
- package/dist/utils/data-loader.d.ts.map +1 -0
- package/dist/utils/data-loader.js +192 -0
- package/dist/utils/data-loader.js.map +1 -0
- package/dist/utils/errors.d.ts +167 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +257 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +220 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +325 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/openapi-discovery.d.ts +31 -0
- package/dist/utils/openapi-discovery.d.ts.map +1 -0
- package/dist/utils/openapi-discovery.js +322 -0
- package/dist/utils/openapi-discovery.js.map +1 -0
- package/dist/utils/path-resolver.d.ts +101 -0
- package/dist/utils/path-resolver.d.ts.map +1 -0
- package/dist/utils/path-resolver.js +167 -0
- package/dist/utils/path-resolver.js.map +1 -0
- package/dist/utils/resilience.d.ts +181 -0
- package/dist/utils/resilience.d.ts.map +1 -0
- package/dist/utils/resilience.js +269 -0
- package/dist/utils/resilience.js.map +1 -0
- package/dist/validators/openapi-validator.d.ts +198 -0
- package/dist/validators/openapi-validator.d.ts.map +1 -0
- package/dist/validators/openapi-validator.js +349 -0
- package/dist/validators/openapi-validator.js.map +1 -0
- package/dist/validators/response-matcher.d.ts +84 -0
- package/dist/validators/response-matcher.d.ts.map +1 -0
- package/dist/validators/response-matcher.js +234 -0
- package/dist/validators/response-matcher.js.map +1 -0
- package/dist/validators/schema-validator.d.ts +174 -0
- package/dist/validators/schema-validator.d.ts.map +1 -0
- package/dist/validators/schema-validator.js +340 -0
- package/dist/validators/schema-validator.js.map +1 -0
- 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
|