@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,425 @@
1
+ import type { Browser, BrowserContext, 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 navigation operations. */
8
+ const NAV_TIMEOUT_MS = 3_000;
9
+
10
+ export class NavigationRoutingTesterAgent extends BaseAgent {
11
+ readonly agentId = 28;
12
+ readonly agentName = 'Navigation & Routing Tester';
13
+ private baseUrl = '';
14
+
15
+ protected async preFlight(): Promise<void> {
16
+ if (!this.config.modules || this.config.modules.length === 0) {
17
+ throw new Error(
18
+ 'NavigationRoutingTesterAgent requires at least one module in config.modules',
19
+ );
20
+ }
21
+
22
+ const { env } = await resolveEnvironment(this.config, this.phase);
23
+ this.baseUrl = env.baseUrl;
24
+ }
25
+
26
+ protected async execute(): Promise<Finding[]> {
27
+ const findings: Finding[] = [];
28
+
29
+ const rawLoginUrl = this.config.auth.loginUrl ?? '/login';
30
+ const loginUrl = rawLoginUrl.startsWith('http') ? rawLoginUrl : `${this.baseUrl}${rawLoginUrl}`;
31
+ const credentials =
32
+ this.config.auth.credentials?.['admin'] ??
33
+ Object.values(this.config.auth.credentials ?? {})[0];
34
+
35
+ if (!credentials) {
36
+ findings.push({
37
+ id: `${this.agentId}-no-credentials`,
38
+ type: 'infra-issue',
39
+ severity: 'medium',
40
+ agentId: this.agentId,
41
+ module: 'navigation-routing-tester',
42
+ description: 'No credentials configured — continuing without authentication',
43
+ });
44
+ }
45
+
46
+ const { chromium } = await import('playwright');
47
+
48
+ let browser: Browser | null = null;
49
+
50
+ try {
51
+ browser = await chromium.launch({ headless: true });
52
+ const page = await browser.newPage();
53
+
54
+ let loggedIn = false;
55
+ if (credentials) {
56
+ try {
57
+ await login(page, credentials, loginUrl);
58
+ loggedIn = true;
59
+ } catch (loginError) {
60
+ findings.push({
61
+ id: `${this.agentId}-login-failed`,
62
+ type: 'infra-issue',
63
+ severity: 'medium',
64
+ agentId: this.agentId,
65
+ module: 'navigation-routing-tester',
66
+ description: `Login failed — continuing anonymously: ${loginError instanceof Error ? loginError.message.split('\n')[0] : String(loginError)}`,
67
+ });
68
+ }
69
+ }
70
+
71
+ // Test 1: Sidebar navigation
72
+ const sidebarFindings = await this.testSidebarNavigation(page);
73
+ findings.push(...sidebarFindings);
74
+
75
+ // Test 2: 404 handling
76
+ const notFoundFindings = await this.test404Handling(page);
77
+ findings.push(...notFoundFindings);
78
+
79
+ // Test 3: Protected routes (only if we have credentials and successfully logged in)
80
+ if (credentials && loggedIn) {
81
+ const protectedFindings = await this.testProtectedRoutes(browser);
82
+ findings.push(...protectedFindings);
83
+ }
84
+
85
+ // Test 4: Link integrity
86
+ const linkFindings = await this.testLinkIntegrity(page);
87
+ findings.push(...linkFindings);
88
+
89
+ // Test 5: Back/forward navigation
90
+ const historyFindings = await this.testBackForward(page);
91
+ findings.push(...historyFindings);
92
+
93
+ await page.close().catch(() => undefined);
94
+ } catch (playwrightError) {
95
+ findings.push({
96
+ id: `${this.agentId}-playwright-failure`,
97
+ type: 'infra-issue',
98
+ severity: 'medium',
99
+ agentId: this.agentId,
100
+ module: 'navigation-routing-tester',
101
+ description: `Playwright execution failed: ${playwrightError instanceof Error ? playwrightError.message.split('\n')[0] : String(playwrightError)}`,
102
+ });
103
+ } finally {
104
+ if (browser) await browser.close().catch(() => undefined);
105
+ }
106
+
107
+ return findings;
108
+ }
109
+
110
+ /**
111
+ * Test 1: For each module with sidebarIcon: true, click its sidebar link
112
+ * and verify the URL changes and content loads.
113
+ */
114
+ private async testSidebarNavigation(page: Page): Promise<Finding[]> {
115
+ const findings: Finding[] = [];
116
+ const sidebarModules = this.config.modules.filter((m) => m.sidebarIcon);
117
+
118
+ for (const mod of sidebarModules) {
119
+ const expectedUrl = mod.route.startsWith('http')
120
+ ? mod.route
121
+ : `${this.baseUrl}${mod.route}`;
122
+
123
+ try {
124
+ await Promise.race([
125
+ page.goto(expectedUrl, { waitUntil: 'domcontentloaded' }),
126
+ new Promise((_, reject) =>
127
+ setTimeout(() => reject(new Error('Navigation timeout')), NAV_TIMEOUT_MS),
128
+ ),
129
+ ]);
130
+
131
+ // Check the page has content (not blank)
132
+ const bodyText = await page.locator('body').innerText().catch(() => '');
133
+ if (bodyText.trim().length === 0) {
134
+ findings.push({
135
+ id: `${this.agentId}-sidebar-blank-${mod.id}`,
136
+ type: 'test-bug',
137
+ severity: 'medium',
138
+ agentId: this.agentId,
139
+ module: mod.id,
140
+ description: `Sidebar navigation to module ${mod.id} (${mod.route}) resulted in a blank page`,
141
+ });
142
+ }
143
+ } catch (navError) {
144
+ findings.push({
145
+ id: `${this.agentId}-sidebar-nav-failed-${mod.id}`,
146
+ type: 'test-bug',
147
+ severity: 'medium',
148
+ agentId: this.agentId,
149
+ module: mod.id,
150
+ description: `Sidebar navigation to module ${mod.id} failed: ${navError instanceof Error ? navError.message.split('\n')[0] : String(navError)}`,
151
+ });
152
+ }
153
+ }
154
+
155
+ return findings;
156
+ }
157
+
158
+ /**
159
+ * Test 2: Navigate to a fake route and verify 404 handling.
160
+ */
161
+ private async test404Handling(page: Page): Promise<Finding[]> {
162
+ const findings: Finding[] = [];
163
+ const fakeRoute = `${this.baseUrl}/this-page-does-not-exist-12345`;
164
+
165
+ try {
166
+ await Promise.race([
167
+ page.goto(fakeRoute, { waitUntil: 'domcontentloaded' }),
168
+ new Promise((_, reject) =>
169
+ setTimeout(() => reject(new Error('Navigation timeout')), NAV_TIMEOUT_MS),
170
+ ),
171
+ ]);
172
+
173
+ // Check if the page shows a 404 indicator or redirect
174
+ const bodyText = await page.locator('body').innerText().catch(() => '');
175
+ const url = page.url();
176
+ const has404Indicator =
177
+ bodyText.toLowerCase().includes('404') ||
178
+ bodyText.toLowerCase().includes('not found') ||
179
+ bodyText.toLowerCase().includes('page not found') ||
180
+ url.includes('/login') || // Redirected to login = acceptable
181
+ url !== fakeRoute; // Redirected somewhere = acceptable
182
+
183
+ if (!has404Indicator && bodyText.trim().length === 0) {
184
+ findings.push({
185
+ id: `${this.agentId}-404-blank`,
186
+ type: 'test-bug',
187
+ severity: 'high',
188
+ agentId: this.agentId,
189
+ module: 'routing',
190
+ description:
191
+ 'App shows a blank page for non-existent routes instead of a 404 page or redirect',
192
+ });
193
+ } else if (!has404Indicator) {
194
+ findings.push({
195
+ id: `${this.agentId}-404-no-handler`,
196
+ type: 'test-bug',
197
+ severity: 'medium',
198
+ agentId: this.agentId,
199
+ module: 'routing',
200
+ description:
201
+ 'Non-existent route did not show a clear 404 indicator or redirect — page may silently render without error handling',
202
+ });
203
+ }
204
+ } catch (navError) {
205
+ findings.push({
206
+ id: `${this.agentId}-404-nav-error`,
207
+ type: 'test-bug',
208
+ severity: 'medium',
209
+ agentId: this.agentId,
210
+ module: 'routing',
211
+ description: `404 test navigation failed: ${navError instanceof Error ? navError.message.split('\n')[0] : String(navError)}`,
212
+ });
213
+ }
214
+
215
+ return findings;
216
+ }
217
+
218
+ /**
219
+ * Test 3: Open a new incognito context (no auth) and navigate to protected routes.
220
+ * Should redirect to login; if the page renders without auth, that is critical.
221
+ */
222
+ private async testProtectedRoutes(browser: Browser): Promise<Finding[]> {
223
+ const findings: Finding[] = [];
224
+
225
+ let incognitoContext: BrowserContext | null = null;
226
+ try {
227
+ incognitoContext = await browser.newContext();
228
+ const incognitoPage = await incognitoContext.newPage();
229
+
230
+ for (const mod of this.config.modules) {
231
+ const fullUrl = mod.route.startsWith('http')
232
+ ? mod.route
233
+ : `${this.baseUrl}${mod.route}`;
234
+
235
+ try {
236
+ await Promise.race([
237
+ incognitoPage.goto(fullUrl, { waitUntil: 'domcontentloaded' }),
238
+ new Promise((_, reject) =>
239
+ setTimeout(() => reject(new Error('Navigation timeout')), NAV_TIMEOUT_MS),
240
+ ),
241
+ ]);
242
+
243
+ const currentUrl = incognitoPage.url();
244
+ const redirectedToLogin =
245
+ currentUrl.includes('/login') ||
246
+ currentUrl.includes('/auth') ||
247
+ currentUrl.includes('/signin');
248
+
249
+ if (!redirectedToLogin) {
250
+ // Check if the page actually has meaningful content (not just a shell)
251
+ const bodyText = await incognitoPage.locator('body').innerText().catch(() => '');
252
+ if (bodyText.trim().length > 0) {
253
+ findings.push({
254
+ id: `${this.agentId}-unprotected-${mod.id}`,
255
+ type: 'code-bug-security',
256
+ severity: 'critical',
257
+ agentId: this.agentId,
258
+ module: mod.id,
259
+ description: `Module ${mod.id} accessible without authentication — no redirect to login page`,
260
+ });
261
+ }
262
+ }
263
+ } catch {
264
+ // Navigation error for this module — skip
265
+ }
266
+ }
267
+
268
+ await incognitoPage.close().catch(() => undefined);
269
+ } catch {
270
+ // Incognito context creation failure — non-critical
271
+ } finally {
272
+ if (incognitoContext) await incognitoContext.close().catch(() => undefined);
273
+ }
274
+
275
+ return findings;
276
+ }
277
+
278
+ /**
279
+ * Test 4: On each module page, find internal links and verify they load.
280
+ */
281
+ private async testLinkIntegrity(page: Page): Promise<Finding[]> {
282
+ const findings: Finding[] = [];
283
+ const testedUrls = new Set<string>();
284
+
285
+ for (const mod of this.config.modules) {
286
+ const fullUrl = mod.route.startsWith('http')
287
+ ? mod.route
288
+ : `${this.baseUrl}${mod.route}`;
289
+
290
+ try {
291
+ await Promise.race([
292
+ page.goto(fullUrl, { waitUntil: 'domcontentloaded' }),
293
+ new Promise((_, reject) =>
294
+ setTimeout(() => reject(new Error('Navigation timeout')), NAV_TIMEOUT_MS),
295
+ ),
296
+ ]);
297
+
298
+ // Find all internal links
299
+ const links = await page.locator('a[href^="/"]').evaluateAll((elements) =>
300
+ elements.map((el) => el.getAttribute('href')).filter(Boolean),
301
+ ).catch(() => [] as string[]);
302
+
303
+ for (const href of links) {
304
+ if (!href || testedUrls.has(href)) continue;
305
+ testedUrls.add(href);
306
+
307
+ const linkUrl = `${this.baseUrl}${href}`;
308
+ try {
309
+ await Promise.race([
310
+ page.goto(linkUrl, { waitUntil: 'domcontentloaded' }),
311
+ new Promise((_, reject) =>
312
+ setTimeout(() => reject(new Error('Navigation timeout')), NAV_TIMEOUT_MS),
313
+ ),
314
+ ]);
315
+
316
+ const bodyText = await page.locator('body').innerText().catch(() => '');
317
+ if (bodyText.trim().length === 0) {
318
+ findings.push({
319
+ id: `${this.agentId}-broken-link-${mod.id}-${href.replace(/\//g, '-')}`,
320
+ type: 'test-bug',
321
+ severity: 'medium',
322
+ agentId: this.agentId,
323
+ module: mod.id,
324
+ description: `Link ${href} on module ${mod.id} leads to a blank page`,
325
+ });
326
+ }
327
+ } catch {
328
+ findings.push({
329
+ id: `${this.agentId}-link-error-${mod.id}-${href.replace(/\//g, '-')}`,
330
+ type: 'test-bug',
331
+ severity: 'medium',
332
+ agentId: this.agentId,
333
+ module: mod.id,
334
+ description: `Link ${href} on module ${mod.id} failed to load`,
335
+ });
336
+ }
337
+ }
338
+ } catch {
339
+ // Navigation to module failed — already covered by sidebar test
340
+ }
341
+ }
342
+
343
+ return findings;
344
+ }
345
+
346
+ /**
347
+ * Test 5: Navigate between two modules, test back/forward browser history.
348
+ */
349
+ private async testBackForward(page: Page): Promise<Finding[]> {
350
+ const findings: Finding[] = [];
351
+
352
+ if (this.config.modules.length < 2) {
353
+ return findings;
354
+ }
355
+
356
+ const mod1 = this.config.modules[0];
357
+ const mod2 = this.config.modules[1];
358
+
359
+ const url1 = mod1.route.startsWith('http')
360
+ ? mod1.route
361
+ : `${this.baseUrl}${mod1.route}`;
362
+ const url2 = mod2.route.startsWith('http')
363
+ ? mod2.route
364
+ : `${this.baseUrl}${mod2.route}`;
365
+
366
+ try {
367
+ // Navigate to module 1
368
+ await Promise.race([
369
+ page.goto(url1, { waitUntil: 'domcontentloaded' }),
370
+ new Promise((_, reject) =>
371
+ setTimeout(() => reject(new Error('Navigation timeout')), NAV_TIMEOUT_MS),
372
+ ),
373
+ ]);
374
+
375
+ // Navigate to module 2
376
+ await Promise.race([
377
+ page.goto(url2, { waitUntil: 'domcontentloaded' }),
378
+ new Promise((_, reject) =>
379
+ setTimeout(() => reject(new Error('Navigation timeout')), NAV_TIMEOUT_MS),
380
+ ),
381
+ ]);
382
+
383
+ // Press back
384
+ await page.goBack({ timeout: NAV_TIMEOUT_MS });
385
+ const afterBack = page.url();
386
+ const expectedUrl1 = new URL(url1).pathname;
387
+ if (!afterBack.includes(expectedUrl1)) {
388
+ findings.push({
389
+ id: `${this.agentId}-back-nav-failed`,
390
+ type: 'test-bug',
391
+ severity: 'medium',
392
+ agentId: this.agentId,
393
+ module: 'routing',
394
+ description: `Back navigation did not return to ${mod1.id} (${mod1.route}) — got ${afterBack}`,
395
+ });
396
+ }
397
+
398
+ // Press forward
399
+ await page.goForward({ timeout: NAV_TIMEOUT_MS });
400
+ const afterForward = page.url();
401
+ const expectedUrl2 = new URL(url2).pathname;
402
+ if (!afterForward.includes(expectedUrl2)) {
403
+ findings.push({
404
+ id: `${this.agentId}-forward-nav-failed`,
405
+ type: 'test-bug',
406
+ severity: 'medium',
407
+ agentId: this.agentId,
408
+ module: 'routing',
409
+ description: `Forward navigation did not return to ${mod2.id} (${mod2.route}) — got ${afterForward}`,
410
+ });
411
+ }
412
+ } catch (historyError) {
413
+ findings.push({
414
+ id: `${this.agentId}-history-nav-error`,
415
+ type: 'test-bug',
416
+ severity: 'medium',
417
+ agentId: this.agentId,
418
+ module: 'routing',
419
+ description: `Back/forward navigation test failed: ${historyError instanceof Error ? historyError.message.split('\n')[0] : String(historyError)}`,
420
+ });
421
+ }
422
+
423
+ return findings;
424
+ }
425
+ }