qa360 2.3.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/README.md +155 -262
  2. package/{cli/dist → dist}/commands/ai.js +1 -1
  3. package/{cli/dist → dist}/commands/coverage.js +1 -1
  4. package/{cli/dist → dist}/commands/crawl.js +2 -2
  5. package/{cli/dist → dist}/commands/doctor.js +2 -2
  6. package/{cli/dist → dist}/commands/explain.js +2 -2
  7. package/{cli/dist → dist}/commands/flakiness.js +1 -1
  8. package/{cli/dist → dist}/commands/generate.js +1 -1
  9. package/{cli/dist → dist}/commands/history.js +1 -1
  10. package/{cli/dist → dist}/commands/monitor.js +3 -3
  11. package/{cli/dist → dist}/commands/ollama.js +1 -1
  12. package/{cli/dist → dist}/commands/pack.js +2 -2
  13. package/{cli/dist → dist}/commands/regression.js +1 -1
  14. package/{cli/dist → dist}/commands/repair.js +1 -1
  15. package/{cli/dist → dist}/commands/retry.js +1 -1
  16. package/{cli/dist → dist}/commands/run.d.ts +1 -1
  17. package/{cli/dist → dist}/commands/run.js +1 -1
  18. package/{cli/dist → dist}/commands/secrets.js +1 -1
  19. package/{cli/dist → dist}/commands/serve.js +1 -1
  20. package/{cli/dist → dist}/commands/slo.js +1 -1
  21. package/{cli/dist → dist}/commands/verify.js +1 -1
  22. package/{cli/dist → dist}/core/adapters/playwright-native-api.d.ts +2 -0
  23. package/{cli/dist → dist}/core/adapters/playwright-native-api.js +20 -1
  24. package/{cli/dist → dist}/core/adapters/playwright-ui.d.ts +21 -0
  25. package/dist/core/adapters/playwright-ui.js +2050 -0
  26. package/{cli/dist → dist}/core/ai/ollama-provider.js +15 -3
  27. package/{cli/dist → dist}/core/artifacts/ui-artifacts.js +24 -4
  28. package/dist/core/auth/backup-codes-provider.d.ts +91 -0
  29. package/dist/core/auth/backup-codes-provider.js +215 -0
  30. package/{cli/dist → dist}/core/auth/basic-auth-provider.d.ts +6 -0
  31. package/{cli/dist → dist}/core/auth/basic-auth-provider.js +24 -6
  32. package/dist/core/auth/digest-auth-provider.d.ts +116 -0
  33. package/dist/core/auth/digest-auth-provider.js +244 -0
  34. package/dist/core/auth/hcaptcha-handler.d.ts +103 -0
  35. package/dist/core/auth/hcaptcha-handler.js +288 -0
  36. package/{cli/dist → dist}/core/auth/index.d.ts +81 -4
  37. package/{cli/dist → dist}/core/auth/index.js +15 -1
  38. package/dist/core/auth/oauth-handler.d.ts +408 -0
  39. package/dist/core/auth/oauth-handler.js +636 -0
  40. package/{cli/dist → dist}/core/auth/oauth2-provider.d.ts +9 -0
  41. package/dist/core/auth/oauth2-provider.js +227 -0
  42. package/dist/core/auth/otp-provider.d.ts +93 -0
  43. package/dist/core/auth/otp-provider.js +288 -0
  44. package/dist/core/auth/recaptcha-handler.d.ts +119 -0
  45. package/dist/core/auth/recaptcha-handler.js +301 -0
  46. package/dist/core/auth/remember-me-handler.d.ts +142 -0
  47. package/dist/core/auth/remember-me-handler.js +255 -0
  48. package/dist/core/auth/saml-handler.d.ts +173 -0
  49. package/dist/core/auth/saml-handler.js +364 -0
  50. package/dist/core/auth/webauthn-handler.d.ts +182 -0
  51. package/dist/core/auth/webauthn-handler.js +310 -0
  52. package/dist/core/crawler/advanced-interactions.d.ts +342 -0
  53. package/dist/core/crawler/advanced-interactions.js +1069 -0
  54. package/dist/core/crawler/blob-url-download-handler.d.ts +145 -0
  55. package/dist/core/crawler/blob-url-download-handler.js +392 -0
  56. package/dist/core/crawler/consent-handler.d.ts +49 -0
  57. package/dist/core/crawler/consent-handler.js +258 -0
  58. package/dist/core/crawler/cookie-manager.d.ts +166 -0
  59. package/dist/core/crawler/cookie-manager.js +353 -0
  60. package/dist/core/crawler/coop-coep-handler.d.ts +136 -0
  61. package/dist/core/crawler/coop-coep-handler.js +338 -0
  62. package/dist/core/crawler/csp-handler.d.ts +151 -0
  63. package/dist/core/crawler/csp-handler.js +415 -0
  64. package/dist/core/crawler/download-handler.d.ts +155 -0
  65. package/dist/core/crawler/download-handler.js +370 -0
  66. package/dist/core/crawler/email-testing-handler.d.ts +214 -0
  67. package/dist/core/crawler/email-testing-handler.js +398 -0
  68. package/dist/core/crawler/error-tracking-handler.d.ts +177 -0
  69. package/dist/core/crawler/error-tracking-handler.js +378 -0
  70. package/dist/core/crawler/form-handler.d.ts +100 -0
  71. package/dist/core/crawler/form-handler.js +465 -0
  72. package/dist/core/crawler/framework-wait-handler.d.ts +96 -0
  73. package/dist/core/crawler/framework-wait-handler.js +464 -0
  74. package/dist/core/crawler/geolocation-handler.d.ts +112 -0
  75. package/dist/core/crawler/geolocation-handler.js +276 -0
  76. package/dist/core/crawler/index.d.ts +78 -0
  77. package/{cli/dist → dist}/core/crawler/index.js +74 -1
  78. package/dist/core/crawler/intelligent-selector-generator.d.ts +164 -0
  79. package/dist/core/crawler/intelligent-selector-generator.js +612 -0
  80. package/{cli/dist → dist}/core/crawler/journey-generator.js +44 -1
  81. package/{cli/dist → dist}/core/crawler/page-analyzer.d.ts +16 -1
  82. package/{cli/dist → dist}/core/crawler/page-analyzer.js +469 -17
  83. package/dist/core/crawler/permissions-handler.d.ts +112 -0
  84. package/dist/core/crawler/permissions-handler.js +236 -0
  85. package/dist/core/crawler/permissions-policy-handler.d.ts +113 -0
  86. package/dist/core/crawler/permissions-policy-handler.js +402 -0
  87. package/dist/core/crawler/presets.d.ts +100 -0
  88. package/dist/core/crawler/presets.js +887 -0
  89. package/dist/core/crawler/repl-debug-handler.d.ts +105 -0
  90. package/dist/core/crawler/repl-debug-handler.js +552 -0
  91. package/dist/core/crawler/reporting-api-handler.d.ts +212 -0
  92. package/dist/core/crawler/reporting-api-handler.js +344 -0
  93. package/{cli/dist → dist}/core/crawler/selector-generator.d.ts +9 -0
  94. package/{cli/dist → dist}/core/crawler/selector-generator.js +99 -23
  95. package/dist/core/crawler/site-profiler.d.ts +89 -0
  96. package/dist/core/crawler/site-profiler.js +290 -0
  97. package/dist/core/crawler/sourcemaps-handler.d.ts +144 -0
  98. package/dist/core/crawler/sourcemaps-handler.js +420 -0
  99. package/dist/core/crawler/stacked-modals-handler.d.ts +118 -0
  100. package/dist/core/crawler/stacked-modals-handler.js +429 -0
  101. package/dist/core/crawler/trusted-types-handler.d.ts +149 -0
  102. package/dist/core/crawler/trusted-types-handler.js +413 -0
  103. package/{cli/dist → dist}/core/crawler/types.d.ts +68 -2
  104. package/dist/core/crawler/wait-strategies.d.ts +108 -0
  105. package/dist/core/crawler/wait-strategies.js +399 -0
  106. package/dist/core/fixtures/factories.d.ts +180 -0
  107. package/dist/core/fixtures/factories.js +279 -0
  108. package/dist/core/fixtures/index.d.ts +6 -0
  109. package/dist/core/fixtures/index.js +6 -0
  110. package/{cli/dist → dist}/core/generation/crawler-pack-generator.d.ts +13 -3
  111. package/dist/core/generation/crawler-pack-generator.js +232 -0
  112. package/{cli/dist → dist}/core/generation/index.d.ts +2 -0
  113. package/{cli/dist → dist}/core/generation/index.js +2 -0
  114. package/{cli/dist → dist}/core/index.d.ts +2 -0
  115. package/{cli/dist → dist}/core/index.js +4 -0
  116. package/dist/core/network/index.d.ts +7 -0
  117. package/dist/core/network/index.js +7 -0
  118. package/dist/core/network/network-manager.d.ts +237 -0
  119. package/dist/core/network/network-manager.js +343 -0
  120. package/dist/core/network/network-simulator.d.ts +158 -0
  121. package/dist/core/network/network-simulator.js +261 -0
  122. package/{cli/dist → dist}/core/pack/validator.js +2 -2
  123. package/{cli/dist → dist}/core/pack-v2/migrator.d.ts +5 -0
  124. package/{cli/dist → dist}/core/pack-v2/migrator.js +81 -6
  125. package/{cli/dist → dist}/core/pack-v2/validator.js +4 -3
  126. package/{cli/dist → dist}/core/pom/base-page.js +1 -1
  127. package/{cli/dist → dist}/core/pom/loader.js +1 -1
  128. package/dist/core/reporting/index.d.ts +9 -0
  129. package/dist/core/reporting/index.js +10 -0
  130. package/dist/core/reporting/junit-reporter.d.ts +114 -0
  131. package/dist/core/reporting/junit-reporter.js +306 -0
  132. package/{cli/dist → dist}/core/runner/e2e-helpers.d.ts +1 -1
  133. package/{cli/dist → dist}/core/runner/e2e-helpers.js +2 -2
  134. package/{cli/dist → dist}/core/runner/phase3-runner.d.ts +3 -0
  135. package/{cli/dist → dist}/core/runner/phase3-runner.js +45 -14
  136. package/dist/core/sharding/test-sharding.d.ts +137 -0
  137. package/dist/core/sharding/test-sharding.js +233 -0
  138. package/dist/core/storage/cookie-manager.d.ts +160 -0
  139. package/dist/core/storage/cookie-manager.js +268 -0
  140. package/dist/core/storage/index.d.ts +7 -0
  141. package/dist/core/storage/index.js +7 -0
  142. package/dist/core/storage/storage-helpers.d.ts +138 -0
  143. package/dist/core/storage/storage-helpers.js +315 -0
  144. package/dist/core/test-helpers/index.d.ts +6 -0
  145. package/dist/core/test-helpers/index.js +6 -0
  146. package/dist/core/test-helpers/state-reset.d.ts +119 -0
  147. package/dist/core/test-helpers/state-reset.js +234 -0
  148. package/{cli/dist → dist}/core/types/pack-v1.d.ts +15 -2
  149. package/{cli/dist → dist}/core/types/pack-v2.d.ts +1 -1
  150. package/dist/core/upload/chunked-uploader.d.ts +150 -0
  151. package/dist/core/upload/chunked-uploader.js +289 -0
  152. package/dist/core/upload/index.d.ts +11 -0
  153. package/dist/core/upload/index.js +8 -0
  154. package/dist/core/upload/mime-validator.d.ts +119 -0
  155. package/dist/core/upload/mime-validator.js +373 -0
  156. package/dist/core/upload/presigned-uploader.d.ts +118 -0
  157. package/dist/core/upload/presigned-uploader.js +274 -0
  158. package/dist/core/utils/device-emulation.d.ts +194 -0
  159. package/dist/core/utils/device-emulation.js +380 -0
  160. package/dist/core/utils/index.d.ts +8 -0
  161. package/dist/core/utils/index.js +8 -0
  162. package/dist/core/utils/retry.d.ts +145 -0
  163. package/dist/core/utils/retry.js +242 -0
  164. package/dist/core/utils/smart-wait.d.ts +133 -0
  165. package/dist/core/utils/smart-wait.js +417 -0
  166. package/dist/core/visual/index.d.ts +7 -0
  167. package/dist/core/visual/index.js +7 -0
  168. package/dist/core/visual/pixel-diff.d.ts +87 -0
  169. package/dist/core/visual/pixel-diff.js +213 -0
  170. package/dist/core/visual/screenshot-helper.d.ts +130 -0
  171. package/dist/core/visual/screenshot-helper.js +223 -0
  172. package/{cli/dist → dist}/utils/config.d.ts +1 -1
  173. package/examples/README.md +160 -0
  174. package/examples/accessibility.yml +48 -0
  175. package/examples/api-basic.yml +27 -0
  176. package/examples/complete.yml +146 -0
  177. package/examples/crawler.yml +38 -0
  178. package/examples/fullstack.yml +78 -0
  179. package/examples/security.yml +58 -0
  180. package/examples/ui-advanced.yml +49 -0
  181. package/examples/ui-basic.yml +24 -0
  182. package/package.json +33 -67
  183. package/CHANGELOG.md +0 -330
  184. package/CONTRIBUTING.md +0 -273
  185. package/QUICK_START.md +0 -191
  186. package/cli/CHANGELOG.md +0 -84
  187. package/cli/LICENSE +0 -24
  188. package/cli/README.md +0 -222
  189. package/cli/dist/core/adapters/playwright-ui.js +0 -864
  190. package/cli/dist/core/auth/oauth2-provider.js +0 -114
  191. package/cli/dist/core/coverage/analyzer.d.ts +0 -101
  192. package/cli/dist/core/coverage/analyzer.js +0 -415
  193. package/cli/dist/core/coverage/collector.d.ts +0 -74
  194. package/cli/dist/core/coverage/collector.js +0 -459
  195. package/cli/dist/core/coverage/config.d.ts +0 -37
  196. package/cli/dist/core/coverage/config.js +0 -156
  197. package/cli/dist/core/coverage/index.d.ts +0 -11
  198. package/cli/dist/core/coverage/index.js +0 -15
  199. package/cli/dist/core/coverage/types.d.ts +0 -267
  200. package/cli/dist/core/coverage/types.js +0 -6
  201. package/cli/dist/core/coverage/vault.d.ts +0 -95
  202. package/cli/dist/core/coverage/vault.js +0 -405
  203. package/cli/dist/core/crawler/index.d.ts +0 -57
  204. package/cli/dist/core/fixtures/index.d.ts +0 -8
  205. package/cli/dist/core/fixtures/index.js +0 -8
  206. package/cli/dist/core/generation/crawler-pack-generator.js +0 -231
  207. package/cli/dist/core/reporting/index.d.ts +0 -6
  208. package/cli/dist/core/reporting/index.js +0 -6
  209. package/cli/dist/core/visual/index.d.ts +0 -6
  210. package/cli/dist/core/visual/index.js +0 -6
  211. package/cli/package.json +0 -76
  212. package/core/LICENSE +0 -24
  213. package/core/README.md +0 -105
  214. package/core/package.json +0 -90
  215. package/core/schemas/pack.schema.json +0 -236
  216. /package/{cli/bin → bin}/qa360.js +0 -0
  217. /package/{cli/dist → dist}/cli-minimal.d.ts +0 -0
  218. /package/{cli/dist → dist}/cli-minimal.js +0 -0
  219. /package/{cli/dist → dist}/commands/ai.d.ts +0 -0
  220. /package/{cli/dist → dist}/commands/ask.d.ts +0 -0
  221. /package/{cli/dist → dist}/commands/ask.js +0 -0
  222. /package/{cli/dist → dist}/commands/coverage.d.ts +0 -0
  223. /package/{cli/dist → dist}/commands/crawl.d.ts +0 -0
  224. /package/{cli/dist → dist}/commands/doctor.d.ts +0 -0
  225. /package/{cli/dist → dist}/commands/examples.d.ts +0 -0
  226. /package/{cli/dist → dist}/commands/examples.js +0 -0
  227. /package/{cli/dist → dist}/commands/explain.d.ts +0 -0
  228. /package/{cli/dist → dist}/commands/flakiness.d.ts +0 -0
  229. /package/{cli/dist → dist}/commands/generate.d.ts +0 -0
  230. /package/{cli/dist → dist}/commands/history.d.ts +0 -0
  231. /package/{cli/dist → dist}/commands/init.d.ts +0 -0
  232. /package/{cli/dist → dist}/commands/init.js +0 -0
  233. /package/{cli/dist → dist}/commands/monitor.d.ts +0 -0
  234. /package/{cli/dist → dist}/commands/ollama.d.ts +0 -0
  235. /package/{cli/dist → dist}/commands/pack.d.ts +0 -0
  236. /package/{cli/dist → dist}/commands/regression.d.ts +0 -0
  237. /package/{cli/dist → dist}/commands/repair.d.ts +0 -0
  238. /package/{cli/dist → dist}/commands/report.d.ts +0 -0
  239. /package/{cli/dist → dist}/commands/report.js +0 -0
  240. /package/{cli/dist → dist}/commands/retry.d.ts +0 -0
  241. /package/{cli/dist → dist}/commands/scan.d.ts +0 -0
  242. /package/{cli/dist → dist}/commands/scan.js +0 -0
  243. /package/{cli/dist → dist}/commands/secrets.d.ts +0 -0
  244. /package/{cli/dist → dist}/commands/serve.d.ts +0 -0
  245. /package/{cli/dist → dist}/commands/slo.d.ts +0 -0
  246. /package/{cli/dist → dist}/commands/verify.d.ts +0 -0
  247. /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.d.ts +0 -0
  248. /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.js +0 -0
  249. /package/{cli/dist → dist}/core/adapters/jest-adapter.d.ts +0 -0
  250. /package/{cli/dist → dist}/core/adapters/jest-adapter.js +0 -0
  251. /package/{cli/dist → dist}/core/adapters/k6-perf.d.ts +0 -0
  252. /package/{cli/dist → dist}/core/adapters/k6-perf.js +0 -0
  253. /package/{cli/dist → dist}/core/adapters/osv-deps.d.ts +0 -0
  254. /package/{cli/dist → dist}/core/adapters/osv-deps.js +0 -0
  255. /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.d.ts +0 -0
  256. /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.js +0 -0
  257. /package/{cli/dist → dist}/core/adapters/pytest-adapter.d.ts +0 -0
  258. /package/{cli/dist → dist}/core/adapters/pytest-adapter.js +0 -0
  259. /package/{cli/dist → dist}/core/adapters/semgrep-sast.d.ts +0 -0
  260. /package/{cli/dist → dist}/core/adapters/semgrep-sast.js +0 -0
  261. /package/{cli/dist → dist}/core/adapters/unit-test-types.d.ts +0 -0
  262. /package/{cli/dist → dist}/core/adapters/unit-test-types.js +0 -0
  263. /package/{cli/dist → dist}/core/adapters/vitest-adapter.d.ts +0 -0
  264. /package/{cli/dist → dist}/core/adapters/vitest-adapter.js +0 -0
  265. /package/{cli/dist → dist}/core/adapters/zap-dast.d.ts +0 -0
  266. /package/{cli/dist → dist}/core/adapters/zap-dast.js +0 -0
  267. /package/{cli/dist → dist}/core/ai/anthropic-provider.d.ts +0 -0
  268. /package/{cli/dist → dist}/core/ai/anthropic-provider.js +0 -0
  269. /package/{cli/dist → dist}/core/ai/deepseek-provider.d.ts +0 -0
  270. /package/{cli/dist → dist}/core/ai/deepseek-provider.js +0 -0
  271. /package/{cli/dist → dist}/core/ai/index.d.ts +0 -0
  272. /package/{cli/dist → dist}/core/ai/index.js +0 -0
  273. /package/{cli/dist → dist}/core/ai/llm-client.d.ts +0 -0
  274. /package/{cli/dist → dist}/core/ai/llm-client.js +0 -0
  275. /package/{cli/dist → dist}/core/ai/mock-provider.d.ts +0 -0
  276. /package/{cli/dist → dist}/core/ai/mock-provider.js +0 -0
  277. /package/{cli/dist → dist}/core/ai/ollama-provider.d.ts +0 -0
  278. /package/{cli/dist → dist}/core/ai/openai-provider.d.ts +0 -0
  279. /package/{cli/dist → dist}/core/ai/openai-provider.js +0 -0
  280. /package/{cli/dist → dist}/core/ai/provider-factory.d.ts +0 -0
  281. /package/{cli/dist → dist}/core/ai/provider-factory.js +0 -0
  282. /package/{cli/dist → dist}/core/artifacts/index.d.ts +0 -0
  283. /package/{cli/dist → dist}/core/artifacts/index.js +0 -0
  284. /package/{cli/dist → dist}/core/artifacts/ui-artifacts.d.ts +0 -0
  285. /package/{cli/dist → dist}/core/assertions/engine.d.ts +0 -0
  286. /package/{cli/dist → dist}/core/assertions/engine.js +0 -0
  287. /package/{cli/dist → dist}/core/assertions/index.d.ts +0 -0
  288. /package/{cli/dist → dist}/core/assertions/index.js +0 -0
  289. /package/{cli/dist → dist}/core/assertions/types.d.ts +0 -0
  290. /package/{cli/dist → dist}/core/assertions/types.js +0 -0
  291. /package/{cli/dist → dist}/core/auth/api-key-provider.d.ts +0 -0
  292. /package/{cli/dist → dist}/core/auth/api-key-provider.js +0 -0
  293. /package/{cli/dist → dist}/core/auth/aws-iam-provider.d.ts +0 -0
  294. /package/{cli/dist → dist}/core/auth/aws-iam-provider.js +0 -0
  295. /package/{cli/dist → dist}/core/auth/azure-ad-provider.d.ts +0 -0
  296. /package/{cli/dist → dist}/core/auth/azure-ad-provider.js +0 -0
  297. /package/{cli/dist → dist}/core/auth/gcp-adc-provider.d.ts +0 -0
  298. /package/{cli/dist → dist}/core/auth/gcp-adc-provider.js +0 -0
  299. /package/{cli/dist → dist}/core/auth/jwt-provider.d.ts +0 -0
  300. /package/{cli/dist → dist}/core/auth/jwt-provider.js +0 -0
  301. /package/{cli/dist → dist}/core/auth/manager.d.ts +0 -0
  302. /package/{cli/dist → dist}/core/auth/manager.js +0 -0
  303. /package/{cli/dist → dist}/core/auth/totp-provider.d.ts +0 -0
  304. /package/{cli/dist → dist}/core/auth/totp-provider.js +0 -0
  305. /package/{cli/dist → dist}/core/auth/ui-login-provider.d.ts +0 -0
  306. /package/{cli/dist → dist}/core/auth/ui-login-provider.js +0 -0
  307. /package/{cli/dist → dist}/core/cache/index.d.ts +0 -0
  308. /package/{cli/dist → dist}/core/cache/index.js +0 -0
  309. /package/{cli/dist → dist}/core/cache/lru-cache.d.ts +0 -0
  310. /package/{cli/dist → dist}/core/cache/lru-cache.js +0 -0
  311. /package/{cli/dist/core → dist}/core/coverage/analyzer.d.ts +0 -0
  312. /package/{cli/dist/core → dist}/core/coverage/analyzer.js +0 -0
  313. /package/{cli/dist/core → dist}/core/coverage/collector.d.ts +0 -0
  314. /package/{cli/dist/core → dist}/core/coverage/collector.js +0 -0
  315. /package/{cli/dist/core → dist}/core/coverage/config.d.ts +0 -0
  316. /package/{cli/dist/core → dist}/core/coverage/config.js +0 -0
  317. /package/{cli/dist/core → dist}/core/coverage/index.d.ts +0 -0
  318. /package/{cli/dist/core → dist}/core/coverage/index.js +0 -0
  319. /package/{cli/dist/core → dist}/core/coverage/types.d.ts +0 -0
  320. /package/{cli/dist/core → dist}/core/coverage/types.js +0 -0
  321. /package/{cli/dist/core → dist}/core/coverage/vault.d.ts +0 -0
  322. /package/{cli/dist/core → dist}/core/coverage/vault.js +0 -0
  323. /package/{cli/dist → dist}/core/crawler/journey-generator.d.ts +0 -0
  324. /package/{cli/dist → dist}/core/crawler/types.js +0 -0
  325. /package/{cli/dist → dist}/core/dashboard/assets.d.ts +0 -0
  326. /package/{cli/dist → dist}/core/dashboard/assets.js +0 -0
  327. /package/{cli/dist → dist}/core/dashboard/index.d.ts +0 -0
  328. /package/{cli/dist → dist}/core/dashboard/index.js +0 -0
  329. /package/{cli/dist → dist}/core/dashboard/server.d.ts +0 -0
  330. /package/{cli/dist → dist}/core/dashboard/server.js +0 -0
  331. /package/{cli/dist → dist}/core/dashboard/types.d.ts +0 -0
  332. /package/{cli/dist → dist}/core/dashboard/types.js +0 -0
  333. /package/{cli/dist → dist}/core/discoverer/index.d.ts +0 -0
  334. /package/{cli/dist → dist}/core/discoverer/index.js +0 -0
  335. /package/{cli/dist → dist}/core/fixtures/loader.d.ts +0 -0
  336. /package/{cli/dist → dist}/core/fixtures/loader.js +0 -0
  337. /package/{cli/dist → dist}/core/fixtures/resolver.d.ts +0 -0
  338. /package/{cli/dist → dist}/core/fixtures/resolver.js +0 -0
  339. /package/{cli/dist → dist}/core/fixtures/types.d.ts +0 -0
  340. /package/{cli/dist → dist}/core/fixtures/types.js +0 -0
  341. /package/{cli/dist → dist}/core/flakiness/index.d.ts +0 -0
  342. /package/{cli/dist → dist}/core/flakiness/index.js +0 -0
  343. /package/{cli/dist → dist}/core/generation/code-formatter.d.ts +0 -0
  344. /package/{cli/dist → dist}/core/generation/code-formatter.js +0 -0
  345. /package/{cli/dist → dist}/core/generation/code-generator.d.ts +0 -0
  346. /package/{cli/dist → dist}/core/generation/code-generator.js +0 -0
  347. /package/{cli/dist → dist}/core/generation/generator.d.ts +0 -0
  348. /package/{cli/dist → dist}/core/generation/generator.js +0 -0
  349. /package/{cli/dist → dist}/core/generation/pack-generator.d.ts +0 -0
  350. /package/{cli/dist → dist}/core/generation/pack-generator.js +0 -0
  351. /package/{cli/dist → dist}/core/generation/prompt-builder.d.ts +0 -0
  352. /package/{cli/dist → dist}/core/generation/prompt-builder.js +0 -0
  353. /package/{cli/dist → dist}/core/generation/source-analyzer.d.ts +0 -0
  354. /package/{cli/dist → dist}/core/generation/source-analyzer.js +0 -0
  355. /package/{cli/dist → dist}/core/generation/test-optimizer.d.ts +0 -0
  356. /package/{cli/dist → dist}/core/generation/test-optimizer.js +0 -0
  357. /package/{cli/dist → dist}/core/generation/types.d.ts +0 -0
  358. /package/{cli/dist → dist}/core/generation/types.js +0 -0
  359. /package/{cli/dist → dist}/core/hooks/compose.d.ts +0 -0
  360. /package/{cli/dist → dist}/core/hooks/compose.js +0 -0
  361. /package/{cli/dist → dist}/core/hooks/runner.d.ts +0 -0
  362. /package/{cli/dist → dist}/core/hooks/runner.js +0 -0
  363. /package/{cli/dist → dist}/core/pack/migrator.d.ts +0 -0
  364. /package/{cli/dist → dist}/core/pack/migrator.js +0 -0
  365. /package/{cli/dist → dist}/core/pack/validator.d.ts +0 -0
  366. /package/{cli/dist → dist}/core/pack-v2/index.d.ts +0 -0
  367. /package/{cli/dist → dist}/core/pack-v2/index.js +0 -0
  368. /package/{cli/dist → dist}/core/pack-v2/loader.d.ts +0 -0
  369. /package/{cli/dist → dist}/core/pack-v2/loader.js +0 -0
  370. /package/{cli/dist → dist}/core/pack-v2/validator.d.ts +0 -0
  371. /package/{cli/dist → dist}/core/parallel/index.d.ts +0 -0
  372. /package/{cli/dist → dist}/core/parallel/index.js +0 -0
  373. /package/{cli/dist → dist}/core/parallel/parallel-runner.d.ts +0 -0
  374. /package/{cli/dist → dist}/core/parallel/parallel-runner.js +0 -0
  375. /package/{cli/dist → dist}/core/pom/base-page.d.ts +0 -0
  376. /package/{cli/dist → dist}/core/pom/index.d.ts +0 -0
  377. /package/{cli/dist → dist}/core/pom/index.js +0 -0
  378. /package/{cli/dist → dist}/core/pom/loader.d.ts +0 -0
  379. /package/{cli/dist → dist}/core/pom/types.d.ts +0 -0
  380. /package/{cli/dist → dist}/core/pom/types.js +0 -0
  381. /package/{cli/dist → dist}/core/proof/bundle.d.ts +0 -0
  382. /package/{cli/dist → dist}/core/proof/bundle.js +0 -0
  383. /package/{cli/dist → dist}/core/proof/canonicalize.d.ts +0 -0
  384. /package/{cli/dist → dist}/core/proof/canonicalize.js +0 -0
  385. /package/{cli/dist → dist}/core/proof/index.d.ts +0 -0
  386. /package/{cli/dist → dist}/core/proof/index.js +0 -0
  387. /package/{cli/dist → dist}/core/proof/schema.d.ts +0 -0
  388. /package/{cli/dist → dist}/core/proof/schema.js +0 -0
  389. /package/{cli/dist → dist}/core/proof/signer.d.ts +0 -0
  390. /package/{cli/dist → dist}/core/proof/signer.js +0 -0
  391. /package/{cli/dist → dist}/core/proof/verifier.d.ts +0 -0
  392. /package/{cli/dist → dist}/core/proof/verifier.js +0 -0
  393. /package/{cli/dist → dist}/core/regression/detector.d.ts +0 -0
  394. /package/{cli/dist → dist}/core/regression/detector.js +0 -0
  395. /package/{cli/dist → dist}/core/regression/index.d.ts +0 -0
  396. /package/{cli/dist → dist}/core/regression/index.js +0 -0
  397. /package/{cli/dist → dist}/core/regression/trend-analyzer.d.ts +0 -0
  398. /package/{cli/dist → dist}/core/regression/trend-analyzer.js +0 -0
  399. /package/{cli/dist → dist}/core/regression/types.d.ts +0 -0
  400. /package/{cli/dist → dist}/core/regression/types.js +0 -0
  401. /package/{cli/dist → dist}/core/regression/vault.d.ts +0 -0
  402. /package/{cli/dist → dist}/core/regression/vault.js +0 -0
  403. /package/{cli/dist → dist}/core/repair/engine/fixer.d.ts +0 -0
  404. /package/{cli/dist → dist}/core/repair/engine/fixer.js +0 -0
  405. /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.d.ts +0 -0
  406. /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.js +0 -0
  407. /package/{cli/dist → dist}/core/repair/index.d.ts +0 -0
  408. /package/{cli/dist → dist}/core/repair/index.js +0 -0
  409. /package/{cli/dist → dist}/core/repair/repairer.d.ts +0 -0
  410. /package/{cli/dist → dist}/core/repair/repairer.js +0 -0
  411. /package/{cli/dist → dist}/core/repair/types.d.ts +0 -0
  412. /package/{cli/dist → dist}/core/repair/types.js +0 -0
  413. /package/{cli/dist → dist}/core/repair/utils/error-analyzer.d.ts +0 -0
  414. /package/{cli/dist → dist}/core/repair/utils/error-analyzer.js +0 -0
  415. /package/{cli/dist → dist}/core/reporting/html-reporter.d.ts +0 -0
  416. /package/{cli/dist → dist}/core/reporting/html-reporter.js +0 -0
  417. /package/{cli/dist → dist}/core/retry/flakiness-integration.d.ts +0 -0
  418. /package/{cli/dist → dist}/core/retry/flakiness-integration.js +0 -0
  419. /package/{cli/dist → dist}/core/retry/index.d.ts +0 -0
  420. /package/{cli/dist → dist}/core/retry/index.js +0 -0
  421. /package/{cli/dist → dist}/core/retry/retry-engine.d.ts +0 -0
  422. /package/{cli/dist → dist}/core/retry/retry-engine.js +0 -0
  423. /package/{cli/dist → dist}/core/retry/types.d.ts +0 -0
  424. /package/{cli/dist → dist}/core/retry/types.js +0 -0
  425. /package/{cli/dist → dist}/core/retry/vault.d.ts +0 -0
  426. /package/{cli/dist → dist}/core/retry/vault.js +0 -0
  427. /package/{cli/dist → dist}/core/schemas/pack.schema.json +0 -0
  428. /package/{cli/dist → dist}/core/secrets/crypto.d.ts +0 -0
  429. /package/{cli/dist → dist}/core/secrets/crypto.js +0 -0
  430. /package/{cli/dist → dist}/core/secrets/manager.d.ts +0 -0
  431. /package/{cli/dist → dist}/core/secrets/manager.js +0 -0
  432. /package/{cli/dist → dist}/core/security/redaction-patterns-extended.d.ts +0 -0
  433. /package/{cli/dist → dist}/core/security/redaction-patterns-extended.js +0 -0
  434. /package/{cli/dist → dist}/core/security/redactor.d.ts +0 -0
  435. /package/{cli/dist → dist}/core/security/redactor.js +0 -0
  436. /package/{cli/dist → dist}/core/self-healing/assertion-healer.d.ts +0 -0
  437. /package/{cli/dist → dist}/core/self-healing/assertion-healer.js +0 -0
  438. /package/{cli/dist → dist}/core/self-healing/engine.d.ts +0 -0
  439. /package/{cli/dist → dist}/core/self-healing/engine.js +0 -0
  440. /package/{cli/dist → dist}/core/self-healing/index.d.ts +0 -0
  441. /package/{cli/dist → dist}/core/self-healing/index.js +0 -0
  442. /package/{cli/dist → dist}/core/self-healing/selector-healer.d.ts +0 -0
  443. /package/{cli/dist → dist}/core/self-healing/selector-healer.js +0 -0
  444. /package/{cli/dist → dist}/core/self-healing/types.d.ts +0 -0
  445. /package/{cli/dist → dist}/core/self-healing/types.js +0 -0
  446. /package/{cli/dist → dist}/core/serve/diagnostics-collector.d.ts +0 -0
  447. /package/{cli/dist → dist}/core/serve/diagnostics-collector.js +0 -0
  448. /package/{cli/dist → dist}/core/serve/health-checker.d.ts +0 -0
  449. /package/{cli/dist → dist}/core/serve/health-checker.js +0 -0
  450. /package/{cli/dist → dist}/core/serve/index.d.ts +0 -0
  451. /package/{cli/dist → dist}/core/serve/index.js +0 -0
  452. /package/{cli/dist → dist}/core/serve/metrics-collector.d.ts +0 -0
  453. /package/{cli/dist → dist}/core/serve/metrics-collector.js +0 -0
  454. /package/{cli/dist → dist}/core/serve/process-manager.d.ts +0 -0
  455. /package/{cli/dist → dist}/core/serve/process-manager.js +0 -0
  456. /package/{cli/dist → dist}/core/serve/server.d.ts +0 -0
  457. /package/{cli/dist → dist}/core/serve/server.js +0 -0
  458. /package/{cli/dist → dist}/core/slo/config.d.ts +0 -0
  459. /package/{cli/dist → dist}/core/slo/config.js +0 -0
  460. /package/{cli/dist → dist}/core/slo/index.d.ts +0 -0
  461. /package/{cli/dist → dist}/core/slo/index.js +0 -0
  462. /package/{cli/dist → dist}/core/slo/sli-calculator.d.ts +0 -0
  463. /package/{cli/dist → dist}/core/slo/sli-calculator.js +0 -0
  464. /package/{cli/dist → dist}/core/slo/slo-tracker.d.ts +0 -0
  465. /package/{cli/dist → dist}/core/slo/slo-tracker.js +0 -0
  466. /package/{cli/dist → dist}/core/slo/types.d.ts +0 -0
  467. /package/{cli/dist → dist}/core/slo/types.js +0 -0
  468. /package/{cli/dist → dist}/core/slo/vault.d.ts +0 -0
  469. /package/{cli/dist → dist}/core/slo/vault.js +0 -0
  470. /package/{cli/dist → dist}/core/tui/index.d.ts +0 -0
  471. /package/{cli/dist → dist}/core/tui/index.js +0 -0
  472. /package/{cli/dist → dist}/core/tui/monitor.d.ts +0 -0
  473. /package/{cli/dist → dist}/core/tui/monitor.js +0 -0
  474. /package/{cli/dist → dist}/core/tui/renderer.d.ts +0 -0
  475. /package/{cli/dist → dist}/core/tui/renderer.js +0 -0
  476. /package/{cli/dist → dist}/core/tui/types.d.ts +0 -0
  477. /package/{cli/dist → dist}/core/tui/types.js +0 -0
  478. /package/{cli/dist → dist}/core/types/pack-v1.js +0 -0
  479. /package/{cli/dist → dist}/core/types/pack-v2.js +0 -0
  480. /package/{cli/dist → dist}/core/types/trust-score.d.ts +0 -0
  481. /package/{cli/dist → dist}/core/types/trust-score.js +0 -0
  482. /package/{cli/dist → dist}/core/vault/cas.d.ts +0 -0
  483. /package/{cli/dist → dist}/core/vault/cas.js +0 -0
  484. /package/{cli/dist → dist}/core/vault/index.d.ts +0 -0
  485. /package/{cli/dist → dist}/core/vault/index.js +0 -0
  486. /package/{cli/dist → dist}/core/visual/visual-regression.d.ts +0 -0
  487. /package/{cli/dist → dist}/core/visual/visual-regression.js +0 -0
  488. /package/{cli/dist → dist}/core/watch/index.d.ts +0 -0
  489. /package/{cli/dist → dist}/core/watch/index.js +0 -0
  490. /package/{cli/dist → dist}/core/watch/watch-mode.d.ts +0 -0
  491. /package/{cli/dist → dist}/core/watch/watch-mode.js +0 -0
  492. /package/{cli/dist → dist}/generators/index.d.ts +0 -0
  493. /package/{cli/dist → dist}/generators/index.js +0 -0
  494. /package/{cli/dist → dist}/generators/json-reporter.d.ts +0 -0
  495. /package/{cli/dist → dist}/generators/json-reporter.js +0 -0
  496. /package/{cli/dist → dist}/generators/test-generator.d.ts +0 -0
  497. /package/{cli/dist → dist}/generators/test-generator.js +0 -0
  498. /package/{cli/dist → dist}/index.d.ts +0 -0
  499. /package/{cli/dist → dist}/index.js +0 -0
  500. /package/{cli/dist → dist}/scanners/dom-scanner.d.ts +0 -0
  501. /package/{cli/dist → dist}/scanners/dom-scanner.js +0 -0
  502. /package/{cli/dist → dist}/scanners/index.d.ts +0 -0
  503. /package/{cli/dist → dist}/scanners/index.js +0 -0
  504. /package/{cli/dist → dist}/schemas/pack.schema.json +0 -0
  505. /package/{cli/dist → dist}/types/scan.d.ts +0 -0
  506. /package/{cli/dist → dist}/types/scan.js +0 -0
  507. /package/{cli/dist → dist}/utils/config.js +0 -0
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Digest Authentication Provider
3
+ *
4
+ * Implements HTTP Digest Authentication (RFC 2617).
5
+ * Handles challenge-response flow with nonce handling.
6
+ *
7
+ * P1 Feature: Digest Auth is more secure than Basic Auth as it doesn't send
8
+ * the password in plaintext. Instead, it uses a challenge-response mechanism
9
+ * with MD5 hashing.
10
+ *
11
+ * Algorithm:
12
+ * 1. Client makes request without auth
13
+ * 2. Server responds with 401 and WWW-Authenticate header containing:
14
+ * - realm: Protection space
15
+ * - nonce: Server-generated unique value
16
+ * - qop: Quality of protection (auth or auth-int)
17
+ * - opaque: Client should return unchanged
18
+ * 3. Client calculates response using MD5 and retries
19
+ *
20
+ * Response calculation:
21
+ * HA1 = MD5(username:realm:password)
22
+ * HA2 = MD5(method:digestURI)
23
+ * response = MD5(HA1:nonce:HA2) // simplified
24
+ */
25
+ import { createCacheKey, authCache } from './index.js';
26
+ /**
27
+ * Generates MD5 hash using Node.js crypto
28
+ */
29
+ function md5Hash(data) {
30
+ const crypto = require('node:crypto');
31
+ return crypto.createHash('md5').update(data).digest('hex');
32
+ }
33
+ /**
34
+ * Generates a client nonce (cnonce)
35
+ */
36
+ function generateCnonce() {
37
+ const crypto = require('node:crypto');
38
+ return crypto.randomBytes(16).toString('hex').substring(0, 32);
39
+ }
40
+ /**
41
+ * Parses WWW-Authenticate header for Digest challenge
42
+ * @example
43
+ * parseDigestHeader('Digest realm="test", nonce="abc123", qop="auth"')
44
+ * // => { realm: 'test', nonce: 'abc123', qop: 'auth' }
45
+ */
46
+ export function parseDigestHeader(header) {
47
+ if (!header.toLowerCase().startsWith('digest ')) {
48
+ return null;
49
+ }
50
+ const challengePart = header.substring(7);
51
+ const result = {};
52
+ // Parse key="value" pairs
53
+ const pairs = challengePart.match(/(\w+)="([^"]*)"/g);
54
+ if (!pairs) {
55
+ return null;
56
+ }
57
+ for (const pair of pairs) {
58
+ const match = pair.match(/(\w+)="([^"]*)"/);
59
+ if (match) {
60
+ const [, key, value] = match;
61
+ result[key] = value;
62
+ }
63
+ }
64
+ if (!result.realm || !result.nonce) {
65
+ return null;
66
+ }
67
+ return result;
68
+ }
69
+ /**
70
+ * Calculates Digest response
71
+ * @param username Username
72
+ * @param password Password
73
+ * @param realm Realm from challenge
74
+ * @param nonce Nonce from challenge
75
+ * @param method HTTP method
76
+ * @param uri Request URI
77
+ * @param qop Quality of protection
78
+ * @param opaque Opaque value from challenge
79
+ * @param nc Nonce count
80
+ * @param cnonce Client nonce
81
+ */
82
+ export function calculateDigestResponse(username, password, realm, nonce, method, uri, qop, opaque, nc = '00000001', cnonce) {
83
+ const clientCnonce = cnonce || generateCnonce();
84
+ // HA1 = MD5(username:realm:password)
85
+ const ha1 = md5Hash(`${username}:${realm}:${password}`);
86
+ // HA2 = MD5(method:uri)
87
+ const ha2 = md5Hash(`${method}:${uri}`);
88
+ // Response
89
+ let response;
90
+ if (qop) {
91
+ // response = MD5(HA1:nonce:nc:cnonce:qop:HA2)
92
+ response = md5Hash(`${ha1}:${nonce}:${nc}:${clientCnonce}:${qop}:${ha2}`);
93
+ }
94
+ else {
95
+ // response = MD5(HA1:nonce:HA2)
96
+ response = md5Hash(`${ha1}:${nonce}:${ha2}`);
97
+ }
98
+ // Build Authorization header value
99
+ const parts = [
100
+ `username="${username}"`,
101
+ `realm="${realm}"`,
102
+ `nonce="${nonce}"`,
103
+ `uri="${uri}"`,
104
+ `response="${response}"`,
105
+ `algorithm=MD5`,
106
+ ];
107
+ if (qop) {
108
+ parts.push(`qop=${qop}`);
109
+ parts.push(`nc=${nc}`);
110
+ parts.push(`cnonce="${clientCnonce}"`);
111
+ }
112
+ if (opaque) {
113
+ parts.push(`opaque="${opaque}"`);
114
+ }
115
+ return `Digest ${parts.join(', ')}`;
116
+ }
117
+ /**
118
+ * Digest Authentication Provider
119
+ */
120
+ export class DigestAuthProvider {
121
+ type = 'digest';
122
+ storedChallenges = new Map();
123
+ nonceCounters = new Map();
124
+ async authenticate(config) {
125
+ const { username, password, realm, cache } = config;
126
+ if (!username || !password) {
127
+ return {
128
+ success: false,
129
+ error: 'Username and password are required for Digest auth'
130
+ };
131
+ }
132
+ const cacheKey = this.getCacheKey(config);
133
+ // Check cache first
134
+ if (cache?.enabled !== false) {
135
+ const cached = authCache.get(cacheKey);
136
+ if (cached) {
137
+ return { success: true, credentials: cached };
138
+ }
139
+ }
140
+ // For Digest auth, we need to make an initial request to get the challenge
141
+ // This will be handled by the adapter when it receives a 401
142
+ // For now, return credentials that can be used to build the header
143
+ const credentials = {
144
+ type: 'digest',
145
+ username,
146
+ password, // Store password securely for challenge response
147
+ realm,
148
+ headers: {
149
+ // Placeholder - actual header will be built on 401 response
150
+ 'X-Digest-Auth-User': username,
151
+ }
152
+ };
153
+ // Cache if enabled
154
+ if (cache?.enabled !== false) {
155
+ const ttl = cache?.ttl || 3600;
156
+ authCache.set(cacheKey, credentials, ttl);
157
+ }
158
+ return {
159
+ success: true,
160
+ credentials
161
+ };
162
+ }
163
+ /**
164
+ * Stores a Digest challenge received from server
165
+ */
166
+ storeChallenge(url, challenge) {
167
+ this.storedChallenges.set(url, challenge);
168
+ }
169
+ /**
170
+ * Retrieves stored challenge for a URL
171
+ */
172
+ getChallenge(url) {
173
+ return this.storedChallenges.get(url);
174
+ }
175
+ /**
176
+ * Builds Authorization header for a request using stored challenge
177
+ */
178
+ async buildAuthorizationHeader(url, method, config) {
179
+ const challenge = this.getChallenge(url);
180
+ if (!challenge) {
181
+ return null;
182
+ }
183
+ const uri = new URL(url).pathname + new URL(url).search;
184
+ const nc = this.getNonceCount(challenge.nonce);
185
+ const cnonce = generateCnonce();
186
+ return calculateDigestResponse(config.username, config.password, challenge.realm, challenge.nonce, method, uri, challenge.qop, challenge.opaque, nc, cnonce);
187
+ }
188
+ /**
189
+ * Gets next nonce count for a given nonce
190
+ */
191
+ getNonceCount(nonce) {
192
+ const current = this.nonceCounters.get(nonce) || 0;
193
+ this.nonceCounters.set(nonce, current + 1);
194
+ return current.toString(16).padStart(8, '0');
195
+ }
196
+ /**
197
+ * Handles 401 response and returns new request headers
198
+ */
199
+ async handleChallenge(url, method, authenticateHeader, config) {
200
+ const challenge = parseDigestHeader(authenticateHeader);
201
+ if (!challenge) {
202
+ return null;
203
+ }
204
+ this.storeChallenge(url, challenge);
205
+ const authHeader = await this.buildAuthorizationHeader(url, method, config);
206
+ if (!authHeader) {
207
+ return null;
208
+ }
209
+ return {
210
+ 'Authorization': authHeader
211
+ };
212
+ }
213
+ async clear(config) {
214
+ const key = this.getCacheKey(config);
215
+ authCache.clear(key);
216
+ }
217
+ async validate(config) {
218
+ return !!(config.username && config.password);
219
+ }
220
+ getCacheKey(config) {
221
+ const crypto = require('node:crypto');
222
+ const hash = crypto
223
+ .createHash('sha256')
224
+ .update(`${config.username}:${config.realm || ''}`)
225
+ .digest('hex')
226
+ .substring(0, 16);
227
+ return createCacheKey('digest', hash);
228
+ }
229
+ /**
230
+ * Clears stored challenges and counters
231
+ */
232
+ clearState() {
233
+ this.storedChallenges.clear();
234
+ this.nonceCounters.clear();
235
+ }
236
+ }
237
+ /**
238
+ * Creates a Digest auth provider instance
239
+ */
240
+ export function createDigestAuthProvider() {
241
+ return new DigestAuthProvider();
242
+ }
243
+ // Re-export types and utilities
244
+ // Types are exported from index.ts
@@ -0,0 +1,103 @@
1
+ /**
2
+ * hCaptcha Handler
3
+ *
4
+ * Supports hCaptcha (privacy-focused CAPTCHA alternative)
5
+ *
6
+ * Test mode bypass uses hCaptcha's official test keys:
7
+ * - Site key: 10000000-ffff-ffff-ffff-000000000001
8
+ * - Secret key: 0x0000000000000000000000000000000000000000
9
+ *
10
+ * @see https://docs.hcaptcha.com/#integration-testing-test-keys
11
+ */
12
+ export interface HcaptchaConfig {
13
+ /** Site key for hCaptcha */
14
+ siteKey?: string;
15
+ /** Use test mode (always returns valid token) */
16
+ testMode?: boolean;
17
+ /** CSS selector for the hCaptcha container */
18
+ selector?: string;
19
+ /** Timeout for solving (ms) */
20
+ timeout?: number;
21
+ /** hCaptcha is invisible/challenge-only */
22
+ isInvisible?: boolean;
23
+ }
24
+ export interface HcaptchaTokenResponse {
25
+ success: boolean;
26
+ token: string;
27
+ challengeTs?: string;
28
+ hostname?: string;
29
+ errorCodes?: string[];
30
+ }
31
+ export declare const HCAPTCHA_TEST_SITE_KEY = "10000000-ffff-ffff-ffff-000000000001";
32
+ export declare const HCAPTCHA_TEST_SECRET = "0x0000000000000000000000000000000000000000";
33
+ export declare class HcaptchaHandler {
34
+ private testMode;
35
+ private timeout;
36
+ constructor(options?: {
37
+ testMode?: boolean;
38
+ timeout?: number;
39
+ });
40
+ /**
41
+ * Detect if hCaptcha is present on the page
42
+ */
43
+ detectHcaptcha(page: any): Promise<{
44
+ present: boolean;
45
+ siteKey?: string;
46
+ isInvisible?: boolean;
47
+ }>;
48
+ /**
49
+ * Solve hCaptcha
50
+ *
51
+ * In test mode, injects a test token
52
+ * In production, waits for user interaction
53
+ */
54
+ solve(page: any, config?: HcaptchaConfig): Promise<HcaptchaTokenResponse>;
55
+ /**
56
+ * Solve hCaptcha in test mode
57
+ */
58
+ private solveTestMode;
59
+ /**
60
+ * Solve hCaptcha in production mode (requires human interaction)
61
+ */
62
+ private solveProduction;
63
+ /**
64
+ * Execute hCaptcha (for invisible hCaptcha)
65
+ */
66
+ execute(page: any, config?: HcaptchaConfig): Promise<HcaptchaTokenResponse>;
67
+ /**
68
+ * Verify an hCaptcha token (server-side simulation)
69
+ *
70
+ * In real usage, this would call hCaptcha's siteverify API:
71
+ * POST https://hcaptcha.com/siteverify
72
+ */
73
+ verifyToken(token: string, secret?: string): Promise<HcaptchaTokenResponse>;
74
+ /**
75
+ * Wait for hCaptcha to be ready
76
+ */
77
+ waitForReady(page: any, timeout?: number): Promise<boolean>;
78
+ /**
79
+ * Inject test site key into page
80
+ */
81
+ injectTestSiteKey(page: any, elementSelector: string): Promise<void>;
82
+ /**
83
+ * Generate a test token for mocking
84
+ */
85
+ private generateTestToken;
86
+ private sleep;
87
+ /**
88
+ * Reset all hCaptcha widgets on the page
89
+ */
90
+ reset(page: any): Promise<void>;
91
+ /**
92
+ * Get the current response token from hCaptcha
93
+ */
94
+ getResponse(page: any, widgetId?: string): Promise<string | null>;
95
+ }
96
+ /**
97
+ * Factory function to create an hCaptcha handler
98
+ */
99
+ export declare function createHcaptchaHandler(options?: {
100
+ testMode?: boolean;
101
+ timeout?: number;
102
+ }): HcaptchaHandler;
103
+ export default HcaptchaHandler;
@@ -0,0 +1,288 @@
1
+ /**
2
+ * hCaptcha Handler
3
+ *
4
+ * Supports hCaptcha (privacy-focused CAPTCHA alternative)
5
+ *
6
+ * Test mode bypass uses hCaptcha's official test keys:
7
+ * - Site key: 10000000-ffff-ffff-ffff-000000000001
8
+ * - Secret key: 0x0000000000000000000000000000000000000000
9
+ *
10
+ * @see https://docs.hcaptcha.com/#integration-testing-test-keys
11
+ */
12
+ // Test keys from hCaptcha (always return valid responses)
13
+ export const HCAPTCHA_TEST_SITE_KEY = '10000000-ffff-ffff-ffff-000000000001';
14
+ export const HCAPTCHA_TEST_SECRET = '0x0000000000000000000000000000000000000000';
15
+ // Common hCaptcha selectors
16
+ const HCAPTCHA_SELECTORS = [
17
+ 'iframe[src*="hcaptcha"]',
18
+ 'div.h-captcha',
19
+ 'div[data-hcaptcha]',
20
+ 'div[data-sitekey*="0x"]',
21
+ ];
22
+ const BYPASS_SCRIPT = (siteKey, testMode) => `
23
+ (function() {
24
+ if (typeof window.hcaptcha !== 'undefined') {
25
+ window.__qa360_hcaptcha_ready = true;
26
+ return;
27
+ }
28
+
29
+ // Mock hcaptcha object for test mode
30
+ if (${testMode}) {
31
+ window.hcaptcha = {
32
+ ready: function(cb) { cb(); },
33
+ execute: function(siteKey, options) {
34
+ return Promise.resolve({
35
+ response: 'TEST_HCAPTCHA_TOKEN',
36
+ key: '${siteKey}'
37
+ });
38
+ },
39
+ render: function(container, options) {
40
+ return 'hcaptcha-widget-id';
41
+ },
42
+ reset: function(widgetId) {},
43
+ getResponse: function(widgetId) {
44
+ return 'TEST_HCAPTCHA_TOKEN';
45
+ },
46
+ getRespKey: function(widgetId) {
47
+ return '${siteKey}';
48
+ }
49
+ };
50
+ window.__qa360_hcaptcha_ready = true;
51
+ }
52
+ })();
53
+ `;
54
+ export class HcaptchaHandler {
55
+ testMode;
56
+ timeout;
57
+ constructor(options = {}) {
58
+ this.testMode = options.testMode ?? true;
59
+ this.timeout = options.timeout ?? 10000;
60
+ }
61
+ /**
62
+ * Detect if hCaptcha is present on the page
63
+ */
64
+ async detectHcaptcha(page) {
65
+ const result = await page.evaluate(() => {
66
+ // Check for hCaptcha elements
67
+ const hcaptchaDiv = document.querySelector('.h-captcha');
68
+ const dataAttr = document.querySelector('[data-hcaptcha]');
69
+ const hcaptchaIframe = document.querySelector('iframe[src*="hcaptcha"]');
70
+ // Check for invisible hCaptcha
71
+ const isInvisible = !!document.querySelector('[data-sitekey*="invisible"]') ||
72
+ !!document.querySelector('.h-captcha[data-size="invisible"]');
73
+ // Try to extract site key
74
+ let siteKey;
75
+ const siteKeyEl = document.querySelector('[data-sitekey]');
76
+ if (siteKeyEl) {
77
+ siteKey = siteKeyEl.getAttribute('data-sitekey') || undefined;
78
+ }
79
+ return {
80
+ present: !!(hcaptchaDiv || dataAttr || hcaptchaIframe),
81
+ siteKey,
82
+ isInvisible,
83
+ };
84
+ });
85
+ return result;
86
+ }
87
+ /**
88
+ * Solve hCaptcha
89
+ *
90
+ * In test mode, injects a test token
91
+ * In production, waits for user interaction
92
+ */
93
+ async solve(page, config = {}) {
94
+ const { testMode = this.testMode, selector } = config;
95
+ const detection = await this.detectHcaptcha(page);
96
+ if (!detection.present) {
97
+ return {
98
+ success: false,
99
+ token: '',
100
+ errorCodes: ['NO_HCAPTCHA_FOUND'],
101
+ };
102
+ }
103
+ if (testMode) {
104
+ return await this.solveTestMode(page, config);
105
+ }
106
+ // Production mode: Wait for user to solve
107
+ return await this.solveProduction(page, selector, detection.isInvisible);
108
+ }
109
+ /**
110
+ * Solve hCaptcha in test mode
111
+ */
112
+ async solveTestMode(page, config) {
113
+ const siteKey = config.siteKey || HCAPTCHA_TEST_SITE_KEY;
114
+ // Inject bypass script
115
+ await page.evaluate(BYPASS_SCRIPT(siteKey, true));
116
+ // Simulate successful callback
117
+ await page.evaluate((testToken) => {
118
+ // Dispatch custom event that hCaptcha fires on success
119
+ const event = new CustomEvent('hcaptcha-success', {
120
+ detail: { response: testToken }
121
+ });
122
+ window.dispatchEvent(event);
123
+ // Set response on any hCaptcha widgets
124
+ const widgets = document.querySelectorAll('.h-captcha');
125
+ widgets.forEach((widget) => {
126
+ widget.dataset.response = testToken;
127
+ });
128
+ }, this.generateTestToken());
129
+ return {
130
+ success: true,
131
+ token: this.generateTestToken(),
132
+ challengeTs: new Date().toISOString(),
133
+ hostname: 'test.hcaptcha.com',
134
+ };
135
+ }
136
+ /**
137
+ * Solve hCaptcha in production mode (requires human interaction)
138
+ */
139
+ async solveProduction(page, selector, isInvisible) {
140
+ const startTime = Date.now();
141
+ while (Date.now() - startTime < this.timeout) {
142
+ const result = await page.evaluate(() => {
143
+ if (typeof window.hcaptcha === 'undefined') {
144
+ return { ready: false, token: null };
145
+ }
146
+ const response = window.hcaptcha.getResponse();
147
+ if (response) {
148
+ return { ready: true, token: response };
149
+ }
150
+ return { ready: false, token: null };
151
+ });
152
+ if (result.ready && result.token) {
153
+ return {
154
+ success: true,
155
+ token: result.token,
156
+ challengeTs: new Date().toISOString(),
157
+ };
158
+ }
159
+ await this.sleep(500);
160
+ }
161
+ return {
162
+ success: false,
163
+ token: '',
164
+ errorCodes: ['TIMEOUT'],
165
+ };
166
+ }
167
+ /**
168
+ * Execute hCaptcha (for invisible hCaptcha)
169
+ */
170
+ async execute(page, config = {}) {
171
+ const { testMode = this.testMode, isInvisible = false } = config;
172
+ if (testMode) {
173
+ return {
174
+ success: true,
175
+ token: this.generateTestToken(),
176
+ challengeTs: new Date().toISOString(),
177
+ hostname: 'test.hcaptcha.com',
178
+ };
179
+ }
180
+ const result = await page.evaluate(() => {
181
+ if (typeof window.hcaptcha === 'undefined') {
182
+ return { success: false, token: null };
183
+ }
184
+ return window.hcaptcha.execute().then((token) => ({
185
+ success: true,
186
+ token,
187
+ })).catch(() => ({
188
+ success: false,
189
+ token: null,
190
+ }));
191
+ });
192
+ if (!result.success) {
193
+ return {
194
+ success: false,
195
+ token: '',
196
+ errorCodes: ['EXECUTION_FAILED'],
197
+ };
198
+ }
199
+ return {
200
+ success: true,
201
+ token: result.token,
202
+ };
203
+ }
204
+ /**
205
+ * Verify an hCaptcha token (server-side simulation)
206
+ *
207
+ * In real usage, this would call hCaptcha's siteverify API:
208
+ * POST https://hcaptcha.com/siteverify
209
+ */
210
+ async verifyToken(token, secret) {
211
+ if (this.testMode) {
212
+ return {
213
+ success: true,
214
+ token,
215
+ challengeTs: new Date().toISOString(),
216
+ hostname: 'test.hcaptcha.com',
217
+ };
218
+ }
219
+ // Production: Would call siteverify endpoint
220
+ return {
221
+ success: false,
222
+ token,
223
+ errorCodes: ['SITEVERIFY_NOT_IMPLEMENTED'],
224
+ };
225
+ }
226
+ /**
227
+ * Wait for hCaptcha to be ready
228
+ */
229
+ async waitForReady(page, timeout = 10000) {
230
+ const startTime = Date.now();
231
+ while (Date.now() - startTime < timeout) {
232
+ const ready = await page.evaluate(() => typeof window.hcaptcha !== 'undefined');
233
+ if (ready)
234
+ return true;
235
+ await this.sleep(100);
236
+ }
237
+ return false;
238
+ }
239
+ /**
240
+ * Inject test site key into page
241
+ */
242
+ async injectTestSiteKey(page, elementSelector) {
243
+ await page.evaluate((sel, testKey) => {
244
+ const el = document.querySelector(sel);
245
+ if (el) {
246
+ el.setAttribute('data-sitekey', testKey);
247
+ }
248
+ }, elementSelector, HCAPTCHA_TEST_SITE_KEY);
249
+ }
250
+ /**
251
+ * Generate a test token for mocking
252
+ */
253
+ generateTestToken() {
254
+ const timestamp = Date.now();
255
+ return `TEST_HCAPTCHA_TOKEN_${timestamp}`;
256
+ }
257
+ sleep(ms) {
258
+ return new Promise(resolve => setTimeout(resolve, ms));
259
+ }
260
+ /**
261
+ * Reset all hCaptcha widgets on the page
262
+ */
263
+ async reset(page) {
264
+ await page.evaluate(() => {
265
+ if (typeof window.hcaptcha !== 'undefined') {
266
+ window.hcaptcha.reset();
267
+ }
268
+ });
269
+ }
270
+ /**
271
+ * Get the current response token from hCaptcha
272
+ */
273
+ async getResponse(page, widgetId) {
274
+ return await page.evaluate((id) => {
275
+ if (typeof window.hcaptcha === 'undefined') {
276
+ return null;
277
+ }
278
+ return window.hcaptcha.getResponse(id);
279
+ }, widgetId);
280
+ }
281
+ }
282
+ /**
283
+ * Factory function to create an hCaptcha handler
284
+ */
285
+ export function createHcaptchaHandler(options) {
286
+ return new HcaptchaHandler(options);
287
+ }
288
+ export default HcaptchaHandler;