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,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Test Sharding Module
|
|
3
|
+
*
|
|
4
|
+
* P0: Split test execution across multiple workers/machines
|
|
5
|
+
* - Consistent hashing for test distribution
|
|
6
|
+
* - Dynamic shard allocation
|
|
7
|
+
* - Load balancing across workers
|
|
8
|
+
* - CI-friendly shard configuration
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Shard configuration
|
|
12
|
+
*/
|
|
13
|
+
export interface ShardConfig {
|
|
14
|
+
/** Total number of shards */
|
|
15
|
+
totalShards: number;
|
|
16
|
+
/** Current shard index (1-based) */
|
|
17
|
+
shardIndex: number;
|
|
18
|
+
/** Optional shard seed for reproducibility */
|
|
19
|
+
seed?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Test metadata for sharding
|
|
23
|
+
*/
|
|
24
|
+
export interface TestMetadata {
|
|
25
|
+
/** Unique test identifier */
|
|
26
|
+
testId: string;
|
|
27
|
+
/** Test file path */
|
|
28
|
+
filePath: string;
|
|
29
|
+
/** Test name */
|
|
30
|
+
testName: string;
|
|
31
|
+
/** Optional test tags/categories */
|
|
32
|
+
tags?: string[];
|
|
33
|
+
/** Optional estimated duration (ms) */
|
|
34
|
+
duration?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Shard allocation result
|
|
38
|
+
*/
|
|
39
|
+
export interface ShardAllocation {
|
|
40
|
+
/** Assigned shard index (1-based) */
|
|
41
|
+
shardIndex: number;
|
|
42
|
+
/** Total number of shards */
|
|
43
|
+
totalShards: number;
|
|
44
|
+
/** Tests assigned to this shard */
|
|
45
|
+
tests: TestMetadata[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Test Sharding Manager
|
|
49
|
+
*/
|
|
50
|
+
export declare class TestSharding {
|
|
51
|
+
private config;
|
|
52
|
+
private seed;
|
|
53
|
+
constructor(config: ShardConfig);
|
|
54
|
+
/**
|
|
55
|
+
* Determine which shard a test belongs to
|
|
56
|
+
* Uses consistent hashing for reproducible distribution
|
|
57
|
+
*/
|
|
58
|
+
getShardForTest(test: TestMetadata): number;
|
|
59
|
+
/**
|
|
60
|
+
* Check if a test should run in current shard
|
|
61
|
+
*/
|
|
62
|
+
shouldRunTest(test: TestMetadata): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Filter tests to only those in current shard
|
|
65
|
+
*/
|
|
66
|
+
filterTests(tests: TestMetadata[]): TestMetadata[];
|
|
67
|
+
/**
|
|
68
|
+
* Allocate tests across all shards
|
|
69
|
+
* Returns distribution stats for all shards
|
|
70
|
+
*/
|
|
71
|
+
allocateTests(tests: TestMetadata[]): Map<number, TestMetadata[]>;
|
|
72
|
+
/**
|
|
73
|
+
* Get shard information for display/logging
|
|
74
|
+
*/
|
|
75
|
+
getShardInfo(): {
|
|
76
|
+
shardIndex: number;
|
|
77
|
+
totalShards: number;
|
|
78
|
+
shardId: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Hash test metadata to a consistent number
|
|
82
|
+
*/
|
|
83
|
+
private hashTest;
|
|
84
|
+
/**
|
|
85
|
+
* Create shard configuration from environment variables
|
|
86
|
+
* CI-friendly: reads SHARD_TOTAL and SHARD_INDEX
|
|
87
|
+
*/
|
|
88
|
+
static fromEnv(): ShardConfig | null;
|
|
89
|
+
/**
|
|
90
|
+
* Check if sharding is enabled via environment
|
|
91
|
+
*/
|
|
92
|
+
static isEnabled(): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Get environment variable with multiple possible names
|
|
95
|
+
*/
|
|
96
|
+
private static getEnvVar;
|
|
97
|
+
/**
|
|
98
|
+
* Parse shard config from string format "index/total"
|
|
99
|
+
* Example: "1/4" -> shardIndex: 1, totalShards: 4
|
|
100
|
+
*/
|
|
101
|
+
static parseShardString(shardStr: string): ShardConfig;
|
|
102
|
+
/**
|
|
103
|
+
* Get recommended shard count based on test count
|
|
104
|
+
*/
|
|
105
|
+
static getRecommendedShardCount(testCount: number, maxShards?: number): number;
|
|
106
|
+
/**
|
|
107
|
+
* Get optimal shard count based on CPU cores
|
|
108
|
+
*/
|
|
109
|
+
static getOptimalShardCount(): number;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create a test sharding manager
|
|
113
|
+
*/
|
|
114
|
+
export declare function createTestSharding(config: ShardConfig): TestSharding;
|
|
115
|
+
/**
|
|
116
|
+
* Create sharding from environment if enabled
|
|
117
|
+
*/
|
|
118
|
+
export declare function createShardingFromEnv(): TestSharding | null;
|
|
119
|
+
/**
|
|
120
|
+
* Vitest filter function for sharding
|
|
121
|
+
* Usage: vitest.config.ts -> test.exclude = [..., createShardingExclude()]
|
|
122
|
+
*/
|
|
123
|
+
export declare function createShardingExclude(): RegExp[] | ((file: string) => boolean);
|
|
124
|
+
/**
|
|
125
|
+
* Setup sharding for Vitest
|
|
126
|
+
* Returns a function that can be used to filter tests
|
|
127
|
+
*/
|
|
128
|
+
export declare function setupVitestSharding(): ((testId: string) => boolean) | null;
|
|
129
|
+
/**
|
|
130
|
+
* Get shard-specific suffix for output files
|
|
131
|
+
* Prevents overwriting artifacts between shards
|
|
132
|
+
*/
|
|
133
|
+
export declare function getShardSuffix(): string;
|
|
134
|
+
/**
|
|
135
|
+
* Create shard-specific report filename
|
|
136
|
+
*/
|
|
137
|
+
export declare function getShardedFilename(baseName: string): string;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Test Sharding Module
|
|
3
|
+
*
|
|
4
|
+
* P0: Split test execution across multiple workers/machines
|
|
5
|
+
* - Consistent hashing for test distribution
|
|
6
|
+
* - Dynamic shard allocation
|
|
7
|
+
* - Load balancing across workers
|
|
8
|
+
* - CI-friendly shard configuration
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from 'crypto';
|
|
11
|
+
/**
|
|
12
|
+
* Test Sharding Manager
|
|
13
|
+
*/
|
|
14
|
+
export class TestSharding {
|
|
15
|
+
config;
|
|
16
|
+
seed;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.config = config;
|
|
19
|
+
this.seed = config.seed || 'qa360-default-seed';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Determine which shard a test belongs to
|
|
23
|
+
* Uses consistent hashing for reproducible distribution
|
|
24
|
+
*/
|
|
25
|
+
getShardForTest(test) {
|
|
26
|
+
// Create a hash from test ID and seed
|
|
27
|
+
const hash = this.hashTest(test);
|
|
28
|
+
// Map hash to shard (1-based)
|
|
29
|
+
return (hash % this.config.totalShards) + 1;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if a test should run in current shard
|
|
33
|
+
*/
|
|
34
|
+
shouldRunTest(test) {
|
|
35
|
+
const shard = this.getShardForTest(test);
|
|
36
|
+
return shard === this.config.shardIndex;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Filter tests to only those in current shard
|
|
40
|
+
*/
|
|
41
|
+
filterTests(tests) {
|
|
42
|
+
return tests.filter(test => this.shouldRunTest(test));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Allocate tests across all shards
|
|
46
|
+
* Returns distribution stats for all shards
|
|
47
|
+
*/
|
|
48
|
+
allocateTests(tests) {
|
|
49
|
+
const allocation = new Map();
|
|
50
|
+
// Initialize all shards
|
|
51
|
+
for (let i = 1; i <= this.config.totalShards; i++) {
|
|
52
|
+
allocation.set(i, []);
|
|
53
|
+
}
|
|
54
|
+
// Distribute tests
|
|
55
|
+
for (const test of tests) {
|
|
56
|
+
const shard = this.getShardForTest(test);
|
|
57
|
+
allocation.get(shard).push(test);
|
|
58
|
+
}
|
|
59
|
+
return allocation;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get shard information for display/logging
|
|
63
|
+
*/
|
|
64
|
+
getShardInfo() {
|
|
65
|
+
return {
|
|
66
|
+
shardIndex: this.config.shardIndex,
|
|
67
|
+
totalShards: this.config.totalShards,
|
|
68
|
+
shardId: `${this.config.shardIndex}/${this.config.totalShards}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Hash test metadata to a consistent number
|
|
73
|
+
*/
|
|
74
|
+
hashTest(test) {
|
|
75
|
+
const input = `${this.seed}:${test.filePath}:${test.testName}`;
|
|
76
|
+
const hash = createHash('sha256').update(input).digest('hex');
|
|
77
|
+
// Convert first 8 chars to number
|
|
78
|
+
return parseInt(hash.substring(0, 8), 16);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create shard configuration from environment variables
|
|
82
|
+
* CI-friendly: reads SHARD_TOTAL and SHARD_INDEX
|
|
83
|
+
*/
|
|
84
|
+
static fromEnv() {
|
|
85
|
+
const totalShards = this.getEnvVar('SHARD_TOTAL');
|
|
86
|
+
const shardIndex = this.getEnvVar('SHARD_INDEX');
|
|
87
|
+
if (!totalShards || !shardIndex) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const total = parseInt(totalShards, 10);
|
|
91
|
+
const index = parseInt(shardIndex, 10);
|
|
92
|
+
if (isNaN(total) || isNaN(index) || index < 1 || index > total) {
|
|
93
|
+
throw new Error(`Invalid shard configuration: SHARD_TOTAL=${totalShards}, SHARD_INDEX=${shardIndex}`);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
totalShards: total,
|
|
97
|
+
shardIndex: index,
|
|
98
|
+
seed: this.getEnvVar('SHARD_SEED'),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Check if sharding is enabled via environment
|
|
103
|
+
*/
|
|
104
|
+
static isEnabled() {
|
|
105
|
+
return !!this.getEnvVar('SHARD_TOTAL');
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get environment variable with multiple possible names
|
|
109
|
+
*/
|
|
110
|
+
static getEnvVar(name) {
|
|
111
|
+
// Try common CI variable naming conventions
|
|
112
|
+
// e.g., SHARD_TOTAL, shard_total, shard-total
|
|
113
|
+
const vars = [
|
|
114
|
+
name, // SHARD_TOTAL
|
|
115
|
+
name.toLowerCase(), // shard_total
|
|
116
|
+
name.replace(/_/g, '-'), // SHARD-TOTAL
|
|
117
|
+
name.toLowerCase().replace(/_/g, '-'), // shard-total
|
|
118
|
+
];
|
|
119
|
+
for (const v of vars) {
|
|
120
|
+
if (process.env[v]) {
|
|
121
|
+
return process.env[v];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Parse shard config from string format "index/total"
|
|
128
|
+
* Example: "1/4" -> shardIndex: 1, totalShards: 4
|
|
129
|
+
*/
|
|
130
|
+
static parseShardString(shardStr) {
|
|
131
|
+
const match = shardStr.match(/^(\d+)\/(\d+)$/);
|
|
132
|
+
if (!match) {
|
|
133
|
+
throw new Error(`Invalid shard string format: "${shardStr}". Expected "index/total" (e.g., "1/4")`);
|
|
134
|
+
}
|
|
135
|
+
const shardIndex = parseInt(match[1], 10);
|
|
136
|
+
const totalShards = parseInt(match[2], 10);
|
|
137
|
+
if (shardIndex < 1 || shardIndex > totalShards) {
|
|
138
|
+
throw new Error(`Shard index must be between 1 and total: ${shardIndex}/${totalShards}`);
|
|
139
|
+
}
|
|
140
|
+
return { shardIndex, totalShards };
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get recommended shard count based on test count
|
|
144
|
+
*/
|
|
145
|
+
static getRecommendedShardCount(testCount, maxShards = 16) {
|
|
146
|
+
if (testCount < 10)
|
|
147
|
+
return 1;
|
|
148
|
+
if (testCount < 50)
|
|
149
|
+
return 2;
|
|
150
|
+
if (testCount < 100)
|
|
151
|
+
return 4;
|
|
152
|
+
if (testCount < 500)
|
|
153
|
+
return 8;
|
|
154
|
+
return Math.min(maxShards, Math.ceil(testCount / 100));
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get optimal shard count based on CPU cores
|
|
158
|
+
*/
|
|
159
|
+
static getOptimalShardCount() {
|
|
160
|
+
const cpuCount = require('os').cpus().length;
|
|
161
|
+
// Leave one core for main process
|
|
162
|
+
return Math.max(1, cpuCount - 1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Create a test sharding manager
|
|
167
|
+
*/
|
|
168
|
+
export function createTestSharding(config) {
|
|
169
|
+
return new TestSharding(config);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Create sharding from environment if enabled
|
|
173
|
+
*/
|
|
174
|
+
export function createShardingFromEnv() {
|
|
175
|
+
const config = TestSharding.fromEnv();
|
|
176
|
+
return config ? createTestSharding(config) : null;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Vitest filter function for sharding
|
|
180
|
+
* Usage: vitest.config.ts -> test.exclude = [..., createShardingExclude()]
|
|
181
|
+
*/
|
|
182
|
+
export function createShardingExclude() {
|
|
183
|
+
const sharding = createShardingFromEnv();
|
|
184
|
+
if (!sharding) {
|
|
185
|
+
return [];
|
|
186
|
+
}
|
|
187
|
+
// This doesn't work well with exclude, but we provide it for completeness
|
|
188
|
+
// Real filtering happens in the test suite
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Setup sharding for Vitest
|
|
193
|
+
* Returns a function that can be used to filter tests
|
|
194
|
+
*/
|
|
195
|
+
export function setupVitestSharding() {
|
|
196
|
+
const sharding = createShardingFromEnv();
|
|
197
|
+
if (!sharding) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
const info = sharding.getShardInfo();
|
|
201
|
+
console.log(`🔪 Sharding enabled: shard ${info.shardId}`);
|
|
202
|
+
return (testId) => {
|
|
203
|
+
// Parse test ID (format: "filePath > testName")
|
|
204
|
+
const [filePath, testName] = testId.split(' > ');
|
|
205
|
+
const test = {
|
|
206
|
+
testId,
|
|
207
|
+
filePath: filePath || testId,
|
|
208
|
+
testName: testName || '',
|
|
209
|
+
};
|
|
210
|
+
return sharding.shouldRunTest(test);
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get shard-specific suffix for output files
|
|
215
|
+
* Prevents overwriting artifacts between shards
|
|
216
|
+
*/
|
|
217
|
+
export function getShardSuffix() {
|
|
218
|
+
const sharding = createShardingFromEnv();
|
|
219
|
+
if (!sharding) {
|
|
220
|
+
return '';
|
|
221
|
+
}
|
|
222
|
+
const info = sharding.getShardInfo();
|
|
223
|
+
return `.shard-${info.shardIndex}`;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Create shard-specific report filename
|
|
227
|
+
*/
|
|
228
|
+
export function getShardedFilename(baseName) {
|
|
229
|
+
const suffix = getShardSuffix();
|
|
230
|
+
const ext = baseName.match(/\.[^.]+$/)?.[0] || '';
|
|
231
|
+
const nameWithoutExt = baseName.replace(ext, '');
|
|
232
|
+
return `${nameWithoutExt}${suffix}${ext}`;
|
|
233
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Cookie Manager Module
|
|
3
|
+
*
|
|
4
|
+
* P0: Cookie manipulation helpers
|
|
5
|
+
* - Get/set/delete cookies with type safety
|
|
6
|
+
* - Cookie filtering and searching
|
|
7
|
+
* - Domain/path scoping
|
|
8
|
+
* - Expiration handling
|
|
9
|
+
*/
|
|
10
|
+
import type { BrowserContext, Page } from '@playwright/test';
|
|
11
|
+
import type { Cookie } from '@playwright/test';
|
|
12
|
+
/**
|
|
13
|
+
* Cookie creation options
|
|
14
|
+
*/
|
|
15
|
+
export interface CookieSetOptions {
|
|
16
|
+
/** Cookie name */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Cookie value */
|
|
19
|
+
value: string;
|
|
20
|
+
/** Cookie domain (defaults to current page domain) */
|
|
21
|
+
domain?: string;
|
|
22
|
+
/** Cookie path (defaults to /) */
|
|
23
|
+
path?: string;
|
|
24
|
+
/** Expiration date (Unix timestamp) or maxAge in seconds */
|
|
25
|
+
expires?: number;
|
|
26
|
+
/** Max age in seconds (alternative to expires) */
|
|
27
|
+
maxAge?: number;
|
|
28
|
+
/** Whether cookie is HTTP-only */
|
|
29
|
+
httpOnly?: boolean;
|
|
30
|
+
/** Whether cookie is secure (HTTPS only) */
|
|
31
|
+
secure?: boolean;
|
|
32
|
+
/** SameSite attribute */
|
|
33
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
34
|
+
/** URL for setting cookie (used for domain inference) */
|
|
35
|
+
url?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Cookie filter options
|
|
39
|
+
*/
|
|
40
|
+
export interface CookieFilterOptions {
|
|
41
|
+
/** Filter by name (supports wildcards) */
|
|
42
|
+
name?: string;
|
|
43
|
+
/** Filter by domain */
|
|
44
|
+
domain?: string;
|
|
45
|
+
/** Filter by path */
|
|
46
|
+
path?: string;
|
|
47
|
+
/** Filter by secure flag */
|
|
48
|
+
secure?: boolean;
|
|
49
|
+
/** Filter by httpOnly flag */
|
|
50
|
+
httpOnly?: boolean;
|
|
51
|
+
/** Filter by sameSite attribute */
|
|
52
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Cookie Manager
|
|
56
|
+
*/
|
|
57
|
+
export declare class CookieManager {
|
|
58
|
+
private context;
|
|
59
|
+
constructor(context: BrowserContext);
|
|
60
|
+
/**
|
|
61
|
+
* Get all cookies
|
|
62
|
+
*/
|
|
63
|
+
all(): Promise<Cookie[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Get cookies matching filter criteria
|
|
66
|
+
*/
|
|
67
|
+
filter(options: CookieFilterOptions): Promise<Cookie[]>;
|
|
68
|
+
/**
|
|
69
|
+
* Get a specific cookie by name
|
|
70
|
+
*/
|
|
71
|
+
get(name: string): Promise<Cookie | undefined>;
|
|
72
|
+
/**
|
|
73
|
+
* Get a cookie value by name
|
|
74
|
+
*/
|
|
75
|
+
getValue(name: string): Promise<string | undefined>;
|
|
76
|
+
/**
|
|
77
|
+
* Check if a cookie exists
|
|
78
|
+
*/
|
|
79
|
+
has(name: string): Promise<boolean>;
|
|
80
|
+
/**
|
|
81
|
+
* Set a cookie
|
|
82
|
+
*/
|
|
83
|
+
set(options: CookieSetOptions): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Set multiple cookies at once
|
|
86
|
+
*/
|
|
87
|
+
setMany(cookies: CookieSetOptions[]): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Update an existing cookie
|
|
90
|
+
*/
|
|
91
|
+
update(name: string, updates: Partial<CookieSetOptions>): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Delete a cookie by name
|
|
94
|
+
*/
|
|
95
|
+
delete(name: string): Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* Delete multiple cookies by name
|
|
98
|
+
*/
|
|
99
|
+
deleteMany(names: string[]): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Delete cookies matching filter criteria
|
|
102
|
+
*/
|
|
103
|
+
deleteFilter(options: CookieFilterOptions): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Clear all cookies
|
|
106
|
+
*/
|
|
107
|
+
clear(): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Clear cookies for a specific domain
|
|
110
|
+
*/
|
|
111
|
+
clearDomain(domain: string): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Get cookies count
|
|
114
|
+
*/
|
|
115
|
+
count(): Promise<number>;
|
|
116
|
+
/**
|
|
117
|
+
* Export cookies as JSON string
|
|
118
|
+
*/
|
|
119
|
+
export(): Promise<string>;
|
|
120
|
+
/**
|
|
121
|
+
* Import cookies from JSON string or array
|
|
122
|
+
*/
|
|
123
|
+
import(data: string | Cookie[]): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Get cookies grouped by domain
|
|
126
|
+
*/
|
|
127
|
+
byDomain(): Promise<Record<string, Cookie[]>>;
|
|
128
|
+
/**
|
|
129
|
+
* Set a session cookie (no expiration)
|
|
130
|
+
*/
|
|
131
|
+
setSession(name: string, value: string, options?: Partial<CookieSetOptions>): Promise<void>;
|
|
132
|
+
/**
|
|
133
|
+
* Set a cookie with max-age (in seconds)
|
|
134
|
+
*/
|
|
135
|
+
setWithMaxAge(name: string, value: string, maxAge: number, options?: Partial<CookieSetOptions>): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Set a cookie that expires in days
|
|
138
|
+
*/
|
|
139
|
+
setExpiringIn(name: string, value: string, days: number, options?: Partial<CookieSetOptions>): Promise<void>;
|
|
140
|
+
/**
|
|
141
|
+
* Normalize cookie options to Playwright format
|
|
142
|
+
*/
|
|
143
|
+
private normalizeCookieOptions;
|
|
144
|
+
/**
|
|
145
|
+
* Check if cookie matches filter criteria
|
|
146
|
+
*/
|
|
147
|
+
private matchesFilter;
|
|
148
|
+
/**
|
|
149
|
+
* Simple wildcard matching
|
|
150
|
+
*/
|
|
151
|
+
private wildcardMatch;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Convenience function to create cookie manager
|
|
155
|
+
*/
|
|
156
|
+
export declare function cookies(context: BrowserContext): CookieManager;
|
|
157
|
+
/**
|
|
158
|
+
* Convenience function to create cookie manager from page
|
|
159
|
+
*/
|
|
160
|
+
export declare function cookiesFromPage(page: Page): CookieManager;
|