qa360 2.2.20 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -262
- package/{cli/dist → dist}/commands/ai.js +1 -1
- package/{cli/dist → dist}/commands/coverage.js +1 -1
- package/{cli/dist → dist}/commands/crawl.d.ts +12 -1
- package/{cli/dist → dist}/commands/crawl.js +70 -9
- package/{cli/dist → dist}/commands/doctor.js +2 -2
- package/{cli/dist → dist}/commands/explain.js +2 -2
- package/{cli/dist → dist}/commands/flakiness.js +1 -1
- package/{cli/dist → dist}/commands/generate.js +1 -1
- package/{cli/dist → dist}/commands/history.js +1 -1
- package/{cli/dist → dist}/commands/monitor.js +3 -3
- package/{cli/dist → dist}/commands/ollama.js +1 -1
- package/{cli/dist → dist}/commands/pack.js +2 -2
- package/{cli/dist → dist}/commands/regression.js +1 -1
- package/{cli/dist → dist}/commands/repair.js +1 -1
- package/{cli/dist → dist}/commands/retry.js +1 -1
- package/{cli/dist → dist}/commands/run.d.ts +1 -1
- package/{cli/dist → dist}/commands/run.js +1 -1
- package/{cli/dist → dist}/commands/secrets.js +1 -1
- package/{cli/dist → dist}/commands/serve.js +1 -1
- package/{cli/dist → dist}/commands/slo.js +1 -1
- package/{cli/dist → dist}/commands/verify.js +1 -1
- package/{cli/dist → dist}/core/adapters/playwright-native-api.d.ts +2 -0
- package/{cli/dist → dist}/core/adapters/playwright-native-api.js +20 -1
- package/{cli/dist → dist}/core/adapters/playwright-ui.d.ts +21 -0
- package/dist/core/adapters/playwright-ui.js +2050 -0
- package/{cli/dist → dist}/core/ai/ollama-provider.js +15 -3
- package/{cli/dist → dist}/core/artifacts/ui-artifacts.js +24 -4
- package/dist/core/auth/backup-codes-provider.d.ts +91 -0
- package/dist/core/auth/backup-codes-provider.js +215 -0
- package/{cli/dist → dist}/core/auth/basic-auth-provider.d.ts +6 -0
- package/{cli/dist → dist}/core/auth/basic-auth-provider.js +24 -6
- package/dist/core/auth/digest-auth-provider.d.ts +116 -0
- package/dist/core/auth/digest-auth-provider.js +244 -0
- package/dist/core/auth/hcaptcha-handler.d.ts +103 -0
- package/dist/core/auth/hcaptcha-handler.js +288 -0
- package/{cli/dist → dist}/core/auth/index.d.ts +81 -4
- package/{cli/dist → dist}/core/auth/index.js +15 -1
- package/dist/core/auth/oauth-handler.d.ts +408 -0
- package/dist/core/auth/oauth-handler.js +636 -0
- package/{cli/dist → dist}/core/auth/oauth2-provider.d.ts +9 -0
- package/dist/core/auth/oauth2-provider.js +227 -0
- package/dist/core/auth/otp-provider.d.ts +93 -0
- package/dist/core/auth/otp-provider.js +288 -0
- package/dist/core/auth/recaptcha-handler.d.ts +119 -0
- package/dist/core/auth/recaptcha-handler.js +301 -0
- package/dist/core/auth/remember-me-handler.d.ts +142 -0
- package/dist/core/auth/remember-me-handler.js +255 -0
- package/dist/core/auth/saml-handler.d.ts +173 -0
- package/dist/core/auth/saml-handler.js +364 -0
- package/dist/core/auth/webauthn-handler.d.ts +182 -0
- package/dist/core/auth/webauthn-handler.js +310 -0
- package/dist/core/crawler/advanced-interactions.d.ts +342 -0
- package/dist/core/crawler/advanced-interactions.js +1069 -0
- package/dist/core/crawler/blob-url-download-handler.d.ts +145 -0
- package/dist/core/crawler/blob-url-download-handler.js +392 -0
- package/dist/core/crawler/consent-handler.d.ts +49 -0
- package/dist/core/crawler/consent-handler.js +258 -0
- package/dist/core/crawler/cookie-manager.d.ts +166 -0
- package/dist/core/crawler/cookie-manager.js +353 -0
- package/dist/core/crawler/coop-coep-handler.d.ts +136 -0
- package/dist/core/crawler/coop-coep-handler.js +338 -0
- package/dist/core/crawler/csp-handler.d.ts +151 -0
- package/dist/core/crawler/csp-handler.js +415 -0
- package/dist/core/crawler/download-handler.d.ts +155 -0
- package/dist/core/crawler/download-handler.js +370 -0
- package/dist/core/crawler/email-testing-handler.d.ts +214 -0
- package/dist/core/crawler/email-testing-handler.js +398 -0
- package/dist/core/crawler/error-tracking-handler.d.ts +177 -0
- package/dist/core/crawler/error-tracking-handler.js +378 -0
- package/dist/core/crawler/form-handler.d.ts +100 -0
- package/dist/core/crawler/form-handler.js +465 -0
- package/dist/core/crawler/framework-wait-handler.d.ts +96 -0
- package/dist/core/crawler/framework-wait-handler.js +464 -0
- package/dist/core/crawler/geolocation-handler.d.ts +112 -0
- package/dist/core/crawler/geolocation-handler.js +276 -0
- package/dist/core/crawler/index.d.ts +78 -0
- package/{cli/dist → dist}/core/crawler/index.js +74 -1
- package/dist/core/crawler/intelligent-selector-generator.d.ts +164 -0
- package/dist/core/crawler/intelligent-selector-generator.js +612 -0
- package/{cli/dist → dist}/core/crawler/journey-generator.js +44 -1
- package/{cli/dist → dist}/core/crawler/page-analyzer.d.ts +16 -1
- package/{cli/dist → dist}/core/crawler/page-analyzer.js +469 -17
- package/dist/core/crawler/permissions-handler.d.ts +112 -0
- package/dist/core/crawler/permissions-handler.js +236 -0
- package/dist/core/crawler/permissions-policy-handler.d.ts +113 -0
- package/dist/core/crawler/permissions-policy-handler.js +402 -0
- package/dist/core/crawler/presets.d.ts +100 -0
- package/dist/core/crawler/presets.js +887 -0
- package/dist/core/crawler/repl-debug-handler.d.ts +105 -0
- package/dist/core/crawler/repl-debug-handler.js +552 -0
- package/dist/core/crawler/reporting-api-handler.d.ts +212 -0
- package/dist/core/crawler/reporting-api-handler.js +344 -0
- package/{cli/dist → dist}/core/crawler/selector-generator.d.ts +9 -0
- package/{cli/dist → dist}/core/crawler/selector-generator.js +99 -23
- package/dist/core/crawler/site-profiler.d.ts +89 -0
- package/dist/core/crawler/site-profiler.js +290 -0
- package/dist/core/crawler/sourcemaps-handler.d.ts +144 -0
- package/dist/core/crawler/sourcemaps-handler.js +420 -0
- package/dist/core/crawler/stacked-modals-handler.d.ts +118 -0
- package/dist/core/crawler/stacked-modals-handler.js +429 -0
- package/dist/core/crawler/trusted-types-handler.d.ts +149 -0
- package/dist/core/crawler/trusted-types-handler.js +413 -0
- package/{cli/dist → dist}/core/crawler/types.d.ts +68 -2
- package/dist/core/crawler/wait-strategies.d.ts +108 -0
- package/dist/core/crawler/wait-strategies.js +399 -0
- package/dist/core/fixtures/factories.d.ts +180 -0
- package/dist/core/fixtures/factories.js +279 -0
- package/dist/core/fixtures/index.d.ts +6 -0
- package/dist/core/fixtures/index.js +6 -0
- package/{cli/dist → dist}/core/generation/crawler-pack-generator.d.ts +13 -3
- package/dist/core/generation/crawler-pack-generator.js +232 -0
- package/{cli/dist → dist}/core/generation/index.d.ts +2 -0
- package/{cli/dist → dist}/core/generation/index.js +2 -0
- package/{cli/dist → dist}/core/index.d.ts +2 -0
- package/{cli/dist → dist}/core/index.js +4 -0
- package/dist/core/network/index.d.ts +7 -0
- package/dist/core/network/index.js +7 -0
- package/dist/core/network/network-manager.d.ts +237 -0
- package/dist/core/network/network-manager.js +343 -0
- package/dist/core/network/network-simulator.d.ts +158 -0
- package/dist/core/network/network-simulator.js +261 -0
- package/{cli/dist → dist}/core/pack/validator.js +2 -2
- package/{cli/dist → dist}/core/pack-v2/migrator.d.ts +5 -0
- package/{cli/dist → dist}/core/pack-v2/migrator.js +81 -6
- package/{cli/dist → dist}/core/pack-v2/validator.js +4 -3
- package/{cli/dist → dist}/core/pom/base-page.js +1 -1
- package/{cli/dist → dist}/core/pom/loader.js +1 -1
- package/dist/core/reporting/index.d.ts +9 -0
- package/dist/core/reporting/index.js +10 -0
- package/dist/core/reporting/junit-reporter.d.ts +114 -0
- package/dist/core/reporting/junit-reporter.js +306 -0
- package/{cli/dist → dist}/core/runner/e2e-helpers.d.ts +1 -1
- package/{cli/dist → dist}/core/runner/e2e-helpers.js +2 -2
- package/{cli/dist → dist}/core/runner/phase3-runner.d.ts +3 -0
- package/{cli/dist → dist}/core/runner/phase3-runner.js +45 -14
- package/dist/core/sharding/test-sharding.d.ts +137 -0
- package/dist/core/sharding/test-sharding.js +233 -0
- package/dist/core/storage/cookie-manager.d.ts +160 -0
- package/dist/core/storage/cookie-manager.js +268 -0
- package/dist/core/storage/index.d.ts +7 -0
- package/dist/core/storage/index.js +7 -0
- package/dist/core/storage/storage-helpers.d.ts +138 -0
- package/dist/core/storage/storage-helpers.js +315 -0
- package/dist/core/test-helpers/index.d.ts +6 -0
- package/dist/core/test-helpers/index.js +6 -0
- package/dist/core/test-helpers/state-reset.d.ts +119 -0
- package/dist/core/test-helpers/state-reset.js +234 -0
- package/{cli/dist → dist}/core/types/pack-v1.d.ts +15 -2
- package/{cli/dist → dist}/core/types/pack-v2.d.ts +1 -1
- package/dist/core/upload/chunked-uploader.d.ts +150 -0
- package/dist/core/upload/chunked-uploader.js +289 -0
- package/dist/core/upload/index.d.ts +11 -0
- package/dist/core/upload/index.js +8 -0
- package/dist/core/upload/mime-validator.d.ts +119 -0
- package/dist/core/upload/mime-validator.js +373 -0
- package/dist/core/upload/presigned-uploader.d.ts +118 -0
- package/dist/core/upload/presigned-uploader.js +274 -0
- package/dist/core/utils/device-emulation.d.ts +194 -0
- package/dist/core/utils/device-emulation.js +380 -0
- package/dist/core/utils/index.d.ts +8 -0
- package/dist/core/utils/index.js +8 -0
- package/dist/core/utils/retry.d.ts +145 -0
- package/dist/core/utils/retry.js +242 -0
- package/dist/core/utils/smart-wait.d.ts +133 -0
- package/dist/core/utils/smart-wait.js +417 -0
- package/dist/core/visual/index.d.ts +7 -0
- package/dist/core/visual/index.js +7 -0
- package/dist/core/visual/pixel-diff.d.ts +87 -0
- package/dist/core/visual/pixel-diff.js +213 -0
- package/dist/core/visual/screenshot-helper.d.ts +130 -0
- package/dist/core/visual/screenshot-helper.js +223 -0
- package/{cli/dist → dist}/utils/config.d.ts +1 -1
- package/examples/README.md +160 -0
- package/examples/accessibility.yml +48 -0
- package/examples/api-basic.yml +27 -0
- package/examples/complete.yml +146 -0
- package/examples/crawler.yml +38 -0
- package/examples/fullstack.yml +78 -0
- package/examples/security.yml +58 -0
- package/examples/ui-advanced.yml +49 -0
- package/examples/ui-basic.yml +24 -0
- package/package.json +33 -67
- package/CHANGELOG.md +0 -262
- package/CONTRIBUTING.md +0 -273
- package/QUICK_START.md +0 -191
- package/cli/CHANGELOG.md +0 -84
- package/cli/LICENSE +0 -24
- package/cli/README.md +0 -222
- package/cli/dist/core/adapters/playwright-ui.js +0 -864
- package/cli/dist/core/auth/oauth2-provider.js +0 -114
- package/cli/dist/core/coverage/analyzer.d.ts +0 -101
- package/cli/dist/core/coverage/analyzer.js +0 -415
- package/cli/dist/core/coverage/collector.d.ts +0 -74
- package/cli/dist/core/coverage/collector.js +0 -459
- package/cli/dist/core/coverage/config.d.ts +0 -37
- package/cli/dist/core/coverage/config.js +0 -156
- package/cli/dist/core/coverage/index.d.ts +0 -11
- package/cli/dist/core/coverage/index.js +0 -15
- package/cli/dist/core/coverage/types.d.ts +0 -267
- package/cli/dist/core/coverage/types.js +0 -6
- package/cli/dist/core/coverage/vault.d.ts +0 -95
- package/cli/dist/core/coverage/vault.js +0 -405
- package/cli/dist/core/crawler/index.d.ts +0 -57
- package/cli/dist/core/fixtures/index.d.ts +0 -8
- package/cli/dist/core/fixtures/index.js +0 -8
- package/cli/dist/core/generation/crawler-pack-generator.js +0 -231
- package/cli/dist/core/reporting/index.d.ts +0 -6
- package/cli/dist/core/reporting/index.js +0 -6
- package/cli/dist/core/visual/index.d.ts +0 -6
- package/cli/dist/core/visual/index.js +0 -6
- package/cli/package.json +0 -76
- package/core/LICENSE +0 -24
- package/core/README.md +0 -64
- package/core/package.json +0 -81
- package/core/schemas/pack.schema.json +0 -236
- /package/{cli/bin → bin}/qa360.js +0 -0
- /package/{cli/dist → dist}/cli-minimal.d.ts +0 -0
- /package/{cli/dist → dist}/cli-minimal.js +0 -0
- /package/{cli/dist → dist}/commands/ai.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ask.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ask.js +0 -0
- /package/{cli/dist → dist}/commands/coverage.d.ts +0 -0
- /package/{cli/dist → dist}/commands/doctor.d.ts +0 -0
- /package/{cli/dist → dist}/commands/examples.d.ts +0 -0
- /package/{cli/dist → dist}/commands/examples.js +0 -0
- /package/{cli/dist → dist}/commands/explain.d.ts +0 -0
- /package/{cli/dist → dist}/commands/flakiness.d.ts +0 -0
- /package/{cli/dist → dist}/commands/generate.d.ts +0 -0
- /package/{cli/dist → dist}/commands/history.d.ts +0 -0
- /package/{cli/dist → dist}/commands/init.d.ts +0 -0
- /package/{cli/dist → dist}/commands/init.js +0 -0
- /package/{cli/dist → dist}/commands/monitor.d.ts +0 -0
- /package/{cli/dist → dist}/commands/ollama.d.ts +0 -0
- /package/{cli/dist → dist}/commands/pack.d.ts +0 -0
- /package/{cli/dist → dist}/commands/regression.d.ts +0 -0
- /package/{cli/dist → dist}/commands/repair.d.ts +0 -0
- /package/{cli/dist → dist}/commands/report.d.ts +0 -0
- /package/{cli/dist → dist}/commands/report.js +0 -0
- /package/{cli/dist → dist}/commands/retry.d.ts +0 -0
- /package/{cli/dist → dist}/commands/scan.d.ts +0 -0
- /package/{cli/dist → dist}/commands/scan.js +0 -0
- /package/{cli/dist → dist}/commands/secrets.d.ts +0 -0
- /package/{cli/dist → dist}/commands/serve.d.ts +0 -0
- /package/{cli/dist → dist}/commands/slo.d.ts +0 -0
- /package/{cli/dist → dist}/commands/verify.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.js +0 -0
- /package/{cli/dist → dist}/core/adapters/jest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/jest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/k6-perf.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/k6-perf.js +0 -0
- /package/{cli/dist → dist}/core/adapters/osv-deps.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/osv-deps.js +0 -0
- /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/pytest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/pytest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/semgrep-sast.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/semgrep-sast.js +0 -0
- /package/{cli/dist → dist}/core/adapters/unit-test-types.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/unit-test-types.js +0 -0
- /package/{cli/dist → dist}/core/adapters/vitest-adapter.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/vitest-adapter.js +0 -0
- /package/{cli/dist → dist}/core/adapters/zap-dast.d.ts +0 -0
- /package/{cli/dist → dist}/core/adapters/zap-dast.js +0 -0
- /package/{cli/dist → dist}/core/ai/anthropic-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/anthropic-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/deepseek-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/deepseek-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/index.js +0 -0
- /package/{cli/dist → dist}/core/ai/llm-client.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/llm-client.js +0 -0
- /package/{cli/dist → dist}/core/ai/mock-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/mock-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/ollama-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/openai-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/openai-provider.js +0 -0
- /package/{cli/dist → dist}/core/ai/provider-factory.d.ts +0 -0
- /package/{cli/dist → dist}/core/ai/provider-factory.js +0 -0
- /package/{cli/dist → dist}/core/artifacts/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/artifacts/index.js +0 -0
- /package/{cli/dist → dist}/core/artifacts/ui-artifacts.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/engine.js +0 -0
- /package/{cli/dist → dist}/core/assertions/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/index.js +0 -0
- /package/{cli/dist → dist}/core/assertions/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/assertions/types.js +0 -0
- /package/{cli/dist → dist}/core/auth/api-key-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/api-key-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/aws-iam-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/aws-iam-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/azure-ad-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/azure-ad-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/gcp-adc-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/gcp-adc-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/jwt-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/jwt-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/manager.js +0 -0
- /package/{cli/dist → dist}/core/auth/totp-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/totp-provider.js +0 -0
- /package/{cli/dist → dist}/core/auth/ui-login-provider.d.ts +0 -0
- /package/{cli/dist → dist}/core/auth/ui-login-provider.js +0 -0
- /package/{cli/dist → dist}/core/cache/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/cache/index.js +0 -0
- /package/{cli/dist → dist}/core/cache/lru-cache.d.ts +0 -0
- /package/{cli/dist → dist}/core/cache/lru-cache.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/analyzer.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/analyzer.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/collector.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/collector.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/config.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/config.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/index.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/index.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/types.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/types.js +0 -0
- /package/{cli/dist/core → dist}/core/coverage/vault.d.ts +0 -0
- /package/{cli/dist/core → dist}/core/coverage/vault.js +0 -0
- /package/{cli/dist → dist}/core/crawler/journey-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/crawler/types.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/assets.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/assets.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/index.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/server.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/server.js +0 -0
- /package/{cli/dist → dist}/core/dashboard/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/dashboard/types.js +0 -0
- /package/{cli/dist → dist}/core/discoverer/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/discoverer/index.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/loader.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/resolver.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/resolver.js +0 -0
- /package/{cli/dist → dist}/core/fixtures/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/fixtures/types.js +0 -0
- /package/{cli/dist → dist}/core/flakiness/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/flakiness/index.js +0 -0
- /package/{cli/dist → dist}/core/generation/code-formatter.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/code-formatter.js +0 -0
- /package/{cli/dist → dist}/core/generation/code-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/code-generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/pack-generator.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/pack-generator.js +0 -0
- /package/{cli/dist → dist}/core/generation/prompt-builder.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/prompt-builder.js +0 -0
- /package/{cli/dist → dist}/core/generation/source-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/source-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/generation/test-optimizer.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/test-optimizer.js +0 -0
- /package/{cli/dist → dist}/core/generation/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/generation/types.js +0 -0
- /package/{cli/dist → dist}/core/hooks/compose.d.ts +0 -0
- /package/{cli/dist → dist}/core/hooks/compose.js +0 -0
- /package/{cli/dist → dist}/core/hooks/runner.d.ts +0 -0
- /package/{cli/dist → dist}/core/hooks/runner.js +0 -0
- /package/{cli/dist → dist}/core/pack/migrator.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack/migrator.js +0 -0
- /package/{cli/dist → dist}/core/pack/validator.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/index.js +0 -0
- /package/{cli/dist → dist}/core/pack-v2/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/pack-v2/loader.js +0 -0
- /package/{cli/dist → dist}/core/pack-v2/validator.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/index.js +0 -0
- /package/{cli/dist → dist}/core/parallel/parallel-runner.d.ts +0 -0
- /package/{cli/dist → dist}/core/parallel/parallel-runner.js +0 -0
- /package/{cli/dist → dist}/core/pom/base-page.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/index.js +0 -0
- /package/{cli/dist → dist}/core/pom/loader.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/pom/types.js +0 -0
- /package/{cli/dist → dist}/core/proof/bundle.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/bundle.js +0 -0
- /package/{cli/dist → dist}/core/proof/canonicalize.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/canonicalize.js +0 -0
- /package/{cli/dist → dist}/core/proof/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/index.js +0 -0
- /package/{cli/dist → dist}/core/proof/schema.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/schema.js +0 -0
- /package/{cli/dist → dist}/core/proof/signer.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/signer.js +0 -0
- /package/{cli/dist → dist}/core/proof/verifier.d.ts +0 -0
- /package/{cli/dist → dist}/core/proof/verifier.js +0 -0
- /package/{cli/dist → dist}/core/regression/detector.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/detector.js +0 -0
- /package/{cli/dist → dist}/core/regression/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/index.js +0 -0
- /package/{cli/dist → dist}/core/regression/trend-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/trend-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/regression/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/types.js +0 -0
- /package/{cli/dist → dist}/core/regression/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/regression/vault.js +0 -0
- /package/{cli/dist → dist}/core/repair/engine/fixer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/engine/fixer.js +0 -0
- /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.js +0 -0
- /package/{cli/dist → dist}/core/repair/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/index.js +0 -0
- /package/{cli/dist → dist}/core/repair/repairer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/repairer.js +0 -0
- /package/{cli/dist → dist}/core/repair/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/types.js +0 -0
- /package/{cli/dist → dist}/core/repair/utils/error-analyzer.d.ts +0 -0
- /package/{cli/dist → dist}/core/repair/utils/error-analyzer.js +0 -0
- /package/{cli/dist → dist}/core/reporting/html-reporter.d.ts +0 -0
- /package/{cli/dist → dist}/core/reporting/html-reporter.js +0 -0
- /package/{cli/dist → dist}/core/retry/flakiness-integration.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/flakiness-integration.js +0 -0
- /package/{cli/dist → dist}/core/retry/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/index.js +0 -0
- /package/{cli/dist → dist}/core/retry/retry-engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/retry-engine.js +0 -0
- /package/{cli/dist → dist}/core/retry/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/types.js +0 -0
- /package/{cli/dist → dist}/core/retry/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/retry/vault.js +0 -0
- /package/{cli/dist → dist}/core/schemas/pack.schema.json +0 -0
- /package/{cli/dist → dist}/core/secrets/crypto.d.ts +0 -0
- /package/{cli/dist → dist}/core/secrets/crypto.js +0 -0
- /package/{cli/dist → dist}/core/secrets/manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/secrets/manager.js +0 -0
- /package/{cli/dist → dist}/core/security/redaction-patterns-extended.d.ts +0 -0
- /package/{cli/dist → dist}/core/security/redaction-patterns-extended.js +0 -0
- /package/{cli/dist → dist}/core/security/redactor.d.ts +0 -0
- /package/{cli/dist → dist}/core/security/redactor.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/assertion-healer.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/assertion-healer.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/engine.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/engine.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/index.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/selector-healer.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/selector-healer.js +0 -0
- /package/{cli/dist → dist}/core/self-healing/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/self-healing/types.js +0 -0
- /package/{cli/dist → dist}/core/serve/diagnostics-collector.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/diagnostics-collector.js +0 -0
- /package/{cli/dist → dist}/core/serve/health-checker.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/health-checker.js +0 -0
- /package/{cli/dist → dist}/core/serve/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/index.js +0 -0
- /package/{cli/dist → dist}/core/serve/metrics-collector.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/metrics-collector.js +0 -0
- /package/{cli/dist → dist}/core/serve/process-manager.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/process-manager.js +0 -0
- /package/{cli/dist → dist}/core/serve/server.d.ts +0 -0
- /package/{cli/dist → dist}/core/serve/server.js +0 -0
- /package/{cli/dist → dist}/core/slo/config.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/config.js +0 -0
- /package/{cli/dist → dist}/core/slo/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/index.js +0 -0
- /package/{cli/dist → dist}/core/slo/sli-calculator.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/sli-calculator.js +0 -0
- /package/{cli/dist → dist}/core/slo/slo-tracker.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/slo-tracker.js +0 -0
- /package/{cli/dist → dist}/core/slo/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/types.js +0 -0
- /package/{cli/dist → dist}/core/slo/vault.d.ts +0 -0
- /package/{cli/dist → dist}/core/slo/vault.js +0 -0
- /package/{cli/dist → dist}/core/tui/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/index.js +0 -0
- /package/{cli/dist → dist}/core/tui/monitor.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/monitor.js +0 -0
- /package/{cli/dist → dist}/core/tui/renderer.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/renderer.js +0 -0
- /package/{cli/dist → dist}/core/tui/types.d.ts +0 -0
- /package/{cli/dist → dist}/core/tui/types.js +0 -0
- /package/{cli/dist → dist}/core/types/pack-v1.js +0 -0
- /package/{cli/dist → dist}/core/types/pack-v2.js +0 -0
- /package/{cli/dist → dist}/core/types/trust-score.d.ts +0 -0
- /package/{cli/dist → dist}/core/types/trust-score.js +0 -0
- /package/{cli/dist → dist}/core/vault/cas.d.ts +0 -0
- /package/{cli/dist → dist}/core/vault/cas.js +0 -0
- /package/{cli/dist → dist}/core/vault/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/vault/index.js +0 -0
- /package/{cli/dist → dist}/core/visual/visual-regression.d.ts +0 -0
- /package/{cli/dist → dist}/core/visual/visual-regression.js +0 -0
- /package/{cli/dist → dist}/core/watch/index.d.ts +0 -0
- /package/{cli/dist → dist}/core/watch/index.js +0 -0
- /package/{cli/dist → dist}/core/watch/watch-mode.d.ts +0 -0
- /package/{cli/dist → dist}/core/watch/watch-mode.js +0 -0
- /package/{cli/dist → dist}/generators/index.d.ts +0 -0
- /package/{cli/dist → dist}/generators/index.js +0 -0
- /package/{cli/dist → dist}/generators/json-reporter.d.ts +0 -0
- /package/{cli/dist → dist}/generators/json-reporter.js +0 -0
- /package/{cli/dist → dist}/generators/test-generator.d.ts +0 -0
- /package/{cli/dist → dist}/generators/test-generator.js +0 -0
- /package/{cli/dist → dist}/index.d.ts +0 -0
- /package/{cli/dist → dist}/index.js +0 -0
- /package/{cli/dist → dist}/scanners/dom-scanner.d.ts +0 -0
- /package/{cli/dist → dist}/scanners/dom-scanner.js +0 -0
- /package/{cli/dist → dist}/scanners/index.d.ts +0 -0
- /package/{cli/dist → dist}/scanners/index.js +0 -0
- /package/{cli/dist → dist}/schemas/pack.schema.json +0 -0
- /package/{cli/dist → dist}/types/scan.d.ts +0 -0
- /package/{cli/dist → dist}/types/scan.js +0 -0
- /package/{cli/dist → dist}/utils/config.js +0 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Testing Handler
|
|
3
|
+
*
|
|
4
|
+
* P1 - Email testing for applications that send emails
|
|
5
|
+
*
|
|
6
|
+
* Supports:
|
|
7
|
+
* - Mailhog integration
|
|
8
|
+
* - Mailtrap integration
|
|
9
|
+
* - Mailgun API
|
|
10
|
+
* - SendGrid API
|
|
11
|
+
* - Generic IMAP/POP3 access
|
|
12
|
+
* - Email parsing and validation
|
|
13
|
+
* - Link extraction from emails
|
|
14
|
+
* - Attachment handling
|
|
15
|
+
*
|
|
16
|
+
* @see https://github.com/mailhog/MailHog
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Email Testing Handler class
|
|
20
|
+
*/
|
|
21
|
+
export class EmailTestingHandler {
|
|
22
|
+
mailhogUrl;
|
|
23
|
+
timeout;
|
|
24
|
+
mailtrapToken;
|
|
25
|
+
mailgunApiKey;
|
|
26
|
+
sendgridApiKey;
|
|
27
|
+
constructor(config = {}) {
|
|
28
|
+
this.mailhogUrl = config.mailhogUrl || 'http://localhost:8025';
|
|
29
|
+
this.timeout = config.timeout || 30000;
|
|
30
|
+
this.mailtrapToken = config.mailtrapToken;
|
|
31
|
+
this.mailgunApiKey = config.mailgunApiKey;
|
|
32
|
+
this.sendgridApiKey = config.sendgridApiKey;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fetch all messages from Mailhog
|
|
36
|
+
*/
|
|
37
|
+
async fetchMessages() {
|
|
38
|
+
const response = await fetch(`${this.mailhogUrl}/api/v2/messages`);
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
throw new Error(`Failed to fetch messages: ${response.statusText}`);
|
|
41
|
+
}
|
|
42
|
+
const data = await response.json();
|
|
43
|
+
return (data.items || []).map(this.parseMailhogMessage);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Delete all messages from Mailhog
|
|
47
|
+
*/
|
|
48
|
+
async deleteAllMessages() {
|
|
49
|
+
await fetch(`${this.mailhogUrl}/api/v1/messages`, { method: 'DELETE' });
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get a specific message by ID
|
|
53
|
+
*/
|
|
54
|
+
async getMessage(id) {
|
|
55
|
+
const response = await fetch(`${this.mailhogUrl}/api/v2/messages/${id}`);
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
if (response.status === 404)
|
|
58
|
+
return null;
|
|
59
|
+
throw new Error(`Failed to fetch message: ${response.statusText}`);
|
|
60
|
+
}
|
|
61
|
+
const data = await response.json();
|
|
62
|
+
return this.parseMailhogMessage(data);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Wait for a new email matching criteria
|
|
66
|
+
*/
|
|
67
|
+
async waitForEmail(options = {}, timeout) {
|
|
68
|
+
const timeoutMs = timeout || this.timeout;
|
|
69
|
+
const startTime = Date.now();
|
|
70
|
+
let lastCount = 0;
|
|
71
|
+
// Get initial count
|
|
72
|
+
try {
|
|
73
|
+
const initialMessages = await this.fetchMessages();
|
|
74
|
+
lastCount = initialMessages.length;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Mailhog might not be available yet
|
|
78
|
+
}
|
|
79
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
80
|
+
await this.sleep(500);
|
|
81
|
+
try {
|
|
82
|
+
const messages = await this.fetchMessages();
|
|
83
|
+
// Check for new messages
|
|
84
|
+
if (messages.length > lastCount) {
|
|
85
|
+
const newMessages = messages.slice(lastCount);
|
|
86
|
+
// Find matching message
|
|
87
|
+
for (const message of newMessages) {
|
|
88
|
+
if (this.matchesCriteria(message, options)) {
|
|
89
|
+
return message;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
lastCount = messages.length;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
// Continue waiting on error
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Search for messages matching criteria
|
|
103
|
+
*/
|
|
104
|
+
async searchMessages(options) {
|
|
105
|
+
const messages = await this.fetchMessages();
|
|
106
|
+
return messages.filter(msg => this.matchesCriteria(msg, options));
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the most recent email matching criteria
|
|
110
|
+
*/
|
|
111
|
+
async getLatestEmail(options = {}) {
|
|
112
|
+
const messages = await this.searchMessages(options);
|
|
113
|
+
if (messages.length === 0)
|
|
114
|
+
return null;
|
|
115
|
+
// Sort by received date descending
|
|
116
|
+
messages.sort((a, b) => b.received.getTime() - a.received.getTime());
|
|
117
|
+
return messages[0];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Extract all links from an email
|
|
121
|
+
*/
|
|
122
|
+
extractLinks(message) {
|
|
123
|
+
const textLinks = [];
|
|
124
|
+
const htmlLinks = [];
|
|
125
|
+
// Extract from plain text
|
|
126
|
+
if (message.text) {
|
|
127
|
+
const urlRegex = /https?:\/\/[^\s]+/gi;
|
|
128
|
+
const matches = message.text.match(urlRegex);
|
|
129
|
+
if (matches) {
|
|
130
|
+
textLinks.push(...matches);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Extract from HTML
|
|
134
|
+
if (message.html) {
|
|
135
|
+
const hrefRegex = /href=["']([^"']+)["']/gi;
|
|
136
|
+
let match;
|
|
137
|
+
while ((match = hrefRegex.exec(message.html)) !== null) {
|
|
138
|
+
htmlLinks.push(match[1]);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
textLinks,
|
|
143
|
+
htmlLinks,
|
|
144
|
+
allLinks: [...textLinks, ...htmlLinks],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Extract verification links (common patterns)
|
|
149
|
+
*/
|
|
150
|
+
extractVerificationLinks(message) {
|
|
151
|
+
const links = this.extractLinks(message).allLinks;
|
|
152
|
+
const result = {
|
|
153
|
+
verifyEmail: [],
|
|
154
|
+
resetPassword: [],
|
|
155
|
+
unsubscribe: [],
|
|
156
|
+
other: [],
|
|
157
|
+
};
|
|
158
|
+
for (const link of links) {
|
|
159
|
+
const lower = link.toLowerCase();
|
|
160
|
+
if (lower.includes('verify') || lower.includes('confirm')) {
|
|
161
|
+
result.verifyEmail.push(link);
|
|
162
|
+
}
|
|
163
|
+
else if (lower.includes('reset') || lower.includes('forgot') || lower.includes('recover')) {
|
|
164
|
+
result.resetPassword.push(link);
|
|
165
|
+
}
|
|
166
|
+
else if (lower.includes('unsubscribe')) {
|
|
167
|
+
result.unsubscribe.push(link);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
result.other.push(link);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Extract OTP/code from email
|
|
177
|
+
*/
|
|
178
|
+
extractCode(message) {
|
|
179
|
+
const content = message.text || message.html || '';
|
|
180
|
+
// Try common patterns
|
|
181
|
+
const patterns = [
|
|
182
|
+
// "Your code is: 123456"
|
|
183
|
+
/(?:code|verification|otp|pin|token)[:\s]+([A-Z0-9]{4,12})/i,
|
|
184
|
+
// "123456 is your verification code"
|
|
185
|
+
/(\d{4,8})\s+(?:is your|verification|code|otp)/i,
|
|
186
|
+
// Just a 6-digit number (common pattern)
|
|
187
|
+
/\b(\d{6})\b/g,
|
|
188
|
+
];
|
|
189
|
+
let bestMatch = null;
|
|
190
|
+
for (const pattern of patterns) {
|
|
191
|
+
const matches = content.match(pattern);
|
|
192
|
+
if (matches) {
|
|
193
|
+
const code = matches[1] || matches[0];
|
|
194
|
+
const confidence = code.length >= 6 ? 0.9 : 0.5;
|
|
195
|
+
if (!bestMatch || confidence > bestMatch.confidence) {
|
|
196
|
+
bestMatch = { code, confidence };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (bestMatch) {
|
|
201
|
+
return {
|
|
202
|
+
code: bestMatch.code,
|
|
203
|
+
type: /^\d+$/.test(bestMatch.code) ? 'numeric' : 'alphanumeric',
|
|
204
|
+
confidence: bestMatch.confidence,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return { confidence: 0 };
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Parse a Mailhog message
|
|
211
|
+
*/
|
|
212
|
+
parseMailhogMessage(data) {
|
|
213
|
+
const raw = data.Content || {};
|
|
214
|
+
const headers = raw.Headers || {};
|
|
215
|
+
const from = headers.From || headers.from || '';
|
|
216
|
+
const to = headers.To || headers.to || [];
|
|
217
|
+
const toList = Array.isArray(to) ? to : [to];
|
|
218
|
+
return {
|
|
219
|
+
id: data.ID || '',
|
|
220
|
+
from: this.parseEmailAddress(from),
|
|
221
|
+
to: toList.map((a) => this.parseEmailAddress(a)),
|
|
222
|
+
cc: headers.Cc || headers.cc ? [headers.Cc || headers.cc].flat() : undefined,
|
|
223
|
+
subject: headers.Subject || headers.subject || '',
|
|
224
|
+
text: raw.Body || raw.Text,
|
|
225
|
+
html: raw.HTML || raw.Html,
|
|
226
|
+
received: new Date(data.Created || Date.now()),
|
|
227
|
+
attachments: this.parseAttachments(raw.Attachments || []),
|
|
228
|
+
headers: headers,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Parse email address from string
|
|
233
|
+
*/
|
|
234
|
+
parseEmailAddress(address) {
|
|
235
|
+
// Remove display name and quotes
|
|
236
|
+
const match = address.match(/<([^>]+)>/);
|
|
237
|
+
if (match)
|
|
238
|
+
return match[1];
|
|
239
|
+
// Remove extra whitespace
|
|
240
|
+
return address.trim();
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Parse attachments from Mailhog format
|
|
244
|
+
*/
|
|
245
|
+
parseAttachments(data) {
|
|
246
|
+
if (!data || !Array.isArray(data))
|
|
247
|
+
return [];
|
|
248
|
+
return data.map(att => ({
|
|
249
|
+
filename: att.FileName || att.filename || 'unknown',
|
|
250
|
+
contentType: att.ContentType || att.contentType || 'application/octet-stream',
|
|
251
|
+
size: att.Size || att.size || 0,
|
|
252
|
+
downloadUrl: att.DownloadUrl || att.downloadUrl,
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Check if message matches search criteria
|
|
257
|
+
*/
|
|
258
|
+
matchesCriteria(message, options) {
|
|
259
|
+
if (options.to) {
|
|
260
|
+
const toFilter = options.to;
|
|
261
|
+
if (!message.to.some((t) => t.includes(toFilter))) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (options.from && !message.from.includes(options.from)) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
if (options.subject && !message.subject.toLowerCase().includes(options.subject.toLowerCase())) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
if (options.contains) {
|
|
272
|
+
const content = (message.text || '') + (message.html || '');
|
|
273
|
+
if (!content.toLowerCase().includes(options.contains.toLowerCase())) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (options.after && message.received < options.after) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
if (options.before && message.received > options.before) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Assert email was received
|
|
287
|
+
*/
|
|
288
|
+
async assertEmailReceived(options, timeout) {
|
|
289
|
+
const email = await this.waitForEmail(options, timeout);
|
|
290
|
+
if (email) {
|
|
291
|
+
return { received: true, email };
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
received: false,
|
|
295
|
+
error: `No email received matching criteria: ${JSON.stringify(options)}`,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Assert email contains link
|
|
300
|
+
*/
|
|
301
|
+
assertEmailContainsLink(message, linkPattern) {
|
|
302
|
+
const links = this.extractLinks(message).allLinks;
|
|
303
|
+
const foundLinks = links.filter(link => {
|
|
304
|
+
if (typeof linkPattern === 'string') {
|
|
305
|
+
return link.includes(linkPattern);
|
|
306
|
+
}
|
|
307
|
+
return linkPattern.test(link);
|
|
308
|
+
});
|
|
309
|
+
return {
|
|
310
|
+
contains: foundLinks.length > 0,
|
|
311
|
+
foundLinks,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get Mailhog status
|
|
316
|
+
*/
|
|
317
|
+
async getMailhogStatus() {
|
|
318
|
+
try {
|
|
319
|
+
const response = await fetch(`${this.mailhogUrl}/api/v2/messages`);
|
|
320
|
+
return { available: response.ok || response.status === 200 };
|
|
321
|
+
}
|
|
322
|
+
catch (e) {
|
|
323
|
+
return {
|
|
324
|
+
available: false,
|
|
325
|
+
error: e instanceof Error ? e.message : String(e),
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
sleep(ms) {
|
|
330
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Fetch messages from Mailtrap (alternative to Mailhog)
|
|
334
|
+
*/
|
|
335
|
+
async fetchMailtrapMessages(inboxId) {
|
|
336
|
+
if (!this.mailtrapToken) {
|
|
337
|
+
throw new Error('Mailtrap token not configured');
|
|
338
|
+
}
|
|
339
|
+
// Mailtrap API v1
|
|
340
|
+
const response = await fetch(`https://mailtrap.io/api/v1/inboxes/${inboxId || '1'}/messages`, {
|
|
341
|
+
headers: {
|
|
342
|
+
'Api-Token': this.mailtrapToken,
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
if (!response.ok) {
|
|
346
|
+
throw new Error(`Failed to fetch Mailtrap messages: ${response.statusText}`);
|
|
347
|
+
}
|
|
348
|
+
const data = await response.json();
|
|
349
|
+
return (data || []).map(this.parseMailtrapMessage);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Parse Mailtrap message
|
|
353
|
+
*/
|
|
354
|
+
parseMailtrapMessage(data) {
|
|
355
|
+
return {
|
|
356
|
+
id: data.id.toString(),
|
|
357
|
+
from: data.from_email || data.from || '',
|
|
358
|
+
to: [data.to_email || data.to || ''].filter(Boolean),
|
|
359
|
+
subject: data.subject || '',
|
|
360
|
+
text: data.text_body || data.text_body,
|
|
361
|
+
html: data.html_body || data.html_body,
|
|
362
|
+
received: new Date(data.created_at || Date.now()),
|
|
363
|
+
attachments: data.attachments?.map((att) => ({
|
|
364
|
+
filename: att.filename,
|
|
365
|
+
contentType: att.content_type,
|
|
366
|
+
size: att.size,
|
|
367
|
+
downloadUrl: att.download_url,
|
|
368
|
+
})) || [],
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Create email testing utilities for test helpers
|
|
373
|
+
*/
|
|
374
|
+
createTestHelpers() {
|
|
375
|
+
return {
|
|
376
|
+
waitForEmail: this.waitForEmail.bind(this),
|
|
377
|
+
getLatestEmail: this.getLatestEmail.bind(this),
|
|
378
|
+
extractLinks: this.extractLinks.bind(this),
|
|
379
|
+
extractCode: this.extractCode.bind(this),
|
|
380
|
+
deleteAll: this.deleteAllMessages.bind(this),
|
|
381
|
+
assertEmailReceived: this.assertEmailReceived.bind(this),
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Factory function to create Email Testing Handler
|
|
387
|
+
*/
|
|
388
|
+
export function createEmailTestingHandler(config) {
|
|
389
|
+
return new EmailTestingHandler(config);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Quick function to wait for email
|
|
393
|
+
*/
|
|
394
|
+
export async function waitForEmail(config, options, timeout) {
|
|
395
|
+
const handler = new EmailTestingHandler(config);
|
|
396
|
+
return handler.waitForEmail(options, timeout);
|
|
397
|
+
}
|
|
398
|
+
export default EmailTestingHandler;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Tracking Handler
|
|
3
|
+
*
|
|
4
|
+
* P1 - Global error tracking and monitoring
|
|
5
|
+
*
|
|
6
|
+
* Supports:
|
|
7
|
+
* - JavaScript error capture
|
|
8
|
+
* - Unhandled rejection tracking
|
|
9
|
+
* - Error aggregation and deduplication
|
|
10
|
+
* - Error context collection
|
|
11
|
+
* - Error reporting
|
|
12
|
+
*
|
|
13
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers
|
|
14
|
+
*/
|
|
15
|
+
export interface ErrorInfo {
|
|
16
|
+
/** Error message */
|
|
17
|
+
message: string;
|
|
18
|
+
/** Error stack trace */
|
|
19
|
+
stack: string;
|
|
20
|
+
/** Error name */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Source file */
|
|
23
|
+
filename?: string;
|
|
24
|
+
/** Line number */
|
|
25
|
+
line?: number;
|
|
26
|
+
/** Column number */
|
|
27
|
+
column?: number;
|
|
28
|
+
/** Error type */
|
|
29
|
+
type: 'error' | 'unhandledrejection' | 'resource' | 'console';
|
|
30
|
+
/** Timestamp */
|
|
31
|
+
timestamp: number;
|
|
32
|
+
/** User agent */
|
|
33
|
+
userAgent: string;
|
|
34
|
+
/** Page URL */
|
|
35
|
+
pageUrl: string;
|
|
36
|
+
/** Additional context */
|
|
37
|
+
context?: {
|
|
38
|
+
viewport?: {
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
41
|
+
};
|
|
42
|
+
console?: string[];
|
|
43
|
+
localStorage?: Record<string, string>;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export interface ErrorGroup {
|
|
47
|
+
/** Unique error key */
|
|
48
|
+
key: string;
|
|
49
|
+
/** Error name */
|
|
50
|
+
name: string;
|
|
51
|
+
/** Error message */
|
|
52
|
+
message: string;
|
|
53
|
+
/** Count of occurrences */
|
|
54
|
+
count: number;
|
|
55
|
+
/** First occurrence timestamp */
|
|
56
|
+
firstSeen: number;
|
|
57
|
+
/** Last occurrence timestamp */
|
|
58
|
+
lastSeen: number;
|
|
59
|
+
/** Sample stack trace */
|
|
60
|
+
stack: string;
|
|
61
|
+
/** Affected pages */
|
|
62
|
+
pages: string[];
|
|
63
|
+
}
|
|
64
|
+
export interface ResourceError {
|
|
65
|
+
/** Resource URL */
|
|
66
|
+
url: string;
|
|
67
|
+
/** Resource type */
|
|
68
|
+
type: string;
|
|
69
|
+
/** Error status */
|
|
70
|
+
status: number;
|
|
71
|
+
/** Error message */
|
|
72
|
+
message: string;
|
|
73
|
+
/** Timestamp */
|
|
74
|
+
timestamp: number;
|
|
75
|
+
}
|
|
76
|
+
export interface ErrorReport {
|
|
77
|
+
/** Total errors captured */
|
|
78
|
+
totalErrors: number;
|
|
79
|
+
/** Errors by type */
|
|
80
|
+
errorsByType: Record<string, number>;
|
|
81
|
+
/** Grouped errors */
|
|
82
|
+
groupedErrors: ErrorGroup[];
|
|
83
|
+
/** Resource errors */
|
|
84
|
+
resourceErrors: ResourceError[];
|
|
85
|
+
/** Most frequent error */
|
|
86
|
+
mostFrequent: ErrorGroup | null;
|
|
87
|
+
/** Unhandled rejections */
|
|
88
|
+
unhandledRejections: number;
|
|
89
|
+
/** Console errors */
|
|
90
|
+
consoleErrors: number;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Error Tracking Handler class
|
|
94
|
+
*/
|
|
95
|
+
export declare class ErrorTrackingHandler {
|
|
96
|
+
private page;
|
|
97
|
+
private errors;
|
|
98
|
+
private resourceErrors;
|
|
99
|
+
private trackingEnabled;
|
|
100
|
+
private consoleErrors;
|
|
101
|
+
constructor(page: any);
|
|
102
|
+
/**
|
|
103
|
+
* Setup global error tracking
|
|
104
|
+
*/
|
|
105
|
+
setupTracking(): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Get all captured errors from the page
|
|
108
|
+
*/
|
|
109
|
+
getErrors(): Promise<ErrorInfo[]>;
|
|
110
|
+
/**
|
|
111
|
+
* Get all resource errors
|
|
112
|
+
*/
|
|
113
|
+
getResourceErrors(): Promise<ResourceError[]>;
|
|
114
|
+
/**
|
|
115
|
+
* Get console errors
|
|
116
|
+
*/
|
|
117
|
+
getConsoleErrors(): Promise<string[]>;
|
|
118
|
+
/**
|
|
119
|
+
* Generate error report
|
|
120
|
+
*/
|
|
121
|
+
generateReport(): Promise<ErrorReport>;
|
|
122
|
+
/**
|
|
123
|
+
* Group errors by similarity
|
|
124
|
+
*/
|
|
125
|
+
private groupErrors;
|
|
126
|
+
/**
|
|
127
|
+
* Capture error with additional context
|
|
128
|
+
*/
|
|
129
|
+
captureError(error: Error, context?: Record<string, unknown>): Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Clear all captured errors
|
|
132
|
+
*/
|
|
133
|
+
clearErrors(): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Get errors by type
|
|
136
|
+
*/
|
|
137
|
+
getErrorsByType(type: ErrorInfo['type']): Promise<ErrorInfo[]>;
|
|
138
|
+
/**
|
|
139
|
+
* Get errors by page URL
|
|
140
|
+
*/
|
|
141
|
+
getErrorsByPage(pageUrl: string): Promise<ErrorInfo[]>;
|
|
142
|
+
/**
|
|
143
|
+
* Check if there are any critical errors
|
|
144
|
+
*/
|
|
145
|
+
hasCriticalErrors(): Promise<boolean>;
|
|
146
|
+
/**
|
|
147
|
+
* Get error statistics
|
|
148
|
+
*/
|
|
149
|
+
getStatistics(): Promise<{
|
|
150
|
+
total: number;
|
|
151
|
+
byType: Record<string, number>;
|
|
152
|
+
critical: number;
|
|
153
|
+
unique: number;
|
|
154
|
+
avgPerMinute: number;
|
|
155
|
+
}>;
|
|
156
|
+
/**
|
|
157
|
+
* Export errors as JSON
|
|
158
|
+
*/
|
|
159
|
+
exportErrors(): Promise<string>;
|
|
160
|
+
/**
|
|
161
|
+
* Setup error threshold monitoring
|
|
162
|
+
*/
|
|
163
|
+
setupThresholdMonitoring(threshold: number, callback: (errors: ErrorInfo[]) => void | Promise<void>): Promise<() => void>;
|
|
164
|
+
/**
|
|
165
|
+
* Check if tracking is enabled
|
|
166
|
+
*/
|
|
167
|
+
isEnabled(): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Disable error tracking
|
|
170
|
+
*/
|
|
171
|
+
disableTracking(): Promise<void>;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Factory function to create Error Tracking Handler
|
|
175
|
+
*/
|
|
176
|
+
export declare function createErrorTrackingHandler(page: any): ErrorTrackingHandler;
|
|
177
|
+
export default ErrorTrackingHandler;
|