qa360 2.3.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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/ask.js +49 -22
  4. package/{cli/dist → dist}/commands/coverage.js +17 -4
  5. package/{cli/dist → dist}/commands/crawl.js +2 -2
  6. package/{cli/dist → dist}/commands/doctor.js +2 -2
  7. package/{cli/dist → dist}/commands/explain.js +2 -2
  8. package/{cli/dist → dist}/commands/flakiness.js +1 -1
  9. package/{cli/dist → dist}/commands/generate.js +12 -5
  10. package/{cli/dist → dist}/commands/history.js +1 -1
  11. package/{cli/dist → dist}/commands/monitor.js +3 -3
  12. package/{cli/dist → dist}/commands/ollama.js +14 -6
  13. package/{cli/dist → dist}/commands/pack.js +2 -2
  14. package/{cli/dist → dist}/commands/regression.js +1 -1
  15. package/{cli/dist → dist}/commands/repair.js +1 -1
  16. package/{cli/dist → dist}/commands/retry.js +1 -1
  17. package/{cli/dist → dist}/commands/run.d.ts +5 -1
  18. package/{cli/dist → dist}/commands/run.js +87 -1
  19. package/{cli/dist → dist}/commands/secrets.js +1 -1
  20. package/{cli/dist → dist}/commands/serve.js +1 -1
  21. package/{cli/dist → dist}/commands/slo.js +1 -1
  22. package/{cli/dist → dist}/commands/verify.js +1 -1
  23. package/{cli/dist → dist}/core/adapters/playwright-native-api.d.ts +2 -0
  24. package/{cli/dist → dist}/core/adapters/playwright-native-api.js +20 -1
  25. package/{cli/dist → dist}/core/adapters/playwright-ui.d.ts +21 -0
  26. package/dist/core/adapters/playwright-ui.js +2050 -0
  27. package/{cli/dist → dist}/core/ai/ollama-provider.d.ts +4 -0
  28. package/{cli/dist → dist}/core/ai/ollama-provider.js +41 -8
  29. package/{cli/dist → dist}/core/artifacts/ui-artifacts.js +24 -4
  30. package/dist/core/auth/backup-codes-provider.d.ts +91 -0
  31. package/dist/core/auth/backup-codes-provider.js +215 -0
  32. package/{cli/dist → dist}/core/auth/basic-auth-provider.d.ts +6 -0
  33. package/{cli/dist → dist}/core/auth/basic-auth-provider.js +24 -6
  34. package/dist/core/auth/digest-auth-provider.d.ts +116 -0
  35. package/dist/core/auth/digest-auth-provider.js +244 -0
  36. package/dist/core/auth/hcaptcha-handler.d.ts +103 -0
  37. package/dist/core/auth/hcaptcha-handler.js +288 -0
  38. package/{cli/dist → dist}/core/auth/index.d.ts +81 -4
  39. package/{cli/dist → dist}/core/auth/index.js +15 -1
  40. package/dist/core/auth/oauth-handler.d.ts +408 -0
  41. package/dist/core/auth/oauth-handler.js +636 -0
  42. package/{cli/dist → dist}/core/auth/oauth2-provider.d.ts +9 -0
  43. package/dist/core/auth/oauth2-provider.js +227 -0
  44. package/dist/core/auth/otp-provider.d.ts +93 -0
  45. package/dist/core/auth/otp-provider.js +288 -0
  46. package/dist/core/auth/recaptcha-handler.d.ts +119 -0
  47. package/dist/core/auth/recaptcha-handler.js +301 -0
  48. package/dist/core/auth/remember-me-handler.d.ts +142 -0
  49. package/dist/core/auth/remember-me-handler.js +255 -0
  50. package/dist/core/auth/saml-handler.d.ts +173 -0
  51. package/dist/core/auth/saml-handler.js +364 -0
  52. package/dist/core/auth/webauthn-handler.d.ts +182 -0
  53. package/dist/core/auth/webauthn-handler.js +310 -0
  54. package/dist/core/crawler/advanced-interactions.d.ts +342 -0
  55. package/dist/core/crawler/advanced-interactions.js +1069 -0
  56. package/dist/core/crawler/blob-url-download-handler.d.ts +145 -0
  57. package/dist/core/crawler/blob-url-download-handler.js +392 -0
  58. package/dist/core/crawler/consent-handler.d.ts +49 -0
  59. package/dist/core/crawler/consent-handler.js +258 -0
  60. package/dist/core/crawler/cookie-manager.d.ts +166 -0
  61. package/dist/core/crawler/cookie-manager.js +353 -0
  62. package/dist/core/crawler/coop-coep-handler.d.ts +136 -0
  63. package/dist/core/crawler/coop-coep-handler.js +338 -0
  64. package/dist/core/crawler/csp-handler.d.ts +151 -0
  65. package/dist/core/crawler/csp-handler.js +415 -0
  66. package/dist/core/crawler/download-handler.d.ts +155 -0
  67. package/dist/core/crawler/download-handler.js +370 -0
  68. package/dist/core/crawler/email-testing-handler.d.ts +214 -0
  69. package/dist/core/crawler/email-testing-handler.js +398 -0
  70. package/dist/core/crawler/error-tracking-handler.d.ts +177 -0
  71. package/dist/core/crawler/error-tracking-handler.js +378 -0
  72. package/dist/core/crawler/form-handler.d.ts +100 -0
  73. package/dist/core/crawler/form-handler.js +465 -0
  74. package/dist/core/crawler/framework-wait-handler.d.ts +96 -0
  75. package/dist/core/crawler/framework-wait-handler.js +464 -0
  76. package/dist/core/crawler/geolocation-handler.d.ts +112 -0
  77. package/dist/core/crawler/geolocation-handler.js +276 -0
  78. package/dist/core/crawler/index.d.ts +78 -0
  79. package/{cli/dist → dist}/core/crawler/index.js +74 -1
  80. package/dist/core/crawler/intelligent-selector-generator.d.ts +164 -0
  81. package/dist/core/crawler/intelligent-selector-generator.js +612 -0
  82. package/{cli/dist → dist}/core/crawler/journey-generator.js +44 -1
  83. package/{cli/dist → dist}/core/crawler/page-analyzer.d.ts +16 -1
  84. package/{cli/dist → dist}/core/crawler/page-analyzer.js +469 -17
  85. package/dist/core/crawler/permissions-handler.d.ts +112 -0
  86. package/dist/core/crawler/permissions-handler.js +236 -0
  87. package/dist/core/crawler/permissions-policy-handler.d.ts +113 -0
  88. package/dist/core/crawler/permissions-policy-handler.js +402 -0
  89. package/dist/core/crawler/presets.d.ts +100 -0
  90. package/dist/core/crawler/presets.js +887 -0
  91. package/dist/core/crawler/repl-debug-handler.d.ts +105 -0
  92. package/dist/core/crawler/repl-debug-handler.js +552 -0
  93. package/dist/core/crawler/reporting-api-handler.d.ts +212 -0
  94. package/dist/core/crawler/reporting-api-handler.js +344 -0
  95. package/{cli/dist → dist}/core/crawler/selector-generator.d.ts +9 -0
  96. package/{cli/dist → dist}/core/crawler/selector-generator.js +99 -23
  97. package/dist/core/crawler/site-profiler.d.ts +89 -0
  98. package/dist/core/crawler/site-profiler.js +290 -0
  99. package/dist/core/crawler/sourcemaps-handler.d.ts +144 -0
  100. package/dist/core/crawler/sourcemaps-handler.js +420 -0
  101. package/dist/core/crawler/stacked-modals-handler.d.ts +118 -0
  102. package/dist/core/crawler/stacked-modals-handler.js +429 -0
  103. package/dist/core/crawler/trusted-types-handler.d.ts +149 -0
  104. package/dist/core/crawler/trusted-types-handler.js +413 -0
  105. package/{cli/dist → dist}/core/crawler/types.d.ts +68 -2
  106. package/dist/core/crawler/wait-strategies.d.ts +108 -0
  107. package/dist/core/crawler/wait-strategies.js +399 -0
  108. package/dist/core/fixtures/factories.d.ts +180 -0
  109. package/dist/core/fixtures/factories.js +279 -0
  110. package/dist/core/fixtures/index.d.ts +6 -0
  111. package/dist/core/fixtures/index.js +6 -0
  112. package/{cli/dist → dist}/core/generation/crawler-pack-generator.d.ts +13 -3
  113. package/dist/core/generation/crawler-pack-generator.js +232 -0
  114. package/{cli/dist → dist}/core/generation/index.d.ts +2 -0
  115. package/{cli/dist → dist}/core/generation/index.js +2 -0
  116. package/{cli/dist → dist}/core/index.d.ts +2 -0
  117. package/{cli/dist → dist}/core/index.js +4 -0
  118. package/dist/core/network/index.d.ts +7 -0
  119. package/dist/core/network/index.js +7 -0
  120. package/dist/core/network/network-manager.d.ts +237 -0
  121. package/dist/core/network/network-manager.js +343 -0
  122. package/dist/core/network/network-simulator.d.ts +158 -0
  123. package/dist/core/network/network-simulator.js +261 -0
  124. package/{cli/dist → dist}/core/pack/validator.js +2 -2
  125. package/{cli/dist → dist}/core/pack-v2/migrator.d.ts +5 -0
  126. package/{cli/dist → dist}/core/pack-v2/migrator.js +81 -6
  127. package/{cli/dist → dist}/core/pack-v2/validator.js +4 -3
  128. package/{cli/dist → dist}/core/pom/base-page.js +1 -1
  129. package/{cli/dist → dist}/core/pom/loader.js +1 -1
  130. package/dist/core/reporting/index.d.ts +9 -0
  131. package/dist/core/reporting/index.js +10 -0
  132. package/dist/core/reporting/junit-reporter.d.ts +114 -0
  133. package/dist/core/reporting/junit-reporter.js +306 -0
  134. package/{cli/dist → dist}/core/runner/e2e-helpers.d.ts +1 -1
  135. package/{cli/dist → dist}/core/runner/e2e-helpers.js +2 -2
  136. package/{cli/dist → dist}/core/runner/phase3-runner.d.ts +3 -0
  137. package/{cli/dist → dist}/core/runner/phase3-runner.js +45 -14
  138. package/dist/core/sharding/test-sharding.d.ts +137 -0
  139. package/dist/core/sharding/test-sharding.js +233 -0
  140. package/dist/core/storage/cookie-manager.d.ts +160 -0
  141. package/dist/core/storage/cookie-manager.js +268 -0
  142. package/dist/core/storage/index.d.ts +7 -0
  143. package/dist/core/storage/index.js +7 -0
  144. package/dist/core/storage/storage-helpers.d.ts +138 -0
  145. package/dist/core/storage/storage-helpers.js +315 -0
  146. package/dist/core/test-helpers/index.d.ts +6 -0
  147. package/dist/core/test-helpers/index.js +6 -0
  148. package/dist/core/test-helpers/state-reset.d.ts +119 -0
  149. package/dist/core/test-helpers/state-reset.js +234 -0
  150. package/{cli/dist → dist}/core/types/pack-v1.d.ts +15 -2
  151. package/{cli/dist → dist}/core/types/pack-v2.d.ts +1 -1
  152. package/dist/core/upload/chunked-uploader.d.ts +150 -0
  153. package/dist/core/upload/chunked-uploader.js +289 -0
  154. package/dist/core/upload/index.d.ts +11 -0
  155. package/dist/core/upload/index.js +8 -0
  156. package/dist/core/upload/mime-validator.d.ts +119 -0
  157. package/dist/core/upload/mime-validator.js +373 -0
  158. package/dist/core/upload/presigned-uploader.d.ts +118 -0
  159. package/dist/core/upload/presigned-uploader.js +274 -0
  160. package/dist/core/utils/device-emulation.d.ts +194 -0
  161. package/dist/core/utils/device-emulation.js +380 -0
  162. package/dist/core/utils/index.d.ts +8 -0
  163. package/dist/core/utils/index.js +8 -0
  164. package/dist/core/utils/retry.d.ts +145 -0
  165. package/dist/core/utils/retry.js +242 -0
  166. package/dist/core/utils/smart-wait.d.ts +133 -0
  167. package/dist/core/utils/smart-wait.js +417 -0
  168. package/dist/core/visual/index.d.ts +7 -0
  169. package/dist/core/visual/index.js +7 -0
  170. package/dist/core/visual/pixel-diff.d.ts +87 -0
  171. package/dist/core/visual/pixel-diff.js +213 -0
  172. package/dist/core/visual/screenshot-helper.d.ts +130 -0
  173. package/dist/core/visual/screenshot-helper.js +223 -0
  174. package/{cli/dist → dist}/index.js +2 -3
  175. package/{cli/dist → dist}/utils/config.d.ts +1 -1
  176. package/{cli/dist → dist}/utils/config.js +36 -3
  177. package/examples/README.md +160 -0
  178. package/examples/accessibility.yml +48 -0
  179. package/examples/api-basic.yml +27 -0
  180. package/examples/complete.yml +146 -0
  181. package/examples/crawler.yml +38 -0
  182. package/examples/fullstack.yml +78 -0
  183. package/examples/security.yml +58 -0
  184. package/examples/ui-advanced.yml +49 -0
  185. package/examples/ui-basic.yml +24 -0
  186. package/package.json +33 -67
  187. package/CHANGELOG.md +0 -330
  188. package/CONTRIBUTING.md +0 -273
  189. package/QUICK_START.md +0 -191
  190. package/cli/CHANGELOG.md +0 -84
  191. package/cli/LICENSE +0 -24
  192. package/cli/README.md +0 -222
  193. package/cli/dist/core/adapters/playwright-ui.js +0 -864
  194. package/cli/dist/core/auth/oauth2-provider.js +0 -114
  195. package/cli/dist/core/coverage/analyzer.d.ts +0 -101
  196. package/cli/dist/core/coverage/analyzer.js +0 -415
  197. package/cli/dist/core/coverage/collector.d.ts +0 -74
  198. package/cli/dist/core/coverage/collector.js +0 -459
  199. package/cli/dist/core/coverage/config.d.ts +0 -37
  200. package/cli/dist/core/coverage/config.js +0 -156
  201. package/cli/dist/core/coverage/index.d.ts +0 -11
  202. package/cli/dist/core/coverage/index.js +0 -15
  203. package/cli/dist/core/coverage/types.d.ts +0 -267
  204. package/cli/dist/core/coverage/types.js +0 -6
  205. package/cli/dist/core/coverage/vault.d.ts +0 -95
  206. package/cli/dist/core/coverage/vault.js +0 -405
  207. package/cli/dist/core/crawler/index.d.ts +0 -57
  208. package/cli/dist/core/fixtures/index.d.ts +0 -8
  209. package/cli/dist/core/fixtures/index.js +0 -8
  210. package/cli/dist/core/generation/crawler-pack-generator.js +0 -231
  211. package/cli/dist/core/reporting/index.d.ts +0 -6
  212. package/cli/dist/core/reporting/index.js +0 -6
  213. package/cli/dist/core/visual/index.d.ts +0 -6
  214. package/cli/dist/core/visual/index.js +0 -6
  215. package/cli/package.json +0 -76
  216. package/core/LICENSE +0 -24
  217. package/core/README.md +0 -105
  218. package/core/package.json +0 -90
  219. package/core/schemas/pack.schema.json +0 -236
  220. /package/{cli/bin → bin}/qa360.js +0 -0
  221. /package/{cli/dist → dist}/cli-minimal.d.ts +0 -0
  222. /package/{cli/dist → dist}/cli-minimal.js +0 -0
  223. /package/{cli/dist → dist}/commands/ai.d.ts +0 -0
  224. /package/{cli/dist → dist}/commands/ask.d.ts +0 -0
  225. /package/{cli/dist → dist}/commands/coverage.d.ts +0 -0
  226. /package/{cli/dist → dist}/commands/crawl.d.ts +0 -0
  227. /package/{cli/dist → dist}/commands/doctor.d.ts +0 -0
  228. /package/{cli/dist → dist}/commands/examples.d.ts +0 -0
  229. /package/{cli/dist → dist}/commands/examples.js +0 -0
  230. /package/{cli/dist → dist}/commands/explain.d.ts +0 -0
  231. /package/{cli/dist → dist}/commands/flakiness.d.ts +0 -0
  232. /package/{cli/dist → dist}/commands/generate.d.ts +0 -0
  233. /package/{cli/dist → dist}/commands/history.d.ts +0 -0
  234. /package/{cli/dist → dist}/commands/init.d.ts +0 -0
  235. /package/{cli/dist → dist}/commands/init.js +0 -0
  236. /package/{cli/dist → dist}/commands/monitor.d.ts +0 -0
  237. /package/{cli/dist → dist}/commands/ollama.d.ts +0 -0
  238. /package/{cli/dist → dist}/commands/pack.d.ts +0 -0
  239. /package/{cli/dist → dist}/commands/regression.d.ts +0 -0
  240. /package/{cli/dist → dist}/commands/repair.d.ts +0 -0
  241. /package/{cli/dist → dist}/commands/report.d.ts +0 -0
  242. /package/{cli/dist → dist}/commands/report.js +0 -0
  243. /package/{cli/dist → dist}/commands/retry.d.ts +0 -0
  244. /package/{cli/dist → dist}/commands/scan.d.ts +0 -0
  245. /package/{cli/dist → dist}/commands/scan.js +0 -0
  246. /package/{cli/dist → dist}/commands/secrets.d.ts +0 -0
  247. /package/{cli/dist → dist}/commands/serve.d.ts +0 -0
  248. /package/{cli/dist → dist}/commands/slo.d.ts +0 -0
  249. /package/{cli/dist → dist}/commands/verify.d.ts +0 -0
  250. /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.d.ts +0 -0
  251. /package/{cli/dist → dist}/core/adapters/gitleaks-secrets.js +0 -0
  252. /package/{cli/dist → dist}/core/adapters/jest-adapter.d.ts +0 -0
  253. /package/{cli/dist → dist}/core/adapters/jest-adapter.js +0 -0
  254. /package/{cli/dist → dist}/core/adapters/k6-perf.d.ts +0 -0
  255. /package/{cli/dist → dist}/core/adapters/k6-perf.js +0 -0
  256. /package/{cli/dist → dist}/core/adapters/osv-deps.d.ts +0 -0
  257. /package/{cli/dist → dist}/core/adapters/osv-deps.js +0 -0
  258. /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.d.ts +0 -0
  259. /package/{cli/dist → dist}/core/adapters/playwright-native-adapter.js +0 -0
  260. /package/{cli/dist → dist}/core/adapters/pytest-adapter.d.ts +0 -0
  261. /package/{cli/dist → dist}/core/adapters/pytest-adapter.js +0 -0
  262. /package/{cli/dist → dist}/core/adapters/semgrep-sast.d.ts +0 -0
  263. /package/{cli/dist → dist}/core/adapters/semgrep-sast.js +0 -0
  264. /package/{cli/dist → dist}/core/adapters/unit-test-types.d.ts +0 -0
  265. /package/{cli/dist → dist}/core/adapters/unit-test-types.js +0 -0
  266. /package/{cli/dist → dist}/core/adapters/vitest-adapter.d.ts +0 -0
  267. /package/{cli/dist → dist}/core/adapters/vitest-adapter.js +0 -0
  268. /package/{cli/dist → dist}/core/adapters/zap-dast.d.ts +0 -0
  269. /package/{cli/dist → dist}/core/adapters/zap-dast.js +0 -0
  270. /package/{cli/dist → dist}/core/ai/anthropic-provider.d.ts +0 -0
  271. /package/{cli/dist → dist}/core/ai/anthropic-provider.js +0 -0
  272. /package/{cli/dist → dist}/core/ai/deepseek-provider.d.ts +0 -0
  273. /package/{cli/dist → dist}/core/ai/deepseek-provider.js +0 -0
  274. /package/{cli/dist → dist}/core/ai/index.d.ts +0 -0
  275. /package/{cli/dist → dist}/core/ai/index.js +0 -0
  276. /package/{cli/dist → dist}/core/ai/llm-client.d.ts +0 -0
  277. /package/{cli/dist → dist}/core/ai/llm-client.js +0 -0
  278. /package/{cli/dist → dist}/core/ai/mock-provider.d.ts +0 -0
  279. /package/{cli/dist → dist}/core/ai/mock-provider.js +0 -0
  280. /package/{cli/dist → dist}/core/ai/openai-provider.d.ts +0 -0
  281. /package/{cli/dist → dist}/core/ai/openai-provider.js +0 -0
  282. /package/{cli/dist → dist}/core/ai/provider-factory.d.ts +0 -0
  283. /package/{cli/dist → dist}/core/ai/provider-factory.js +0 -0
  284. /package/{cli/dist → dist}/core/artifacts/index.d.ts +0 -0
  285. /package/{cli/dist → dist}/core/artifacts/index.js +0 -0
  286. /package/{cli/dist → dist}/core/artifacts/ui-artifacts.d.ts +0 -0
  287. /package/{cli/dist → dist}/core/assertions/engine.d.ts +0 -0
  288. /package/{cli/dist → dist}/core/assertions/engine.js +0 -0
  289. /package/{cli/dist → dist}/core/assertions/index.d.ts +0 -0
  290. /package/{cli/dist → dist}/core/assertions/index.js +0 -0
  291. /package/{cli/dist → dist}/core/assertions/types.d.ts +0 -0
  292. /package/{cli/dist → dist}/core/assertions/types.js +0 -0
  293. /package/{cli/dist → dist}/core/auth/api-key-provider.d.ts +0 -0
  294. /package/{cli/dist → dist}/core/auth/api-key-provider.js +0 -0
  295. /package/{cli/dist → dist}/core/auth/aws-iam-provider.d.ts +0 -0
  296. /package/{cli/dist → dist}/core/auth/aws-iam-provider.js +0 -0
  297. /package/{cli/dist → dist}/core/auth/azure-ad-provider.d.ts +0 -0
  298. /package/{cli/dist → dist}/core/auth/azure-ad-provider.js +0 -0
  299. /package/{cli/dist → dist}/core/auth/gcp-adc-provider.d.ts +0 -0
  300. /package/{cli/dist → dist}/core/auth/gcp-adc-provider.js +0 -0
  301. /package/{cli/dist → dist}/core/auth/jwt-provider.d.ts +0 -0
  302. /package/{cli/dist → dist}/core/auth/jwt-provider.js +0 -0
  303. /package/{cli/dist → dist}/core/auth/manager.d.ts +0 -0
  304. /package/{cli/dist → dist}/core/auth/manager.js +0 -0
  305. /package/{cli/dist → dist}/core/auth/totp-provider.d.ts +0 -0
  306. /package/{cli/dist → dist}/core/auth/totp-provider.js +0 -0
  307. /package/{cli/dist → dist}/core/auth/ui-login-provider.d.ts +0 -0
  308. /package/{cli/dist → dist}/core/auth/ui-login-provider.js +0 -0
  309. /package/{cli/dist → dist}/core/cache/index.d.ts +0 -0
  310. /package/{cli/dist → dist}/core/cache/index.js +0 -0
  311. /package/{cli/dist → dist}/core/cache/lru-cache.d.ts +0 -0
  312. /package/{cli/dist → dist}/core/cache/lru-cache.js +0 -0
  313. /package/{cli/dist/core → dist}/core/coverage/analyzer.d.ts +0 -0
  314. /package/{cli/dist/core → dist}/core/coverage/analyzer.js +0 -0
  315. /package/{cli/dist/core → dist}/core/coverage/collector.d.ts +0 -0
  316. /package/{cli/dist/core → dist}/core/coverage/collector.js +0 -0
  317. /package/{cli/dist/core → dist}/core/coverage/config.d.ts +0 -0
  318. /package/{cli/dist/core → dist}/core/coverage/config.js +0 -0
  319. /package/{cli/dist/core → dist}/core/coverage/index.d.ts +0 -0
  320. /package/{cli/dist/core → dist}/core/coverage/index.js +0 -0
  321. /package/{cli/dist/core → dist}/core/coverage/types.d.ts +0 -0
  322. /package/{cli/dist/core → dist}/core/coverage/types.js +0 -0
  323. /package/{cli/dist/core → dist}/core/coverage/vault.d.ts +0 -0
  324. /package/{cli/dist/core → dist}/core/coverage/vault.js +0 -0
  325. /package/{cli/dist → dist}/core/crawler/journey-generator.d.ts +0 -0
  326. /package/{cli/dist → dist}/core/crawler/types.js +0 -0
  327. /package/{cli/dist → dist}/core/dashboard/assets.d.ts +0 -0
  328. /package/{cli/dist → dist}/core/dashboard/assets.js +0 -0
  329. /package/{cli/dist → dist}/core/dashboard/index.d.ts +0 -0
  330. /package/{cli/dist → dist}/core/dashboard/index.js +0 -0
  331. /package/{cli/dist → dist}/core/dashboard/server.d.ts +0 -0
  332. /package/{cli/dist → dist}/core/dashboard/server.js +0 -0
  333. /package/{cli/dist → dist}/core/dashboard/types.d.ts +0 -0
  334. /package/{cli/dist → dist}/core/dashboard/types.js +0 -0
  335. /package/{cli/dist → dist}/core/discoverer/index.d.ts +0 -0
  336. /package/{cli/dist → dist}/core/discoverer/index.js +0 -0
  337. /package/{cli/dist → dist}/core/fixtures/loader.d.ts +0 -0
  338. /package/{cli/dist → dist}/core/fixtures/loader.js +0 -0
  339. /package/{cli/dist → dist}/core/fixtures/resolver.d.ts +0 -0
  340. /package/{cli/dist → dist}/core/fixtures/resolver.js +0 -0
  341. /package/{cli/dist → dist}/core/fixtures/types.d.ts +0 -0
  342. /package/{cli/dist → dist}/core/fixtures/types.js +0 -0
  343. /package/{cli/dist → dist}/core/flakiness/index.d.ts +0 -0
  344. /package/{cli/dist → dist}/core/flakiness/index.js +0 -0
  345. /package/{cli/dist → dist}/core/generation/code-formatter.d.ts +0 -0
  346. /package/{cli/dist → dist}/core/generation/code-formatter.js +0 -0
  347. /package/{cli/dist → dist}/core/generation/code-generator.d.ts +0 -0
  348. /package/{cli/dist → dist}/core/generation/code-generator.js +0 -0
  349. /package/{cli/dist → dist}/core/generation/generator.d.ts +0 -0
  350. /package/{cli/dist → dist}/core/generation/generator.js +0 -0
  351. /package/{cli/dist → dist}/core/generation/pack-generator.d.ts +0 -0
  352. /package/{cli/dist → dist}/core/generation/pack-generator.js +0 -0
  353. /package/{cli/dist → dist}/core/generation/prompt-builder.d.ts +0 -0
  354. /package/{cli/dist → dist}/core/generation/prompt-builder.js +0 -0
  355. /package/{cli/dist → dist}/core/generation/source-analyzer.d.ts +0 -0
  356. /package/{cli/dist → dist}/core/generation/source-analyzer.js +0 -0
  357. /package/{cli/dist → dist}/core/generation/test-optimizer.d.ts +0 -0
  358. /package/{cli/dist → dist}/core/generation/test-optimizer.js +0 -0
  359. /package/{cli/dist → dist}/core/generation/types.d.ts +0 -0
  360. /package/{cli/dist → dist}/core/generation/types.js +0 -0
  361. /package/{cli/dist → dist}/core/hooks/compose.d.ts +0 -0
  362. /package/{cli/dist → dist}/core/hooks/compose.js +0 -0
  363. /package/{cli/dist → dist}/core/hooks/runner.d.ts +0 -0
  364. /package/{cli/dist → dist}/core/hooks/runner.js +0 -0
  365. /package/{cli/dist → dist}/core/pack/migrator.d.ts +0 -0
  366. /package/{cli/dist → dist}/core/pack/migrator.js +0 -0
  367. /package/{cli/dist → dist}/core/pack/validator.d.ts +0 -0
  368. /package/{cli/dist → dist}/core/pack-v2/index.d.ts +0 -0
  369. /package/{cli/dist → dist}/core/pack-v2/index.js +0 -0
  370. /package/{cli/dist → dist}/core/pack-v2/loader.d.ts +0 -0
  371. /package/{cli/dist → dist}/core/pack-v2/loader.js +0 -0
  372. /package/{cli/dist → dist}/core/pack-v2/validator.d.ts +0 -0
  373. /package/{cli/dist → dist}/core/parallel/index.d.ts +0 -0
  374. /package/{cli/dist → dist}/core/parallel/index.js +0 -0
  375. /package/{cli/dist → dist}/core/parallel/parallel-runner.d.ts +0 -0
  376. /package/{cli/dist → dist}/core/parallel/parallel-runner.js +0 -0
  377. /package/{cli/dist → dist}/core/pom/base-page.d.ts +0 -0
  378. /package/{cli/dist → dist}/core/pom/index.d.ts +0 -0
  379. /package/{cli/dist → dist}/core/pom/index.js +0 -0
  380. /package/{cli/dist → dist}/core/pom/loader.d.ts +0 -0
  381. /package/{cli/dist → dist}/core/pom/types.d.ts +0 -0
  382. /package/{cli/dist → dist}/core/pom/types.js +0 -0
  383. /package/{cli/dist → dist}/core/proof/bundle.d.ts +0 -0
  384. /package/{cli/dist → dist}/core/proof/bundle.js +0 -0
  385. /package/{cli/dist → dist}/core/proof/canonicalize.d.ts +0 -0
  386. /package/{cli/dist → dist}/core/proof/canonicalize.js +0 -0
  387. /package/{cli/dist → dist}/core/proof/index.d.ts +0 -0
  388. /package/{cli/dist → dist}/core/proof/index.js +0 -0
  389. /package/{cli/dist → dist}/core/proof/schema.d.ts +0 -0
  390. /package/{cli/dist → dist}/core/proof/schema.js +0 -0
  391. /package/{cli/dist → dist}/core/proof/signer.d.ts +0 -0
  392. /package/{cli/dist → dist}/core/proof/signer.js +0 -0
  393. /package/{cli/dist → dist}/core/proof/verifier.d.ts +0 -0
  394. /package/{cli/dist → dist}/core/proof/verifier.js +0 -0
  395. /package/{cli/dist → dist}/core/regression/detector.d.ts +0 -0
  396. /package/{cli/dist → dist}/core/regression/detector.js +0 -0
  397. /package/{cli/dist → dist}/core/regression/index.d.ts +0 -0
  398. /package/{cli/dist → dist}/core/regression/index.js +0 -0
  399. /package/{cli/dist → dist}/core/regression/trend-analyzer.d.ts +0 -0
  400. /package/{cli/dist → dist}/core/regression/trend-analyzer.js +0 -0
  401. /package/{cli/dist → dist}/core/regression/types.d.ts +0 -0
  402. /package/{cli/dist → dist}/core/regression/types.js +0 -0
  403. /package/{cli/dist → dist}/core/regression/vault.d.ts +0 -0
  404. /package/{cli/dist → dist}/core/regression/vault.js +0 -0
  405. /package/{cli/dist → dist}/core/repair/engine/fixer.d.ts +0 -0
  406. /package/{cli/dist → dist}/core/repair/engine/fixer.js +0 -0
  407. /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.d.ts +0 -0
  408. /package/{cli/dist → dist}/core/repair/engine/suggestion-engine.js +0 -0
  409. /package/{cli/dist → dist}/core/repair/index.d.ts +0 -0
  410. /package/{cli/dist → dist}/core/repair/index.js +0 -0
  411. /package/{cli/dist → dist}/core/repair/repairer.d.ts +0 -0
  412. /package/{cli/dist → dist}/core/repair/repairer.js +0 -0
  413. /package/{cli/dist → dist}/core/repair/types.d.ts +0 -0
  414. /package/{cli/dist → dist}/core/repair/types.js +0 -0
  415. /package/{cli/dist → dist}/core/repair/utils/error-analyzer.d.ts +0 -0
  416. /package/{cli/dist → dist}/core/repair/utils/error-analyzer.js +0 -0
  417. /package/{cli/dist → dist}/core/reporting/html-reporter.d.ts +0 -0
  418. /package/{cli/dist → dist}/core/reporting/html-reporter.js +0 -0
  419. /package/{cli/dist → dist}/core/retry/flakiness-integration.d.ts +0 -0
  420. /package/{cli/dist → dist}/core/retry/flakiness-integration.js +0 -0
  421. /package/{cli/dist → dist}/core/retry/index.d.ts +0 -0
  422. /package/{cli/dist → dist}/core/retry/index.js +0 -0
  423. /package/{cli/dist → dist}/core/retry/retry-engine.d.ts +0 -0
  424. /package/{cli/dist → dist}/core/retry/retry-engine.js +0 -0
  425. /package/{cli/dist → dist}/core/retry/types.d.ts +0 -0
  426. /package/{cli/dist → dist}/core/retry/types.js +0 -0
  427. /package/{cli/dist → dist}/core/retry/vault.d.ts +0 -0
  428. /package/{cli/dist → dist}/core/retry/vault.js +0 -0
  429. /package/{cli/dist → dist}/core/schemas/pack.schema.json +0 -0
  430. /package/{cli/dist → dist}/core/secrets/crypto.d.ts +0 -0
  431. /package/{cli/dist → dist}/core/secrets/crypto.js +0 -0
  432. /package/{cli/dist → dist}/core/secrets/manager.d.ts +0 -0
  433. /package/{cli/dist → dist}/core/secrets/manager.js +0 -0
  434. /package/{cli/dist → dist}/core/security/redaction-patterns-extended.d.ts +0 -0
  435. /package/{cli/dist → dist}/core/security/redaction-patterns-extended.js +0 -0
  436. /package/{cli/dist → dist}/core/security/redactor.d.ts +0 -0
  437. /package/{cli/dist → dist}/core/security/redactor.js +0 -0
  438. /package/{cli/dist → dist}/core/self-healing/assertion-healer.d.ts +0 -0
  439. /package/{cli/dist → dist}/core/self-healing/assertion-healer.js +0 -0
  440. /package/{cli/dist → dist}/core/self-healing/engine.d.ts +0 -0
  441. /package/{cli/dist → dist}/core/self-healing/engine.js +0 -0
  442. /package/{cli/dist → dist}/core/self-healing/index.d.ts +0 -0
  443. /package/{cli/dist → dist}/core/self-healing/index.js +0 -0
  444. /package/{cli/dist → dist}/core/self-healing/selector-healer.d.ts +0 -0
  445. /package/{cli/dist → dist}/core/self-healing/selector-healer.js +0 -0
  446. /package/{cli/dist → dist}/core/self-healing/types.d.ts +0 -0
  447. /package/{cli/dist → dist}/core/self-healing/types.js +0 -0
  448. /package/{cli/dist → dist}/core/serve/diagnostics-collector.d.ts +0 -0
  449. /package/{cli/dist → dist}/core/serve/diagnostics-collector.js +0 -0
  450. /package/{cli/dist → dist}/core/serve/health-checker.d.ts +0 -0
  451. /package/{cli/dist → dist}/core/serve/health-checker.js +0 -0
  452. /package/{cli/dist → dist}/core/serve/index.d.ts +0 -0
  453. /package/{cli/dist → dist}/core/serve/index.js +0 -0
  454. /package/{cli/dist → dist}/core/serve/metrics-collector.d.ts +0 -0
  455. /package/{cli/dist → dist}/core/serve/metrics-collector.js +0 -0
  456. /package/{cli/dist → dist}/core/serve/process-manager.d.ts +0 -0
  457. /package/{cli/dist → dist}/core/serve/process-manager.js +0 -0
  458. /package/{cli/dist → dist}/core/serve/server.d.ts +0 -0
  459. /package/{cli/dist → dist}/core/serve/server.js +0 -0
  460. /package/{cli/dist → dist}/core/slo/config.d.ts +0 -0
  461. /package/{cli/dist → dist}/core/slo/config.js +0 -0
  462. /package/{cli/dist → dist}/core/slo/index.d.ts +0 -0
  463. /package/{cli/dist → dist}/core/slo/index.js +0 -0
  464. /package/{cli/dist → dist}/core/slo/sli-calculator.d.ts +0 -0
  465. /package/{cli/dist → dist}/core/slo/sli-calculator.js +0 -0
  466. /package/{cli/dist → dist}/core/slo/slo-tracker.d.ts +0 -0
  467. /package/{cli/dist → dist}/core/slo/slo-tracker.js +0 -0
  468. /package/{cli/dist → dist}/core/slo/types.d.ts +0 -0
  469. /package/{cli/dist → dist}/core/slo/types.js +0 -0
  470. /package/{cli/dist → dist}/core/slo/vault.d.ts +0 -0
  471. /package/{cli/dist → dist}/core/slo/vault.js +0 -0
  472. /package/{cli/dist → dist}/core/tui/index.d.ts +0 -0
  473. /package/{cli/dist → dist}/core/tui/index.js +0 -0
  474. /package/{cli/dist → dist}/core/tui/monitor.d.ts +0 -0
  475. /package/{cli/dist → dist}/core/tui/monitor.js +0 -0
  476. /package/{cli/dist → dist}/core/tui/renderer.d.ts +0 -0
  477. /package/{cli/dist → dist}/core/tui/renderer.js +0 -0
  478. /package/{cli/dist → dist}/core/tui/types.d.ts +0 -0
  479. /package/{cli/dist → dist}/core/tui/types.js +0 -0
  480. /package/{cli/dist → dist}/core/types/pack-v1.js +0 -0
  481. /package/{cli/dist → dist}/core/types/pack-v2.js +0 -0
  482. /package/{cli/dist → dist}/core/types/trust-score.d.ts +0 -0
  483. /package/{cli/dist → dist}/core/types/trust-score.js +0 -0
  484. /package/{cli/dist → dist}/core/vault/cas.d.ts +0 -0
  485. /package/{cli/dist → dist}/core/vault/cas.js +0 -0
  486. /package/{cli/dist → dist}/core/vault/index.d.ts +0 -0
  487. /package/{cli/dist → dist}/core/vault/index.js +0 -0
  488. /package/{cli/dist → dist}/core/visual/visual-regression.d.ts +0 -0
  489. /package/{cli/dist → dist}/core/visual/visual-regression.js +0 -0
  490. /package/{cli/dist → dist}/core/watch/index.d.ts +0 -0
  491. /package/{cli/dist → dist}/core/watch/index.js +0 -0
  492. /package/{cli/dist → dist}/core/watch/watch-mode.d.ts +0 -0
  493. /package/{cli/dist → dist}/core/watch/watch-mode.js +0 -0
  494. /package/{cli/dist → dist}/generators/index.d.ts +0 -0
  495. /package/{cli/dist → dist}/generators/index.js +0 -0
  496. /package/{cli/dist → dist}/generators/json-reporter.d.ts +0 -0
  497. /package/{cli/dist → dist}/generators/json-reporter.js +0 -0
  498. /package/{cli/dist → dist}/generators/test-generator.d.ts +0 -0
  499. /package/{cli/dist → dist}/generators/test-generator.js +0 -0
  500. /package/{cli/dist → dist}/index.d.ts +0 -0
  501. /package/{cli/dist → dist}/scanners/dom-scanner.d.ts +0 -0
  502. /package/{cli/dist → dist}/scanners/dom-scanner.js +0 -0
  503. /package/{cli/dist → dist}/scanners/index.d.ts +0 -0
  504. /package/{cli/dist → dist}/scanners/index.js +0 -0
  505. /package/{cli/dist → dist}/schemas/pack.schema.json +0 -0
  506. /package/{cli/dist → dist}/types/scan.d.ts +0 -0
  507. /package/{cli/dist → dist}/types/scan.js +0 -0
