@avi770/testteam 1.2.0 → 2.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 (300) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +53 -6
  3. package/agents/24-signup-onboarding-tester.ts +429 -0
  4. package/agents/25-crud-flow-tester.ts +302 -0
  5. package/agents/26-form-validator.ts +297 -0
  6. package/agents/27-search-filter-tester.ts +326 -0
  7. package/agents/28-navigation-routing-tester.ts +425 -0
  8. package/agents/29-responsive-interaction-tester.ts +350 -0
  9. package/agents/30-multi-user-scenario-tester.ts +319 -0
  10. package/agents/31-load-tester.ts +134 -0
  11. package/agents/32-memory-leak-detector.ts +194 -0
  12. package/agents/33-bundle-analyzer.ts +132 -0
  13. package/agents/34-xss-scanner.ts +191 -0
  14. package/agents/35-csrf-tester.ts +82 -0
  15. package/agents/36-auth-fuzzer.ts +194 -0
  16. package/agents/37-dependency-scanner.ts +176 -0
  17. package/agents/38-secrets-scanner.ts +137 -0
  18. package/agents/39-api-contract-tester.ts +199 -0
  19. package/agents/40-rate-limit-tester.ts +94 -0
  20. package/agents/41-api-pagination-tester.ts +97 -0
  21. package/agents/42-graphql-tester.ts +222 -0
  22. package/agents/43-data-consistency-checker.ts +205 -0
  23. package/agents/44-backup-recovery-tester.ts +152 -0
  24. package/agents/45-data-privacy-scanner.ts +125 -0
  25. package/agents/46-seo-auditor.ts +294 -0
  26. package/agents/47-social-preview-tester.ts +232 -0
  27. package/agents/48-lighthouse-auditor.ts +213 -0
  28. package/agents/49-i18n-tester.ts +198 -0
  29. package/agents/50-timezone-tester.ts +173 -0
  30. package/agents/51-error-recovery-tester.ts +155 -0
  31. package/agents/52-offline-mode-tester.ts +180 -0
  32. package/agents/53-graceful-degradation-tester.ts +156 -0
  33. package/agents/54-websocket-tester.ts +151 -0
  34. package/agents/55-realtime-sync-tester.ts +194 -0
  35. package/agents/56-file-upload-tester.ts +194 -0
  36. package/agents/57-export-tester.ts +174 -0
  37. package/agents/58-payment-flow-tester.ts +183 -0
  38. package/agents/59-ssl-tls-auditor.ts +141 -0
  39. package/agents/60-dns-cdn-tester.ts +117 -0
  40. package/agents/61-docker-health-checker.ts +111 -0
  41. package/agents/62-env-config-validator.ts +152 -0
  42. package/agents/63-log-quality-auditor.ts +136 -0
  43. package/agents/64-analytics-tracker-tester.ts +165 -0
  44. package/agents/65-gdpr-compliance-tester.ts +215 -0
  45. package/agents/66-soc2-control-validator.ts +210 -0
  46. package/agents/67-wcag-aaa-tester.ts +241 -0
  47. package/agents/68-dead-code-detector.ts +135 -0
  48. package/agents/69-type-safety-auditor.ts +164 -0
  49. package/agents/70-complexity-analyzer.ts +179 -0
  50. package/agents/__tests__/24-signup-onboarding-tester.test.ts +274 -0
  51. package/agents/__tests__/25-crud-flow-tester.test.ts +322 -0
  52. package/agents/__tests__/26-form-validator.test.ts +345 -0
  53. package/agents/__tests__/27-search-filter-tester.test.ts +311 -0
  54. package/agents/__tests__/28-navigation-routing-tester.test.ts +328 -0
  55. package/agents/__tests__/29-responsive-interaction-tester.test.ts +297 -0
  56. package/agents/__tests__/30-multi-user-scenario-tester.test.ts +328 -0
  57. package/agents/__tests__/31-load-tester.test.ts +189 -0
  58. package/agents/__tests__/32-memory-leak-detector.test.ts +251 -0
  59. package/agents/__tests__/33-bundle-analyzer.test.ts +237 -0
  60. package/agents/__tests__/34-xss-scanner.test.ts +258 -0
  61. package/agents/__tests__/35-csrf-tester.test.ts +200 -0
  62. package/agents/__tests__/36-auth-fuzzer.test.ts +214 -0
  63. package/agents/__tests__/37-dependency-scanner.test.ts +266 -0
  64. package/agents/__tests__/38-secrets-scanner.test.ts +224 -0
  65. package/agents/__tests__/39-api-contract-tester.test.ts +312 -0
  66. package/agents/__tests__/40-rate-limit-tester.test.ts +192 -0
  67. package/agents/__tests__/41-api-pagination-tester.test.ts +198 -0
  68. package/agents/__tests__/42-graphql-tester.test.ts +252 -0
  69. package/agents/__tests__/43-data-consistency-checker.test.ts +232 -0
  70. package/agents/__tests__/44-backup-recovery-tester.test.ts +222 -0
  71. package/agents/__tests__/45-data-privacy-scanner.test.ts +223 -0
  72. package/agents/__tests__/46-seo-auditor.test.ts +261 -0
  73. package/agents/__tests__/47-social-preview-tester.test.ts +245 -0
  74. package/agents/__tests__/48-lighthouse-auditor.test.ts +276 -0
  75. package/agents/__tests__/49-i18n-tester.test.ts +201 -0
  76. package/agents/__tests__/50-timezone-tester.test.ts +172 -0
  77. package/agents/__tests__/51-error-recovery-tester.test.ts +162 -0
  78. package/agents/__tests__/52-offline-mode-tester.test.ts +164 -0
  79. package/agents/__tests__/53-graceful-degradation-tester.test.ts +168 -0
  80. package/agents/__tests__/54-websocket-tester.test.ts +157 -0
  81. package/agents/__tests__/55-realtime-sync-tester.test.ts +181 -0
  82. package/agents/__tests__/56-file-upload-tester.test.ts +172 -0
  83. package/agents/__tests__/57-export-tester.test.ts +169 -0
  84. package/agents/__tests__/58-payment-flow-tester.test.ts +182 -0
  85. package/agents/__tests__/59-ssl-tls-auditor.test.ts +179 -0
  86. package/agents/__tests__/60-dns-cdn-tester.test.ts +176 -0
  87. package/agents/__tests__/61-docker-health-checker.test.ts +150 -0
  88. package/agents/__tests__/62-env-config-validator.test.ts +166 -0
  89. package/agents/__tests__/63-log-quality-auditor.test.ts +175 -0
  90. package/agents/__tests__/64-analytics-tracker-tester.test.ts +158 -0
  91. package/agents/__tests__/65-gdpr-compliance-tester.test.ts +174 -0
  92. package/agents/__tests__/66-soc2-control-validator.test.ts +183 -0
  93. package/agents/__tests__/67-wcag-aaa-tester.test.ts +190 -0
  94. package/agents/__tests__/68-dead-code-detector.test.ts +174 -0
  95. package/agents/__tests__/69-type-safety-auditor.test.ts +173 -0
  96. package/agents/__tests__/70-complexity-analyzer.test.ts +177 -0
  97. package/agents/__tests__/registry.test.ts +13 -13
  98. package/agents/registry.ts +146 -5
  99. package/core/__tests__/integration.test.ts +4 -4
  100. package/core/__tests__/orchestrator.test.ts +17 -16
  101. package/core/license.ts +208 -211
  102. package/core/orchestrator.ts +6 -4
  103. package/dist/agents/24-signup-onboarding-tester.d.ts +35 -0
  104. package/dist/agents/24-signup-onboarding-tester.d.ts.map +1 -0
  105. package/dist/agents/24-signup-onboarding-tester.js +357 -0
  106. package/dist/agents/24-signup-onboarding-tester.js.map +1 -0
  107. package/dist/agents/25-crud-flow-tester.d.ts +11 -0
  108. package/dist/agents/25-crud-flow-tester.d.ts.map +1 -0
  109. package/dist/agents/25-crud-flow-tester.js +253 -0
  110. package/dist/agents/25-crud-flow-tester.js.map +1 -0
  111. package/dist/agents/26-form-validator.d.ts +12 -0
  112. package/dist/agents/26-form-validator.d.ts.map +1 -0
  113. package/dist/agents/26-form-validator.js +257 -0
  114. package/dist/agents/26-form-validator.js.map +1 -0
  115. package/dist/agents/27-search-filter-tester.d.ts +20 -0
  116. package/dist/agents/27-search-filter-tester.d.ts.map +1 -0
  117. package/dist/agents/27-search-filter-tester.js +267 -0
  118. package/dist/agents/27-search-filter-tester.js.map +1 -0
  119. package/dist/agents/28-navigation-routing-tester.d.ts +32 -0
  120. package/dist/agents/28-navigation-routing-tester.d.ts.map +1 -0
  121. package/dist/agents/28-navigation-routing-tester.js +363 -0
  122. package/dist/agents/28-navigation-routing-tester.js.map +1 -0
  123. package/dist/agents/29-responsive-interaction-tester.d.ts +26 -0
  124. package/dist/agents/29-responsive-interaction-tester.d.ts.map +1 -0
  125. package/dist/agents/29-responsive-interaction-tester.js +272 -0
  126. package/dist/agents/29-responsive-interaction-tester.js.map +1 -0
  127. package/dist/agents/30-multi-user-scenario-tester.d.ts +24 -0
  128. package/dist/agents/30-multi-user-scenario-tester.d.ts.map +1 -0
  129. package/dist/agents/30-multi-user-scenario-tester.js +254 -0
  130. package/dist/agents/30-multi-user-scenario-tester.js.map +1 -0
  131. package/dist/agents/31-load-tester.d.ts +12 -0
  132. package/dist/agents/31-load-tester.d.ts.map +1 -0
  133. package/dist/agents/31-load-tester.js +110 -0
  134. package/dist/agents/31-load-tester.js.map +1 -0
  135. package/dist/agents/32-memory-leak-detector.d.ts +12 -0
  136. package/dist/agents/32-memory-leak-detector.d.ts.map +1 -0
  137. package/dist/agents/32-memory-leak-detector.js +167 -0
  138. package/dist/agents/32-memory-leak-detector.js.map +1 -0
  139. package/dist/agents/33-bundle-analyzer.d.ts +10 -0
  140. package/dist/agents/33-bundle-analyzer.d.ts.map +1 -0
  141. package/dist/agents/33-bundle-analyzer.js +111 -0
  142. package/dist/agents/33-bundle-analyzer.js.map +1 -0
  143. package/dist/agents/34-xss-scanner.d.ts +11 -0
  144. package/dist/agents/34-xss-scanner.d.ts.map +1 -0
  145. package/dist/agents/34-xss-scanner.js +164 -0
  146. package/dist/agents/34-xss-scanner.js.map +1 -0
  147. package/dist/agents/35-csrf-tester.d.ts +11 -0
  148. package/dist/agents/35-csrf-tester.d.ts.map +1 -0
  149. package/dist/agents/35-csrf-tester.js +70 -0
  150. package/dist/agents/35-csrf-tester.js.map +1 -0
  151. package/dist/agents/36-auth-fuzzer.d.ts +13 -0
  152. package/dist/agents/36-auth-fuzzer.d.ts.map +1 -0
  153. package/dist/agents/36-auth-fuzzer.js +163 -0
  154. package/dist/agents/36-auth-fuzzer.js.map +1 -0
  155. package/dist/agents/37-dependency-scanner.d.ts +11 -0
  156. package/dist/agents/37-dependency-scanner.d.ts.map +1 -0
  157. package/dist/agents/37-dependency-scanner.js +139 -0
  158. package/dist/agents/37-dependency-scanner.js.map +1 -0
  159. package/dist/agents/38-secrets-scanner.d.ts +11 -0
  160. package/dist/agents/38-secrets-scanner.d.ts.map +1 -0
  161. package/dist/agents/38-secrets-scanner.js +116 -0
  162. package/dist/agents/38-secrets-scanner.js.map +1 -0
  163. package/dist/agents/39-api-contract-tester.d.ts +12 -0
  164. package/dist/agents/39-api-contract-tester.d.ts.map +1 -0
  165. package/dist/agents/39-api-contract-tester.js +142 -0
  166. package/dist/agents/39-api-contract-tester.js.map +1 -0
  167. package/dist/agents/40-rate-limit-tester.d.ts +12 -0
  168. package/dist/agents/40-rate-limit-tester.d.ts.map +1 -0
  169. package/dist/agents/40-rate-limit-tester.js +79 -0
  170. package/dist/agents/40-rate-limit-tester.js.map +1 -0
  171. package/dist/agents/41-api-pagination-tester.d.ts +12 -0
  172. package/dist/agents/41-api-pagination-tester.d.ts.map +1 -0
  173. package/dist/agents/41-api-pagination-tester.js +79 -0
  174. package/dist/agents/41-api-pagination-tester.js.map +1 -0
  175. package/dist/agents/42-graphql-tester.d.ts +13 -0
  176. package/dist/agents/42-graphql-tester.d.ts.map +1 -0
  177. package/dist/agents/42-graphql-tester.js +187 -0
  178. package/dist/agents/42-graphql-tester.js.map +1 -0
  179. package/dist/agents/43-data-consistency-checker.d.ts +11 -0
  180. package/dist/agents/43-data-consistency-checker.d.ts.map +1 -0
  181. package/dist/agents/43-data-consistency-checker.js +176 -0
  182. package/dist/agents/43-data-consistency-checker.js.map +1 -0
  183. package/dist/agents/44-backup-recovery-tester.d.ts +11 -0
  184. package/dist/agents/44-backup-recovery-tester.d.ts.map +1 -0
  185. package/dist/agents/44-backup-recovery-tester.js +128 -0
  186. package/dist/agents/44-backup-recovery-tester.js.map +1 -0
  187. package/dist/agents/45-data-privacy-scanner.d.ts +11 -0
  188. package/dist/agents/45-data-privacy-scanner.d.ts.map +1 -0
  189. package/dist/agents/45-data-privacy-scanner.js +100 -0
  190. package/dist/agents/45-data-privacy-scanner.js.map +1 -0
  191. package/dist/agents/46-seo-auditor.d.ts +12 -0
  192. package/dist/agents/46-seo-auditor.d.ts.map +1 -0
  193. package/dist/agents/46-seo-auditor.js +275 -0
  194. package/dist/agents/46-seo-auditor.js.map +1 -0
  195. package/dist/agents/47-social-preview-tester.d.ts +11 -0
  196. package/dist/agents/47-social-preview-tester.d.ts.map +1 -0
  197. package/dist/agents/47-social-preview-tester.js +219 -0
  198. package/dist/agents/47-social-preview-tester.js.map +1 -0
  199. package/dist/agents/48-lighthouse-auditor.d.ts +11 -0
  200. package/dist/agents/48-lighthouse-auditor.d.ts.map +1 -0
  201. package/dist/agents/48-lighthouse-auditor.js +192 -0
  202. package/dist/agents/48-lighthouse-auditor.js.map +1 -0
  203. package/dist/agents/49-i18n-tester.d.ts +13 -0
  204. package/dist/agents/49-i18n-tester.d.ts.map +1 -0
  205. package/dist/agents/49-i18n-tester.js +172 -0
  206. package/dist/agents/49-i18n-tester.js.map +1 -0
  207. package/dist/agents/50-timezone-tester.d.ts +11 -0
  208. package/dist/agents/50-timezone-tester.d.ts.map +1 -0
  209. package/dist/agents/50-timezone-tester.js +152 -0
  210. package/dist/agents/50-timezone-tester.js.map +1 -0
  211. package/dist/agents/51-error-recovery-tester.d.ts +11 -0
  212. package/dist/agents/51-error-recovery-tester.d.ts.map +1 -0
  213. package/dist/agents/51-error-recovery-tester.js +134 -0
  214. package/dist/agents/51-error-recovery-tester.js.map +1 -0
  215. package/dist/agents/52-offline-mode-tester.d.ts +12 -0
  216. package/dist/agents/52-offline-mode-tester.d.ts.map +1 -0
  217. package/dist/agents/52-offline-mode-tester.js +161 -0
  218. package/dist/agents/52-offline-mode-tester.js.map +1 -0
  219. package/dist/agents/53-graceful-degradation-tester.d.ts +12 -0
  220. package/dist/agents/53-graceful-degradation-tester.d.ts.map +1 -0
  221. package/dist/agents/53-graceful-degradation-tester.js +130 -0
  222. package/dist/agents/53-graceful-degradation-tester.js.map +1 -0
  223. package/dist/agents/54-websocket-tester.d.ts +10 -0
  224. package/dist/agents/54-websocket-tester.d.ts.map +1 -0
  225. package/dist/agents/54-websocket-tester.js +132 -0
  226. package/dist/agents/54-websocket-tester.js.map +1 -0
  227. package/dist/agents/55-realtime-sync-tester.d.ts +11 -0
  228. package/dist/agents/55-realtime-sync-tester.d.ts.map +1 -0
  229. package/dist/agents/55-realtime-sync-tester.js +175 -0
  230. package/dist/agents/55-realtime-sync-tester.js.map +1 -0
  231. package/dist/agents/56-file-upload-tester.d.ts +12 -0
  232. package/dist/agents/56-file-upload-tester.d.ts.map +1 -0
  233. package/dist/agents/56-file-upload-tester.js +166 -0
  234. package/dist/agents/56-file-upload-tester.js.map +1 -0
  235. package/dist/agents/57-export-tester.d.ts +11 -0
  236. package/dist/agents/57-export-tester.d.ts.map +1 -0
  237. package/dist/agents/57-export-tester.js +155 -0
  238. package/dist/agents/57-export-tester.js.map +1 -0
  239. package/dist/agents/58-payment-flow-tester.d.ts +11 -0
  240. package/dist/agents/58-payment-flow-tester.d.ts.map +1 -0
  241. package/dist/agents/58-payment-flow-tester.js +159 -0
  242. package/dist/agents/58-payment-flow-tester.js.map +1 -0
  243. package/dist/agents/59-ssl-tls-auditor.d.ts +10 -0
  244. package/dist/agents/59-ssl-tls-auditor.d.ts.map +1 -0
  245. package/dist/agents/59-ssl-tls-auditor.js +132 -0
  246. package/dist/agents/59-ssl-tls-auditor.js.map +1 -0
  247. package/dist/agents/60-dns-cdn-tester.d.ts +10 -0
  248. package/dist/agents/60-dns-cdn-tester.d.ts.map +1 -0
  249. package/dist/agents/60-dns-cdn-tester.js +105 -0
  250. package/dist/agents/60-dns-cdn-tester.js.map +1 -0
  251. package/dist/agents/61-docker-health-checker.d.ts +10 -0
  252. package/dist/agents/61-docker-health-checker.d.ts.map +1 -0
  253. package/dist/agents/61-docker-health-checker.js +95 -0
  254. package/dist/agents/61-docker-health-checker.js.map +1 -0
  255. package/dist/agents/62-env-config-validator.d.ts +10 -0
  256. package/dist/agents/62-env-config-validator.d.ts.map +1 -0
  257. package/dist/agents/62-env-config-validator.js +132 -0
  258. package/dist/agents/62-env-config-validator.js.map +1 -0
  259. package/dist/agents/63-log-quality-auditor.d.ts +9 -0
  260. package/dist/agents/63-log-quality-auditor.d.ts.map +1 -0
  261. package/dist/agents/63-log-quality-auditor.js +121 -0
  262. package/dist/agents/63-log-quality-auditor.js.map +1 -0
  263. package/dist/agents/64-analytics-tracker-tester.d.ts +10 -0
  264. package/dist/agents/64-analytics-tracker-tester.d.ts.map +1 -0
  265. package/dist/agents/64-analytics-tracker-tester.js +146 -0
  266. package/dist/agents/64-analytics-tracker-tester.js.map +1 -0
  267. package/dist/agents/65-gdpr-compliance-tester.d.ts +13 -0
  268. package/dist/agents/65-gdpr-compliance-tester.d.ts.map +1 -0
  269. package/dist/agents/65-gdpr-compliance-tester.js +186 -0
  270. package/dist/agents/65-gdpr-compliance-tester.js.map +1 -0
  271. package/dist/agents/66-soc2-control-validator.d.ts +14 -0
  272. package/dist/agents/66-soc2-control-validator.d.ts.map +1 -0
  273. package/dist/agents/66-soc2-control-validator.js +178 -0
  274. package/dist/agents/66-soc2-control-validator.js.map +1 -0
  275. package/dist/agents/67-wcag-aaa-tester.d.ts +13 -0
  276. package/dist/agents/67-wcag-aaa-tester.d.ts.map +1 -0
  277. package/dist/agents/67-wcag-aaa-tester.js +207 -0
  278. package/dist/agents/67-wcag-aaa-tester.js.map +1 -0
  279. package/dist/agents/68-dead-code-detector.d.ts +9 -0
  280. package/dist/agents/68-dead-code-detector.d.ts.map +1 -0
  281. package/dist/agents/68-dead-code-detector.js +116 -0
  282. package/dist/agents/68-dead-code-detector.js.map +1 -0
  283. package/dist/agents/69-type-safety-auditor.d.ts +9 -0
  284. package/dist/agents/69-type-safety-auditor.d.ts.map +1 -0
  285. package/dist/agents/69-type-safety-auditor.js +148 -0
  286. package/dist/agents/69-type-safety-auditor.js.map +1 -0
  287. package/dist/agents/70-complexity-analyzer.d.ts +10 -0
  288. package/dist/agents/70-complexity-analyzer.d.ts.map +1 -0
  289. package/dist/agents/70-complexity-analyzer.js +154 -0
  290. package/dist/agents/70-complexity-analyzer.js.map +1 -0
  291. package/dist/agents/registry.d.ts +3 -3
  292. package/dist/agents/registry.d.ts.map +1 -1
  293. package/dist/agents/registry.js +146 -5
  294. package/dist/agents/registry.js.map +1 -1
  295. package/dist/core/license.js +2 -5
  296. package/dist/core/license.js.map +1 -1
  297. package/dist/core/orchestrator.d.ts.map +1 -1
  298. package/dist/core/orchestrator.js +6 -4
  299. package/dist/core/orchestrator.js.map +1 -1
  300. package/package.json +2 -2
