qa360 2.3.0 → 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.js +2 -2
- 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 -330
- 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 -105
- package/core/package.json +0 -90
- 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/crawl.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,417 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Smart Wait Module
|
|
3
|
+
*
|
|
4
|
+
* P0: Smart element waiting strategies
|
|
5
|
+
* - Wait for element visibility
|
|
6
|
+
* - Wait for element to be hidden/removed
|
|
7
|
+
* - Wait for element state changes
|
|
8
|
+
* - Wait for network idle
|
|
9
|
+
* - Wait for content stability
|
|
10
|
+
* - Polling with smart intervals
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Smart Wait Helper
|
|
14
|
+
*/
|
|
15
|
+
export class SmartWait {
|
|
16
|
+
page;
|
|
17
|
+
constructor(page) {
|
|
18
|
+
this.page = page;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Wait for element to be visible
|
|
22
|
+
*/
|
|
23
|
+
async visible(locator, options = {}) {
|
|
24
|
+
const { timeout = 30000 } = options;
|
|
25
|
+
try {
|
|
26
|
+
await locator.waitFor({ state: 'visible', timeout });
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
if (options.throwOnTimeout !== false) {
|
|
31
|
+
throw new Error(`Element not visible within ${timeout}ms`);
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Wait for element to be hidden
|
|
38
|
+
*/
|
|
39
|
+
async hidden(locator, options = {}) {
|
|
40
|
+
const { timeout = 30000 } = options;
|
|
41
|
+
try {
|
|
42
|
+
await locator.waitFor({ state: 'hidden', timeout });
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
if (options.throwOnTimeout !== false) {
|
|
47
|
+
throw new Error(`Element not hidden within ${timeout}ms`);
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Wait for element to be attached to DOM
|
|
54
|
+
*/
|
|
55
|
+
async attached(locator, options = {}) {
|
|
56
|
+
const { timeout = 30000 } = options;
|
|
57
|
+
try {
|
|
58
|
+
await locator.waitFor({ state: 'attached', timeout });
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
if (options.throwOnTimeout !== false) {
|
|
63
|
+
throw new Error(`Element not attached within ${timeout}ms`);
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Wait for element to be detached from DOM
|
|
70
|
+
*/
|
|
71
|
+
async detached(locator, options = {}) {
|
|
72
|
+
const { timeout = 30000 } = options;
|
|
73
|
+
try {
|
|
74
|
+
await locator.waitFor({ state: 'detached', timeout });
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
if (options.throwOnTimeout !== false) {
|
|
79
|
+
throw new Error(`Element not detached within ${timeout}ms`);
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Wait for element to reach a specific state
|
|
86
|
+
*/
|
|
87
|
+
async state(locator, state, options = {}) {
|
|
88
|
+
const { timeout = 30000 } = options;
|
|
89
|
+
try {
|
|
90
|
+
await locator.waitFor({ state, timeout });
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
if (options.throwOnTimeout !== false) {
|
|
95
|
+
throw new Error(`Element not ${state} within ${timeout}ms`);
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Wait for multiple elements to be visible
|
|
102
|
+
*/
|
|
103
|
+
async allVisible(locators, options = {}) {
|
|
104
|
+
const { timeout = 30000 } = options;
|
|
105
|
+
const startTime = Date.now();
|
|
106
|
+
const results = await Promise.allSettled(locators.map((locator) => locator.waitFor({ state: 'visible', timeout })));
|
|
107
|
+
return results.map((result, index) => {
|
|
108
|
+
if (result.status === 'fulfilled') {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (options.throwOnTimeout !== false) {
|
|
112
|
+
throw new Error(`Element ${index} not visible within ${timeout}ms`);
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Wait for at least one of multiple elements to be visible
|
|
119
|
+
*/
|
|
120
|
+
async anyVisible(locators, options = {}) {
|
|
121
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
122
|
+
const startTime = Date.now();
|
|
123
|
+
while (Date.now() - startTime < timeout) {
|
|
124
|
+
for (const locator of locators) {
|
|
125
|
+
if (await locator.isVisible().catch(() => false)) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
await this.sleep(interval);
|
|
130
|
+
}
|
|
131
|
+
if (options.throwOnTimeout !== false) {
|
|
132
|
+
throw new Error(`No element visible within ${timeout}ms`);
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Wait for element text content to match
|
|
138
|
+
*/
|
|
139
|
+
async text(locator, text, options = {}) {
|
|
140
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
141
|
+
const startTime = Date.now();
|
|
142
|
+
while (Date.now() - startTime < timeout) {
|
|
143
|
+
try {
|
|
144
|
+
const actualText = await locator.textContent({ timeout: interval });
|
|
145
|
+
if (actualText !== null) {
|
|
146
|
+
if (typeof text === 'string') {
|
|
147
|
+
if (actualText.trim() === text || actualText.includes(text)) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else if (text.test(actualText)) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// Element not yet available, continue waiting
|
|
158
|
+
}
|
|
159
|
+
await this.sleep(interval);
|
|
160
|
+
}
|
|
161
|
+
if (options.throwOnTimeout !== false) {
|
|
162
|
+
throw new Error(`Element text does not match "${text}" within ${timeout}ms`);
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Wait for element text content to change
|
|
168
|
+
*/
|
|
169
|
+
async textChange(locator, options = {}) {
|
|
170
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
171
|
+
const startTime = Date.now();
|
|
172
|
+
const initialText = await locator.textContent().catch(() => null);
|
|
173
|
+
while (Date.now() - startTime < timeout) {
|
|
174
|
+
const currentText = await locator.textContent().catch(() => null);
|
|
175
|
+
if (currentText !== initialText) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
await this.sleep(interval);
|
|
179
|
+
}
|
|
180
|
+
if (options.throwOnTimeout !== false) {
|
|
181
|
+
throw new Error(`Element text did not change within ${timeout}ms`);
|
|
182
|
+
}
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Wait for element attribute to have a value
|
|
187
|
+
*/
|
|
188
|
+
async attribute(locator, name, value, options = {}) {
|
|
189
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
190
|
+
const startTime = Date.now();
|
|
191
|
+
while (Date.now() - startTime < timeout) {
|
|
192
|
+
try {
|
|
193
|
+
const actualValue = await locator.getAttribute(name);
|
|
194
|
+
if (actualValue !== null) {
|
|
195
|
+
if (typeof value === 'string') {
|
|
196
|
+
if (actualValue === value || actualValue.includes(value)) {
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else if (value.test(actualValue)) {
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// Element not yet available, continue waiting
|
|
207
|
+
}
|
|
208
|
+
await this.sleep(interval);
|
|
209
|
+
}
|
|
210
|
+
if (options.throwOnTimeout !== false) {
|
|
211
|
+
throw new Error(`Element attribute "${name}" does not match "${value}" within ${timeout}ms`);
|
|
212
|
+
}
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Wait for element to have a specific CSS class
|
|
217
|
+
*/
|
|
218
|
+
async hasClass(locator, className, options = {}) {
|
|
219
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
220
|
+
const startTime = Date.now();
|
|
221
|
+
while (Date.now() - startTime < timeout) {
|
|
222
|
+
try {
|
|
223
|
+
const classes = await locator.getAttribute('class');
|
|
224
|
+
if (classes && classes.split(/\s+/).includes(className)) {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
// Element not yet available, continue waiting
|
|
230
|
+
}
|
|
231
|
+
await this.sleep(interval);
|
|
232
|
+
}
|
|
233
|
+
if (options.throwOnTimeout !== false) {
|
|
234
|
+
throw new Error(`Element does not have class "${className}" within ${timeout}ms`);
|
|
235
|
+
}
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Wait for element count to match expected
|
|
240
|
+
*/
|
|
241
|
+
async count(locator, expected, options = {}) {
|
|
242
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
243
|
+
const startTime = Date.now();
|
|
244
|
+
while (Date.now() - startTime < timeout) {
|
|
245
|
+
try {
|
|
246
|
+
const count = await locator.count();
|
|
247
|
+
if (count === expected) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
// Element not yet available, continue waiting
|
|
253
|
+
}
|
|
254
|
+
await this.sleep(interval);
|
|
255
|
+
}
|
|
256
|
+
if (options.throwOnTimeout !== false) {
|
|
257
|
+
throw new Error(`Element count is not ${expected} within ${timeout}ms`);
|
|
258
|
+
}
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Wait for content to stabilize (no changes for specified duration)
|
|
263
|
+
*/
|
|
264
|
+
async stable(locator, stableDuration = 500, options = {}) {
|
|
265
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
266
|
+
const startTime = Date.now();
|
|
267
|
+
const snapshots = [];
|
|
268
|
+
let checks = 0;
|
|
269
|
+
while (Date.now() - startTime < timeout) {
|
|
270
|
+
checks++;
|
|
271
|
+
try {
|
|
272
|
+
const snapshot = await locator.innerHTML();
|
|
273
|
+
snapshots.push(snapshot);
|
|
274
|
+
// Keep only last few snapshots for comparison
|
|
275
|
+
if (snapshots.length > stableDuration / interval + 1) {
|
|
276
|
+
snapshots.shift();
|
|
277
|
+
}
|
|
278
|
+
// Check if content has been stable
|
|
279
|
+
if (snapshots.length >= 2) {
|
|
280
|
+
const allSame = snapshots.every((s) => s === snapshots[0]);
|
|
281
|
+
if (allSame && (Date.now() - startTime >= stableDuration)) {
|
|
282
|
+
return {
|
|
283
|
+
stable: true,
|
|
284
|
+
checks,
|
|
285
|
+
elapsed: Date.now() - startTime,
|
|
286
|
+
stability: 100,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// Element not yet available
|
|
293
|
+
snapshots.push('');
|
|
294
|
+
}
|
|
295
|
+
await this.sleep(interval);
|
|
296
|
+
}
|
|
297
|
+
// Calculate stability percentage
|
|
298
|
+
const uniqueSnapshots = new Set(snapshots).size;
|
|
299
|
+
const stability = Math.max(0, 100 - (uniqueSnapshots / snapshots.length) * 100);
|
|
300
|
+
return {
|
|
301
|
+
stable: false,
|
|
302
|
+
checks,
|
|
303
|
+
elapsed: Date.now() - startTime,
|
|
304
|
+
stability,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Wait for network idle (no network requests for specified duration)
|
|
309
|
+
*/
|
|
310
|
+
async networkIdle(idleTime = 500, options = {}) {
|
|
311
|
+
const { timeout = 30000 } = options;
|
|
312
|
+
try {
|
|
313
|
+
await this.page.waitForLoadState('networkidle', { timeout: idleTime });
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
if (options.throwOnTimeout !== false) {
|
|
318
|
+
throw new Error(`Network not idle within ${timeout}ms`);
|
|
319
|
+
}
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Wait for URL to match
|
|
325
|
+
*/
|
|
326
|
+
async url(match, options = {}) {
|
|
327
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
328
|
+
const startTime = Date.now();
|
|
329
|
+
while (Date.now() - startTime < timeout) {
|
|
330
|
+
const url = this.page.url();
|
|
331
|
+
if (typeof match === 'string') {
|
|
332
|
+
if (url === match || url.includes(match)) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
else if (match instanceof RegExp) {
|
|
337
|
+
if (match.test(url)) {
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else if (match(new URL(url))) {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
await this.sleep(interval);
|
|
345
|
+
}
|
|
346
|
+
if (options.throwOnTimeout !== false) {
|
|
347
|
+
throw new Error(`URL does not match "${match}" within ${timeout}ms`);
|
|
348
|
+
}
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Wait for selector to exist in page
|
|
353
|
+
*/
|
|
354
|
+
async selector(selector, options = {}) {
|
|
355
|
+
return await this.attached(this.page.locator(selector), options);
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Wait for multiple conditions to be met
|
|
359
|
+
*/
|
|
360
|
+
async all(conditions, options = {}) {
|
|
361
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
362
|
+
const startTime = Date.now();
|
|
363
|
+
while (Date.now() - startTime < timeout) {
|
|
364
|
+
const results = await Promise.all(conditions.map((fn) => fn().catch(() => false)));
|
|
365
|
+
if (results.every((r) => r)) {
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
await this.sleep(interval);
|
|
369
|
+
}
|
|
370
|
+
if (options.throwOnTimeout !== false) {
|
|
371
|
+
throw new Error(`Not all conditions met within ${timeout}ms`);
|
|
372
|
+
}
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Wait for at least one condition to be met
|
|
377
|
+
*/
|
|
378
|
+
async any(conditions, options = {}) {
|
|
379
|
+
const { timeout = 30000, interval = 100 } = options;
|
|
380
|
+
const startTime = Date.now();
|
|
381
|
+
while (Date.now() - startTime < timeout) {
|
|
382
|
+
const results = await Promise.allSettled(conditions.map((fn) => fn()));
|
|
383
|
+
if (results.some((r) => r.status === 'fulfilled' && r.value === true)) {
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
await this.sleep(interval);
|
|
387
|
+
}
|
|
388
|
+
if (options.throwOnTimeout !== false) {
|
|
389
|
+
throw new Error(`No condition met within ${timeout}ms`);
|
|
390
|
+
}
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Sleep utility
|
|
395
|
+
*/
|
|
396
|
+
sleep(ms) {
|
|
397
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Convenience function to create smart wait helper
|
|
402
|
+
*/
|
|
403
|
+
export function smartWait(page) {
|
|
404
|
+
return new SmartWait(page);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Convenience functions for common waits
|
|
408
|
+
*/
|
|
409
|
+
export async function waitForVisible(locator, options) {
|
|
410
|
+
return await new SmartWait(locator.page() || locator._page).visible(locator, options);
|
|
411
|
+
}
|
|
412
|
+
export async function waitForHidden(locator, options) {
|
|
413
|
+
return await new SmartWait(locator.page() || locator._page).hidden(locator, options);
|
|
414
|
+
}
|
|
415
|
+
export async function waitForText(locator, text, options) {
|
|
416
|
+
return await new SmartWait(locator.page() || locator._page).text(locator, text, options);
|
|
417
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Visual Testing Module
|
|
3
|
+
*
|
|
4
|
+
* P0 Features: Visual regression testing with pixel diff
|
|
5
|
+
*/
|
|
6
|
+
export { PixelDiff, compareImages, compareImageBuffers, type PixelDiffResult, type PixelDiffOptions, } from './pixel-diff.js';
|
|
7
|
+
export { Screenshot, screenshot, type ScreenshotCaptureOptions, type ScreenshotCompareResult, type BaselineConfig, } from './screenshot-helper.js';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Visual Comparison Module
|
|
3
|
+
*
|
|
4
|
+
* P0 Features: Pixel diff for visual regression testing
|
|
5
|
+
* - Pixel-by-pixel comparison
|
|
6
|
+
* - Perceptual diff with anti-aliasing tolerance
|
|
7
|
+
* - Configurable thresholds
|
|
8
|
+
* - Diff image generation
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Pixel comparison result
|
|
12
|
+
*/
|
|
13
|
+
export interface PixelDiffResult {
|
|
14
|
+
/** Whether images are considered identical */
|
|
15
|
+
identical: boolean;
|
|
16
|
+
/** Number of differing pixels */
|
|
17
|
+
diffPixels: number;
|
|
18
|
+
/** Total pixels compared */
|
|
19
|
+
totalPixels: number;
|
|
20
|
+
/** Percentage of difference (0-100) */
|
|
21
|
+
diffPercentage: number;
|
|
22
|
+
/** Path to generated diff image */
|
|
23
|
+
diffImagePath?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Pixel comparison options
|
|
27
|
+
*/
|
|
28
|
+
export interface PixelDiffOptions {
|
|
29
|
+
/** Maximum allowed difference percentage (0-100) */
|
|
30
|
+
threshold?: number;
|
|
31
|
+
/** Pixel color difference threshold (0-255) */
|
|
32
|
+
pixelThreshold?: number;
|
|
33
|
+
/** Whether to generate a diff image */
|
|
34
|
+
generateDiffImage?: boolean;
|
|
35
|
+
/** Output directory for diff images */
|
|
36
|
+
outputDir?: string;
|
|
37
|
+
/** Antialiasing tolerance (ignore minor color differences) */
|
|
38
|
+
antialiasing?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Pixel Diff Comparator
|
|
42
|
+
*/
|
|
43
|
+
export declare class PixelDiff {
|
|
44
|
+
/**
|
|
45
|
+
* Compare two images pixel by pixel
|
|
46
|
+
*
|
|
47
|
+
* @param image1Path - Path to baseline image
|
|
48
|
+
* @param image2Path - Path to current image
|
|
49
|
+
* @param options - Comparison options
|
|
50
|
+
* @returns Comparison result
|
|
51
|
+
*/
|
|
52
|
+
static compare(image1Path: string, image2Path: string, options?: PixelDiffOptions): Promise<PixelDiffResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Compare two image buffers directly
|
|
55
|
+
*
|
|
56
|
+
* @param buffer1 - First image buffer (PNG)
|
|
57
|
+
* @param buffer2 - Second image buffer (PNG)
|
|
58
|
+
* @param options - Comparison options
|
|
59
|
+
* @returns Comparison result
|
|
60
|
+
*/
|
|
61
|
+
static compareBuffers(buffer1: Buffer, buffer2: Buffer, options?: PixelDiffOptions): Promise<PixelDiffResult>;
|
|
62
|
+
/**
|
|
63
|
+
* Calculate perceptual color difference
|
|
64
|
+
* Uses Euclidean distance in RGB space
|
|
65
|
+
*/
|
|
66
|
+
private static colorDifference;
|
|
67
|
+
/**
|
|
68
|
+
* Load image from file path
|
|
69
|
+
*/
|
|
70
|
+
private static loadImage;
|
|
71
|
+
/**
|
|
72
|
+
* Decode PNG buffer to image data
|
|
73
|
+
*/
|
|
74
|
+
private static decodeBuffer;
|
|
75
|
+
/**
|
|
76
|
+
* Save diff image to file
|
|
77
|
+
*/
|
|
78
|
+
private static saveDiffImage;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Convenience function to compare two images
|
|
82
|
+
*/
|
|
83
|
+
export declare function compareImages(image1Path: string, image2Path: string, options?: PixelDiffOptions): Promise<PixelDiffResult>;
|
|
84
|
+
/**
|
|
85
|
+
* Convenience function to compare two image buffers
|
|
86
|
+
*/
|
|
87
|
+
export declare function compareImageBuffers(buffer1: Buffer, buffer2: Buffer, options?: PixelDiffOptions): Promise<PixelDiffResult>;
|