@@ -0,0 +1,429 @@
1
+ /**
2
+ * Stacked Modals Handler
3
+ *
4
+ * P1 - Detection and management of stacked/nested modals
5
+ *
6
+ * Supports:
7
+ * - Detection of stacked modals (multiple overlays)
8
+ * - Z-index analysis
9
+ * - Modal type detection (dialog, popover, dropdown)
10
+ * - Modal hierarchy traversal
11
+ * - Modal dismissal strategies
12
+ *
13
+ * @see https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/
14
+ */
15
+ /**
16
+ * Stacked Modals Handler class
17
+ */
18
+ export class StackedModalsHandler {
19
+ /**
20
+ * Detect all modals on the page
21
+ */
22
+ async detectModals(page) {
23
+ const result = await page.evaluate(() => {
24
+ const modals = [];
25
+ const issues = [];
26
+ // Common modal selectors
27
+ const modalSelectors = [
28
+ 'dialog',
29
+ '[role="dialog"]',
30
+ '[role="alertdialog"]',
31
+ '[role="menu"]',
32
+ '[role="listbox"]',
33
+ '[role="tooltip"]',
34
+ '.modal',
35
+ '.dialog',
36
+ '.popover',
37
+ '.dropdown-menu',
38
+ '[data-modal]',
39
+ '[data-dialog]',
40
+ '[data-popover]',
41
+ ];
42
+ // Find all potential modals
43
+ const elements = [];
44
+ for (const selector of modalSelectors) {
45
+ const found = document.querySelectorAll(selector);
46
+ found.forEach(el => elements.push(el));
47
+ }
48
+ // Check for backdrop overlays
49
+ const backdrops = document.querySelectorAll('.modal-backdrop, .overlay, [data-backdrop]');
50
+ if (backdrops.length > 1) {
51
+ issues.push(`Multiple backdrops detected: ${backdrops.length}`);
52
+ }
53
+ // Process each modal
54
+ for (const element of elements) {
55
+ // Skip duplicates
56
+ if (modals.some((m) => m.element === element))
57
+ continue;
58
+ const computed = window.getComputedStyle(element);
59
+ const isVisible = computed.display !== 'none' &&
60
+ computed.visibility !== 'hidden' &&
61
+ computed.opacity !== '0';
62
+ const zIndex = parseInt(computed.zIndex, 10) || 0;
63
+ const position = computed.position;
64
+ // Detect modal type
65
+ let type = 'custom';
66
+ if (element.tagName === 'DIALOG') {
67
+ type = 'dialog';
68
+ }
69
+ else if (element.getAttribute('role') === 'dialog' ||
70
+ element.getAttribute('role') === 'alertdialog') {
71
+ type = 'dialog';
72
+ }
73
+ else if (element.classList.contains('modal') ||
74
+ element.classList.contains('dialog')) {
75
+ type = 'dialog';
76
+ }
77
+ else if (element.classList.contains('popover')) {
78
+ type = 'popover';
79
+ }
80
+ else if (element.classList.contains('dropdown-menu') ||
81
+ element.getAttribute('role') === 'menu') {
82
+ type = 'dropdown';
83
+ }
84
+ else if (element.getAttribute('role') === 'tooltip') {
85
+ type = 'tooltip';
86
+ }
87
+ else if (element.getAttribute('role') === 'alert') {
88
+ type = 'alert';
89
+ }
90
+ // Check ARIA attributes
91
+ const ariaModal = element.getAttribute('aria-modal') === 'true';
92
+ const ariaLabelledby = element.getAttribute('aria-labelledby') || undefined;
93
+ const ariaDescribedby = element.getAttribute('aria-describedby') || undefined;
94
+ const ariaLabel = element.getAttribute('aria-label') || undefined;
95
+ // Find close buttons
96
+ const closeButtons = [];
97
+ const closeSelectors = [
98
+ 'button[aria-label*="close" i]',
99
+ 'button[aria-label*="Close" i]',
100
+ 'button.close',
101
+ '.close',
102
+ '.modal-close',
103
+ '[data-dismiss]',
104
+ '[data-close]',
105
+ ];
106
+ for (const closeSel of closeSelectors) {
107
+ const closeBtn = element.querySelector(closeSel);
108
+ if (closeBtn) {
109
+ closeButtons.push(closeSel);
110
+ }
111
+ }
112
+ // Generate unique selector
113
+ let selector = element.tagName.toLowerCase();
114
+ if (element.id) {
115
+ selector = `#${element.id}`;
116
+ }
117
+ else if (element.className) {
118
+ const classes = element.className.split(' ').filter((c) => c).slice(0, 2);
119
+ if (classes.length > 0) {
120
+ selector = `${element.tagName.toLowerCase()}.${classes.join('.')}`;
121
+ }
122
+ }
123
+ // Check for backdrop/overlay that blocks interaction
124
+ const hasBackdrop = computed.position === 'fixed' &&
125
+ computed.inset !== 'auto' &&
126
+ computed.backgroundColor !== 'rgba(0, 0, 0, 0)';
127
+ modals.push({
128
+ element,
129
+ selector,
130
+ type,
131
+ zIndex,
132
+ position,
133
+ isVisible,
134
+ hasBackdrop,
135
+ ariaModal,
136
+ ariaLabelledby,
137
+ ariaDescribedby,
138
+ ariaLabel,
139
+ closeButtons,
140
+ });
141
+ }
142
+ // Sort by z-index and determine stack position
143
+ modals.sort((a, b) => a.zIndex - b.zIndex);
144
+ // Assign stack positions and find relationships
145
+ modals.forEach((modal, index) => {
146
+ modal.stackPosition = index;
147
+ // Find parent (modal below that contains this one)
148
+ for (let i = index - 1; i >= 0; i--) {
149
+ const parent = modals[i];
150
+ if (parent.element.contains(modal.element)) {
151
+ modal.parent = parent.selector;
152
+ parent.children = parent.children || [];
153
+ parent.children.push(modal.selector);
154
+ break;
155
+ }
156
+ }
157
+ });
158
+ // Identify issues
159
+ const visibleModals = modals.filter((m) => m.isVisible);
160
+ if (visibleModals.length > 3) {
161
+ issues.push(`Too many visible modals: ${visibleModals.length}`);
162
+ }
163
+ // Check for modals without proper ARIA
164
+ for (const modal of visibleModals) {
165
+ if (modal.type === 'dialog' && !modal.ariaModal) {
166
+ issues.push(`Modal ${modal.selector} missing aria-modal="true"`);
167
+ }
168
+ if (modal.type === 'dialog' && !modal.ariaLabel && !modal.ariaLabelledby) {
169
+ issues.push(`Modal ${modal.selector} missing aria-label or aria-labelledby`);
170
+ }
171
+ }
172
+ return {
173
+ modals: modals.map((m) => ({
174
+ selector: m.selector,
175
+ type: m.type,
176
+ zIndex: m.zIndex,
177
+ stackPosition: m.stackPosition,
178
+ visible: m.isVisible,
179
+ blocksInteraction: m.hasBackdrop,
180
+ aria: {
181
+ modal: m.ariaModal,
182
+ labelledby: m.ariaLabelledby,
183
+ describedby: m.ariaDescribedby,
184
+ label: m.ariaLabel,
185
+ },
186
+ parent: m.parent,
187
+ children: m.children || [],
188
+ closeSelectors: m.closeButtons,
189
+ })),
190
+ totalModals: modals.length,
191
+ visibleModals: visibleModals.length,
192
+ issues,
193
+ };
194
+ });
195
+ return {
196
+ totalModals: result.totalModals,
197
+ visibleModals: result.visibleModals,
198
+ stack: result.modals,
199
+ topModal: result.modals[result.modals.length - 1],
200
+ issues: result.issues,
201
+ };
202
+ }
203
+ /**
204
+ * Get the top-most (active) modal
205
+ */
206
+ async getTopModal(page) {
207
+ const hierarchy = await this.detectModals(page);
208
+ return hierarchy.topModal || null;
209
+ }
210
+ /**
211
+ * Wait for a modal to appear
212
+ */
213
+ async waitForModal(page, options = {}) {
214
+ const timeout = options.timeout || 30000;
215
+ const startTime = Date.now();
216
+ while (Date.now() - startTime < timeout) {
217
+ const hierarchy = await this.detectModals(page);
218
+ for (const modal of hierarchy.stack) {
219
+ if (!modal.visible)
220
+ continue;
221
+ if (options.type && modal.type !== options.type)
222
+ continue;
223
+ if (options.selector && !modal.selector.includes(options.selector))
224
+ continue;
225
+ if (options.minZIndex && modal.zIndex < options.minZIndex)
226
+ continue;
227
+ return modal;
228
+ }
229
+ await new Promise(resolve => setTimeout(resolve, 100));
230
+ }
231
+ return null;
232
+ }
233
+ /**
234
+ * Close a modal
235
+ */
236
+ async closeModal(page, modal, options = {}) {
237
+ const selector = typeof modal === 'string' ? modal : modal.selector;
238
+ const timeout = options.timeout || 5000;
239
+ if (options.waitFor !== false) {
240
+ await page.waitForSelector(selector, { state: 'visible', timeout });
241
+ }
242
+ // Try different close methods
243
+ const closeMethods = [
244
+ // Try ESC key
245
+ async () => {
246
+ await page.keyboard.press('Escape');
247
+ await page.waitForTimeout(500);
248
+ },
249
+ // Try close button
250
+ async () => {
251
+ const closeBtn = await page.locator(`${selector} button[aria-label*="close" i], ${selector} .close, ${selector} [data-dismiss]`).first();
252
+ if (await closeBtn.count() > 0) {
253
+ await closeBtn.click();
254
+ await page.waitForTimeout(500);
255
+ return true;
256
+ }
257
+ return false;
258
+ },
259
+ // Try clicking backdrop
260
+ async () => {
261
+ const backdrop = await page.locator('.modal-backdrop, .overlay, [data-backdrop]').first();
262
+ if (await backdrop.count() > 0) {
263
+ await backdrop.click({ position: { x: 10, y: 10 } });
264
+ await page.waitForTimeout(500);
265
+ return true;
266
+ }
267
+ return false;
268
+ },
269
+ ];
270
+ for (const method of closeMethods) {
271
+ try {
272
+ const result = await method();
273
+ if (result === true) {
274
+ // Check if modal is now hidden
275
+ const isVisible = await page.locator(selector).isVisible().catch(() => false);
276
+ if (!isVisible) {
277
+ return true;
278
+ }
279
+ }
280
+ }
281
+ catch {
282
+ // Try next method
283
+ }
284
+ }
285
+ return false;
286
+ }
287
+ /**
288
+ * Close all modals from top to bottom
289
+ */
290
+ async closeAllModals(page, options = {}) {
291
+ let closed = 0;
292
+ let hierarchy = await this.detectModals(page);
293
+ while (hierarchy.visibleModals > 0) {
294
+ const topModal = hierarchy.topModal;
295
+ if (!topModal)
296
+ break;
297
+ const success = await this.closeModal(page, topModal, options);
298
+ if (!success)
299
+ break;
300
+ closed++;
301
+ hierarchy = await this.detectModals(page);
302
+ // Safety check
303
+ if (closed > 10)
304
+ break;
305
+ }
306
+ return closed;
307
+ }
308
+ /**
309
+ * Get modal hierarchy for debugging
310
+ */
311
+ async getModalTree(page) {
312
+ const hierarchy = await this.detectModals(page);
313
+ const lines = [
314
+ `Modal Stack (${hierarchy.visibleModals}/${hierarchy.totalModals} visible)`,
315
+ '',
316
+ ];
317
+ for (const modal of hierarchy.stack) {
318
+ const indent = ' '.repeat(modal.stackPosition);
319
+ const status = modal.visible ? '✓' : '✗';
320
+ const typeIcon = {
321
+ dialog: '⬚',
322
+ popover: '◐',
323
+ dropdown: '▼',
324
+ tooltip: 'ⓘ',
325
+ alert: '⚠',
326
+ custom: '○',
327
+ }[modal.type];
328
+ lines.push(`${indent}${status} ${typeIcon} ${modal.selector} (z-index: ${modal.zIndex})`);
329
+ if (modal.parent) {
330
+ lines.push(`${indent} └─ parent: ${modal.parent}`);
331
+ }
332
+ if (modal.closeSelectors.length > 0) {
333
+ lines.push(`${indent} └─ close: ${modal.closeSelectors[0]}`);
334
+ }
335
+ }
336
+ if (hierarchy.issues.length > 0) {
337
+ lines.push('');
338
+ lines.push('Issues:');
339
+ for (const issue of hierarchy.issues) {
340
+ lines.push(` ⚠ ${issue}`);
341
+ }
342
+ }
343
+ return lines.join('\n');
344
+ }
345
+ /**
346
+ * Verify modal accessibility
347
+ */
348
+ async verifyAccessibility(page, modal) {
349
+ const selector = typeof modal === 'string' ? modal : modal.selector;
350
+ const issues = [];
351
+ const result = await page.evaluate((sel) => {
352
+ const element = document.querySelector(sel);
353
+ if (!element)
354
+ return { found: false };
355
+ const computed = window.getComputedStyle(element);
356
+ return {
357
+ found: true,
358
+ hasAriaModal: element.getAttribute('aria-modal') === 'true',
359
+ hasAriaLabel: !!element.getAttribute('aria-label'),
360
+ hasAriaLabelledby: !!element.getAttribute('aria-labelledby'),
361
+ role: element.getAttribute('role'),
362
+ tagName: element.tagName,
363
+ display: computed.display,
364
+ visible: computed.display !== 'none' &&
365
+ computed.visibility !== 'hidden' &&
366
+ computed.opacity !== '0',
367
+ // Check for focus trap
368
+ focusableElements: element.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])').length,
369
+ };
370
+ }, selector);
371
+ if (!result.found) {
372
+ return { valid: false, issues: ['Element not found'] };
373
+ }
374
+ // Check ARIA attributes
375
+ if (result.tagName !== 'DIALOG' && result.role !== 'dialog' && result.role !== 'alertdialog') {
376
+ issues.push(`Element is not a dialog (role: ${result.role})`);
377
+ }
378
+ if (!result.hasAriaModal && result.tagName !== 'DIALOG') {
379
+ issues.push('Missing aria-modal="true" attribute');
380
+ }
381
+ if (!result.hasAriaLabel && !result.hasAriaLabelledby) {
382
+ issues.push('Missing aria-label or aria-labelledby attribute');
383
+ }
384
+ if (result.focusableElements === 0) {
385
+ issues.push('No focusable elements found in modal');
386
+ }
387
+ return {
388
+ valid: issues.length === 0,
389
+ issues,
390
+ };
391
+ }
392
+ /**
393
+ * Get modal statistics
394
+ */
395
+ async getStatistics(page) {
396
+ const hierarchy = await this.detectModals(page);
397
+ const byType = {};
398
+ let totalZIndex = 0;
399
+ let maxStack = 0;
400
+ for (const modal of hierarchy.stack) {
401
+ byType[modal.type] = (byType[modal.type] || 0) + 1;
402
+ totalZIndex += modal.zIndex;
403
+ maxStack = Math.max(maxStack, modal.stackPosition);
404
+ }
405
+ const avgZIndex = hierarchy.stack.length > 0
406
+ ? totalZIndex / hierarchy.stack.length
407
+ : 0;
408
+ // Calculate accessibility score
409
+ let accessibilityScore = 100;
410
+ for (const issue of hierarchy.issues) {
411
+ if (issue.includes('aria') || issue.includes('label')) {
412
+ accessibilityScore -= 10;
413
+ }
414
+ }
415
+ return {
416
+ byType,
417
+ averageZIndex: Math.round(avgZIndex),
418
+ maxStackDepth: maxStack + 1,
419
+ accessibilityScore: Math.max(0, accessibilityScore),
420
+ };
421
+ }
422
+ }
423
+ /**
424
+ * Factory function to create Stacked Modals Handler
425
+ */
426
+ export function createStackedModalsHandler() {
427
+ return new StackedModalsHandler();
428
+ }
429
+ export default StackedModalsHandler;
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Trusted Types Handler
3
+ *
4
+ * P1 - Trusted Types API for XSS prevention
5
+ *
6
+ * Supports:
7
+ * - Trusted Types detection
8
+ * - CSP trusted-types directive parsing
9
+ * - Trusted type policy creation
10
+ * - XSS sink monitoring
11
+ * - Trusted types violation tracking
12
+ *
13
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types
14
+ */
15
+ export interface TrustedTypesConfig {
16
+ /** CSP trusted-types directive values */
17
+ directiveValues: string[];
18
+ /** Policy names */
19
+ policyNames: string[];
20
+ /** 'none' is set (no policies allowed) */
21
+ allowsNone: boolean;
22
+ /** '*' is set (any policy allowed) */
23
+ allowsAll: boolean;
24
+ }
25
+ export interface TrustedTypePolicy {
26
+ /** Policy name */
27
+ name: string;
28
+ /** createHTML function */
29
+ createHTML?: (input: string) => any;
30
+ /** createScriptURL function */
31
+ createScriptURL?: (input: string) => any;
32
+ /** createScript function */
33
+ createScript?: (input: string) => any;
34
+ }
35
+ export interface XSSSink {
36
+ /** Sink type (e.g., 'innerHTML', 'location') */
37
+ type: string;
38
+ /** Element or object */
39
+ element?: string;
40
+ /** Current value */
41
+ value?: string;
42
+ /** Whether it's a known XSS sink */
43
+ isXSSSink: boolean;
44
+ }
45
+ export interface TrustedTypesReport {
46
+ /** Trusted Types supported */
47
+ supported: boolean;
48
+ /** CSP directive config */
49
+ config: TrustedTypesConfig;
50
+ /** Existing policies */
51
+ policies: string[];
52
+ /** XSS sinks detected */
53
+ xssSinks: XSSSink[];
54
+ /** Violations collected */
55
+ violations: Array<{
56
+ message: string;
57
+ sink: string;
58
+ value: string;
59
+ }>;
60
+ /** Security score (0-100) */
61
+ securityScore: number;
62
+ /** Recommendations */
63
+ recommendations: string[];
64
+ }
65
+ /**
66
+ * Trusted Types Handler class
67
+ */
68
+ export declare class TrustedTypesHandler {
69
+ private page;
70
+ private violations;
71
+ constructor(page: any);
72
+ /**
73
+ * Check if Trusted Types is supported
74
+ */
75
+ isSupported(): Promise<boolean>;
76
+ /**
77
+ * Get Trusted Types CSP directive
78
+ */
79
+ getTrustedTypesDirective(): Promise<string | null>;
80
+ /**
81
+ * Parse Trusted Types CSP directive
82
+ */
83
+ parseTrustedTypesDirective(directive: string | null): TrustedTypesConfig;
84
+ /**
85
+ * Get existing Trusted Type policies
86
+ */
87
+ getExistingPolicies(): Promise<string[]>;
88
+ /**
89
+ * Detect XSS sinks in the page
90
+ */
91
+ detectXSSSinks(): Promise<XSSSink[]>;
92
+ /**
93
+ * Create a test Trusted Type policy
94
+ */
95
+ createTestPolicy(policyName: string): Promise<boolean>;
96
+ /**
97
+ * Test if a sink requires Trusted Type
98
+ */
99
+ testSinkRequiresTrustedType(sinkType: 'innerHTML' | 'outerHTML' | 'src'): Promise<boolean>;
100
+ /**
101
+ * Setup violation monitoring
102
+ */
103
+ setupViolationMonitoring(): Promise<void>;
104
+ /**
105
+ * Get collected violations
106
+ */
107
+ getViolations(): Array<{
108
+ message: string;
109
+ sink: string;
110
+ value: string;
111
+ }>;
112
+ /**
113
+ * Clear violations
114
+ */
115
+ clearViolations(): void;
116
+ /**
117
+ * Generate full Trusted Types report
118
+ */
119
+ generateReport(): Promise<TrustedTypesReport>;
120
+ /**
121
+ * Validate Trusted Types configuration
122
+ */
123
+ validate(): Promise<{
124
+ valid: boolean;
125
+ errors: string[];
126
+ warnings: string[];
127
+ }>;
128
+ /**
129
+ * Generate recommended CSP snippet for Trusted Types
130
+ */
131
+ generateRecommendedCSP(policyNames?: string[], requireTrustedTypesFor?: string[]): string;
132
+ /**
133
+ * Test if a string passes Trusted Types validation
134
+ */
135
+ testTrustedString(policyName: string, input: string, type?: 'createHTML' | 'createScriptURL' | 'createScript'): Promise<{
136
+ success: boolean;
137
+ result?: string;
138
+ error?: string;
139
+ }>;
140
+ /**
141
+ * Get documentation URL
142
+ */
143
+ getDocumentation(): string;
144
+ }
145
+ /**
146
+ * Factory function to create Trusted Types Handler
147
+ */
148
+ export declare function createTrustedTypesHandler(page: any): TrustedTypesHandler;
149
+ export default TrustedTypesHandler;