@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,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response Handler
|
|
3
|
+
*
|
|
4
|
+
* Pure functions that operate on a completed HTTP response:
|
|
5
|
+
* - path-based value extraction (dataFlow)
|
|
6
|
+
* - agnostic token auto-detection
|
|
7
|
+
* - dataFlow value extraction
|
|
8
|
+
* - response validation (schema or matcher-based)
|
|
9
|
+
*
|
|
10
|
+
* @module executor/response-handler
|
|
11
|
+
*/
|
|
12
|
+
import { validateResponse } from '../validators/openapi-validator.js';
|
|
13
|
+
import { validateResponse as validateResponseMatchers } from '../validators/response-matcher.js';
|
|
14
|
+
import { findTokenInResponse } from './token-detector/index.js';
|
|
15
|
+
import { createLogger } from '../utils/logger.js';
|
|
16
|
+
const log = createLogger('response-handler');
|
|
17
|
+
/**
|
|
18
|
+
* Extracts a value from a response object using a dot-notation path.
|
|
19
|
+
* Path must start with "response" (e.g. "response.body.access_token").
|
|
20
|
+
*
|
|
21
|
+
* @param response - The HTTP response object
|
|
22
|
+
* @param path - Dot-notation path starting with "response"
|
|
23
|
+
* @returns The extracted value, or undefined if not found
|
|
24
|
+
*/
|
|
25
|
+
export function extractValueFromPath(response, path) {
|
|
26
|
+
const parts = path.split('.');
|
|
27
|
+
if (parts[0] !== 'response') {
|
|
28
|
+
log.warn('DataFlow extract path must start with "response"', { path });
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
let current = response;
|
|
32
|
+
for (let i = 1; i < parts.length; i++) {
|
|
33
|
+
if (current === null || current === undefined || typeof current !== 'object') {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
current = current[parts[i]];
|
|
37
|
+
}
|
|
38
|
+
return current;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Attempts to auto-detect an auth token in a successful response.
|
|
42
|
+
* Returns the token value if found, or null if the response is not a
|
|
43
|
+
* successful auth response or no token is detected.
|
|
44
|
+
*
|
|
45
|
+
* @param response - The HTTP response
|
|
46
|
+
* @param testCase - The test case that produced the response
|
|
47
|
+
* @param currentToken - Current auto-detected token (null if none yet)
|
|
48
|
+
* @returns Detected token string, or null if nothing new was found
|
|
49
|
+
*/
|
|
50
|
+
export function handleTokenDetection(response, testCase, currentToken) {
|
|
51
|
+
if (currentToken !== null ||
|
|
52
|
+
response.status < 200 ||
|
|
53
|
+
response.status >= 300 ||
|
|
54
|
+
!response.body ||
|
|
55
|
+
typeof response.body !== 'object') {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const detected = findTokenInResponse(response.body, testCase.tokenField);
|
|
59
|
+
if (!detected)
|
|
60
|
+
return null;
|
|
61
|
+
log.info('Auto-detected authentication token (will use for all subsequent requests)', {
|
|
62
|
+
endpoint: `${testCase.method} ${testCase.path}`,
|
|
63
|
+
tokenField: detected.field,
|
|
64
|
+
tokenPath: detected.path,
|
|
65
|
+
method: detected.method,
|
|
66
|
+
tokenPreview: `${detected.value.substring(0, 20)}...`,
|
|
67
|
+
});
|
|
68
|
+
return detected.value;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Extracts dataFlow values from a successful response and returns them
|
|
72
|
+
* as a plain object to be merged into the shared data context.
|
|
73
|
+
*
|
|
74
|
+
* @param response - The HTTP response
|
|
75
|
+
* @param testDataFlow - DataFlow config entry for this test
|
|
76
|
+
* @param testId - Test ID (for logging)
|
|
77
|
+
* @returns Object with extracted key-value pairs (may be empty)
|
|
78
|
+
*/
|
|
79
|
+
export function extractDataFlowValues(response, testDataFlow, testId) {
|
|
80
|
+
const extracted = {};
|
|
81
|
+
if (!testDataFlow?.extract || response.status < 200 || response.status >= 300) {
|
|
82
|
+
return extracted;
|
|
83
|
+
}
|
|
84
|
+
for (const [varName, extractPath] of Object.entries(testDataFlow.extract)) {
|
|
85
|
+
const value = extractValueFromPath(response, extractPath);
|
|
86
|
+
if (value !== undefined) {
|
|
87
|
+
extracted[varName] = value;
|
|
88
|
+
log.debug('DataFlow extract: saved to context', {
|
|
89
|
+
varName,
|
|
90
|
+
extractPath,
|
|
91
|
+
testId,
|
|
92
|
+
valuePreview: typeof value === 'string'
|
|
93
|
+
? value.substring(0, 30) + '...'
|
|
94
|
+
: JSON.stringify(value).substring(0, 30),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
log.debug('DataFlow extract: value not found', { varName, extractPath, testId });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return extracted;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Validates the response against the endpoint schema or configured matchers.
|
|
105
|
+
*
|
|
106
|
+
* @param response - The HTTP response
|
|
107
|
+
* @param endpoint - Parsed endpoint definition (may be undefined)
|
|
108
|
+
* @param testCase - The test case
|
|
109
|
+
* @param validateSchemas - Whether schema validation is enabled
|
|
110
|
+
* @param useMatchers - Whether matcher-based validation is enabled
|
|
111
|
+
* @param matchers - Matcher configuration keyed by test ID or "*"
|
|
112
|
+
* @returns Array of schema errors (empty if valid)
|
|
113
|
+
*/
|
|
114
|
+
export function validateTestResponse(response, endpoint, testCase, validateSchemas, useMatchers, matchers) {
|
|
115
|
+
if (useMatchers && matchers) {
|
|
116
|
+
const testMatchers = matchers[testCase.id] || matchers['*'];
|
|
117
|
+
if (testMatchers) {
|
|
118
|
+
const validation = validateResponseMatchers({ body: response.body, headers: response.headers }, testMatchers);
|
|
119
|
+
if (!validation.valid) {
|
|
120
|
+
return validation.errors.map(err => ({
|
|
121
|
+
field: err.split('"')[1] || 'unknown',
|
|
122
|
+
message: err,
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
if (validateSchemas && endpoint && testCase.validateSchema !== false) {
|
|
129
|
+
const validation = validateResponse({ status: response.status, headers: response.headers ?? {}, body: response.body }, endpoint, testCase.expectedStatus);
|
|
130
|
+
if (!validation.valid)
|
|
131
|
+
return validation.errors;
|
|
132
|
+
}
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=response-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-handler.js","sourceRoot":"","sources":["../../src/executor/response-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result Processor
|
|
3
|
+
*
|
|
4
|
+
* Standalone functions for generating a TestSuiteSummary from results and
|
|
5
|
+
* persisting the results+summary to disk.
|
|
6
|
+
*
|
|
7
|
+
* @module executor/result-processor
|
|
8
|
+
*/
|
|
9
|
+
import type { TestResult, TestSuiteSummary } from '../types/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Generates a summary from an array of test results.
|
|
12
|
+
*
|
|
13
|
+
* @param results - Array of test results
|
|
14
|
+
* @returns Aggregated test suite summary
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateSummary(results: TestResult[]): TestSuiteSummary;
|
|
17
|
+
/**
|
|
18
|
+
* Saves test results and summary to a JSON file in the test-results directory.
|
|
19
|
+
*
|
|
20
|
+
* @param results - Array of test results
|
|
21
|
+
* @param summary - Generated test suite summary
|
|
22
|
+
* @param workingDirectory - Base directory for test-results folder
|
|
23
|
+
* @param environmentName - Name of the environment (for the JSON payload)
|
|
24
|
+
* @returns Path to the saved file, or empty string on failure
|
|
25
|
+
*/
|
|
26
|
+
export declare function saveResults(results: TestResult[], summary: TestSuiteSummary, workingDirectory: string, environmentName: string): Promise<string>;
|
|
27
|
+
//# sourceMappingURL=result-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-processor.d.ts","sourceRoot":"","sources":["../../src/executor/result-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAOtE;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAsDvE;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,gBAAgB,EACzB,gBAAgB,EAAE,MAAM,EACxB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,CAqEjB"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result Processor
|
|
3
|
+
*
|
|
4
|
+
* Standalone functions for generating a TestSuiteSummary from results and
|
|
5
|
+
* persisting the results+summary to disk.
|
|
6
|
+
*
|
|
7
|
+
* @module executor/result-processor
|
|
8
|
+
*/
|
|
9
|
+
import { createLogger } from '../utils/logger.js';
|
|
10
|
+
import { promises as fs } from 'fs';
|
|
11
|
+
import { join } from 'path';
|
|
12
|
+
const log = createLogger('result-processor');
|
|
13
|
+
/**
|
|
14
|
+
* Generates a summary from an array of test results.
|
|
15
|
+
*
|
|
16
|
+
* @param results - Array of test results
|
|
17
|
+
* @returns Aggregated test suite summary
|
|
18
|
+
*/
|
|
19
|
+
export function generateSummary(results) {
|
|
20
|
+
const passed = results.filter(r => r.status === 'passed').length;
|
|
21
|
+
const failed = results.filter(r => r.status === 'failed').length;
|
|
22
|
+
const skipped = results.filter(r => r.status === 'skipped').length;
|
|
23
|
+
const totalResponseTime = results.reduce((sum, r) => sum + (r.responseTime || 0), 0);
|
|
24
|
+
const avgResponseTime = results.length > 0 ? totalResponseTime / results.length : 0;
|
|
25
|
+
const startTime = results.length > 0
|
|
26
|
+
? new Date(Math.min(...results.map(r => r.startTime.getTime())))
|
|
27
|
+
: new Date();
|
|
28
|
+
const endTime = results.length > 0 && results.every(r => r.endTime)
|
|
29
|
+
? new Date(Math.max(...results.map(r => r.endTime.getTime())))
|
|
30
|
+
: new Date();
|
|
31
|
+
const duration = endTime.getTime() - startTime.getTime();
|
|
32
|
+
const byCategory = {};
|
|
33
|
+
const byEndpoint = {};
|
|
34
|
+
for (const result of results) {
|
|
35
|
+
const category = result.testCase.category;
|
|
36
|
+
const endpoint = `${result.testCase.method} ${result.testCase.path}`;
|
|
37
|
+
if (!byCategory[category]) {
|
|
38
|
+
byCategory[category] = { passed: 0, failed: 0, total: 0 };
|
|
39
|
+
}
|
|
40
|
+
byCategory[category].total++;
|
|
41
|
+
if (result.status === 'passed')
|
|
42
|
+
byCategory[category].passed++;
|
|
43
|
+
else if (result.status === 'failed')
|
|
44
|
+
byCategory[category].failed++;
|
|
45
|
+
if (!byEndpoint[endpoint]) {
|
|
46
|
+
byEndpoint[endpoint] = { passed: 0, failed: 0, total: 0 };
|
|
47
|
+
}
|
|
48
|
+
byEndpoint[endpoint].total++;
|
|
49
|
+
if (result.status === 'passed')
|
|
50
|
+
byEndpoint[endpoint].passed++;
|
|
51
|
+
else if (result.status === 'failed')
|
|
52
|
+
byEndpoint[endpoint].failed++;
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
total: results.length,
|
|
56
|
+
passed,
|
|
57
|
+
failed,
|
|
58
|
+
skipped,
|
|
59
|
+
duration,
|
|
60
|
+
avgResponseTime,
|
|
61
|
+
startTime,
|
|
62
|
+
endTime,
|
|
63
|
+
byCategory,
|
|
64
|
+
byEndpoint,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Saves test results and summary to a JSON file in the test-results directory.
|
|
69
|
+
*
|
|
70
|
+
* @param results - Array of test results
|
|
71
|
+
* @param summary - Generated test suite summary
|
|
72
|
+
* @param workingDirectory - Base directory for test-results folder
|
|
73
|
+
* @param environmentName - Name of the environment (for the JSON payload)
|
|
74
|
+
* @returns Path to the saved file, or empty string on failure
|
|
75
|
+
*/
|
|
76
|
+
export async function saveResults(results, summary, workingDirectory, environmentName) {
|
|
77
|
+
try {
|
|
78
|
+
const resultsDir = join(workingDirectory, 'test-results');
|
|
79
|
+
await fs.mkdir(resultsDir, { recursive: true });
|
|
80
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
|
|
81
|
+
const filename = `test-results-${timestamp}.json`;
|
|
82
|
+
const filepath = join(resultsDir, filename);
|
|
83
|
+
const allTests = results.map(r => ({
|
|
84
|
+
id: r.testCase.id,
|
|
85
|
+
name: r.testCase.name,
|
|
86
|
+
category: r.testCase.category,
|
|
87
|
+
status: r.status,
|
|
88
|
+
method: r.testCase.method,
|
|
89
|
+
path: r.testCase.path,
|
|
90
|
+
endpoint: `${r.testCase.method} ${r.testCase.path}`,
|
|
91
|
+
expectedStatus: r.testCase.expectedStatus,
|
|
92
|
+
actualStatus: r.actualStatus,
|
|
93
|
+
duration: r.responseTime,
|
|
94
|
+
error: r.error,
|
|
95
|
+
schemaErrors: r.schemaErrors,
|
|
96
|
+
}));
|
|
97
|
+
const failedTests = results
|
|
98
|
+
.filter(r => r.status === 'failed')
|
|
99
|
+
.map(r => ({
|
|
100
|
+
name: r.testCase.name,
|
|
101
|
+
error: r.error,
|
|
102
|
+
expectedStatus: r.testCase.expectedStatus,
|
|
103
|
+
actualStatus: r.actualStatus,
|
|
104
|
+
}));
|
|
105
|
+
const data = {
|
|
106
|
+
environment: environmentName,
|
|
107
|
+
timestamp: new Date().toISOString(),
|
|
108
|
+
summary: {
|
|
109
|
+
total: summary.total,
|
|
110
|
+
passed: summary.passed,
|
|
111
|
+
failed: summary.failed,
|
|
112
|
+
skipped: summary.skipped,
|
|
113
|
+
duration: summary.duration,
|
|
114
|
+
avgResponseTime: summary.avgResponseTime,
|
|
115
|
+
passRate: summary.total > 0
|
|
116
|
+
? `${((summary.passed / summary.total) * 100).toFixed(2)}%`
|
|
117
|
+
: '0.00%',
|
|
118
|
+
},
|
|
119
|
+
byCategory: summary.byCategory,
|
|
120
|
+
byEndpoint: summary.byEndpoint,
|
|
121
|
+
allTests,
|
|
122
|
+
failedTests,
|
|
123
|
+
};
|
|
124
|
+
await fs.writeFile(filepath, JSON.stringify(data, null, 2), 'utf-8');
|
|
125
|
+
log.info('Test results saved', {
|
|
126
|
+
filepath,
|
|
127
|
+
totalTests: results.length,
|
|
128
|
+
passed: summary.passed,
|
|
129
|
+
failed: summary.failed,
|
|
130
|
+
});
|
|
131
|
+
return filepath;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
log.warn('Failed to save test results', {
|
|
135
|
+
error: error instanceof Error ? error.message : String(error),
|
|
136
|
+
});
|
|
137
|
+
return '';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=result-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-processor.js","sourceRoot":"","sources":["../../src/executor/result-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Result Utilities
|
|
3
|
+
*
|
|
4
|
+
* Helper functions for filtering and analyzing test results.
|
|
5
|
+
*
|
|
6
|
+
* @module executor/result-utils
|
|
7
|
+
*/
|
|
8
|
+
import type { TestResult, TestCase } from '../types/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Filters test results by status
|
|
11
|
+
*/
|
|
12
|
+
export declare function filterResultsByStatus(results: TestResult[], status: TestResult['status']): TestResult[];
|
|
13
|
+
/**
|
|
14
|
+
* Filters test results by category
|
|
15
|
+
*/
|
|
16
|
+
export declare function filterResultsByCategory(results: TestResult[], category: TestCase['category']): TestResult[];
|
|
17
|
+
/**
|
|
18
|
+
* Gets the slowest test results sorted by response time
|
|
19
|
+
*/
|
|
20
|
+
export declare function getSlowestTests(results: TestResult[], count?: number): TestResult[];
|
|
21
|
+
//# sourceMappingURL=result-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-utils.d.ts","sourceRoot":"","sources":["../../src/executor/result-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE9D;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,UAAU,EAAE,EACrB,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,GAC3B,UAAU,EAAE,CAEd;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,UAAU,EAAE,EACrB,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAC7B,UAAU,EAAE,CAEd;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,KAAK,SAAK,GAAG,UAAU,EAAE,CAK/E"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Result Utilities
|
|
3
|
+
*
|
|
4
|
+
* Helper functions for filtering and analyzing test results.
|
|
5
|
+
*
|
|
6
|
+
* @module executor/result-utils
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Filters test results by status
|
|
10
|
+
*/
|
|
11
|
+
export function filterResultsByStatus(results, status) {
|
|
12
|
+
return results.filter(r => r.status === status);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Filters test results by category
|
|
16
|
+
*/
|
|
17
|
+
export function filterResultsByCategory(results, category) {
|
|
18
|
+
return results.filter(r => r.testCase.category === category);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Gets the slowest test results sorted by response time
|
|
22
|
+
*/
|
|
23
|
+
export function getSlowestTests(results, count = 10) {
|
|
24
|
+
return results
|
|
25
|
+
.filter(r => r.responseTime !== undefined)
|
|
26
|
+
.sort((a, b) => (b.responseTime || 0) - (a.responseTime || 0))
|
|
27
|
+
.slice(0, count);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=result-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-utils.js","sourceRoot":"","sources":["../../src/executor/result-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAqB,EACrB,MAA4B;IAE5B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAqB,EACrB,QAA8B;IAE9B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAqB,EAAE,KAAK,GAAG,EAAE;IAC/D,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,SAAS,CAAC;SACzC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;SAC7D,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Executor
|
|
3
|
+
*
|
|
4
|
+
* Standalone function that executes a single test case end-to-end:
|
|
5
|
+
* lifecycle hooks → dataFlow injection → HTTP request → token detection
|
|
6
|
+
* → dataFlow extraction → response validation → result construction.
|
|
7
|
+
*
|
|
8
|
+
* Chain of Responsibility pattern: inject → execute → validate → extract.
|
|
9
|
+
*
|
|
10
|
+
* @module executor/test-executor
|
|
11
|
+
*/
|
|
12
|
+
import type { TestCase, TestResult, ParsedEndpoint } from '../types/index.js';
|
|
13
|
+
import type { HttpClient } from './http-client.js';
|
|
14
|
+
export interface ExecutionContext {
|
|
15
|
+
autoDetectedToken: string | null;
|
|
16
|
+
dataContext: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export interface ExecutionOptions {
|
|
19
|
+
validateSchemas: boolean;
|
|
20
|
+
dataFlow?: Record<string, {
|
|
21
|
+
extract?: Record<string, string>;
|
|
22
|
+
inject?: Record<string, string>;
|
|
23
|
+
}>;
|
|
24
|
+
useMatchers?: boolean;
|
|
25
|
+
matchers?: Record<string, Record<string, import('../types/index.js').ResponseMatcher>>;
|
|
26
|
+
beforeTest?: (testCase: TestCase) => Promise<void> | void;
|
|
27
|
+
afterTest?: (testCase: TestCase) => Promise<void> | void;
|
|
28
|
+
environment?: {
|
|
29
|
+
auth?: import('../types/index.js').Environment['auth'];
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface ExecutionResult {
|
|
33
|
+
testResult: TestResult;
|
|
34
|
+
detectedToken: string | null;
|
|
35
|
+
extractedData: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Executes a single test case and returns the result plus any mutations to
|
|
39
|
+
* shared context (detected token, extracted dataFlow values).
|
|
40
|
+
*
|
|
41
|
+
* @param testCase - Test case to execute
|
|
42
|
+
* @param client - Initialized HTTP client
|
|
43
|
+
* @param context - Shared mutable execution context (token + dataContext)
|
|
44
|
+
* @param endpointMap - Map of endpoint definitions for schema validation
|
|
45
|
+
* @param options - Execution options (validation, dataFlow, hooks, etc.)
|
|
46
|
+
* @returns Execution result with test result and context mutations
|
|
47
|
+
*/
|
|
48
|
+
export declare function executeSingleTest(testCase: TestCase, client: HttpClient, context: ExecutionContext, endpointMap: Map<string, ParsedEndpoint>, options: ExecutionOptions): Promise<ExecutionResult>;
|
|
49
|
+
//# sourceMappingURL=test-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-executor.d.ts","sourceRoot":"","sources":["../../src/executor/test-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAUnD,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC,CAAC;IACjG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,mBAAmB,EAAE,eAAe,CAAC,CAAC,CAAC;IACvF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACzD,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;KAAE,CAAC;CAC1E;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAkHD;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,gBAAgB,EACzB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACxC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CAiI1B"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Executor
|
|
3
|
+
*
|
|
4
|
+
* Standalone function that executes a single test case end-to-end:
|
|
5
|
+
* lifecycle hooks → dataFlow injection → HTTP request → token detection
|
|
6
|
+
* → dataFlow extraction → response validation → result construction.
|
|
7
|
+
*
|
|
8
|
+
* Chain of Responsibility pattern: inject → execute → validate → extract.
|
|
9
|
+
*
|
|
10
|
+
* @module executor/test-executor
|
|
11
|
+
*/
|
|
12
|
+
import { createLogger } from '../utils/logger.js';
|
|
13
|
+
import { handleTokenDetection, extractDataFlowValues, validateTestResponse, } from './response-handler.js';
|
|
14
|
+
const log = createLogger('test-executor');
|
|
15
|
+
/**
|
|
16
|
+
* Applies dataFlow injection rules, mutating the provided header/body/path refs.
|
|
17
|
+
* Returns the potentially updated path so callers can use it for the HTTP request.
|
|
18
|
+
*/
|
|
19
|
+
function applyDataFlowInject(testDataFlow, dataContext, testCase, requestHeaders, requestBody, requestPath) {
|
|
20
|
+
if (!testDataFlow?.inject || testCase.skipDataFlow === true) {
|
|
21
|
+
return { path: requestPath, body: requestBody };
|
|
22
|
+
}
|
|
23
|
+
let path = requestPath;
|
|
24
|
+
let body = requestBody;
|
|
25
|
+
for (const [varName, injectSpec] of Object.entries(testDataFlow.inject)) {
|
|
26
|
+
const value = dataContext[varName];
|
|
27
|
+
if (value === undefined) {
|
|
28
|
+
log.debug('DataFlow inject: variable not found in context', { varName, testId: testCase.id });
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (injectSpec.startsWith('header.')) {
|
|
32
|
+
const headerPart = injectSpec.substring(7);
|
|
33
|
+
const colonIdx = headerPart.indexOf(':');
|
|
34
|
+
if (colonIdx > 0) {
|
|
35
|
+
const headerName = headerPart.substring(0, colonIdx);
|
|
36
|
+
const format = headerPart.substring(colonIdx + 1);
|
|
37
|
+
requestHeaders[headerName] = format.replace('{value}', String(value));
|
|
38
|
+
log.debug('DataFlow inject: header', { headerName, varName, testId: testCase.id });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (injectSpec.startsWith('body.')) {
|
|
42
|
+
const fieldName = injectSpec.substring(5);
|
|
43
|
+
if (!body || typeof body !== 'object')
|
|
44
|
+
body = {};
|
|
45
|
+
body[fieldName] = value;
|
|
46
|
+
log.debug('DataFlow inject: body field', { fieldName, varName, testId: testCase.id });
|
|
47
|
+
}
|
|
48
|
+
else if (injectSpec.startsWith('path:')) {
|
|
49
|
+
const pathTemplate = injectSpec.substring(5);
|
|
50
|
+
path = pathTemplate.replace('{value}', String(value));
|
|
51
|
+
log.debug('DataFlow inject: path', { requestPath: path, varName, testId: testCase.id });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { path, body };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Applies token injection rules to request headers based on priority:
|
|
58
|
+
* 1. Existing explicit token (already present in headers)
|
|
59
|
+
* 2. Placeholder replacement ({{TOKEN}} etc.)
|
|
60
|
+
* 3. No-header injection from env or auto-detected token
|
|
61
|
+
*/
|
|
62
|
+
function applyTokenInjection(testCase, requestHeaders, context, auth) {
|
|
63
|
+
if (!testCase.requiresAuth || testCase.category === 'error-case')
|
|
64
|
+
return;
|
|
65
|
+
const envToken = auth?.type === 'bearer' ? auth.token : undefined;
|
|
66
|
+
if (requestHeaders['Authorization']) {
|
|
67
|
+
const authHeader = requestHeaders['Authorization'];
|
|
68
|
+
const isPlaceholder = authHeader.includes('{{TOKEN}}') ||
|
|
69
|
+
authHeader.includes('{{OAUTH_TOKEN}}') ||
|
|
70
|
+
authHeader.includes('{{OIDC_TOKEN}}');
|
|
71
|
+
if (isPlaceholder) {
|
|
72
|
+
if (envToken) {
|
|
73
|
+
requestHeaders['Authorization'] = `Bearer ${envToken}`;
|
|
74
|
+
log.info('Replaced placeholder with environment token', { path: testCase.path });
|
|
75
|
+
}
|
|
76
|
+
else if (context.autoDetectedToken) {
|
|
77
|
+
requestHeaders['Authorization'] = `Bearer ${context.autoDetectedToken}`;
|
|
78
|
+
log.info('Replaced placeholder with auto-detected token', {
|
|
79
|
+
path: testCase.path,
|
|
80
|
+
method: testCase.method,
|
|
81
|
+
tokenPreview: context.autoDetectedToken.substring(0, 20) + '...',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
log.warn('No token available to replace placeholder', {
|
|
86
|
+
path: testCase.path,
|
|
87
|
+
method: testCase.method,
|
|
88
|
+
placeholder: authHeader,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
if (envToken) {
|
|
95
|
+
requestHeaders['Authorization'] = `Bearer ${envToken}`;
|
|
96
|
+
log.info('Injected environment token', { path: testCase.path });
|
|
97
|
+
}
|
|
98
|
+
else if (context.autoDetectedToken) {
|
|
99
|
+
requestHeaders['Authorization'] = `Bearer ${context.autoDetectedToken}`;
|
|
100
|
+
log.info('Injected auto-detected token', {
|
|
101
|
+
path: testCase.path,
|
|
102
|
+
method: testCase.method,
|
|
103
|
+
tokenPreview: context.autoDetectedToken.substring(0, 20) + '...',
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
log.warn('No token available for authenticated endpoint', {
|
|
108
|
+
path: testCase.path,
|
|
109
|
+
method: testCase.method,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Executes a single test case and returns the result plus any mutations to
|
|
116
|
+
* shared context (detected token, extracted dataFlow values).
|
|
117
|
+
*
|
|
118
|
+
* @param testCase - Test case to execute
|
|
119
|
+
* @param client - Initialized HTTP client
|
|
120
|
+
* @param context - Shared mutable execution context (token + dataContext)
|
|
121
|
+
* @param endpointMap - Map of endpoint definitions for schema validation
|
|
122
|
+
* @param options - Execution options (validation, dataFlow, hooks, etc.)
|
|
123
|
+
* @returns Execution result with test result and context mutations
|
|
124
|
+
*/
|
|
125
|
+
export async function executeSingleTest(testCase, client, context, endpointMap, options) {
|
|
126
|
+
const startTime = new Date();
|
|
127
|
+
try {
|
|
128
|
+
// Lifecycle hook: before
|
|
129
|
+
if (options.beforeTest) {
|
|
130
|
+
log.debug('Executing beforeTest hook', { testId: testCase.id });
|
|
131
|
+
await options.beforeTest(testCase);
|
|
132
|
+
}
|
|
133
|
+
// Prepare mutable request properties
|
|
134
|
+
const requestHeaders = { ...testCase.headers };
|
|
135
|
+
const testDataFlow = options.dataFlow?.[testCase.id];
|
|
136
|
+
// DataFlow injection
|
|
137
|
+
const { path: requestPath, body: requestBody } = applyDataFlowInject(testDataFlow, context.dataContext, testCase, requestHeaders, testCase.body, testCase.path);
|
|
138
|
+
// Token injection
|
|
139
|
+
applyTokenInjection(testCase, requestHeaders, context, options.environment?.auth);
|
|
140
|
+
// Execute HTTP request
|
|
141
|
+
const response = await client.request(testCase.method, requestPath, {
|
|
142
|
+
body: requestBody,
|
|
143
|
+
queryParams: testCase.queryParams,
|
|
144
|
+
pathParams: testCase.pathParams,
|
|
145
|
+
headers: requestHeaders,
|
|
146
|
+
requiresAuth: testCase.requiresAuth,
|
|
147
|
+
contentType: testCase.contentType,
|
|
148
|
+
});
|
|
149
|
+
const endTime = new Date();
|
|
150
|
+
// Token auto-detection
|
|
151
|
+
const detectedToken = handleTokenDetection(response, testCase, context.autoDetectedToken);
|
|
152
|
+
// DataFlow extraction
|
|
153
|
+
const extractedData = extractDataFlowValues(response, testDataFlow, testCase.id);
|
|
154
|
+
// Schema / matcher validation
|
|
155
|
+
const endpoint = endpointMap.get(`${testCase.method}:${testCase.path}`);
|
|
156
|
+
const schemaErrors = validateTestResponse(response, endpoint, testCase, options.validateSchemas, options.useMatchers ?? false, options.matchers);
|
|
157
|
+
// Determine status
|
|
158
|
+
const statusMatches = response.status === testCase.expectedStatus;
|
|
159
|
+
const hasSchemaErrors = schemaErrors.length > 0;
|
|
160
|
+
let status;
|
|
161
|
+
let error;
|
|
162
|
+
if (statusMatches && !hasSchemaErrors) {
|
|
163
|
+
status = 'passed';
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
status = 'failed';
|
|
167
|
+
const errors = [];
|
|
168
|
+
if (!statusMatches) {
|
|
169
|
+
errors.push(`Expected status ${testCase.expectedStatus}, got ${response.status}`);
|
|
170
|
+
}
|
|
171
|
+
if (hasSchemaErrors) {
|
|
172
|
+
errors.push(`Schema validation failed: ${schemaErrors.map(e => `${e.field}: ${e.message}`).join(', ')}`);
|
|
173
|
+
}
|
|
174
|
+
error = errors.join('; ');
|
|
175
|
+
}
|
|
176
|
+
const testResult = {
|
|
177
|
+
testCase,
|
|
178
|
+
status,
|
|
179
|
+
actualStatus: response.status,
|
|
180
|
+
actualBody: response.body,
|
|
181
|
+
actualHeaders: response.headers,
|
|
182
|
+
responseTime: response.responseTime,
|
|
183
|
+
error,
|
|
184
|
+
schemaErrors: hasSchemaErrors
|
|
185
|
+
? schemaErrors.map(e => ({
|
|
186
|
+
instancePath: `/${e.field}`,
|
|
187
|
+
message: e.message,
|
|
188
|
+
keyword: e.code || 'validation',
|
|
189
|
+
}))
|
|
190
|
+
: undefined,
|
|
191
|
+
startTime,
|
|
192
|
+
endTime,
|
|
193
|
+
};
|
|
194
|
+
// Lifecycle hook: after
|
|
195
|
+
if (options.afterTest) {
|
|
196
|
+
log.debug('Executing afterTest hook', { testId: testCase.id });
|
|
197
|
+
await options.afterTest(testCase);
|
|
198
|
+
}
|
|
199
|
+
return { testResult, detectedToken, extractedData };
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
const endTime = new Date();
|
|
203
|
+
// afterTest hook even on failure
|
|
204
|
+
if (options.afterTest) {
|
|
205
|
+
try {
|
|
206
|
+
log.debug('Executing afterTest hook (after error)', { testId: testCase.id });
|
|
207
|
+
await options.afterTest(testCase);
|
|
208
|
+
}
|
|
209
|
+
catch (hookError) {
|
|
210
|
+
log.warn('afterTest hook failed', { testId: testCase.id, error: hookError });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
testResult: {
|
|
215
|
+
testCase,
|
|
216
|
+
status: 'failed',
|
|
217
|
+
error: `Request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
218
|
+
startTime,
|
|
219
|
+
endTime,
|
|
220
|
+
},
|
|
221
|
+
detectedToken: null,
|
|
222
|
+
extractedData: {},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=test-executor.js.map
|