@avi770/testteam 1.2.0 → 3.0.0

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 (324) hide show
  1. package/CHANGELOG.md +53 -1
  2. package/README.md +72 -7
  3. package/agents/15-regression-sentinel.ts +3 -2
  4. package/agents/24-signup-onboarding-tester.ts +429 -0
  5. package/agents/25-crud-flow-tester.ts +302 -0
  6. package/agents/26-form-validator.ts +297 -0
  7. package/agents/27-search-filter-tester.ts +326 -0
  8. package/agents/28-navigation-routing-tester.ts +425 -0
  9. package/agents/29-responsive-interaction-tester.ts +350 -0
  10. package/agents/30-multi-user-scenario-tester.ts +319 -0
  11. package/agents/31-load-tester.ts +134 -0
  12. package/agents/32-memory-leak-detector.ts +194 -0
  13. package/agents/33-bundle-analyzer.ts +132 -0
  14. package/agents/34-xss-scanner.ts +191 -0
  15. package/agents/35-csrf-tester.ts +82 -0
  16. package/agents/36-auth-fuzzer.ts +194 -0
  17. package/agents/37-dependency-scanner.ts +176 -0
  18. package/agents/38-secrets-scanner.ts +137 -0
  19. package/agents/39-api-contract-tester.ts +199 -0
  20. package/agents/40-rate-limit-tester.ts +94 -0
  21. package/agents/41-api-pagination-tester.ts +97 -0
  22. package/agents/42-graphql-tester.ts +222 -0
  23. package/agents/43-data-consistency-checker.ts +205 -0
  24. package/agents/44-backup-recovery-tester.ts +152 -0
  25. package/agents/45-data-privacy-scanner.ts +125 -0
  26. package/agents/46-seo-auditor.ts +294 -0
  27. package/agents/47-social-preview-tester.ts +232 -0
  28. package/agents/48-lighthouse-auditor.ts +213 -0
  29. package/agents/49-i18n-tester.ts +198 -0
  30. package/agents/50-timezone-tester.ts +173 -0
  31. package/agents/51-error-recovery-tester.ts +155 -0
  32. package/agents/52-offline-mode-tester.ts +180 -0
  33. package/agents/53-graceful-degradation-tester.ts +156 -0
  34. package/agents/54-websocket-tester.ts +151 -0
  35. package/agents/55-realtime-sync-tester.ts +194 -0
  36. package/agents/56-file-upload-tester.ts +194 -0
  37. package/agents/57-export-tester.ts +174 -0
  38. package/agents/58-payment-flow-tester.ts +183 -0
  39. package/agents/59-ssl-tls-auditor.ts +141 -0
  40. package/agents/60-dns-cdn-tester.ts +117 -0
  41. package/agents/61-docker-health-checker.ts +111 -0
  42. package/agents/62-env-config-validator.ts +152 -0
  43. package/agents/63-log-quality-auditor.ts +136 -0
  44. package/agents/64-analytics-tracker-tester.ts +165 -0
  45. package/agents/65-gdpr-compliance-tester.ts +215 -0
  46. package/agents/66-soc2-control-validator.ts +210 -0
  47. package/agents/67-wcag-aaa-tester.ts +241 -0
  48. package/agents/68-dead-code-detector.ts +135 -0
  49. package/agents/69-type-safety-auditor.ts +164 -0
  50. package/agents/70-complexity-analyzer.ts +179 -0
  51. package/agents/__tests__/24-signup-onboarding-tester.test.ts +274 -0
  52. package/agents/__tests__/25-crud-flow-tester.test.ts +322 -0
  53. package/agents/__tests__/26-form-validator.test.ts +345 -0
  54. package/agents/__tests__/27-search-filter-tester.test.ts +311 -0
  55. package/agents/__tests__/28-navigation-routing-tester.test.ts +328 -0
  56. package/agents/__tests__/29-responsive-interaction-tester.test.ts +297 -0
  57. package/agents/__tests__/30-multi-user-scenario-tester.test.ts +328 -0
  58. package/agents/__tests__/31-load-tester.test.ts +189 -0
  59. package/agents/__tests__/32-memory-leak-detector.test.ts +251 -0
  60. package/agents/__tests__/33-bundle-analyzer.test.ts +237 -0
  61. package/agents/__tests__/34-xss-scanner.test.ts +258 -0
  62. package/agents/__tests__/35-csrf-tester.test.ts +200 -0
  63. package/agents/__tests__/36-auth-fuzzer.test.ts +214 -0
  64. package/agents/__tests__/37-dependency-scanner.test.ts +266 -0
  65. package/agents/__tests__/38-secrets-scanner.test.ts +224 -0
  66. package/agents/__tests__/39-api-contract-tester.test.ts +312 -0
  67. package/agents/__tests__/40-rate-limit-tester.test.ts +192 -0
  68. package/agents/__tests__/41-api-pagination-tester.test.ts +198 -0
  69. package/agents/__tests__/42-graphql-tester.test.ts +252 -0
  70. package/agents/__tests__/43-data-consistency-checker.test.ts +232 -0
  71. package/agents/__tests__/44-backup-recovery-tester.test.ts +222 -0
  72. package/agents/__tests__/45-data-privacy-scanner.test.ts +223 -0
  73. package/agents/__tests__/46-seo-auditor.test.ts +261 -0
  74. package/agents/__tests__/47-social-preview-tester.test.ts +245 -0
  75. package/agents/__tests__/48-lighthouse-auditor.test.ts +276 -0
  76. package/agents/__tests__/49-i18n-tester.test.ts +201 -0
  77. package/agents/__tests__/50-timezone-tester.test.ts +172 -0
  78. package/agents/__tests__/51-error-recovery-tester.test.ts +162 -0
  79. package/agents/__tests__/52-offline-mode-tester.test.ts +164 -0
  80. package/agents/__tests__/53-graceful-degradation-tester.test.ts +168 -0
  81. package/agents/__tests__/54-websocket-tester.test.ts +157 -0
  82. package/agents/__tests__/55-realtime-sync-tester.test.ts +181 -0
  83. package/agents/__tests__/56-file-upload-tester.test.ts +172 -0
  84. package/agents/__tests__/57-export-tester.test.ts +169 -0
  85. package/agents/__tests__/58-payment-flow-tester.test.ts +182 -0
  86. package/agents/__tests__/59-ssl-tls-auditor.test.ts +179 -0
  87. package/agents/__tests__/60-dns-cdn-tester.test.ts +176 -0
  88. package/agents/__tests__/61-docker-health-checker.test.ts +150 -0
  89. package/agents/__tests__/62-env-config-validator.test.ts +166 -0
  90. package/agents/__tests__/63-log-quality-auditor.test.ts +175 -0
  91. package/agents/__tests__/64-analytics-tracker-tester.test.ts +158 -0
  92. package/agents/__tests__/65-gdpr-compliance-tester.test.ts +174 -0
  93. package/agents/__tests__/66-soc2-control-validator.test.ts +183 -0
  94. package/agents/__tests__/67-wcag-aaa-tester.test.ts +190 -0
  95. package/agents/__tests__/68-dead-code-detector.test.ts +174 -0
  96. package/agents/__tests__/69-type-safety-auditor.test.ts +173 -0
  97. package/agents/__tests__/70-complexity-analyzer.test.ts +177 -0
  98. package/agents/__tests__/registry.test.ts +13 -13
  99. package/agents/base-agent.ts +8 -0
  100. package/agents/registry.ts +171 -28
  101. package/core/__tests__/integration.test.ts +4 -4
  102. package/core/__tests__/orchestrator.test.ts +17 -16
  103. package/core/cli.ts +128 -6
  104. package/core/license.ts +208 -211
  105. package/core/orchestrator.ts +78 -5
  106. package/dist/agents/15-regression-sentinel.d.ts +2 -1
  107. package/dist/agents/15-regression-sentinel.d.ts.map +1 -1
  108. package/dist/agents/15-regression-sentinel.js +2 -2
  109. package/dist/agents/15-regression-sentinel.js.map +1 -1
  110. package/dist/agents/24-signup-onboarding-tester.d.ts +35 -0
  111. package/dist/agents/24-signup-onboarding-tester.d.ts.map +1 -0
  112. package/dist/agents/24-signup-onboarding-tester.js +357 -0
  113. package/dist/agents/24-signup-onboarding-tester.js.map +1 -0
  114. package/dist/agents/25-crud-flow-tester.d.ts +11 -0
  115. package/dist/agents/25-crud-flow-tester.d.ts.map +1 -0
  116. package/dist/agents/25-crud-flow-tester.js +253 -0
  117. package/dist/agents/25-crud-flow-tester.js.map +1 -0
  118. package/dist/agents/26-form-validator.d.ts +12 -0
  119. package/dist/agents/26-form-validator.d.ts.map +1 -0
  120. package/dist/agents/26-form-validator.js +257 -0
  121. package/dist/agents/26-form-validator.js.map +1 -0
  122. package/dist/agents/27-search-filter-tester.d.ts +20 -0
  123. package/dist/agents/27-search-filter-tester.d.ts.map +1 -0
  124. package/dist/agents/27-search-filter-tester.js +267 -0
  125. package/dist/agents/27-search-filter-tester.js.map +1 -0
  126. package/dist/agents/28-navigation-routing-tester.d.ts +32 -0
  127. package/dist/agents/28-navigation-routing-tester.d.ts.map +1 -0
  128. package/dist/agents/28-navigation-routing-tester.js +363 -0
  129. package/dist/agents/28-navigation-routing-tester.js.map +1 -0
  130. package/dist/agents/29-responsive-interaction-tester.d.ts +26 -0
  131. package/dist/agents/29-responsive-interaction-tester.d.ts.map +1 -0
  132. package/dist/agents/29-responsive-interaction-tester.js +272 -0
  133. package/dist/agents/29-responsive-interaction-tester.js.map +1 -0
  134. package/dist/agents/30-multi-user-scenario-tester.d.ts +24 -0
  135. package/dist/agents/30-multi-user-scenario-tester.d.ts.map +1 -0
  136. package/dist/agents/30-multi-user-scenario-tester.js +254 -0
  137. package/dist/agents/30-multi-user-scenario-tester.js.map +1 -0
  138. package/dist/agents/31-load-tester.d.ts +12 -0
  139. package/dist/agents/31-load-tester.d.ts.map +1 -0
  140. package/dist/agents/31-load-tester.js +110 -0
  141. package/dist/agents/31-load-tester.js.map +1 -0
  142. package/dist/agents/32-memory-leak-detector.d.ts +12 -0
  143. package/dist/agents/32-memory-leak-detector.d.ts.map +1 -0
  144. package/dist/agents/32-memory-leak-detector.js +167 -0
  145. package/dist/agents/32-memory-leak-detector.js.map +1 -0
  146. package/dist/agents/33-bundle-analyzer.d.ts +10 -0
  147. package/dist/agents/33-bundle-analyzer.d.ts.map +1 -0
  148. package/dist/agents/33-bundle-analyzer.js +111 -0
  149. package/dist/agents/33-bundle-analyzer.js.map +1 -0
  150. package/dist/agents/34-xss-scanner.d.ts +11 -0
  151. package/dist/agents/34-xss-scanner.d.ts.map +1 -0
  152. package/dist/agents/34-xss-scanner.js +164 -0
  153. package/dist/agents/34-xss-scanner.js.map +1 -0
  154. package/dist/agents/35-csrf-tester.d.ts +11 -0
  155. package/dist/agents/35-csrf-tester.d.ts.map +1 -0
  156. package/dist/agents/35-csrf-tester.js +70 -0
  157. package/dist/agents/35-csrf-tester.js.map +1 -0
  158. package/dist/agents/36-auth-fuzzer.d.ts +13 -0
  159. package/dist/agents/36-auth-fuzzer.d.ts.map +1 -0
  160. package/dist/agents/36-auth-fuzzer.js +163 -0
  161. package/dist/agents/36-auth-fuzzer.js.map +1 -0
  162. package/dist/agents/37-dependency-scanner.d.ts +11 -0
  163. package/dist/agents/37-dependency-scanner.d.ts.map +1 -0
  164. package/dist/agents/37-dependency-scanner.js +139 -0
  165. package/dist/agents/37-dependency-scanner.js.map +1 -0
  166. package/dist/agents/38-secrets-scanner.d.ts +11 -0
  167. package/dist/agents/38-secrets-scanner.d.ts.map +1 -0
  168. package/dist/agents/38-secrets-scanner.js +116 -0
  169. package/dist/agents/38-secrets-scanner.js.map +1 -0
  170. package/dist/agents/39-api-contract-tester.d.ts +12 -0
  171. package/dist/agents/39-api-contract-tester.d.ts.map +1 -0
  172. package/dist/agents/39-api-contract-tester.js +142 -0
  173. package/dist/agents/39-api-contract-tester.js.map +1 -0
  174. package/dist/agents/40-rate-limit-tester.d.ts +12 -0
  175. package/dist/agents/40-rate-limit-tester.d.ts.map +1 -0
  176. package/dist/agents/40-rate-limit-tester.js +79 -0
  177. package/dist/agents/40-rate-limit-tester.js.map +1 -0
  178. package/dist/agents/41-api-pagination-tester.d.ts +12 -0
  179. package/dist/agents/41-api-pagination-tester.d.ts.map +1 -0
  180. package/dist/agents/41-api-pagination-tester.js +79 -0
  181. package/dist/agents/41-api-pagination-tester.js.map +1 -0
  182. package/dist/agents/42-graphql-tester.d.ts +13 -0
  183. package/dist/agents/42-graphql-tester.d.ts.map +1 -0
  184. package/dist/agents/42-graphql-tester.js +187 -0
  185. package/dist/agents/42-graphql-tester.js.map +1 -0
  186. package/dist/agents/43-data-consistency-checker.d.ts +11 -0
  187. package/dist/agents/43-data-consistency-checker.d.ts.map +1 -0
  188. package/dist/agents/43-data-consistency-checker.js +176 -0
  189. package/dist/agents/43-data-consistency-checker.js.map +1 -0
  190. package/dist/agents/44-backup-recovery-tester.d.ts +11 -0
  191. package/dist/agents/44-backup-recovery-tester.d.ts.map +1 -0
  192. package/dist/agents/44-backup-recovery-tester.js +128 -0
  193. package/dist/agents/44-backup-recovery-tester.js.map +1 -0
  194. package/dist/agents/45-data-privacy-scanner.d.ts +11 -0
  195. package/dist/agents/45-data-privacy-scanner.d.ts.map +1 -0
  196. package/dist/agents/45-data-privacy-scanner.js +100 -0
  197. package/dist/agents/45-data-privacy-scanner.js.map +1 -0
  198. package/dist/agents/46-seo-auditor.d.ts +12 -0
  199. package/dist/agents/46-seo-auditor.d.ts.map +1 -0
  200. package/dist/agents/46-seo-auditor.js +275 -0
  201. package/dist/agents/46-seo-auditor.js.map +1 -0
  202. package/dist/agents/47-social-preview-tester.d.ts +11 -0
  203. package/dist/agents/47-social-preview-tester.d.ts.map +1 -0
  204. package/dist/agents/47-social-preview-tester.js +219 -0
  205. package/dist/agents/47-social-preview-tester.js.map +1 -0
  206. package/dist/agents/48-lighthouse-auditor.d.ts +11 -0
  207. package/dist/agents/48-lighthouse-auditor.d.ts.map +1 -0
  208. package/dist/agents/48-lighthouse-auditor.js +192 -0
  209. package/dist/agents/48-lighthouse-auditor.js.map +1 -0
  210. package/dist/agents/49-i18n-tester.d.ts +13 -0
  211. package/dist/agents/49-i18n-tester.d.ts.map +1 -0
  212. package/dist/agents/49-i18n-tester.js +172 -0
  213. package/dist/agents/49-i18n-tester.js.map +1 -0
  214. package/dist/agents/50-timezone-tester.d.ts +11 -0
  215. package/dist/agents/50-timezone-tester.d.ts.map +1 -0
  216. package/dist/agents/50-timezone-tester.js +152 -0
  217. package/dist/agents/50-timezone-tester.js.map +1 -0
  218. package/dist/agents/51-error-recovery-tester.d.ts +11 -0
  219. package/dist/agents/51-error-recovery-tester.d.ts.map +1 -0
  220. package/dist/agents/51-error-recovery-tester.js +134 -0
  221. package/dist/agents/51-error-recovery-tester.js.map +1 -0
  222. package/dist/agents/52-offline-mode-tester.d.ts +12 -0
  223. package/dist/agents/52-offline-mode-tester.d.ts.map +1 -0
  224. package/dist/agents/52-offline-mode-tester.js +161 -0
  225. package/dist/agents/52-offline-mode-tester.js.map +1 -0
  226. package/dist/agents/53-graceful-degradation-tester.d.ts +12 -0
  227. package/dist/agents/53-graceful-degradation-tester.d.ts.map +1 -0
  228. package/dist/agents/53-graceful-degradation-tester.js +130 -0
  229. package/dist/agents/53-graceful-degradation-tester.js.map +1 -0
  230. package/dist/agents/54-websocket-tester.d.ts +10 -0
  231. package/dist/agents/54-websocket-tester.d.ts.map +1 -0
  232. package/dist/agents/54-websocket-tester.js +132 -0
  233. package/dist/agents/54-websocket-tester.js.map +1 -0
  234. package/dist/agents/55-realtime-sync-tester.d.ts +11 -0
  235. package/dist/agents/55-realtime-sync-tester.d.ts.map +1 -0
  236. package/dist/agents/55-realtime-sync-tester.js +175 -0
  237. package/dist/agents/55-realtime-sync-tester.js.map +1 -0
  238. package/dist/agents/56-file-upload-tester.d.ts +12 -0
  239. package/dist/agents/56-file-upload-tester.d.ts.map +1 -0
  240. package/dist/agents/56-file-upload-tester.js +166 -0
  241. package/dist/agents/56-file-upload-tester.js.map +1 -0
  242. package/dist/agents/57-export-tester.d.ts +11 -0
  243. package/dist/agents/57-export-tester.d.ts.map +1 -0
  244. package/dist/agents/57-export-tester.js +155 -0
  245. package/dist/agents/57-export-tester.js.map +1 -0
  246. package/dist/agents/58-payment-flow-tester.d.ts +11 -0
  247. package/dist/agents/58-payment-flow-tester.d.ts.map +1 -0
  248. package/dist/agents/58-payment-flow-tester.js +159 -0
  249. package/dist/agents/58-payment-flow-tester.js.map +1 -0
  250. package/dist/agents/59-ssl-tls-auditor.d.ts +10 -0
  251. package/dist/agents/59-ssl-tls-auditor.d.ts.map +1 -0
  252. package/dist/agents/59-ssl-tls-auditor.js +132 -0
  253. package/dist/agents/59-ssl-tls-auditor.js.map +1 -0
  254. package/dist/agents/60-dns-cdn-tester.d.ts +10 -0
  255. package/dist/agents/60-dns-cdn-tester.d.ts.map +1 -0
  256. package/dist/agents/60-dns-cdn-tester.js +105 -0
  257. package/dist/agents/60-dns-cdn-tester.js.map +1 -0
  258. package/dist/agents/61-docker-health-checker.d.ts +10 -0
  259. package/dist/agents/61-docker-health-checker.d.ts.map +1 -0
  260. package/dist/agents/61-docker-health-checker.js +95 -0
  261. package/dist/agents/61-docker-health-checker.js.map +1 -0
  262. package/dist/agents/62-env-config-validator.d.ts +10 -0
  263. package/dist/agents/62-env-config-validator.d.ts.map +1 -0
  264. package/dist/agents/62-env-config-validator.js +132 -0
  265. package/dist/agents/62-env-config-validator.js.map +1 -0
  266. package/dist/agents/63-log-quality-auditor.d.ts +9 -0
  267. package/dist/agents/63-log-quality-auditor.d.ts.map +1 -0
  268. package/dist/agents/63-log-quality-auditor.js +121 -0
  269. package/dist/agents/63-log-quality-auditor.js.map +1 -0
  270. package/dist/agents/64-analytics-tracker-tester.d.ts +10 -0
  271. package/dist/agents/64-analytics-tracker-tester.d.ts.map +1 -0
  272. package/dist/agents/64-analytics-tracker-tester.js +146 -0
  273. package/dist/agents/64-analytics-tracker-tester.js.map +1 -0
  274. package/dist/agents/65-gdpr-compliance-tester.d.ts +13 -0
  275. package/dist/agents/65-gdpr-compliance-tester.d.ts.map +1 -0
  276. package/dist/agents/65-gdpr-compliance-tester.js +186 -0
  277. package/dist/agents/65-gdpr-compliance-tester.js.map +1 -0
  278. package/dist/agents/66-soc2-control-validator.d.ts +14 -0
  279. package/dist/agents/66-soc2-control-validator.d.ts.map +1 -0
  280. package/dist/agents/66-soc2-control-validator.js +178 -0
  281. package/dist/agents/66-soc2-control-validator.js.map +1 -0
  282. package/dist/agents/67-wcag-aaa-tester.d.ts +13 -0
  283. package/dist/agents/67-wcag-aaa-tester.d.ts.map +1 -0
  284. package/dist/agents/67-wcag-aaa-tester.js +207 -0
  285. package/dist/agents/67-wcag-aaa-tester.js.map +1 -0
  286. package/dist/agents/68-dead-code-detector.d.ts +9 -0
  287. package/dist/agents/68-dead-code-detector.d.ts.map +1 -0
  288. package/dist/agents/68-dead-code-detector.js +116 -0
  289. package/dist/agents/68-dead-code-detector.js.map +1 -0
  290. package/dist/agents/69-type-safety-auditor.d.ts +9 -0
  291. package/dist/agents/69-type-safety-auditor.d.ts.map +1 -0
  292. package/dist/agents/69-type-safety-auditor.js +148 -0
  293. package/dist/agents/69-type-safety-auditor.js.map +1 -0
  294. package/dist/agents/70-complexity-analyzer.d.ts +10 -0
  295. package/dist/agents/70-complexity-analyzer.d.ts.map +1 -0
  296. package/dist/agents/70-complexity-analyzer.js +154 -0
  297. package/dist/agents/70-complexity-analyzer.js.map +1 -0
  298. package/dist/agents/base-agent.d.ts +3 -1
  299. package/dist/agents/base-agent.d.ts.map +1 -1
  300. package/dist/agents/base-agent.js +7 -1
  301. package/dist/agents/base-agent.js.map +1 -1
  302. package/dist/agents/registry.d.ts +5 -4
  303. package/dist/agents/registry.d.ts.map +1 -1
  304. package/dist/agents/registry.js +170 -29
  305. package/dist/agents/registry.js.map +1 -1
  306. package/dist/clients/agent-mvp.d.ts +66 -0
  307. package/dist/clients/agent-mvp.d.ts.map +1 -0
  308. package/dist/clients/agent-mvp.js +91 -0
  309. package/dist/clients/agent-mvp.js.map +1 -0
  310. package/dist/clients/total-recall.d.ts +37 -0
  311. package/dist/clients/total-recall.d.ts.map +1 -0
  312. package/dist/clients/total-recall.js +224 -0
  313. package/dist/clients/total-recall.js.map +1 -0
  314. package/dist/core/cli.d.ts +3 -0
  315. package/dist/core/cli.d.ts.map +1 -1
  316. package/dist/core/cli.js +122 -6
  317. package/dist/core/cli.js.map +1 -1
  318. package/dist/core/license.js +2 -5
  319. package/dist/core/license.js.map +1 -1
  320. package/dist/core/orchestrator.d.ts +10 -1
  321. package/dist/core/orchestrator.d.ts.map +1 -1
  322. package/dist/core/orchestrator.js +66 -5
  323. package/dist/core/orchestrator.js.map +1 -1
  324. package/package.json +2 -2
