qa360 2.3.0 → 2.3.2
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/ask.js +49 -22
- package/{cli/dist → dist}/commands/coverage.js +17 -4
- 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 +12 -5
- 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 +14 -6
- 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 +5 -1
- package/{cli/dist → dist}/commands/run.js +87 -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.d.ts +4 -0
- package/{cli/dist → dist}/core/ai/ollama-provider.js +41 -8
- 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}/index.js +2 -3
- package/{cli/dist → dist}/utils/config.d.ts +1 -1
- package/{cli/dist → dist}/utils/config.js +36 -3
- 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/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/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}/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
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* reCAPTCHA Handler
|
|
3
|
+
*
|
|
4
|
+
* Supports reCAPTCHA v2 (checkbox) and v3 (score-based, invisible)
|
|
5
|
+
*
|
|
6
|
+
* Test mode bypass uses Google's official test keys:
|
|
7
|
+
* - Site key: 6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-
|
|
8
|
+
* - Secret key: 6Le-wvkSAAAAAGGOV5XwRZ0nLfwPgJZsYNiWBvvC
|
|
9
|
+
*
|
|
10
|
+
* These always return a valid token with predictable score (v3) or success (v2)
|
|
11
|
+
*
|
|
12
|
+
* @see https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do
|
|
13
|
+
*/
|
|
14
|
+
export interface RecaptchaV2Config {
|
|
15
|
+
/** Site key for reCAPTCHA v2 */
|
|
16
|
+
siteKey?: string;
|
|
17
|
+
/** Use test mode (always returns valid token) */
|
|
18
|
+
testMode?: boolean;
|
|
19
|
+
/** CSS selector for the reCAPTCHA iframe */
|
|
20
|
+
selector?: string;
|
|
21
|
+
/** Timeout for solving (ms) */
|
|
22
|
+
timeout?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface RecaptchaV3Config {
|
|
25
|
+
/** Site key for reCAPTCHA v3 */
|
|
26
|
+
siteKey?: string;
|
|
27
|
+
/** Action name for the request */
|
|
28
|
+
action?: string;
|
|
29
|
+
/** Use test mode (always returns score 0.9) */
|
|
30
|
+
testMode?: boolean;
|
|
31
|
+
/** Minimum acceptable score (0.0 - 1.0) */
|
|
32
|
+
minScore?: number;
|
|
33
|
+
/** Timeout for solving (ms) */
|
|
34
|
+
timeout?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface RecaptchaTokenResponse {
|
|
37
|
+
success: boolean;
|
|
38
|
+
token: string;
|
|
39
|
+
score?: number;
|
|
40
|
+
action?: string;
|
|
41
|
+
challengeTs?: string;
|
|
42
|
+
hostname?: string;
|
|
43
|
+
errorCodes?: string[];
|
|
44
|
+
}
|
|
45
|
+
export declare const RECAPTCHA_V2_TEST_SITE_KEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-";
|
|
46
|
+
export declare const RECAPTCHA_V2_TEST_SECRET = "6Le-wvkSAAAAAGGOV5XwRZ0nLfwPgJZsYNiWBvvC";
|
|
47
|
+
export declare const RECAPTCHA_V3_TEST_SITE_KEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-";
|
|
48
|
+
export declare const RECAPTCHA_V3_TEST_SECRET = "6Le-wvkSAAAAAGGOV5XwRZ0nLfwPgJZsYNiWBvvC";
|
|
49
|
+
export declare class RecaptchaHandler {
|
|
50
|
+
private testMode;
|
|
51
|
+
private timeout;
|
|
52
|
+
constructor(options?: {
|
|
53
|
+
testMode?: boolean;
|
|
54
|
+
timeout?: number;
|
|
55
|
+
});
|
|
56
|
+
/**
|
|
57
|
+
* Detect if reCAPTCHA is present on the page
|
|
58
|
+
*/
|
|
59
|
+
detectRecaptcha(page: any): Promise<{
|
|
60
|
+
present: boolean;
|
|
61
|
+
version?: 'v2' | 'v3';
|
|
62
|
+
siteKey?: string;
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Solve reCAPTCHA v2 (checkbox)
|
|
66
|
+
*
|
|
67
|
+
* In test mode, injects a test token
|
|
68
|
+
* In production, waits for user interaction
|
|
69
|
+
*/
|
|
70
|
+
solveV2(page: any, config?: RecaptchaV2Config): Promise<RecaptchaTokenResponse>;
|
|
71
|
+
/**
|
|
72
|
+
* Solve reCAPTCHA v2 in test mode
|
|
73
|
+
*/
|
|
74
|
+
private solveV2TestMode;
|
|
75
|
+
/**
|
|
76
|
+
* Solve reCAPTCHA v2 in production mode (requires human interaction)
|
|
77
|
+
*/
|
|
78
|
+
private solveV2Production;
|
|
79
|
+
/**
|
|
80
|
+
* Execute reCAPTCHA v3 (invisible, score-based)
|
|
81
|
+
*/
|
|
82
|
+
executeV3(page: any, config?: RecaptchaV3Config): Promise<RecaptchaTokenResponse>;
|
|
83
|
+
/**
|
|
84
|
+
* Verify a reCAPTCHA token (server-side simulation)
|
|
85
|
+
*
|
|
86
|
+
* In real usage, this would call Google's siteverify API:
|
|
87
|
+
* POST https://www.google.com/recaptcha/api/siteverify
|
|
88
|
+
*/
|
|
89
|
+
verifyToken(token: string, secret?: string): Promise<RecaptchaTokenResponse>;
|
|
90
|
+
/**
|
|
91
|
+
* Wait for reCAPTCHA to be ready
|
|
92
|
+
*/
|
|
93
|
+
waitForReady(page: any, timeout?: number): Promise<boolean>;
|
|
94
|
+
/**
|
|
95
|
+
* Inject test site key into page
|
|
96
|
+
*/
|
|
97
|
+
injectTestSiteKey(page: any, elementSelector: string): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Generate a test token for mocking
|
|
100
|
+
*/
|
|
101
|
+
private generateTestToken;
|
|
102
|
+
private sleep;
|
|
103
|
+
/**
|
|
104
|
+
* Reset all reCAPTCHA widgets on the page
|
|
105
|
+
*/
|
|
106
|
+
reset(page: any): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Get the current response token from reCAPTCHA
|
|
109
|
+
*/
|
|
110
|
+
getResponse(page: any, widgetId?: string): Promise<string | null>;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Factory function to create a reCAPTCHA handler
|
|
114
|
+
*/
|
|
115
|
+
export declare function createRecaptchaHandler(options?: {
|
|
116
|
+
testMode?: boolean;
|
|
117
|
+
timeout?: number;
|
|
118
|
+
}): RecaptchaHandler;
|
|
119
|
+
export default RecaptchaHandler;
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* reCAPTCHA Handler
|
|
3
|
+
*
|
|
4
|
+
* Supports reCAPTCHA v2 (checkbox) and v3 (score-based, invisible)
|
|
5
|
+
*
|
|
6
|
+
* Test mode bypass uses Google's official test keys:
|
|
7
|
+
* - Site key: 6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-
|
|
8
|
+
* - Secret key: 6Le-wvkSAAAAAGGOV5XwRZ0nLfwPgJZsYNiWBvvC
|
|
9
|
+
*
|
|
10
|
+
* These always return a valid token with predictable score (v3) or success (v2)
|
|
11
|
+
*
|
|
12
|
+
* @see https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do
|
|
13
|
+
*/
|
|
14
|
+
// Test keys from Google (always return valid responses)
|
|
15
|
+
export const RECAPTCHA_V2_TEST_SITE_KEY = '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-';
|
|
16
|
+
export const RECAPTCHA_V2_TEST_SECRET = '6Le-wvkSAAAAAGGOV5XwRZ0nLfwPgJZsYNiWBvvC';
|
|
17
|
+
export const RECAPTCHA_V3_TEST_SITE_KEY = '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-';
|
|
18
|
+
export const RECAPTCHA_V3_TEST_SECRET = '6Le-wvkSAAAAAGGOV5XwRZ0nLfwPgJZsYNiWBvvC';
|
|
19
|
+
// Common reCAPTCHA iframe selectors
|
|
20
|
+
const RECAPTCHA_SELECTORS = [
|
|
21
|
+
'iframe[src*="recaptcha"]',
|
|
22
|
+
'iframe[src*="google.com/recaptcha"]',
|
|
23
|
+
'div.g-recaptcha',
|
|
24
|
+
'div[data-recaptcha]',
|
|
25
|
+
'div[data-sitekey]',
|
|
26
|
+
];
|
|
27
|
+
// DOM injection script for bypass
|
|
28
|
+
const BYPASS_SCRIPT = (siteKey, testMode) => `
|
|
29
|
+
(function() {
|
|
30
|
+
if (typeof window.grecaptcha !== 'undefined') {
|
|
31
|
+
// reCAPTCHA already loaded
|
|
32
|
+
window.__qa360_recaptcha_ready = true;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Mock grecaptcha object for test mode
|
|
37
|
+
if (${testMode}) {
|
|
38
|
+
window.grecaptcha = {
|
|
39
|
+
ready: function(cb) { cb(); },
|
|
40
|
+
execute: function(siteKey, options) {
|
|
41
|
+
return Promise.resolve('${RECAPTCHA_V2_TEST_SITE_KEY}');
|
|
42
|
+
},
|
|
43
|
+
render: function(container, options) {
|
|
44
|
+
return '${RECAPTCHA_V2_TEST_SITE_KEY}';
|
|
45
|
+
},
|
|
46
|
+
reset: function() {},
|
|
47
|
+
getResponse: function(widgetId) {
|
|
48
|
+
return 'TEST_TOKEN_SUCCESS';
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
window.__qa360_recaptcha_ready = true;
|
|
52
|
+
}
|
|
53
|
+
})();
|
|
54
|
+
`;
|
|
55
|
+
export class RecaptchaHandler {
|
|
56
|
+
testMode;
|
|
57
|
+
timeout;
|
|
58
|
+
constructor(options = {}) {
|
|
59
|
+
this.testMode = options.testMode ?? true;
|
|
60
|
+
this.timeout = options.timeout ?? 10000;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Detect if reCAPTCHA is present on the page
|
|
64
|
+
*/
|
|
65
|
+
async detectRecaptcha(page) {
|
|
66
|
+
const result = await page.evaluate(() => {
|
|
67
|
+
// Check for v2 checkbox
|
|
68
|
+
const v2Checkbox = document.querySelector('div.g-recaptcha');
|
|
69
|
+
const v2DataAttr = document.querySelector('[data-sitekey]');
|
|
70
|
+
const v2Iframe = document.querySelector('iframe[src*="recaptcha/api2"]');
|
|
71
|
+
// Check for v3
|
|
72
|
+
const v3Script = Array.from(document.scripts).some(s => s.src.includes('recaptcha/api3') || s.src.includes('recaptcha/v3'));
|
|
73
|
+
const hasGrecaptchaV3 = window.grecaptcha?.execute;
|
|
74
|
+
let version;
|
|
75
|
+
if (v2Checkbox || v2DataAttr || v2Iframe) {
|
|
76
|
+
version = 'v2';
|
|
77
|
+
}
|
|
78
|
+
else if (v3Script || hasGrecaptchaV3) {
|
|
79
|
+
version = 'v3';
|
|
80
|
+
}
|
|
81
|
+
// Try to extract site key
|
|
82
|
+
let siteKey;
|
|
83
|
+
const siteKeyEl = document.querySelector('[data-sitekey]');
|
|
84
|
+
if (siteKeyEl) {
|
|
85
|
+
siteKey = siteKeyEl.getAttribute('data-sitekey') || undefined;
|
|
86
|
+
}
|
|
87
|
+
return { version, siteKey };
|
|
88
|
+
});
|
|
89
|
+
return {
|
|
90
|
+
present: !!result.version,
|
|
91
|
+
version: result.version,
|
|
92
|
+
siteKey: result.siteKey,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Solve reCAPTCHA v2 (checkbox)
|
|
97
|
+
*
|
|
98
|
+
* In test mode, injects a test token
|
|
99
|
+
* In production, waits for user interaction
|
|
100
|
+
*/
|
|
101
|
+
async solveV2(page, config = {}) {
|
|
102
|
+
const { testMode = this.testMode, selector } = config;
|
|
103
|
+
const detection = await this.detectRecaptcha(page);
|
|
104
|
+
if (!detection.present || detection.version !== 'v2') {
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
token: '',
|
|
108
|
+
errorCodes: ['NO_RECAPTCHA_V2_FOUND'],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (testMode) {
|
|
112
|
+
return await this.solveV2TestMode(page, config);
|
|
113
|
+
}
|
|
114
|
+
// Production mode: Wait for user to solve
|
|
115
|
+
return await this.solveV2Production(page, selector);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Solve reCAPTCHA v2 in test mode
|
|
119
|
+
*/
|
|
120
|
+
async solveV2TestMode(page, config) {
|
|
121
|
+
const siteKey = config.siteKey || RECAPTCHA_V2_TEST_SITE_KEY;
|
|
122
|
+
// Inject bypass script
|
|
123
|
+
await page.evaluate(BYPASS_SCRIPT(siteKey, true));
|
|
124
|
+
// Set callback token
|
|
125
|
+
await page.evaluate((testToken) => {
|
|
126
|
+
const callbackName = '___grecaptcha_cfg';
|
|
127
|
+
if (window[callbackName]?.fns) {
|
|
128
|
+
window[callbackName].fns.forEach((cb) => cb(testToken));
|
|
129
|
+
}
|
|
130
|
+
}, this.generateTestToken('v2'));
|
|
131
|
+
return {
|
|
132
|
+
success: true,
|
|
133
|
+
token: this.generateTestToken('v2'),
|
|
134
|
+
challengeTs: new Date().toISOString(),
|
|
135
|
+
hostname: 'test.google.com',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Solve reCAPTCHA v2 in production mode (requires human interaction)
|
|
140
|
+
*/
|
|
141
|
+
async solveV2Production(page, selector) {
|
|
142
|
+
// Wait for the checkbox to be clicked by user
|
|
143
|
+
const startTime = Date.now();
|
|
144
|
+
while (Date.now() - startTime < this.timeout) {
|
|
145
|
+
const result = await page.evaluate(() => {
|
|
146
|
+
if (typeof window.grecaptcha === 'undefined') {
|
|
147
|
+
return { ready: false, token: null };
|
|
148
|
+
}
|
|
149
|
+
const response = window.grecaptcha.getResponse();
|
|
150
|
+
if (response) {
|
|
151
|
+
return { ready: true, token: response };
|
|
152
|
+
}
|
|
153
|
+
return { ready: false, token: null };
|
|
154
|
+
});
|
|
155
|
+
if (result.ready && result.token) {
|
|
156
|
+
return {
|
|
157
|
+
success: true,
|
|
158
|
+
token: result.token,
|
|
159
|
+
challengeTs: new Date().toISOString(),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
await this.sleep(500);
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
token: '',
|
|
167
|
+
errorCodes: ['TIMEOUT'],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Execute reCAPTCHA v3 (invisible, score-based)
|
|
172
|
+
*/
|
|
173
|
+
async executeV3(page, config = {}) {
|
|
174
|
+
const { testMode = this.testMode, action = 'verify', minScore = 0.5 } = config;
|
|
175
|
+
if (testMode) {
|
|
176
|
+
return {
|
|
177
|
+
success: true,
|
|
178
|
+
token: this.generateTestToken('v3'),
|
|
179
|
+
score: 0.9, // Test mode always returns high score
|
|
180
|
+
action,
|
|
181
|
+
challengeTs: new Date().toISOString(),
|
|
182
|
+
hostname: 'test.google.com',
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// Production mode: Call grecaptcha.execute
|
|
186
|
+
const result = await page.evaluate((act) => {
|
|
187
|
+
if (typeof window.grecaptcha === 'undefined') {
|
|
188
|
+
return { success: false, token: null, error: 'GRECAPTCHA_NOT_LOADED' };
|
|
189
|
+
}
|
|
190
|
+
return window.grecaptcha.execute(act).then((token) => ({
|
|
191
|
+
success: true,
|
|
192
|
+
token,
|
|
193
|
+
})).catch((err) => ({
|
|
194
|
+
success: false,
|
|
195
|
+
token: null,
|
|
196
|
+
error: err.message,
|
|
197
|
+
}));
|
|
198
|
+
}, action);
|
|
199
|
+
if (!result.success) {
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
token: '',
|
|
203
|
+
errorCodes: [result.error || 'EXECUTION_FAILED'],
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// In production, we can't verify the score without server-side validation
|
|
207
|
+
// The token would need to be sent to the backend for verification
|
|
208
|
+
return {
|
|
209
|
+
success: true,
|
|
210
|
+
token: result.token,
|
|
211
|
+
action,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Verify a reCAPTCHA token (server-side simulation)
|
|
216
|
+
*
|
|
217
|
+
* In real usage, this would call Google's siteverify API:
|
|
218
|
+
* POST https://www.google.com/recaptcha/api/siteverify
|
|
219
|
+
*/
|
|
220
|
+
async verifyToken(token, secret) {
|
|
221
|
+
if (this.testMode) {
|
|
222
|
+
// In test mode, always return success
|
|
223
|
+
return {
|
|
224
|
+
success: true,
|
|
225
|
+
token,
|
|
226
|
+
score: 0.9,
|
|
227
|
+
challengeTs: new Date().toISOString(),
|
|
228
|
+
hostname: 'test.google.com',
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
// Production: Would call siteverify endpoint
|
|
232
|
+
// For now, return a mock response
|
|
233
|
+
return {
|
|
234
|
+
success: false,
|
|
235
|
+
token,
|
|
236
|
+
errorCodes: ['SITEVERIFY_NOT_IMPLEMENTED'],
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Wait for reCAPTCHA to be ready
|
|
241
|
+
*/
|
|
242
|
+
async waitForReady(page, timeout = 10000) {
|
|
243
|
+
const startTime = Date.now();
|
|
244
|
+
while (Date.now() - startTime < timeout) {
|
|
245
|
+
const ready = await page.evaluate(() => typeof window.grecaptcha !== 'undefined');
|
|
246
|
+
if (ready)
|
|
247
|
+
return true;
|
|
248
|
+
await this.sleep(100);
|
|
249
|
+
}
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Inject test site key into page
|
|
254
|
+
*/
|
|
255
|
+
async injectTestSiteKey(page, elementSelector) {
|
|
256
|
+
await page.evaluate((sel, testKey) => {
|
|
257
|
+
const el = document.querySelector(sel);
|
|
258
|
+
if (el) {
|
|
259
|
+
el.setAttribute('data-sitekey', testKey);
|
|
260
|
+
}
|
|
261
|
+
}, elementSelector, RECAPTCHA_V2_TEST_SITE_KEY);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Generate a test token for mocking
|
|
265
|
+
*/
|
|
266
|
+
generateTestToken(version) {
|
|
267
|
+
const timestamp = Date.now();
|
|
268
|
+
return `TEST_${version}_TOKEN_${timestamp}`;
|
|
269
|
+
}
|
|
270
|
+
sleep(ms) {
|
|
271
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Reset all reCAPTCHA widgets on the page
|
|
275
|
+
*/
|
|
276
|
+
async reset(page) {
|
|
277
|
+
await page.evaluate(() => {
|
|
278
|
+
if (typeof window.grecaptcha !== 'undefined') {
|
|
279
|
+
window.grecaptcha.reset();
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get the current response token from reCAPTCHA
|
|
285
|
+
*/
|
|
286
|
+
async getResponse(page, widgetId) {
|
|
287
|
+
return await page.evaluate((id) => {
|
|
288
|
+
if (typeof window.grecaptcha === 'undefined') {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
return window.grecaptcha.getResponse(id);
|
|
292
|
+
}, widgetId);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Factory function to create a reCAPTCHA handler
|
|
297
|
+
*/
|
|
298
|
+
export function createRecaptchaHandler(options) {
|
|
299
|
+
return new RecaptchaHandler(options);
|
|
300
|
+
}
|
|
301
|
+
export default RecaptchaHandler;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remember Me Handler
|
|
3
|
+
*
|
|
4
|
+
* P1 - Persistent session management
|
|
5
|
+
*
|
|
6
|
+
* Supports:
|
|
7
|
+
* - Generating secure remember me tokens
|
|
8
|
+
* - Validating persistent tokens
|
|
9
|
+
* - Token rotation for security
|
|
10
|
+
* - Configurable token expiration
|
|
11
|
+
*
|
|
12
|
+
* @see https://cheatsheetseries.owasp.org/cheatsheets/Remember_Me_Cheat_Sheet.html
|
|
13
|
+
*/
|
|
14
|
+
export interface RememberMeConfig {
|
|
15
|
+
/** Token expiration time in days (default: 30) */
|
|
16
|
+
expiresInDays?: number;
|
|
17
|
+
/** Token length in bytes (default: 32) */
|
|
18
|
+
tokenLength?: number;
|
|
19
|
+
/** Secret key for signing tokens */
|
|
20
|
+
secret: string;
|
|
21
|
+
/** Cookie name */
|
|
22
|
+
cookieName?: string;
|
|
23
|
+
/** Cookie path */
|
|
24
|
+
cookiePath?: string;
|
|
25
|
+
/** Cookie domain */
|
|
26
|
+
cookieDomain?: string;
|
|
27
|
+
/** Secure flag for cookies */
|
|
28
|
+
secure?: boolean;
|
|
29
|
+
/** HttpOnly flag for cookies */
|
|
30
|
+
httpOnly?: boolean;
|
|
31
|
+
/** SameSite attribute */
|
|
32
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
33
|
+
}
|
|
34
|
+
export interface RememberMeToken {
|
|
35
|
+
/** Token value (selector) */
|
|
36
|
+
selector: string;
|
|
37
|
+
/** Validator (hashed token) */
|
|
38
|
+
validator: string;
|
|
39
|
+
/** User ID associated with token */
|
|
40
|
+
userId: string;
|
|
41
|
+
/** Token expiration timestamp */
|
|
42
|
+
expiresAt: Date;
|
|
43
|
+
}
|
|
44
|
+
export interface RememberMeResult {
|
|
45
|
+
success: boolean;
|
|
46
|
+
token?: RememberMeToken;
|
|
47
|
+
userId?: string;
|
|
48
|
+
error?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Remember Me Handler class
|
|
52
|
+
*/
|
|
53
|
+
export declare class RememberMeHandler {
|
|
54
|
+
private config;
|
|
55
|
+
private tokens;
|
|
56
|
+
/** Store raw validators for testing purposes (in production, only send to client via cookie) */
|
|
57
|
+
private rawValidators;
|
|
58
|
+
constructor(config: RememberMeConfig);
|
|
59
|
+
/**
|
|
60
|
+
* Generate a new remember me token
|
|
61
|
+
* Creates a secure random token pair (selector + validator)
|
|
62
|
+
*/
|
|
63
|
+
generateToken(userId: string): RememberMeToken;
|
|
64
|
+
/**
|
|
65
|
+
* Validate a remember me token
|
|
66
|
+
* Checks selector and validator against stored tokens
|
|
67
|
+
*/
|
|
68
|
+
validateToken(selector: string, rawValidator: string): RememberMeResult;
|
|
69
|
+
/**
|
|
70
|
+
* Rotate a remember me token
|
|
71
|
+
* Generates a new token while invalidating the old one
|
|
72
|
+
*/
|
|
73
|
+
rotateToken(selector: string, rawValidator: string): RememberMeResult;
|
|
74
|
+
/**
|
|
75
|
+
* Revoke (invalidate) a remember me token
|
|
76
|
+
*/
|
|
77
|
+
revokeToken(selector: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Revoke all tokens for a user
|
|
80
|
+
*/
|
|
81
|
+
revokeAllUserTokens(userId: string): number;
|
|
82
|
+
/**
|
|
83
|
+
* Clean up expired tokens
|
|
84
|
+
*/
|
|
85
|
+
cleanupExpiredTokens(): number;
|
|
86
|
+
/**
|
|
87
|
+
* Get cookie configuration for setting remember me cookie
|
|
88
|
+
*/
|
|
89
|
+
getCookieConfig(token: RememberMeToken): {
|
|
90
|
+
name: string;
|
|
91
|
+
value: string;
|
|
92
|
+
options: {
|
|
93
|
+
expires: Date;
|
|
94
|
+
path: string;
|
|
95
|
+
domain?: string;
|
|
96
|
+
secure: boolean;
|
|
97
|
+
httpOnly: boolean;
|
|
98
|
+
sameSite: 'Strict' | 'Lax' | 'None';
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Parse cookie value to extract selector and validator
|
|
103
|
+
*/
|
|
104
|
+
parseCookieValue(cookieValue: string): {
|
|
105
|
+
selector: string;
|
|
106
|
+
validator: string;
|
|
107
|
+
} | null;
|
|
108
|
+
/**
|
|
109
|
+
* Check if a token is expired
|
|
110
|
+
*/
|
|
111
|
+
isTokenExpired(token: RememberMeToken): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Get token by selector
|
|
114
|
+
*/
|
|
115
|
+
getToken(selector: string): RememberMeToken | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Get all tokens
|
|
118
|
+
*/
|
|
119
|
+
getAllTokens(): RememberMeToken[];
|
|
120
|
+
/**
|
|
121
|
+
* Clear all tokens
|
|
122
|
+
*/
|
|
123
|
+
clearAllTokens(): void;
|
|
124
|
+
/**
|
|
125
|
+
* Set custom secret (for testing)
|
|
126
|
+
*/
|
|
127
|
+
setSecret(secret: string): void;
|
|
128
|
+
/**
|
|
129
|
+
* Get raw validator for a selector (testing only)
|
|
130
|
+
* In production, the raw validator is only sent to the client via cookie
|
|
131
|
+
*/
|
|
132
|
+
getRawValidator(selector: string): string | undefined;
|
|
133
|
+
/**
|
|
134
|
+
* Get number of active tokens
|
|
135
|
+
*/
|
|
136
|
+
get tokenCount(): number;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Factory function to create Remember Me handler
|
|
140
|
+
*/
|
|
141
|
+
export declare function createRememberMeHandler(config: RememberMeConfig): RememberMeHandler;
|
|
142
|
+
export default RememberMeHandler;
|