qa360 2.2.20 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -262
- package/{cli/dist → dist}/commands/ai.js +1 -1
- package/{cli/dist → dist}/commands/coverage.js +1 -1
- package/{cli/dist → dist}/commands/crawl.d.ts +12 -1
- package/{cli/dist → dist}/commands/crawl.js +70 -9
- package/{cli/dist → dist}/commands/doctor.js +2 -2
- package/{cli/dist → dist}/commands/explain.js +2 -2
- package/{cli/dist → dist}/commands/flakiness.js +1 -1
- package/{cli/dist → dist}/commands/generate.js +1 -1
- package/{cli/dist → dist}/commands/history.js +1 -1
- package/{cli/dist → dist}/commands/monitor.js +3 -3
- package/{cli/dist → dist}/commands/ollama.js +1 -1
- package/{cli/dist → dist}/commands/pack.js +2 -2
- package/{cli/dist → dist}/commands/regression.js +1 -1
- package/{cli/dist → dist}/commands/repair.js +1 -1
- package/{cli/dist → dist}/commands/retry.js +1 -1
- package/{cli/dist → dist}/commands/run.d.ts +1 -1
- package/{cli/dist → dist}/commands/run.js +1 -1
- package/{cli/dist → dist}/commands/secrets.js +1 -1
- package/{cli/dist → dist}/commands/serve.js +1 -1
- package/{cli/dist → dist}/commands/slo.js +1 -1
- package/{cli/dist → dist}/commands/verify.js +1 -1
- package/{cli/dist → dist}/core/adapters/playwright-native-api.d.ts +2 -0
- package/{cli/dist → dist}/core/adapters/playwright-native-api.js +20 -1
- package/{cli/dist → dist}/core/adapters/playwright-ui.d.ts +21 -0
- package/dist/core/adapters/playwright-ui.js +2050 -0
- package/{cli/dist → dist}/core/ai/ollama-provider.js +15 -3
- package/{cli/dist → dist}/core/artifacts/ui-artifacts.js +24 -4
- package/dist/core/auth/backup-codes-provider.d.ts +91 -0
- package/dist/core/auth/backup-codes-provider.js +215 -0
- package/{cli/dist → dist}/core/auth/basic-auth-provider.d.ts +6 -0
- package/{cli/dist → dist}/core/auth/basic-auth-provider.js +24 -6
- package/dist/core/auth/digest-auth-provider.d.ts +116 -0
- package/dist/core/auth/digest-auth-provider.js +244 -0
- package/dist/core/auth/hcaptcha-handler.d.ts +103 -0
- package/dist/core/auth/hcaptcha-handler.js +288 -0
- package/{cli/dist → dist}/core/auth/index.d.ts +81 -4
- package/{cli/dist → dist}/core/auth/index.js +15 -1
- package/dist/core/auth/oauth-handler.d.ts +408 -0
- package/dist/core/auth/oauth-handler.js +636 -0
- package/{cli/dist → dist}/core/auth/oauth2-provider.d.ts +9 -0
- package/dist/core/auth/oauth2-provider.js +227 -0
- package/dist/core/auth/otp-provider.d.ts +93 -0
- package/dist/core/auth/otp-provider.js +288 -0
- package/dist/core/auth/recaptcha-handler.d.ts +119 -0
- package/dist/core/auth/recaptcha-handler.js +301 -0
- package/dist/core/auth/remember-me-handler.d.ts +142 -0
- package/dist/core/auth/remember-me-handler.js +255 -0
- package/dist/core/auth/saml-handler.d.ts +173 -0
- package/dist/core/auth/saml-handler.js +364 -0
- package/dist/core/auth/webauthn-handler.d.ts +182 -0
- package/dist/core/auth/webauthn-handler.js +310 -0
- package/dist/core/crawler/advanced-interactions.d.ts +342 -0
- package/dist/core/crawler/advanced-interactions.js +1069 -0
- package/dist/core/crawler/blob-url-download-handler.d.ts +145 -0
- package/dist/core/crawler/blob-url-download-handler.js +392 -0
- package/dist/core/crawler/consent-handler.d.ts +49 -0
- package/dist/core/crawler/consent-handler.js +258 -0
- package/dist/core/crawler/cookie-manager.d.ts +166 -0
- package/dist/core/crawler/cookie-manager.js +353 -0
- package/dist/core/crawler/coop-coep-handler.d.ts +136 -0
- package/dist/core/crawler/coop-coep-handler.js +338 -0
- package/dist/core/crawler/csp-handler.d.ts +151 -0
- package/dist/core/crawler/csp-handler.js +415 -0
- package/dist/core/crawler/download-handler.d.ts +155 -0
- package/dist/core/crawler/download-handler.js +370 -0
- package/dist/core/crawler/email-testing-handler.d.ts +214 -0
- package/dist/core/crawler/email-testing-handler.js +398 -0
- package/dist/core/crawler/error-tracking-handler.d.ts +177 -0
- package/dist/core/crawler/error-tracking-handler.js +378 -0
- package/dist/core/crawler/form-handler.d.ts +100 -0
- package/dist/core/crawler/form-handler.js +465 -0
- package/dist/core/crawler/framework-wait-handler.d.ts +96 -0
- package/dist/core/crawler/framework-wait-handler.js +464 -0
- package/dist/core/crawler/geolocation-handler.d.ts +112 -0
- package/dist/core/crawler/geolocation-handler.js +276 -0
- package/dist/core/crawler/index.d.ts +78 -0
- package/{cli/dist → dist}/core/crawler/index.js +74 -1
- package/dist/core/crawler/intelligent-selector-generator.d.ts +164 -0
- package/dist/core/crawler/intelligent-selector-generator.js +612 -0
- package/{cli/dist → dist}/core/crawler/journey-generator.js +44 -1
- package/{cli/dist → dist}/core/crawler/page-analyzer.d.ts +16 -1
- package/{cli/dist → dist}/core/crawler/page-analyzer.js +469 -17
- package/dist/core/crawler/permissions-handler.d.ts +112 -0
- package/dist/core/crawler/permissions-handler.js +236 -0
- package/dist/core/crawler/permissions-policy-handler.d.ts +113 -0
- package/dist/core/crawler/permissions-policy-handler.js +402 -0
- package/dist/core/crawler/presets.d.ts +100 -0
- package/dist/core/crawler/presets.js +887 -0
- package/dist/core/crawler/repl-debug-handler.d.ts +105 -0
- package/dist/core/crawler/repl-debug-handler.js +552 -0
- package/dist/core/crawler/reporting-api-handler.d.ts +212 -0
- package/dist/core/crawler/reporting-api-handler.js +344 -0
- package/{cli/dist → dist}/core/crawler/selector-generator.d.ts +9 -0
- package/{cli/dist → dist}/core/crawler/selector-generator.js +99 -23
- package/dist/core/crawler/site-profiler.d.ts +89 -0
- package/dist/core/crawler/site-profiler.js +290 -0
- package/dist/core/crawler/sourcemaps-handler.d.ts +144 -0
- package/dist/core/crawler/sourcemaps-handler.js +420 -0
- package/dist/core/crawler/stacked-modals-handler.d.ts +118 -0
- package/dist/core/crawler/stacked-modals-handler.js +429 -0
- package/dist/core/crawler/trusted-types-handler.d.ts +149 -0
- package/dist/core/crawler/trusted-types-handler.js +413 -0
- package/{cli/dist → dist}/core/crawler/types.d.ts +68 -2
- package/dist/core/crawler/wait-strategies.d.ts +108 -0
- package/dist/core/crawler/wait-strategies.js +399 -0
- package/dist/core/fixtures/factories.d.ts +180 -0
- package/dist/core/fixtures/factories.js +279 -0
- package/dist/core/fixtures/index.d.ts +6 -0
- package/dist/core/fixtures/index.js +6 -0
- package/{cli/dist → dist}/core/generation/crawler-pack-generator.d.ts +13 -3
- package/dist/core/generation/crawler-pack-generator.js +232 -0
- package/{cli/dist → dist}/core/generation/index.d.ts +2 -0
- package/{cli/dist → dist}/core/generation/index.js +2 -0
- package/{cli/dist → dist}/core/index.d.ts +2 -0
- package/{cli/dist → dist}/core/index.js +4 -0
- package/dist/core/network/index.d.ts +7 -0
- package/dist/core/network/index.js +7 -0
- package/dist/core/network/network-manager.d.ts +237 -0
- package/dist/core/network/network-manager.js +343 -0
- package/dist/core/network/network-simulator.d.ts +158 -0
- package/dist/core/network/network-simulator.js +261 -0
- package/{cli/dist → dist}/core/pack/validator.js +2 -2
- package/{cli/dist → dist}/core/pack-v2/migrator.d.ts +5 -0
- package/{cli/dist → dist}/core/pack-v2/migrator.js +81 -6
- package/{cli/dist → dist}/core/pack-v2/validator.js +4 -3
- package/{cli/dist → dist}/core/pom/base-page.js +1 -1
- package/{cli/dist → dist}/core/pom/loader.js +1 -1
- package/dist/core/reporting/index.d.ts +9 -0
- package/dist/core/reporting/index.js +10 -0
- package/dist/core/reporting/junit-reporter.d.ts +114 -0
- package/dist/core/reporting/junit-reporter.js +306 -0
- package/{cli/dist → dist}/core/runner/e2e-helpers.d.ts +1 -1
- package/{cli/dist → dist}/core/runner/e2e-helpers.js +2 -2
- package/{cli/dist → dist}/core/runner/phase3-runner.d.ts +3 -0
- package/{cli/dist → dist}/core/runner/phase3-runner.js +45 -14
- package/dist/core/sharding/test-sharding.d.ts +137 -0
- package/dist/core/sharding/test-sharding.js +233 -0
- package/dist/core/storage/cookie-manager.d.ts +160 -0
- package/dist/core/storage/cookie-manager.js +268 -0
- package/dist/core/storage/index.d.ts +7 -0
- package/dist/core/storage/index.js +7 -0
- package/dist/core/storage/storage-helpers.d.ts +138 -0
- package/dist/core/storage/storage-helpers.js +315 -0
- package/dist/core/test-helpers/index.d.ts +6 -0
- package/dist/core/test-helpers/index.js +6 -0
- package/dist/core/test-helpers/state-reset.d.ts +119 -0
- package/dist/core/test-helpers/state-reset.js +234 -0
- package/{cli/dist → dist}/core/types/pack-v1.d.ts +15 -2
- package/{cli/dist → dist}/core/types/pack-v2.d.ts +1 -1
- package/dist/core/upload/chunked-uploader.d.ts +150 -0
- package/dist/core/upload/chunked-uploader.js +289 -0
- package/dist/core/upload/index.d.ts +11 -0
- package/dist/core/upload/index.js +8 -0
- package/dist/core/upload/mime-validator.d.ts +119 -0
- package/dist/core/upload/mime-validator.js +373 -0
- package/dist/core/upload/presigned-uploader.d.ts +118 -0
- package/dist/core/upload/presigned-uploader.js +274 -0
- package/dist/core/utils/device-emulation.d.ts +194 -0
- package/dist/core/utils/device-emulation.js +380 -0
- package/dist/core/utils/index.d.ts +8 -0
- package/dist/core/utils/index.js +8 -0
- package/dist/core/utils/retry.d.ts +145 -0
- package/dist/core/utils/retry.js +242 -0
- package/dist/core/utils/smart-wait.d.ts +133 -0
- package/dist/core/utils/smart-wait.js +417 -0
- package/dist/core/visual/index.d.ts +7 -0
- package/dist/core/visual/index.js +7 -0
- package/dist/core/visual/pixel-diff.d.ts +87 -0
- package/dist/core/visual/pixel-diff.js +213 -0
- package/dist/core/visual/screenshot-helper.d.ts +130 -0
- package/dist/core/visual/screenshot-helper.js +223 -0
- package/{cli/dist → dist}/utils/config.d.ts +1 -1
- package/examples/README.md +160 -0
- package/examples/accessibility.yml +48 -0
- package/examples/api-basic.yml +27 -0
- package/examples/complete.yml +146 -0
- package/examples/crawler.yml +38 -0
- package/examples/fullstack.yml +78 -0
- package/examples/security.yml +58 -0
- package/examples/ui-advanced.yml +49 -0
- package/examples/ui-basic.yml +24 -0
- package/package.json +33 -67
- package/CHANGELOG.md +0 -262
- package/CONTRIBUTING.md +0 -273
- package/QUICK_START.md +0 -191
- package/cli/CHANGELOG.md +0 -84
- package/cli/LICENSE +0 -24
- package/cli/README.md +0 -222
- package/cli/dist/core/adapters/playwright-ui.js +0 -864
- package/cli/dist/core/auth/oauth2-provider.js +0 -114
- package/cli/dist/core/coverage/analyzer.d.ts +0 -101
- package/cli/dist/core/coverage/analyzer.js +0 -415
- package/cli/dist/core/coverage/collector.d.ts +0 -74
- package/cli/dist/core/coverage/collector.js +0 -459
- package/cli/dist/core/coverage/config.d.ts +0 -37
- package/cli/dist/core/coverage/config.js +0 -156
- package/cli/dist/core/coverage/index.d.ts +0 -11
- package/cli/dist/core/coverage/index.js +0 -15
- package/cli/dist/core/coverage/types.d.ts +0 -267
- package/cli/dist/core/coverage/types.js +0 -6
- package/cli/dist/core/coverage/vault.d.ts +0 -95
- package/cli/dist/core/coverage/vault.js +0 -405
- package/cli/dist/core/crawler/index.d.ts +0 -57
- package/cli/dist/core/fixtures/index.d.ts +0 -8
- package/cli/dist/core/fixtures/index.js +0 -8
- package/cli/dist/core/generation/crawler-pack-generator.js +0 -231
- package/cli/dist/core/reporting/index.d.ts +0 -6
- package/cli/dist/core/reporting/index.js +0 -6
- package/cli/dist/core/visual/index.d.ts +0 -6
- package/cli/dist/core/visual/index.js +0 -6
- package/cli/package.json +0 -76
- package/core/LICENSE +0 -24
- package/core/README.md +0 -64
- package/core/package.json +0 -81
- package/core/schemas/pack.schema.json +0 -236
- /package/{cli/bin → bin}/qa360.js +0 -0
- /package/{cli/dist → dist}/cli-minimal.d.ts +0 -0
- /package/{cli/dist → dist}/cli-minimal.js +0 -0
- /package/{cli/dist → dist}/commands/ai.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ask.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ask.js +0 -0
- /package/{cli/dist → dist}/commands/coverage.d.ts +0 -0
- /package/{cli/dist → dist}/commands/doctor.d.ts +0 -0
- /package/{cli/dist → dist}/commands/examples.d.ts +0 -0
- /package/{cli/dist → dist}/commands/examples.js +0 -0
- /package/{cli/dist → dist}/commands/explain.d.ts +0 -0
- /package/{cli/dist → dist}/commands/flakiness.d.ts +0 -0
- /package/{cli/dist → dist}/commands/generate.d.ts +0 -0
- /package/{cli/dist → dist}/commands/history.d.ts +0 -0
- /package/{cli/dist → dist}/commands/init.d.ts +0 -0
- /package/{cli/dist → dist}/commands/init.js +0 -0
- /package/{cli/dist → dist}/commands/monitor.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ollama.d.ts +0 -0
- /package/{cli/dist → dist}/commands/pack.d.ts +0 -0
- /package/{cli/dist → dist}/commands/regression.d.ts +0 -0
- /package/{cli/dist → dist}/commands/repair.d.ts +0 -0
- /package/{cli/dist → dist}/commands/report.d.ts +0 -0
- /package/{cli/dist → dist}/commands/report.js +0 -0
- /package/{cli/dist → dist}/commands/retry.d.ts +0 -0
- /package/{cli/dist → dist}/commands/scan.d.ts +0 -0
- /package/{cli/dist → dist}/commands/scan.js +0 -0
- /package/{cli/dist → dist}/commands/secrets.d.ts +0 -0
- /package/{cli/dist → dist}/commands/serve.d.ts +0 -0
- /package/{cli/dist → dist}/commands/slo.d.ts +0 -0
- /package/{cli/dist → dist}/commands/verify.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.js +0 -0
- /package/{cli/dist → dist}/core/adapters/jest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/jest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/k6-perf.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/k6-perf.js +0 -0
- /package/{cli/dist → dist}/core/adapters/osv-deps.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/osv-deps.js +0 -0
- /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/pytest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/pytest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/semgrep-sast.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/semgrep-sast.js +0 -0
- /package/{cli/dist → dist}/core/adapters/unit-test-types.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/unit-test-types.js +0 -0
- /package/{cli/dist → dist}/core/adapters/vitest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/vitest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/zap-dast.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/zap-dast.js +0 -0
- /package/{cli/dist → dist}/core/ai/anthropic-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/anthropic-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/deepseek-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/deepseek-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/index.js +0 -0
- /package/{cli/dist → dist}/core/ai/llm-client.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/llm-client.js +0 -0
- /package/{cli/dist → dist}/core/ai/mock-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/mock-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/ollama-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/openai-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/openai-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/provider-factory.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/provider-factory.js +0 -0
- /package/{cli/dist → dist}/core/artifacts/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/artifacts/index.js +0 -0
- /package/{cli/dist → dist}/core/artifacts/ui-artifacts.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/engine.js +0 -0
- /package/{cli/dist → dist}/core/assertions/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/index.js +0 -0
- /package/{cli/dist → dist}/core/assertions/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/types.js +0 -0
- /package/{cli/dist → dist}/core/auth/api-key-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/api-key-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/aws-iam-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/aws-iam-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/azure-ad-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/azure-ad-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/gcp-adc-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/gcp-adc-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/jwt-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/jwt-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/manager.js +0 -0
- /package/{cli/dist → dist}/core/auth/totp-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/totp-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/ui-login-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/ui-login-provider.js +0 -0
- /package/{cli/dist → dist}/core/cache/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/cache/index.js +0 -0
- /package/{cli/dist → dist}/core/cache/lru-cache.d.ts +0 -0
- /package/{cli/dist → dist}/core/cache/lru-cache.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/analyzer.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/analyzer.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/collector.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/collector.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/config.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/config.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/index.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/index.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/types.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/types.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/vault.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/vault.js +0 -0
- /package/{cli/dist → dist}/core/crawler/journey-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/crawler/types.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/assets.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/assets.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/index.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/server.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/server.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/types.js +0 -0
- /package/{cli/dist → dist}/core/discoverer/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/discoverer/index.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/loader.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/resolver.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/resolver.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/types.js +0 -0
- /package/{cli/dist → dist}/core/flakiness/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/flakiness/index.js +0 -0
- /package/{cli/dist → dist}/core/generation/code-formatter.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/code-formatter.js +0 -0
- /package/{cli/dist → dist}/core/generation/code-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/code-generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/pack-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/pack-generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/prompt-builder.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/prompt-builder.js +0 -0
- /package/{cli/dist → dist}/core/generation/source-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/source-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/generation/test-optimizer.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/test-optimizer.js +0 -0
- /package/{cli/dist → dist}/core/generation/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/types.js +0 -0
- /package/{cli/dist → dist}/core/hooks/compose.d.ts +0 -0
- /package/{cli/dist → dist}/core/hooks/compose.js +0 -0
- /package/{cli/dist → dist}/core/hooks/runner.d.ts +0 -0
- /package/{cli/dist → dist}/core/hooks/runner.js +0 -0
- /package/{cli/dist → dist}/core/pack/migrator.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack/migrator.js +0 -0
- /package/{cli/dist → dist}/core/pack/validator.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/index.js +0 -0
- /package/{cli/dist → dist}/core/pack-v2/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/loader.js +0 -0
- /package/{cli/dist → dist}/core/pack-v2/validator.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/index.js +0 -0
- /package/{cli/dist → dist}/core/parallel/parallel-runner.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/parallel-runner.js +0 -0
- /package/{cli/dist → dist}/core/pom/base-page.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/index.js +0 -0
- /package/{cli/dist → dist}/core/pom/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/types.js +0 -0
- /package/{cli/dist → dist}/core/proof/bundle.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/bundle.js +0 -0
- /package/{cli/dist → dist}/core/proof/canonicalize.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/canonicalize.js +0 -0
- /package/{cli/dist → dist}/core/proof/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/index.js +0 -0
- /package/{cli/dist → dist}/core/proof/schema.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/schema.js +0 -0
- /package/{cli/dist → dist}/core/proof/signer.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/signer.js +0 -0
- /package/{cli/dist → dist}/core/proof/verifier.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/verifier.js +0 -0
- /package/{cli/dist → dist}/core/regression/detector.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/detector.js +0 -0
- /package/{cli/dist → dist}/core/regression/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/index.js +0 -0
- /package/{cli/dist → dist}/core/regression/trend-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/trend-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/regression/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/types.js +0 -0
- /package/{cli/dist → dist}/core/regression/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/vault.js +0 -0
- /package/{cli/dist → dist}/core/repair/engine/fixer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/engine/fixer.js +0 -0
- /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.js +0 -0
- /package/{cli/dist → dist}/core/repair/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/index.js +0 -0
- /package/{cli/dist → dist}/core/repair/repairer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/repairer.js +0 -0
- /package/{cli/dist → dist}/core/repair/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/types.js +0 -0
- /package/{cli/dist → dist}/core/repair/utils/error-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/utils/error-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/reporting/html-reporter.d.ts +0 -0
- /package/{cli/dist → dist}/core/reporting/html-reporter.js +0 -0
- /package/{cli/dist → dist}/core/retry/flakiness-integration.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/flakiness-integration.js +0 -0
- /package/{cli/dist → dist}/core/retry/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/index.js +0 -0
- /package/{cli/dist → dist}/core/retry/retry-engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/retry-engine.js +0 -0
- /package/{cli/dist → dist}/core/retry/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/types.js +0 -0
- /package/{cli/dist → dist}/core/retry/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/vault.js +0 -0
- /package/{cli/dist → dist}/core/schemas/pack.schema.json +0 -0
- /package/{cli/dist → dist}/core/secrets/crypto.d.ts +0 -0
- /package/{cli/dist → dist}/core/secrets/crypto.js +0 -0
- /package/{cli/dist → dist}/core/secrets/manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/secrets/manager.js +0 -0
- /package/{cli/dist → dist}/core/security/redaction-patterns-extended.d.ts +0 -0
- /package/{cli/dist → dist}/core/security/redaction-patterns-extended.js +0 -0
- /package/{cli/dist → dist}/core/security/redactor.d.ts +0 -0
- /package/{cli/dist → dist}/core/security/redactor.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/assertion-healer.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/assertion-healer.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/engine.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/index.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/selector-healer.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/selector-healer.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/types.js +0 -0
- /package/{cli/dist → dist}/core/serve/diagnostics-collector.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/diagnostics-collector.js +0 -0
- /package/{cli/dist → dist}/core/serve/health-checker.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/health-checker.js +0 -0
- /package/{cli/dist → dist}/core/serve/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/index.js +0 -0
- /package/{cli/dist → dist}/core/serve/metrics-collector.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/metrics-collector.js +0 -0
- /package/{cli/dist → dist}/core/serve/process-manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/process-manager.js +0 -0
- /package/{cli/dist → dist}/core/serve/server.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/server.js +0 -0
- /package/{cli/dist → dist}/core/slo/config.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/config.js +0 -0
- /package/{cli/dist → dist}/core/slo/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/index.js +0 -0
- /package/{cli/dist → dist}/core/slo/sli-calculator.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/sli-calculator.js +0 -0
- /package/{cli/dist → dist}/core/slo/slo-tracker.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/slo-tracker.js +0 -0
- /package/{cli/dist → dist}/core/slo/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/types.js +0 -0
- /package/{cli/dist → dist}/core/slo/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/vault.js +0 -0
- /package/{cli/dist → dist}/core/tui/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/index.js +0 -0
- /package/{cli/dist → dist}/core/tui/monitor.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/monitor.js +0 -0
- /package/{cli/dist → dist}/core/tui/renderer.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/renderer.js +0 -0
- /package/{cli/dist → dist}/core/tui/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/types.js +0 -0
- /package/{cli/dist → dist}/core/types/pack-v1.js +0 -0
- /package/{cli/dist → dist}/core/types/pack-v2.js +0 -0
- /package/{cli/dist → dist}/core/types/trust-score.d.ts +0 -0
- /package/{cli/dist → dist}/core/types/trust-score.js +0 -0
- /package/{cli/dist → dist}/core/vault/cas.d.ts +0 -0
- /package/{cli/dist → dist}/core/vault/cas.js +0 -0
- /package/{cli/dist → dist}/core/vault/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/vault/index.js +0 -0
- /package/{cli/dist → dist}/core/visual/visual-regression.d.ts +0 -0
- /package/{cli/dist → dist}/core/visual/visual-regression.js +0 -0
- /package/{cli/dist → dist}/core/watch/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/watch/index.js +0 -0
- /package/{cli/dist → dist}/core/watch/watch-mode.d.ts +0 -0
- /package/{cli/dist → dist}/core/watch/watch-mode.js +0 -0
- /package/{cli/dist → dist}/generators/index.d.ts +0 -0
- /package/{cli/dist → dist}/generators/index.js +0 -0
- /package/{cli/dist → dist}/generators/json-reporter.d.ts +0 -0
- /package/{cli/dist → dist}/generators/json-reporter.js +0 -0
- /package/{cli/dist → dist}/generators/test-generator.d.ts +0 -0
- /package/{cli/dist → dist}/generators/test-generator.js +0 -0
- /package/{cli/dist → dist}/index.d.ts +0 -0
- /package/{cli/dist → dist}/index.js +0 -0
- /package/{cli/dist → dist}/scanners/dom-scanner.d.ts +0 -0
- /package/{cli/dist → dist}/scanners/dom-scanner.js +0 -0
- /package/{cli/dist → dist}/scanners/index.d.ts +0 -0
- /package/{cli/dist → dist}/scanners/index.js +0 -0
- /package/{cli/dist → dist}/schemas/pack.schema.json +0 -0
- /package/{cli/dist → dist}/types/scan.d.ts +0 -0
- /package/{cli/dist → dist}/types/scan.js +0 -0
- /package/{cli/dist → dist}/utils/config.js +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 JUnit XML Reporter
|
|
3
|
+
*
|
|
4
|
+
* P0 Feature: Generates JUnit XML format for CI/CD integration
|
|
5
|
+
* Compatible with Jenkins, GitLab CI, GitHub Actions, CircleCI, etc.
|
|
6
|
+
*
|
|
7
|
+
* JUnit XML schema:
|
|
8
|
+
* - testsuite: Contains test results
|
|
9
|
+
* - testcase: Individual test case with status
|
|
10
|
+
* - failure: Error details for failed tests
|
|
11
|
+
* - skipped: Skipped test information
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* JUnit XML compatible test case
|
|
15
|
+
*/
|
|
16
|
+
export interface JUnitTestCase {
|
|
17
|
+
name: string;
|
|
18
|
+
classname?: string;
|
|
19
|
+
time: number;
|
|
20
|
+
failure?: {
|
|
21
|
+
message: string;
|
|
22
|
+
type: string;
|
|
23
|
+
text: string;
|
|
24
|
+
};
|
|
25
|
+
error?: {
|
|
26
|
+
message: string;
|
|
27
|
+
type: string;
|
|
28
|
+
text: string;
|
|
29
|
+
};
|
|
30
|
+
skipped?: {
|
|
31
|
+
message?: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* System output (stdout)
|
|
35
|
+
*/
|
|
36
|
+
'system-out'?: string;
|
|
37
|
+
/**
|
|
38
|
+
* System error (stderr)
|
|
39
|
+
*/
|
|
40
|
+
'system-err'?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* JUnit XML compatible test suite
|
|
44
|
+
*/
|
|
45
|
+
export interface JUnitTestSuite {
|
|
46
|
+
name: string;
|
|
47
|
+
tests: number;
|
|
48
|
+
failures: number;
|
|
49
|
+
errors: number;
|
|
50
|
+
skipped: number;
|
|
51
|
+
time: number;
|
|
52
|
+
timestamp: string;
|
|
53
|
+
hostname?: string;
|
|
54
|
+
properties?: Record<string, string>;
|
|
55
|
+
testcases: JUnitTestCase[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* JUnit XML report options
|
|
59
|
+
*/
|
|
60
|
+
export interface JUnitOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Suite name (default: "QA360 Test Suite")
|
|
63
|
+
*/
|
|
64
|
+
suiteName?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Environment properties to include
|
|
67
|
+
*/
|
|
68
|
+
properties?: Record<string, string>;
|
|
69
|
+
/**
|
|
70
|
+
* Include stack traces in failure output
|
|
71
|
+
*/
|
|
72
|
+
includeStackTrace?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* JUnit XML Reporter
|
|
76
|
+
*/
|
|
77
|
+
export declare class JUnitReporter {
|
|
78
|
+
/**
|
|
79
|
+
* Generate JUnit XML from test suite data
|
|
80
|
+
*/
|
|
81
|
+
static generate(suite: JUnitTestSuite, options?: JUnitOptions): string;
|
|
82
|
+
/**
|
|
83
|
+
* Generate JUnit XML and write to file
|
|
84
|
+
*/
|
|
85
|
+
static generateToFile(suite: JUnitTestSuite, outputPath: string, options?: JUnitOptions): void;
|
|
86
|
+
/**
|
|
87
|
+
* Convert from ReportData format (used by HTMLReporter)
|
|
88
|
+
*/
|
|
89
|
+
static fromReportData(data: import('./html-reporter.js').ReportData, options?: JUnitOptions): JUnitTestSuite;
|
|
90
|
+
/**
|
|
91
|
+
* Convert from UiSmokeResult format (used by PlaywrightUiAdapter)
|
|
92
|
+
*/
|
|
93
|
+
static fromUiSmokeResult(result: import('../adapters/playwright-ui.js').UiSmokeResult, suiteName?: string, options?: JUnitOptions): JUnitTestSuite;
|
|
94
|
+
/**
|
|
95
|
+
* Merge multiple test suites into a single XML
|
|
96
|
+
*/
|
|
97
|
+
static generateMerged(suites: JUnitTestSuite[], options?: JUnitOptions): string;
|
|
98
|
+
/**
|
|
99
|
+
* Escape special XML characters
|
|
100
|
+
*/
|
|
101
|
+
private static escapeXml;
|
|
102
|
+
/**
|
|
103
|
+
* Format time duration (seconds with 3 decimal places)
|
|
104
|
+
*/
|
|
105
|
+
private static formatTime;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Convenience function to generate JUnit XML
|
|
109
|
+
*/
|
|
110
|
+
export declare function generateJUnitReport(suite: JUnitTestSuite, options?: JUnitOptions): string;
|
|
111
|
+
/**
|
|
112
|
+
* Convenience function to generate JUnit XML and write to file
|
|
113
|
+
*/
|
|
114
|
+
export declare function generateJUnitReportToFile(suite: JUnitTestSuite, outputPath: string, options?: JUnitOptions): void;
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 JUnit XML Reporter
|
|
3
|
+
*
|
|
4
|
+
* P0 Feature: Generates JUnit XML format for CI/CD integration
|
|
5
|
+
* Compatible with Jenkins, GitLab CI, GitHub Actions, CircleCI, etc.
|
|
6
|
+
*
|
|
7
|
+
* JUnit XML schema:
|
|
8
|
+
* - testsuite: Contains test results
|
|
9
|
+
* - testcase: Individual test case with status
|
|
10
|
+
* - failure: Error details for failed tests
|
|
11
|
+
* - skipped: Skipped test information
|
|
12
|
+
*/
|
|
13
|
+
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
14
|
+
import { dirname } from 'path';
|
|
15
|
+
/**
|
|
16
|
+
* JUnit XML Reporter
|
|
17
|
+
*/
|
|
18
|
+
export class JUnitReporter {
|
|
19
|
+
/**
|
|
20
|
+
* Generate JUnit XML from test suite data
|
|
21
|
+
*/
|
|
22
|
+
static generate(suite, options = {}) {
|
|
23
|
+
const suiteName = options.suiteName || suite.name || 'QA360 Test Suite';
|
|
24
|
+
const timestamp = suite.timestamp || new Date().toISOString();
|
|
25
|
+
const hostname = suite.hostname || 'localhost';
|
|
26
|
+
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
|
27
|
+
// Calculate totals from testcases if not provided
|
|
28
|
+
const totalTests = suite.tests || suite.testcases.length;
|
|
29
|
+
const totalFailures = suite.failures || suite.testcases.filter(t => t.failure).length;
|
|
30
|
+
const totalErrors = suite.errors || suite.testcases.filter(t => t.error).length;
|
|
31
|
+
const totalSkipped = suite.skipped || suite.testcases.filter(t => t.skipped).length;
|
|
32
|
+
const totalTime = suite.time || suite.testcases.reduce((sum, t) => sum + t.time, 0);
|
|
33
|
+
xml += `<testsuite`;
|
|
34
|
+
xml += ` name="${this.escapeXml(suiteName)}"`;
|
|
35
|
+
xml += ` tests="${totalTests}"`;
|
|
36
|
+
xml += ` failures="${totalFailures}"`;
|
|
37
|
+
xml += ` errors="${totalErrors}"`;
|
|
38
|
+
xml += ` skipped="${totalSkipped}"`;
|
|
39
|
+
xml += ` time="${this.formatTime(totalTime)}"`;
|
|
40
|
+
xml += ` timestamp="${timestamp}"`;
|
|
41
|
+
xml += ` hostname="${this.escapeXml(hostname)}"`;
|
|
42
|
+
xml += `>\n`;
|
|
43
|
+
// Properties
|
|
44
|
+
const allProperties = { ...suite.properties, ...options.properties };
|
|
45
|
+
if (Object.keys(allProperties).length > 0) {
|
|
46
|
+
xml += ' <properties>\n';
|
|
47
|
+
for (const [key, value] of Object.entries(allProperties)) {
|
|
48
|
+
xml += ` <property name="${this.escapeXml(key)}" value="${this.escapeXml(value)}"/>\n`;
|
|
49
|
+
}
|
|
50
|
+
xml += ' </properties>\n';
|
|
51
|
+
}
|
|
52
|
+
// Test cases
|
|
53
|
+
for (const testcase of suite.testcases) {
|
|
54
|
+
xml += ' <testcase';
|
|
55
|
+
xml += ` name="${this.escapeXml(testcase.name)}"`;
|
|
56
|
+
if (testcase.classname) {
|
|
57
|
+
xml += ` classname="${this.escapeXml(testcase.classname)}"`;
|
|
58
|
+
}
|
|
59
|
+
xml += ` time="${this.formatTime(testcase.time)}"`;
|
|
60
|
+
xml += `>\n`;
|
|
61
|
+
// Failure
|
|
62
|
+
if (testcase.failure) {
|
|
63
|
+
xml += ' <failure';
|
|
64
|
+
xml += ` message="${this.escapeXml(testcase.failure.message)}"`;
|
|
65
|
+
xml += ` type="${this.escapeXml(testcase.failure.type)}"`;
|
|
66
|
+
xml += `><![CDATA[${testcase.failure.text}]]></failure>\n`;
|
|
67
|
+
}
|
|
68
|
+
// Error
|
|
69
|
+
if (testcase.error) {
|
|
70
|
+
xml += ' <error';
|
|
71
|
+
xml += ` message="${this.escapeXml(testcase.error.message)}"`;
|
|
72
|
+
xml += ` type="${this.escapeXml(testcase.error.type)}"`;
|
|
73
|
+
xml += `><![CDATA[${testcase.error.text}]]></error>\n`;
|
|
74
|
+
}
|
|
75
|
+
// Skipped
|
|
76
|
+
if (testcase.skipped) {
|
|
77
|
+
xml += ' <skipped';
|
|
78
|
+
if (testcase.skipped.message) {
|
|
79
|
+
xml += ` message="${this.escapeXml(testcase.skipped.message)}"`;
|
|
80
|
+
}
|
|
81
|
+
xml += '/>\n';
|
|
82
|
+
}
|
|
83
|
+
// System out
|
|
84
|
+
if (testcase['system-out']) {
|
|
85
|
+
xml += ` <system-out><![CDATA[${testcase['system-out']}]]></system-out>\n`;
|
|
86
|
+
}
|
|
87
|
+
// System err
|
|
88
|
+
if (testcase['system-err']) {
|
|
89
|
+
xml += ` <system-err><![CDATA[${testcase['system-err']}]]></system-err>\n`;
|
|
90
|
+
}
|
|
91
|
+
xml += ' </testcase>\n';
|
|
92
|
+
}
|
|
93
|
+
// Standard output/error for the entire suite
|
|
94
|
+
/*
|
|
95
|
+
xml += ' <system-out><![CDATA[]]></system-out>\n';
|
|
96
|
+
xml += ' <system-err><![CDATA[]]></system-err>\n';
|
|
97
|
+
*/
|
|
98
|
+
xml += '</testsuite>\n';
|
|
99
|
+
return xml;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Generate JUnit XML and write to file
|
|
103
|
+
*/
|
|
104
|
+
static generateToFile(suite, outputPath, options = {}) {
|
|
105
|
+
const xml = this.generate(suite, options);
|
|
106
|
+
const dir = dirname(outputPath);
|
|
107
|
+
if (!existsSync(dir)) {
|
|
108
|
+
mkdirSync(dir, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
writeFileSync(outputPath, xml, 'utf-8');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Convert from ReportData format (used by HTMLReporter)
|
|
114
|
+
*/
|
|
115
|
+
static fromReportData(data, options = {}) {
|
|
116
|
+
const testcases = data.tests.map(test => {
|
|
117
|
+
const testcase = {
|
|
118
|
+
name: test.name,
|
|
119
|
+
classname: data.title,
|
|
120
|
+
time: test.duration / 1000, // Convert ms to seconds
|
|
121
|
+
};
|
|
122
|
+
if (test.status === 'failed') {
|
|
123
|
+
testcase.failure = {
|
|
124
|
+
message: test.error || 'Test failed',
|
|
125
|
+
type: 'AssertionError',
|
|
126
|
+
text: test.error || 'Test failed without error message'
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
else if (test.status === 'skipped') {
|
|
130
|
+
testcase.skipped = {
|
|
131
|
+
message: 'Test was skipped'
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Add system output with step details
|
|
135
|
+
if (test.steps && test.steps.length > 0) {
|
|
136
|
+
const stepsOutput = test.steps.map((step, i) => `${i + 1}. ${step.name}: ${step.status} (${step.duration}ms)`).join('\n');
|
|
137
|
+
testcase['system-out'] = stepsOutput;
|
|
138
|
+
}
|
|
139
|
+
// Add artifacts info to system output
|
|
140
|
+
if (test.artifacts) {
|
|
141
|
+
const artifacts = [];
|
|
142
|
+
if (test.artifacts.screenshots?.length) {
|
|
143
|
+
artifacts.push(`Screenshots: ${test.artifacts.screenshots.join(', ')}`);
|
|
144
|
+
}
|
|
145
|
+
if (test.artifacts.video) {
|
|
146
|
+
artifacts.push(`Video: ${test.artifacts.video}`);
|
|
147
|
+
}
|
|
148
|
+
if (test.artifacts.trace) {
|
|
149
|
+
artifacts.push(`Trace: ${test.artifacts.trace}`);
|
|
150
|
+
}
|
|
151
|
+
if (artifacts.length > 0) {
|
|
152
|
+
testcase['system-out'] = (testcase['system-out'] || '') + '\n' + artifacts.join('\n');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return testcase;
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
name: options.suiteName || data.title,
|
|
159
|
+
tests: data.summary.total,
|
|
160
|
+
failures: data.summary.failed,
|
|
161
|
+
errors: 0, // ReportData doesn't separate errors from failures
|
|
162
|
+
skipped: data.summary.skipped,
|
|
163
|
+
time: data.summary.duration / 1000,
|
|
164
|
+
timestamp: data.summary.timestamp,
|
|
165
|
+
hostname: 'localhost',
|
|
166
|
+
properties: {
|
|
167
|
+
...data.environment,
|
|
168
|
+
...options.properties
|
|
169
|
+
},
|
|
170
|
+
testcases
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Convert from UiSmokeResult format (used by PlaywrightUiAdapter)
|
|
175
|
+
*/
|
|
176
|
+
static fromUiSmokeResult(result, suiteName = 'UI Smoke Tests', options = {}) {
|
|
177
|
+
const testcases = result.results.map(r => {
|
|
178
|
+
const testcase = {
|
|
179
|
+
name: r.page,
|
|
180
|
+
classname: suiteName,
|
|
181
|
+
time: r.loadTime / 1000,
|
|
182
|
+
};
|
|
183
|
+
if (!r.success) {
|
|
184
|
+
testcase.failure = {
|
|
185
|
+
message: r.error || 'Page test failed',
|
|
186
|
+
type: 'AssertionError',
|
|
187
|
+
text: r.error || 'Page test failed without error message'
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
// Add accessibility info to system output
|
|
191
|
+
if (r.accessibility) {
|
|
192
|
+
testcase['system-out'] = `Accessibility Score: ${r.accessibility.score}%\n`;
|
|
193
|
+
if (r.accessibility.violations.length > 0) {
|
|
194
|
+
testcase['system-out'] += `Violations: ${r.accessibility.violations.map(v => `- ${v.id}: ${v.description} (${v.impact})`).join('\n')}`;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return testcase;
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
name: suiteName,
|
|
201
|
+
tests: result.summary.total,
|
|
202
|
+
failures: result.summary.failed,
|
|
203
|
+
errors: 0,
|
|
204
|
+
skipped: 0,
|
|
205
|
+
time: result.results.reduce((sum, r) => sum + r.loadTime, 0) / 1000,
|
|
206
|
+
timestamp: new Date().toISOString(),
|
|
207
|
+
hostname: 'localhost',
|
|
208
|
+
properties: options.properties,
|
|
209
|
+
testcases
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Merge multiple test suites into a single XML
|
|
214
|
+
*/
|
|
215
|
+
static generateMerged(suites, options = {}) {
|
|
216
|
+
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
|
217
|
+
xml += '<testsuites>\n';
|
|
218
|
+
const totalTests = suites.reduce((sum, s) => sum + s.tests, 0);
|
|
219
|
+
const totalFailures = suites.reduce((sum, s) => sum + s.failures, 0);
|
|
220
|
+
const totalErrors = suites.reduce((sum, s) => sum + s.errors, 0);
|
|
221
|
+
const totalSkipped = suites.reduce((sum, s) => sum + s.skipped, 0);
|
|
222
|
+
const totalTime = suites.reduce((sum, s) => sum + s.time, 0);
|
|
223
|
+
xml += ` <testsuite`;
|
|
224
|
+
xml += ` name="${this.escapeXml(options.suiteName || 'QA360 Test Suite')}"`;
|
|
225
|
+
xml += ` tests="${totalTests}"`;
|
|
226
|
+
xml += ` failures="${totalFailures}"`;
|
|
227
|
+
xml += ` errors="${totalErrors}"`;
|
|
228
|
+
xml += ` skipped="${totalSkipped}"`;
|
|
229
|
+
xml += ` time="${this.formatTime(totalTime)}"`;
|
|
230
|
+
xml += `>\n`;
|
|
231
|
+
for (const suite of suites) {
|
|
232
|
+
for (const testcase of suite.testcases) {
|
|
233
|
+
xml += ' <testcase';
|
|
234
|
+
xml += ` name="${this.escapeXml(testcase.name)}"`;
|
|
235
|
+
if (testcase.classname) {
|
|
236
|
+
xml += ` classname="${this.escapeXml(testcase.classname)}"`;
|
|
237
|
+
}
|
|
238
|
+
xml += ` time="${this.formatTime(testcase.time)}"`;
|
|
239
|
+
const hasContent = testcase.failure || testcase.error || testcase.skipped ||
|
|
240
|
+
testcase['system-out'] || testcase['system-err'];
|
|
241
|
+
if (!hasContent) {
|
|
242
|
+
xml += '/>\n';
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
xml += '>\n';
|
|
246
|
+
if (testcase.failure) {
|
|
247
|
+
xml += ` <failure message="${this.escapeXml(testcase.failure.message)}"` +
|
|
248
|
+
` type="${this.escapeXml(testcase.failure.type)}"` +
|
|
249
|
+
`><![CDATA[${testcase.failure.text}]]></failure>\n`;
|
|
250
|
+
}
|
|
251
|
+
if (testcase.error) {
|
|
252
|
+
xml += ` <error message="${this.escapeXml(testcase.error.message)}"` +
|
|
253
|
+
` type="${this.escapeXml(testcase.error.type)}"` +
|
|
254
|
+
`><![CDATA[${testcase.error.text}]]></error>\n`;
|
|
255
|
+
}
|
|
256
|
+
if (testcase.skipped) {
|
|
257
|
+
xml += ` <skipped`;
|
|
258
|
+
if (testcase.skipped.message) {
|
|
259
|
+
xml += ` message="${this.escapeXml(testcase.skipped.message)}"`;
|
|
260
|
+
}
|
|
261
|
+
xml += '/>\n';
|
|
262
|
+
}
|
|
263
|
+
if (testcase['system-out']) {
|
|
264
|
+
xml += ` <system-out><![CDATA[${testcase['system-out']}]]></system-out>\n`;
|
|
265
|
+
}
|
|
266
|
+
if (testcase['system-err']) {
|
|
267
|
+
xml += ` <system-err><![CDATA[${testcase['system-err']}]]></system-err>\n`;
|
|
268
|
+
}
|
|
269
|
+
xml += ' </testcase>\n';
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
xml += ' </testsuite>\n';
|
|
274
|
+
xml += '</testsuites>\n';
|
|
275
|
+
return xml;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Escape special XML characters
|
|
279
|
+
*/
|
|
280
|
+
static escapeXml(str) {
|
|
281
|
+
return str
|
|
282
|
+
.replace(/&/g, '&')
|
|
283
|
+
.replace(/</g, '<')
|
|
284
|
+
.replace(/>/g, '>')
|
|
285
|
+
.replace(/"/g, '"')
|
|
286
|
+
.replace(/'/g, ''');
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Format time duration (seconds with 3 decimal places)
|
|
290
|
+
*/
|
|
291
|
+
static formatTime(seconds) {
|
|
292
|
+
return seconds.toFixed(3);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Convenience function to generate JUnit XML
|
|
297
|
+
*/
|
|
298
|
+
export function generateJUnitReport(suite, options) {
|
|
299
|
+
return JUnitReporter.generate(suite, options);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Convenience function to generate JUnit XML and write to file
|
|
303
|
+
*/
|
|
304
|
+
export function generateJUnitReportToFile(suite, outputPath, options) {
|
|
305
|
+
JUnitReporter.generateToFile(suite, outputPath, options);
|
|
306
|
+
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* @returns Health check result
|
|
13
13
|
*/
|
|
14
14
|
export async function healthCheck(url, options = {}) {
|
|
15
|
-
const { timeout =
|
|
15
|
+
const { timeout = 10000, method = 'HEAD', expectedStatus = [200, 301, 302, 304] } = options;
|
|
16
16
|
const startTime = Date.now();
|
|
17
17
|
try {
|
|
18
18
|
const controller = new AbortController();
|
|
@@ -97,7 +97,7 @@ export const E2E_TARGETS = {
|
|
|
97
97
|
},
|
|
98
98
|
reqres: {
|
|
99
99
|
url: 'https://reqres.in/api',
|
|
100
|
-
timeout:
|
|
100
|
+
timeout: 10000,
|
|
101
101
|
description: 'Reqres.in fake REST API'
|
|
102
102
|
}
|
|
103
103
|
};
|
|
@@ -16,6 +16,8 @@ export interface Phase3RunnerOptions {
|
|
|
16
16
|
flakyDetect?: boolean;
|
|
17
17
|
/** Number of consecutive runs for flakiness detection (default: 3) */
|
|
18
18
|
flakyRuns?: number;
|
|
19
|
+
/** Run browser in headed mode (visible UI) */
|
|
20
|
+
headed?: boolean;
|
|
19
21
|
}
|
|
20
22
|
export interface GateResult {
|
|
21
23
|
gate: string;
|
|
@@ -64,6 +66,7 @@ export declare class Phase3Runner {
|
|
|
64
66
|
private flakyDetect;
|
|
65
67
|
private flakyRuns;
|
|
66
68
|
private flakinessDetector;
|
|
69
|
+
private headed;
|
|
67
70
|
private fixtureLoader?;
|
|
68
71
|
private fixtureResolver?;
|
|
69
72
|
private pageObjectLoader?;
|
|
@@ -40,6 +40,7 @@ export class Phase3Runner {
|
|
|
40
40
|
flakyDetect;
|
|
41
41
|
flakyRuns;
|
|
42
42
|
flakinessDetector;
|
|
43
|
+
headed; // CLI override for headed mode
|
|
43
44
|
// v2.2.0 Data Fixtures & POM
|
|
44
45
|
fixtureLoader;
|
|
45
46
|
fixtureResolver;
|
|
@@ -53,6 +54,7 @@ export class Phase3Runner {
|
|
|
53
54
|
this.authManager = new AuthManager();
|
|
54
55
|
this.flakyDetect = options.flakyDetect || false;
|
|
55
56
|
this.flakyRuns = options.flakyRuns || DEFAULT_FLAKINESS_OPTIONS.consecutiveRuns;
|
|
57
|
+
this.headed = options.headed || false;
|
|
56
58
|
this.flakinessDetector = new FlakinessDetector({
|
|
57
59
|
consecutiveRuns: this.flakyRuns,
|
|
58
60
|
minRuns: 2,
|
|
@@ -616,40 +618,58 @@ export class Phase3Runner {
|
|
|
616
618
|
const { PlaywrightUiAdapter } = await import('../adapters/playwright-ui.js');
|
|
617
619
|
const adapter = new PlaywrightUiAdapter();
|
|
618
620
|
// Transform v2 config to adapter format
|
|
619
|
-
// v2: { baseUrl, pages
|
|
620
|
-
// adapter expects: { target: { baseUrl, pages
|
|
621
|
+
// v2: { target: { baseUrl, pages, uiTests }, config: { ... } }
|
|
622
|
+
// adapter expects: { target: { baseUrl, pages, uiTests, ... }, ... }
|
|
623
|
+
const gateTarget = gateConfig.target || {};
|
|
621
624
|
const gateConfigData = gateConfig.config || {};
|
|
622
625
|
const gateOptions = gateConfig.options || {};
|
|
623
626
|
// Transform page objects to full URLs
|
|
624
|
-
// v2 pages format: [{ url: '/',
|
|
625
|
-
|
|
627
|
+
// v2 pages format: [{ url: '/', actions: [...] }] or ['/', '/about']
|
|
628
|
+
// Preserve page objects with actions for user journey execution
|
|
629
|
+
const rawPages = gateTarget.pages || gateConfigData.pages;
|
|
626
630
|
let pages;
|
|
627
631
|
if (rawPages && Array.isArray(rawPages) && rawPages.length > 0) {
|
|
628
|
-
const baseUrl = gateConfigData.baseUrl || '';
|
|
632
|
+
const baseUrl = gateTarget.baseUrl || gateConfigData.baseUrl || '';
|
|
629
633
|
pages = rawPages.map((p) => {
|
|
630
634
|
if (typeof p === 'string') {
|
|
631
635
|
// Already a URL string - make it absolute if relative
|
|
632
636
|
return p.startsWith('http') ? p : `${baseUrl.replace(/\/$/, '')}${p}`;
|
|
633
637
|
}
|
|
634
638
|
else if (p && typeof p === 'object' && p.url) {
|
|
635
|
-
// Page object { url: '/', ... } - convert to full URL
|
|
639
|
+
// Page object { url: '/', actions: [...] } - convert to full URL and preserve actions
|
|
636
640
|
const url = p.url;
|
|
637
|
-
|
|
641
|
+
const absoluteUrl = url.startsWith('http') ? url : `${baseUrl.replace(/\/$/, '')}${url}`;
|
|
642
|
+
// Preserve the full page object if it has actions, otherwise return just the URL
|
|
643
|
+
return p.actions && p.actions.length > 0
|
|
644
|
+
? { url: absoluteUrl, actions: p.actions }
|
|
645
|
+
: absoluteUrl;
|
|
638
646
|
}
|
|
639
647
|
return p;
|
|
640
648
|
});
|
|
641
649
|
}
|
|
642
|
-
else if (gateConfigData.baseUrl) {
|
|
643
|
-
pages = [gateConfigData.baseUrl];
|
|
650
|
+
else if (gateTarget.baseUrl || gateConfigData.baseUrl) {
|
|
651
|
+
pages = [gateTarget.baseUrl || gateConfigData.baseUrl];
|
|
644
652
|
}
|
|
653
|
+
// Build target config - merge from both target and config sections
|
|
654
|
+
const targetConfig = {
|
|
655
|
+
baseUrl: gateTarget.baseUrl || gateConfigData.baseUrl,
|
|
656
|
+
pages: pages,
|
|
657
|
+
};
|
|
658
|
+
// Add uiTests if present in target
|
|
659
|
+
if (gateTarget.uiTests && Array.isArray(gateTarget.uiTests)) {
|
|
660
|
+
targetConfig.uiTests = gateTarget.uiTests;
|
|
661
|
+
}
|
|
662
|
+
// Add other target properties
|
|
663
|
+
if (gateTarget.headless !== undefined)
|
|
664
|
+
targetConfig.headless = gateTarget.headless;
|
|
665
|
+
if (gateConfigData.headless !== undefined)
|
|
666
|
+
targetConfig.headless = gateConfigData.headless;
|
|
645
667
|
const config = {
|
|
646
|
-
target:
|
|
647
|
-
baseUrl: gateConfigData.baseUrl,
|
|
648
|
-
pages: pages
|
|
649
|
-
},
|
|
668
|
+
target: targetConfig,
|
|
650
669
|
budgets: gateConfigData.budgets,
|
|
651
670
|
timeout: gateOptions.timeout || gateConfigData.timeout,
|
|
652
671
|
auth: credentials,
|
|
672
|
+
cliHeaded: this.headed,
|
|
653
673
|
// Playwright++ features
|
|
654
674
|
artifacts: gateConfigData.artifacts,
|
|
655
675
|
htmlReport: gateConfigData.htmlReport,
|
|
@@ -881,10 +901,21 @@ export class Phase3Runner {
|
|
|
881
901
|
* Run UI gate (includes basic accessibility)
|
|
882
902
|
*/
|
|
883
903
|
async runUiGate() {
|
|
884
|
-
|
|
904
|
+
let target = this.getTargetWeb();
|
|
885
905
|
if (!target) {
|
|
886
906
|
throw new Error('UI gate requires targets.web configuration or gate config with baseUrl');
|
|
887
907
|
}
|
|
908
|
+
// Transform relative pages to full URLs for v1 packs
|
|
909
|
+
if (target.pages && target.baseUrl && !this.isPackV2(this.pack)) {
|
|
910
|
+
const baseUrl = target.baseUrl.replace(/\/$/, '');
|
|
911
|
+
target.pages = target.pages.map((p) => {
|
|
912
|
+
const pageStr = typeof p === 'object' && p.url ? p.url : p;
|
|
913
|
+
if (typeof pageStr === 'string' && !pageStr.startsWith('http')) {
|
|
914
|
+
return `${baseUrl}${pageStr.startsWith('/') ? '' : '/'}${pageStr}`;
|
|
915
|
+
}
|
|
916
|
+
return p;
|
|
917
|
+
});
|
|
918
|
+
}
|
|
888
919
|
const credentials = await this.getCredentialsForGate('ui');
|
|
889
920
|
const adapter = new PlaywrightUiAdapter();
|
|
890
921
|
return await adapter.runSmokeTests({
|