@@ -0,0 +1,326 @@
1
+ import type { Browser, Page } from 'playwright';
2
+ import type { Finding } from '../core/types';
3
+ import { BaseAgent } from './base-agent';
4
+ import { resolveEnvironment } from '../helpers/env-resolver';
5
+ import { login } from '../helpers/navigation';
6
+
7
+ /** Timeout (ms) for individual search/filter operations. */
8
+ const OP_TIMEOUT_MS = 5_000;
9
+
10
+ /** Selectors for search inputs. */
11
+ const SEARCH_SELECTORS = [
12
+ 'input[type="search"]',
13
+ 'input[placeholder*="search" i]',
14
+ 'input[placeholder*="find" i]',
15
+ '[data-testid*="search"]',
16
+ '[role="searchbox"]',
17
+ ] as const;
18
+
19
+ /** Selectors for filter controls. */
20
+ const FILTER_SELECTORS = [
21
+ 'select',
22
+ '[role="combobox"]',
23
+ 'button:has-text("Filter")',
24
+ '[data-testid*="filter"]',
25
+ ] as const;
26
+
27
+ export class SearchFilterTesterAgent extends BaseAgent {
28
+ readonly agentId = 27;
29
+ readonly agentName = 'Search & Filter Tester';
30
+ private baseUrl = '';
31
+
32
+ protected async preFlight(): Promise<void> {
33
+ if (!this.config.modules || this.config.modules.length === 0) {
34
+ throw new Error('SearchFilterTesterAgent requires at least one module in config.modules');
35
+ }
36
+
37
+ const { env } = await resolveEnvironment(this.config, this.phase);
38
+ this.baseUrl = env.baseUrl;
39
+ }
40
+
41
+ protected async execute(): Promise<Finding[]> {
42
+ const findings: Finding[] = [];
43
+
44
+ const rawLoginUrl = this.config.auth.loginUrl ?? '/login';
45
+ const loginUrl = rawLoginUrl.startsWith('http') ? rawLoginUrl : `${this.baseUrl}${rawLoginUrl}`;
46
+ const credentials =
47
+ this.config.auth.credentials?.['admin'] ??
48
+ Object.values(this.config.auth.credentials ?? {})[0];
49
+
50
+ if (!credentials) {
51
+ findings.push({
52
+ id: `${this.agentId}-no-credentials`,
53
+ type: 'infra-issue',
54
+ severity: 'medium',
55
+ agentId: this.agentId,
56
+ module: 'search-filter-tester',
57
+ description: 'No credentials configured — continuing without authentication',
58
+ });
59
+ }
60
+
61
+ const { chromium } = await import('playwright');
62
+
63
+ let browser: Browser | null = null;
64
+
65
+ try {
66
+ browser = await chromium.launch({ headless: true });
67
+ const page = await browser.newPage();
68
+
69
+ if (credentials) {
70
+ try {
71
+ await login(page, credentials, loginUrl);
72
+ } catch (loginError) {
73
+ findings.push({
74
+ id: `${this.agentId}-login-failed`,
75
+ type: 'infra-issue',
76
+ severity: 'medium',
77
+ agentId: this.agentId,
78
+ module: 'search-filter-tester',
79
+ description: `Login failed — continuing anonymously: ${loginError instanceof Error ? loginError.message.split('\n')[0] : String(loginError)}`,
80
+ });
81
+ }
82
+ }
83
+
84
+ for (const mod of this.config.modules) {
85
+ const moduleFindings = await this.testModuleSearchFilter(page, mod.id, mod.route);
86
+ findings.push(...moduleFindings);
87
+ }
88
+
89
+ await page.close().catch(() => undefined);
90
+ } catch (playwrightError) {
91
+ findings.push({
92
+ id: `${this.agentId}-playwright-failure`,
93
+ type: 'infra-issue',
94
+ severity: 'medium',
95
+ agentId: this.agentId,
96
+ module: 'search-filter-tester',
97
+ description: `Playwright execution failed: ${playwrightError instanceof Error ? playwrightError.message.split('\n')[0] : String(playwrightError)}`,
98
+ });
99
+ } finally {
100
+ if (browser) await browser.close().catch(() => undefined);
101
+ }
102
+
103
+ return findings;
104
+ }
105
+
106
+ private async testModuleSearchFilter(
107
+ page: Page,
108
+ moduleId: string,
109
+ moduleRoute: string,
110
+ ): Promise<Finding[]> {
111
+ const findings: Finding[] = [];
112
+ const fullUrl = moduleRoute.startsWith('http')
113
+ ? moduleRoute
114
+ : `${this.baseUrl}${moduleRoute}`;
115
+
116
+ try {
117
+ await Promise.race([
118
+ page.goto(fullUrl, { waitUntil: 'domcontentloaded' }),
119
+ new Promise((_, reject) =>
120
+ setTimeout(() => reject(new Error('Navigation timeout')), OP_TIMEOUT_MS),
121
+ ),
122
+ ]);
123
+ } catch {
124
+ findings.push({
125
+ id: `${this.agentId}-nav-failed-${moduleId}`,
126
+ type: 'test-bug',
127
+ severity: 'medium',
128
+ agentId: this.agentId,
129
+ module: moduleId,
130
+ description: `Failed to navigate to module ${moduleId} at ${moduleRoute}`,
131
+ });
132
+ return findings;
133
+ }
134
+
135
+ // Find search inputs
136
+ const searchSelector = SEARCH_SELECTORS.join(', ');
137
+ let searchCount = 0;
138
+ try {
139
+ searchCount = await Promise.race([
140
+ page.locator(searchSelector).count(),
141
+ new Promise<number>((_, reject) =>
142
+ setTimeout(() => reject(new Error('Timeout')), OP_TIMEOUT_MS),
143
+ ),
144
+ ]) as number;
145
+ } catch {
146
+ // Timeout discovering search inputs
147
+ }
148
+
149
+ if (searchCount > 0) {
150
+ const searchFindings = await this.testSearch(page, moduleId);
151
+ findings.push(...searchFindings);
152
+ }
153
+
154
+ // Find filters
155
+ const filterSelector = FILTER_SELECTORS.join(', ');
156
+ let filterCount = 0;
157
+ try {
158
+ filterCount = await Promise.race([
159
+ page.locator(filterSelector).count(),
160
+ new Promise<number>((_, reject) =>
161
+ setTimeout(() => reject(new Error('Timeout')), OP_TIMEOUT_MS),
162
+ ),
163
+ ]) as number;
164
+ } catch {
165
+ // Timeout discovering filters
166
+ }
167
+
168
+ if (filterCount > 0) {
169
+ const filterFindings = await this.testFilter(page, moduleId, filterCount);
170
+ findings.push(...filterFindings);
171
+ }
172
+
173
+ if (searchCount === 0 && filterCount === 0) {
174
+ findings.push({
175
+ id: `${this.agentId}-no-search-filter-${moduleId}`,
176
+ type: 'test-bug',
177
+ severity: 'low',
178
+ agentId: this.agentId,
179
+ module: moduleId,
180
+ description: `No search or filter UI found in module ${moduleId}`,
181
+ });
182
+ }
183
+
184
+ return findings;
185
+ }
186
+
187
+ /**
188
+ * Test search functionality: type query, check results change,
189
+ * clear, check restore, type gibberish, check empty state.
190
+ */
191
+ private async testSearch(page: Page, moduleId: string): Promise<Finding[]> {
192
+ const findings: Finding[] = [];
193
+ const searchSelector = SEARCH_SELECTORS.join(', ');
194
+ const searchInput = page.locator(searchSelector).first();
195
+
196
+ try {
197
+ // Type "test" and wait for results
198
+ await Promise.race([
199
+ searchInput.fill('test'),
200
+ new Promise((_, reject) =>
201
+ setTimeout(() => reject(new Error('Timeout')), OP_TIMEOUT_MS),
202
+ ),
203
+ ]);
204
+
205
+ await page.waitForTimeout(1000);
206
+
207
+ // Clear search
208
+ await Promise.race([
209
+ searchInput.fill(''),
210
+ new Promise((_, reject) =>
211
+ setTimeout(() => reject(new Error('Timeout')), OP_TIMEOUT_MS),
212
+ ),
213
+ ]);
214
+
215
+ await page.waitForTimeout(1000);
216
+
217
+ // Type gibberish
218
+ await Promise.race([
219
+ searchInput.fill('zzz999xxx'),
220
+ new Promise((_, reject) =>
221
+ setTimeout(() => reject(new Error('Timeout')), OP_TIMEOUT_MS),
222
+ ),
223
+ ]);
224
+
225
+ await page.waitForTimeout(1000);
226
+
227
+ // Check if results area shows content (meaning search may not be filtering)
228
+ const noResultsIndicators = await page
229
+ .locator(
230
+ ':text("no results"), :text("not found"), :text("no matches"), [data-testid*="empty"], .empty-state',
231
+ )
232
+ .count()
233
+ .catch(() => 0);
234
+
235
+ // Check if list items still exist
236
+ const listItems = await page
237
+ .locator('tr, [class*="list-item"], [class*="card"], li')
238
+ .count()
239
+ .catch(() => 0);
240
+
241
+ if (noResultsIndicators === 0 && listItems > 0) {
242
+ findings.push({
243
+ id: `${this.agentId}-search-not-filtering-${moduleId}`,
244
+ type: 'test-bug',
245
+ severity: 'medium',
246
+ agentId: this.agentId,
247
+ module: moduleId,
248
+ description: 'Search may not be filtering — gibberish query still shows list items',
249
+ });
250
+ }
251
+
252
+ // Clear search for next tests
253
+ await searchInput.fill('').catch(() => undefined);
254
+ } catch (searchError) {
255
+ findings.push({
256
+ id: `${this.agentId}-search-error-${moduleId}`,
257
+ type: 'test-bug',
258
+ severity: 'medium',
259
+ agentId: this.agentId,
260
+ module: moduleId,
261
+ description: `Search test failed in module ${moduleId}: ${searchError instanceof Error ? searchError.message.split('\n')[0] : String(searchError)}`,
262
+ });
263
+ }
264
+
265
+ return findings;
266
+ }
267
+
268
+ /**
269
+ * Test filter controls: click/select, verify list updates.
270
+ */
271
+ private async testFilter(
272
+ page: Page,
273
+ moduleId: string,
274
+ filterCount: number,
275
+ ): Promise<Finding[]> {
276
+ const findings: Finding[] = [];
277
+ const filterSelector = FILTER_SELECTORS.join(', ');
278
+
279
+ try {
280
+ const firstFilter = page.locator(filterSelector).first();
281
+ const tagName = await firstFilter.evaluate((el) => el.tagName.toLowerCase()).catch(() => '');
282
+
283
+ if (tagName === 'select') {
284
+ const optionCount = await firstFilter.locator('option').count();
285
+ if (optionCount > 1) {
286
+ const value = await firstFilter.locator('option').nth(1).getAttribute('value');
287
+ if (value) {
288
+ await Promise.race([
289
+ firstFilter.selectOption(value),
290
+ new Promise((_, reject) =>
291
+ setTimeout(() => reject(new Error('Timeout')), OP_TIMEOUT_MS),
292
+ ),
293
+ ]);
294
+ }
295
+ }
296
+ } else {
297
+ await Promise.race([
298
+ firstFilter.click(),
299
+ new Promise((_, reject) =>
300
+ setTimeout(() => reject(new Error('Timeout')), OP_TIMEOUT_MS),
301
+ ),
302
+ ]);
303
+ }
304
+
305
+ findings.push({
306
+ id: `${this.agentId}-filter-found-${moduleId}`,
307
+ type: 'infra-issue',
308
+ severity: 'info',
309
+ agentId: this.agentId,
310
+ module: moduleId,
311
+ description: `Found ${filterCount} filter control(s) in module ${moduleId}`,
312
+ });
313
+ } catch (filterError) {
314
+ findings.push({
315
+ id: `${this.agentId}-filter-error-${moduleId}`,
316
+ type: 'test-bug',
317
+ severity: 'medium',
318
+ agentId: this.agentId,
319
+ module: moduleId,
320
+ description: `Filter test failed in module ${moduleId}: ${filterError instanceof Error ? filterError.message.split('\n')[0] : String(filterError)}`,
321
+ });
322
+ }
323
+
324
+ return findings;
325
+ }
326
+ }