@@ -0,0 +1,245 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import type { ValidatedConfig } from '../../core/config';
3
+ import type { Phase } from '../../core/types';
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Stub config helpers
7
+ // ---------------------------------------------------------------------------
8
+
9
+ function makeConfig(overrides: Partial<ValidatedConfig> = {}): ValidatedConfig {
10
+ return {
11
+ schemaVersion: 1,
12
+ name: 'test',
13
+ auth: {
14
+ loginUrl: 'http://localhost/login',
15
+ credentials: {
16
+ admin: { email: 'admin@test.com', password: 'secret' },
17
+ },
18
+ },
19
+ modules: [{ id: 'home', route: '/', sidebarIcon: true }],
20
+ environments: {
21
+ alpha: { baseUrl: 'http://localhost:3000', seed: false },
22
+ },
23
+ portals: [],
24
+ breakpoints: [],
25
+ integrations: [],
26
+ workers: [],
27
+ workflows: [],
28
+ accuracy: { enabled: false, decimalPrecision: 2, currencySymbol: '$', timezone: 'UTC' },
29
+ tenancy: { enabled: false, isolationField: 'firmId', testFirms: [] },
30
+ costBudget: { maxPerRun: 100, maxPerAgent: 10, alertThreshold: 0.8, onExceeded: 'abort' },
31
+ agentClassification: { blocking: [], advisory: [47] },
32
+ thresholds: {
33
+ unitCoverage: { lines: 80, functions: 80, branches: 80, statements: 80 },
34
+ lighthouse: { accessibility: 90, performance: 90, bestPractices: 90, seo: 90 },
35
+ apiResponseTime: 2000,
36
+ bundleSizeLimit: 500000,
37
+ maxConsoleErrors: 0,
38
+ },
39
+ disabledAgents: [],
40
+ disabledAgentSet: new Set<number>(),
41
+ ...overrides,
42
+ };
43
+ }
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Mock fetch
47
+ // ---------------------------------------------------------------------------
48
+
49
+ const fetchMock = vi.fn();
50
+ vi.stubGlobal('fetch', fetchMock);
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Mock helpers
54
+ // ---------------------------------------------------------------------------
55
+
56
+ const loginMock = vi.fn().mockResolvedValue(undefined);
57
+
58
+ vi.mock('../../helpers/navigation', () => ({
59
+ login: (...args: unknown[]) => loginMock(...args),
60
+ waitForSectionLoad: vi.fn().mockResolvedValue(undefined),
61
+ navigateToSection: vi.fn().mockResolvedValue(undefined),
62
+ switchPortal: vi.fn().mockResolvedValue(undefined),
63
+ }));
64
+
65
+ // ---------------------------------------------------------------------------
66
+ // Mock Playwright
67
+ // ---------------------------------------------------------------------------
68
+
69
+ interface MockPage {
70
+ close: ReturnType<typeof vi.fn>;
71
+ goto: ReturnType<typeof vi.fn>;
72
+ evaluate: ReturnType<typeof vi.fn>;
73
+ }
74
+
75
+ function makeMockPage(): MockPage {
76
+ return {
77
+ close: vi.fn().mockResolvedValue(undefined),
78
+ goto: vi.fn().mockResolvedValue(undefined),
79
+ evaluate: vi.fn().mockResolvedValue(null),
80
+ };
81
+ }
82
+
83
+ let currentMockPage: MockPage;
84
+ let mockBrowser: { newPage: ReturnType<typeof vi.fn>; close: ReturnType<typeof vi.fn> };
85
+
86
+ vi.mock('playwright', async () => ({
87
+ chromium: {
88
+ launch: vi.fn().mockImplementation(async () => mockBrowser),
89
+ },
90
+ }));
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // Dynamic import AFTER mocks
94
+ // ---------------------------------------------------------------------------
95
+
96
+ const { SocialPreviewTesterAgent } = await import('../47-social-preview-tester');
97
+
98
+ function createAgent(
99
+ config: ValidatedConfig = makeConfig(),
100
+ phase: Phase = 'beta',
101
+ ): InstanceType<typeof SocialPreviewTesterAgent> {
102
+ return new SocialPreviewTesterAgent(config, phase, '/tmp/test-run');
103
+ }
104
+
105
+ // ---------------------------------------------------------------------------
106
+ // Tests
107
+ // ---------------------------------------------------------------------------
108
+
109
+ describe('SocialPreviewTesterAgent', () => {
110
+ beforeEach(() => {
111
+ fetchMock.mockReset().mockResolvedValue({ ok: true, status: 200 });
112
+ loginMock.mockReset().mockResolvedValue(undefined);
113
+
114
+ currentMockPage = makeMockPage();
115
+ mockBrowser = {
116
+ newPage: vi.fn().mockResolvedValue(currentMockPage),
117
+ close: vi.fn().mockResolvedValue(undefined),
118
+ };
119
+ });
120
+
121
+ it('has agentId 47 and correct agentName', () => {
122
+ const agent = createAgent();
123
+ expect(agent.agentId).toBe(47);
124
+ expect(agent.agentName).toBe('Social Preview Tester');
125
+ });
126
+
127
+ it('throws when modules array is empty', async () => {
128
+ const config = makeConfig({ modules: [] });
129
+ const agent = createAgent(config);
130
+ const result = await agent.run();
131
+ expect(result.status).toBe('failed');
132
+ });
133
+
134
+ it('detects missing og:image', async () => {
135
+ currentMockPage.evaluate.mockResolvedValue(null);
136
+
137
+ const agent = createAgent();
138
+ const result = await agent.run();
139
+
140
+ const noImage = result.findings.find(f => f.id.includes('no-og-image'));
141
+ expect(noImage).toBeDefined();
142
+ expect(noImage!.severity).toBe('medium');
143
+ });
144
+
145
+ it('detects broken og:image URL', async () => {
146
+ currentMockPage.evaluate.mockImplementation((fn: unknown) => {
147
+ const fnStr = String(fn);
148
+ if (fnStr.includes('og:image')) return Promise.resolve('http://localhost:3000/broken.png');
149
+ return Promise.resolve(null);
150
+ });
151
+ fetchMock.mockImplementation((url: string) => {
152
+ if (typeof url === 'string' && url.includes('broken.png')) {
153
+ return Promise.resolve({ ok: false, status: 404 });
154
+ }
155
+ return Promise.resolve({ ok: true, status: 200 });
156
+ });
157
+
158
+ const agent = createAgent();
159
+ const result = await agent.run();
160
+
161
+ const brokenImage = result.findings.find(f => f.id.includes('og-image-broken'));
162
+ expect(brokenImage).toBeDefined();
163
+ });
164
+
165
+ it('detects missing og:title', async () => {
166
+ currentMockPage.evaluate.mockResolvedValue(null);
167
+
168
+ const agent = createAgent();
169
+ const result = await agent.run();
170
+
171
+ const noTitle = result.findings.find(f => f.id.includes('no-og-title'));
172
+ expect(noTitle).toBeDefined();
173
+ });
174
+
175
+ it('detects long og:title', async () => {
176
+ currentMockPage.evaluate.mockImplementation((fn: unknown) => {
177
+ const fnStr = String(fn);
178
+ if (fnStr.includes('og:title')) return Promise.resolve('A'.repeat(80));
179
+ return Promise.resolve(null);
180
+ });
181
+
182
+ const agent = createAgent();
183
+ const result = await agent.run();
184
+
185
+ const longTitle = result.findings.find(f => f.id.includes('long-og-title'));
186
+ expect(longTitle).toBeDefined();
187
+ });
188
+
189
+ it('detects missing og:description', async () => {
190
+ currentMockPage.evaluate.mockResolvedValue(null);
191
+
192
+ const agent = createAgent();
193
+ const result = await agent.run();
194
+
195
+ const noDesc = result.findings.find(f => f.id.includes('no-og-desc'));
196
+ expect(noDesc).toBeDefined();
197
+ });
198
+
199
+ it('detects missing twitter:card', async () => {
200
+ currentMockPage.evaluate.mockResolvedValue(null);
201
+
202
+ const agent = createAgent();
203
+ const result = await agent.run();
204
+
205
+ const noCard = result.findings.find(f => f.id.includes('no-twitter-card'));
206
+ expect(noCard).toBeDefined();
207
+ });
208
+
209
+ it('produces medium finding when login fails', async () => {
210
+ loginMock.mockRejectedValue(new Error('Auth failed'));
211
+
212
+ const agent = createAgent();
213
+ const result = await agent.run();
214
+
215
+ const loginFinding = result.findings.find(f => f.id.includes('login-failed'));
216
+ expect(loginFinding).toBeDefined();
217
+ });
218
+
219
+ it('produces medium finding when Playwright crashes', async () => {
220
+ mockBrowser.newPage.mockRejectedValue(new Error('Browser crashed'));
221
+
222
+ const agent = createAgent();
223
+ const result = await agent.run();
224
+
225
+ const pwFinding = result.findings.find(f => f.id.includes('playwright-failure'));
226
+ expect(pwFinding).toBeDefined();
227
+ });
228
+
229
+ it('closes browser even when an error occurs', async () => {
230
+ mockBrowser.newPage.mockRejectedValue(new Error('Launch error'));
231
+ const agent = createAgent();
232
+ await agent.run();
233
+ expect(mockBrowser.close).toHaveBeenCalled();
234
+ });
235
+
236
+ it('produces medium finding when navigation fails', async () => {
237
+ currentMockPage.goto.mockRejectedValue(new Error('Navigation failed'));
238
+
239
+ const agent = createAgent();
240
+ const result = await agent.run();
241
+
242
+ const navFinding = result.findings.find(f => f.id.includes('nav-failed'));
243
+ expect(navFinding).toBeDefined();
244
+ });
245
+ });
@@ -0,0 +1,276 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import type { ValidatedConfig } from '../../core/config';
3
+ import type { Phase } from '../../core/types';
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Stub config helpers
7
+ // ---------------------------------------------------------------------------
8
+
9
+ function makeConfig(overrides: Partial<ValidatedConfig> = {}): ValidatedConfig {
10
+ return {
11
+ schemaVersion: 1,
12
+ name: 'test',
13
+ auth: {
14
+ loginUrl: 'http://localhost/login',
15
+ credentials: {
16
+ admin: { email: 'admin@test.com', password: 'secret' },
17
+ },
18
+ },
19
+ modules: [{ id: 'home', route: '/', sidebarIcon: true }],
20
+ environments: {
21
+ alpha: { baseUrl: 'http://localhost:3000', seed: false },
22
+ },
23
+ portals: [],
24
+ breakpoints: [],
25
+ integrations: [],
26
+ workers: [],
27
+ workflows: [],
28
+ accuracy: { enabled: false, decimalPrecision: 2, currencySymbol: '$', timezone: 'UTC' },
29
+ tenancy: { enabled: false, isolationField: 'firmId', testFirms: [] },
30
+ costBudget: { maxPerRun: 100, maxPerAgent: 10, alertThreshold: 0.8, onExceeded: 'abort' },
31
+ agentClassification: { blocking: [], advisory: [48] },
32
+ thresholds: {
33
+ unitCoverage: { lines: 80, functions: 80, branches: 80, statements: 80 },
34
+ lighthouse: { accessibility: 90, performance: 90, bestPractices: 90, seo: 90 },
35
+ apiResponseTime: 2000,
36
+ bundleSizeLimit: 500000,
37
+ maxConsoleErrors: 0,
38
+ },
39
+ disabledAgents: [],
40
+ disabledAgentSet: new Set<number>(),
41
+ ...overrides,
42
+ };
43
+ }
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Mock fetch
47
+ // ---------------------------------------------------------------------------
48
+
49
+ const fetchMock = vi.fn();
50
+ vi.stubGlobal('fetch', fetchMock);
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Mock helpers
54
+ // ---------------------------------------------------------------------------
55
+
56
+ const loginMock = vi.fn().mockResolvedValue(undefined);
57
+
58
+ vi.mock('../../helpers/navigation', () => ({
59
+ login: (...args: unknown[]) => loginMock(...args),
60
+ waitForSectionLoad: vi.fn().mockResolvedValue(undefined),
61
+ navigateToSection: vi.fn().mockResolvedValue(undefined),
62
+ switchPortal: vi.fn().mockResolvedValue(undefined),
63
+ }));
64
+
65
+ // ---------------------------------------------------------------------------
66
+ // Mock Playwright
67
+ // ---------------------------------------------------------------------------
68
+
69
+ interface MockLocator {
70
+ count: ReturnType<typeof vi.fn>;
71
+ }
72
+
73
+ function makeMockLocator(countVal = 0): MockLocator {
74
+ return { count: vi.fn().mockResolvedValue(countVal) };
75
+ }
76
+
77
+ interface MockPage {
78
+ close: ReturnType<typeof vi.fn>;
79
+ goto: ReturnType<typeof vi.fn>;
80
+ evaluate: ReturnType<typeof vi.fn>;
81
+ locator: ReturnType<typeof vi.fn>;
82
+ }
83
+
84
+ function makeMockPage(): MockPage {
85
+ return {
86
+ close: vi.fn().mockResolvedValue(undefined),
87
+ goto: vi.fn().mockResolvedValue(undefined),
88
+ evaluate: vi.fn().mockResolvedValue({
89
+ domContentLoaded: 500,
90
+ loadComplete: 800,
91
+ fcp: 1200,
92
+ }),
93
+ locator: vi.fn().mockReturnValue(makeMockLocator(0)),
94
+ };
95
+ }
96
+
97
+ let currentMockPage: MockPage;
98
+ let mockBrowser: { newPage: ReturnType<typeof vi.fn>; close: ReturnType<typeof vi.fn> };
99
+
100
+ vi.mock('playwright', async () => ({
101
+ chromium: {
102
+ launch: vi.fn().mockImplementation(async () => mockBrowser),
103
+ },
104
+ }));
105
+
106
+ // ---------------------------------------------------------------------------
107
+ // Dynamic import AFTER mocks
108
+ // ---------------------------------------------------------------------------
109
+
110
+ const { LighthouseAuditorAgent } = await import('../48-lighthouse-auditor');
111
+
112
+ function createAgent(
113
+ config: ValidatedConfig = makeConfig(),
114
+ phase: Phase = 'beta',
115
+ ): InstanceType<typeof LighthouseAuditorAgent> {
116
+ return new LighthouseAuditorAgent(config, phase, '/tmp/test-run');
117
+ }
118
+
119
+ // ---------------------------------------------------------------------------
120
+ // Tests
121
+ // ---------------------------------------------------------------------------
122
+
123
+ describe('LighthouseAuditorAgent', () => {
124
+ beforeEach(() => {
125
+ fetchMock.mockReset().mockResolvedValue({ ok: true, status: 200 });
126
+ loginMock.mockReset().mockResolvedValue(undefined);
127
+
128
+ currentMockPage = makeMockPage();
129
+ mockBrowser = {
130
+ newPage: vi.fn().mockResolvedValue(currentMockPage),
131
+ close: vi.fn().mockResolvedValue(undefined),
132
+ };
133
+ });
134
+
135
+ it('has agentId 48 and correct agentName', () => {
136
+ const agent = createAgent();
137
+ expect(agent.agentId).toBe(48);
138
+ expect(agent.agentName).toBe('Lighthouse Auditor');
139
+ });
140
+
141
+ it('throws when modules array is empty', async () => {
142
+ const config = makeConfig({ modules: [] });
143
+ const agent = createAgent(config);
144
+ const result = await agent.run();
145
+ expect(result.status).toBe('failed');
146
+ });
147
+
148
+ it('detects missing viewport meta tag', async () => {
149
+ let callCount = 0;
150
+ currentMockPage.evaluate.mockImplementation(() => {
151
+ callCount++;
152
+ if (callCount === 1) return Promise.resolve({ domContentLoaded: 500, loadComplete: 800, fcp: 1200 });
153
+ if (callCount === 2) return Promise.resolve(false); // no viewport
154
+ return Promise.resolve(true);
155
+ });
156
+
157
+ const agent = createAgent();
158
+ const result = await agent.run();
159
+
160
+ const noViewport = result.findings.find(f => f.id.includes('no-viewport'));
161
+ expect(noViewport).toBeDefined();
162
+ expect(noViewport!.severity).toBe('medium');
163
+ });
164
+
165
+ it('detects missing lang attribute', async () => {
166
+ let callCount = 0;
167
+ currentMockPage.evaluate.mockImplementation(() => {
168
+ callCount++;
169
+ if (callCount === 1) return Promise.resolve({ domContentLoaded: 500, loadComplete: 800, fcp: 1200 });
170
+ if (callCount === 2) return Promise.resolve(true); // viewport present
171
+ if (callCount === 3) return Promise.resolve(false); // no lang
172
+ return Promise.resolve(true);
173
+ });
174
+
175
+ const agent = createAgent();
176
+ const result = await agent.run();
177
+
178
+ const noLang = result.findings.find(f => f.id.includes('no-lang'));
179
+ expect(noLang).toBeDefined();
180
+ });
181
+
182
+ it('detects missing charset meta tag', async () => {
183
+ let callCount = 0;
184
+ currentMockPage.evaluate.mockImplementation(() => {
185
+ callCount++;
186
+ if (callCount === 1) return Promise.resolve({ domContentLoaded: 500, loadComplete: 800, fcp: 1200 });
187
+ if (callCount === 2) return Promise.resolve(true); // viewport
188
+ if (callCount === 3) return Promise.resolve(true); // lang
189
+ if (callCount === 4) return Promise.resolve(false); // no charset
190
+ return Promise.resolve(true);
191
+ });
192
+
193
+ const agent = createAgent();
194
+ const result = await agent.run();
195
+
196
+ const noCharset = result.findings.find(f => f.id.includes('no-charset'));
197
+ expect(noCharset).toBeDefined();
198
+ });
199
+
200
+ it('detects slow DOMContentLoaded', async () => {
201
+ currentMockPage.evaluate.mockImplementation(() => {
202
+ return Promise.resolve({
203
+ domContentLoaded: 5000,
204
+ loadComplete: 8000,
205
+ fcp: 1200,
206
+ });
207
+ });
208
+
209
+ const agent = createAgent();
210
+ const result = await agent.run();
211
+
212
+ const slowDcl = result.findings.find(f => f.id.includes('slow-dcl'));
213
+ expect(slowDcl).toBeDefined();
214
+ expect(slowDcl!.severity).toBe('medium');
215
+ });
216
+
217
+ it('records performance evidence', async () => {
218
+ currentMockPage.evaluate.mockResolvedValue({
219
+ domContentLoaded: 500,
220
+ loadComplete: 800,
221
+ fcp: 1200,
222
+ });
223
+
224
+ const agent = createAgent();
225
+ const result = await agent.run();
226
+
227
+ expect(result.evidence.some(e => e.description.includes('FCP'))).toBe(true);
228
+ });
229
+
230
+ it('produces medium finding when login fails', async () => {
231
+ loginMock.mockRejectedValue(new Error('Auth failed'));
232
+
233
+ const agent = createAgent();
234
+ const result = await agent.run();
235
+
236
+ const loginFinding = result.findings.find(f => f.id.includes('login-failed'));
237
+ expect(loginFinding).toBeDefined();
238
+ });
239
+
240
+ it('produces medium finding when Playwright crashes', async () => {
241
+ mockBrowser.newPage.mockRejectedValue(new Error('Browser crashed'));
242
+
243
+ const agent = createAgent();
244
+ const result = await agent.run();
245
+
246
+ const pwFinding = result.findings.find(f => f.id.includes('playwright-failure'));
247
+ expect(pwFinding).toBeDefined();
248
+ });
249
+
250
+ it('closes browser even when an error occurs', async () => {
251
+ mockBrowser.newPage.mockRejectedValue(new Error('Launch error'));
252
+ const agent = createAgent();
253
+ await agent.run();
254
+ expect(mockBrowser.close).toHaveBeenCalled();
255
+ });
256
+
257
+ it('produces medium finding when navigation fails', async () => {
258
+ currentMockPage.goto.mockRejectedValue(new Error('Navigation failed'));
259
+
260
+ const agent = createAgent();
261
+ const result = await agent.run();
262
+
263
+ const navFinding = result.findings.find(f => f.id.includes('nav-failed'));
264
+ expect(navFinding).toBeDefined();
265
+ });
266
+
267
+ it('handles performance metrics evaluation error gracefully', async () => {
268
+ currentMockPage.evaluate.mockRejectedValue(new Error('Evaluate failed'));
269
+
270
+ const agent = createAgent();
271
+ const result = await agent.run();
272
+
273
+ // Should not crash — just skip metrics
274
+ expect(result.status).toBeDefined();
275
+ });
276
+ });