@empline/preflight 1.1.11 → 1.1.13

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 (709) hide show
  1. package/dist/checks/consolidated/auth-storage-state.d.ts +3 -0
  2. package/dist/checks/consolidated/auth-storage-state.d.ts.map +1 -0
  3. package/dist/checks/consolidated/auth-storage-state.js +146 -0
  4. package/dist/checks/consolidated/auth-storage-state.js.map +1 -0
  5. package/dist/checks/consolidated/business.d.ts +50 -0
  6. package/dist/checks/consolidated/business.d.ts.map +1 -0
  7. package/dist/checks/consolidated/business.js +252 -0
  8. package/dist/checks/consolidated/business.js.map +1 -0
  9. package/dist/checks/consolidated/caching-strategy.d.ts +104 -0
  10. package/dist/checks/consolidated/caching-strategy.d.ts.map +1 -0
  11. package/dist/checks/consolidated/caching-strategy.js +725 -0
  12. package/dist/checks/consolidated/caching-strategy.js.map +1 -0
  13. package/dist/checks/consolidated/code-quality.d.ts +83 -0
  14. package/dist/checks/consolidated/code-quality.d.ts.map +1 -0
  15. package/dist/checks/consolidated/code-quality.js +445 -0
  16. package/dist/checks/consolidated/code-quality.js.map +1 -0
  17. package/dist/checks/consolidated/console-statements.d.ts +32 -0
  18. package/dist/checks/consolidated/console-statements.d.ts.map +1 -0
  19. package/dist/checks/consolidated/console-statements.js +304 -0
  20. package/dist/checks/consolidated/console-statements.js.map +1 -0
  21. package/dist/checks/consolidated/css-advanced-validation.d.ts +24 -0
  22. package/dist/checks/consolidated/css-advanced-validation.d.ts.map +1 -0
  23. package/dist/checks/consolidated/css-advanced-validation.js +415 -0
  24. package/dist/checks/consolidated/css-advanced-validation.js.map +1 -0
  25. package/dist/checks/consolidated/css-organization.d.ts +14 -0
  26. package/dist/checks/consolidated/css-organization.d.ts.map +1 -0
  27. package/dist/checks/consolidated/css-organization.js +432 -0
  28. package/dist/checks/consolidated/css-organization.js.map +1 -0
  29. package/dist/checks/consolidated/css-runtime-validation.d.ts +22 -0
  30. package/dist/checks/consolidated/css-runtime-validation.d.ts.map +1 -0
  31. package/dist/checks/consolidated/css-runtime-validation.js +330 -0
  32. package/dist/checks/consolidated/css-runtime-validation.js.map +1 -0
  33. package/dist/checks/consolidated/css-variable-validation.d.ts +17 -0
  34. package/dist/checks/consolidated/css-variable-validation.d.ts.map +1 -0
  35. package/dist/checks/consolidated/css-variable-validation.js +412 -0
  36. package/dist/checks/consolidated/css-variable-validation.js.map +1 -0
  37. package/dist/checks/consolidated/dark-mode-consistency.d.ts +23 -0
  38. package/dist/checks/consolidated/dark-mode-consistency.d.ts.map +1 -0
  39. package/dist/checks/consolidated/dark-mode-consistency.js +291 -0
  40. package/dist/checks/consolidated/dark-mode-consistency.js.map +1 -0
  41. package/dist/checks/consolidated/database.d.ts +95 -0
  42. package/dist/checks/consolidated/database.d.ts.map +1 -0
  43. package/dist/checks/consolidated/database.js +427 -0
  44. package/dist/checks/consolidated/database.js.map +1 -0
  45. package/dist/checks/consolidated/e2e-checks.d.ts +52 -0
  46. package/dist/checks/consolidated/e2e-checks.d.ts.map +1 -0
  47. package/dist/checks/consolidated/e2e-checks.js +157 -0
  48. package/dist/checks/consolidated/e2e-checks.js.map +1 -0
  49. package/dist/checks/consolidated/e2e-regression-coverage.d.ts +14 -0
  50. package/dist/checks/consolidated/e2e-regression-coverage.d.ts.map +1 -0
  51. package/dist/checks/consolidated/e2e-regression-coverage.js +151 -0
  52. package/dist/checks/consolidated/e2e-regression-coverage.js.map +1 -0
  53. package/dist/checks/consolidated/e2e-validation.d.ts +137 -0
  54. package/dist/checks/consolidated/e2e-validation.d.ts.map +1 -0
  55. package/dist/checks/consolidated/e2e-validation.js +1001 -0
  56. package/dist/checks/consolidated/e2e-validation.js.map +1 -0
  57. package/dist/checks/consolidated/enterprise-baseline.d.ts +9 -0
  58. package/dist/checks/consolidated/enterprise-baseline.d.ts.map +1 -0
  59. package/dist/checks/consolidated/enterprise-baseline.js +277 -0
  60. package/dist/checks/consolidated/enterprise-baseline.js.map +1 -0
  61. package/dist/checks/consolidated/generate-pageload-config.d.ts +6 -0
  62. package/dist/checks/consolidated/generate-pageload-config.d.ts.map +1 -0
  63. package/dist/checks/consolidated/generate-pageload-config.js +161 -0
  64. package/dist/checks/consolidated/generate-pageload-config.js.map +1 -0
  65. package/dist/checks/consolidated/hardened-checks.d.ts +276 -0
  66. package/dist/checks/consolidated/hardened-checks.d.ts.map +1 -0
  67. package/dist/checks/consolidated/hardened-checks.js +3056 -0
  68. package/dist/checks/consolidated/hardened-checks.js.map +1 -0
  69. package/dist/checks/consolidated/homepage-ux.d.ts +12 -0
  70. package/dist/checks/consolidated/homepage-ux.d.ts.map +1 -0
  71. package/dist/checks/consolidated/homepage-ux.js +242 -0
  72. package/dist/checks/consolidated/homepage-ux.js.map +1 -0
  73. package/dist/checks/consolidated/images.d.ts +76 -0
  74. package/dist/checks/consolidated/images.d.ts.map +1 -0
  75. package/dist/checks/consolidated/images.js +311 -0
  76. package/dist/checks/consolidated/images.js.map +1 -0
  77. package/dist/checks/consolidated/import-cycles.d.ts +63 -0
  78. package/dist/checks/consolidated/import-cycles.d.ts.map +1 -0
  79. package/dist/checks/consolidated/import-cycles.js +291 -0
  80. package/dist/checks/consolidated/import-cycles.js.map +1 -0
  81. package/dist/checks/consolidated/imports.d.ts +112 -0
  82. package/dist/checks/consolidated/imports.d.ts.map +1 -0
  83. package/dist/checks/consolidated/imports.js +977 -0
  84. package/dist/checks/consolidated/imports.js.map +1 -0
  85. package/dist/checks/consolidated/inline-style-conflicts.d.ts +21 -0
  86. package/dist/checks/consolidated/inline-style-conflicts.d.ts.map +1 -0
  87. package/dist/checks/consolidated/inline-style-conflicts.js +300 -0
  88. package/dist/checks/consolidated/inline-style-conflicts.js.map +1 -0
  89. package/dist/checks/consolidated/lib-organization.d.ts +12 -0
  90. package/dist/checks/consolidated/lib-organization.d.ts.map +1 -0
  91. package/dist/checks/consolidated/lib-organization.js +419 -0
  92. package/dist/checks/consolidated/lib-organization.js.map +1 -0
  93. package/dist/checks/consolidated/n-plus-one.d.ts +63 -0
  94. package/dist/checks/consolidated/n-plus-one.d.ts.map +1 -0
  95. package/dist/checks/consolidated/n-plus-one.js +331 -0
  96. package/dist/checks/consolidated/n-plus-one.js.map +1 -0
  97. package/dist/checks/consolidated/nextjs.d.ts +51 -0
  98. package/dist/checks/consolidated/nextjs.d.ts.map +1 -0
  99. package/dist/checks/consolidated/nextjs.js +205 -0
  100. package/dist/checks/consolidated/nextjs.js.map +1 -0
  101. package/dist/checks/consolidated/organization.d.ts +54 -0
  102. package/dist/checks/consolidated/organization.d.ts.map +1 -0
  103. package/dist/checks/consolidated/organization.js +158 -0
  104. package/dist/checks/consolidated/organization.js.map +1 -0
  105. package/dist/checks/consolidated/pageload.d.ts +12 -0
  106. package/dist/checks/consolidated/pageload.d.ts.map +1 -0
  107. package/dist/checks/consolidated/pageload.js +138 -0
  108. package/dist/checks/consolidated/pageload.js.map +1 -0
  109. package/dist/checks/consolidated/performance.d.ts +112 -0
  110. package/dist/checks/consolidated/performance.d.ts.map +1 -0
  111. package/dist/checks/consolidated/performance.js +1546 -0
  112. package/dist/checks/consolidated/performance.js.map +1 -0
  113. package/dist/checks/consolidated/quality.d.ts +52 -0
  114. package/dist/checks/consolidated/quality.d.ts.map +1 -0
  115. package/dist/checks/consolidated/quality.js +253 -0
  116. package/dist/checks/consolidated/quality.js.map +1 -0
  117. package/dist/checks/consolidated/react.d.ts +48 -0
  118. package/dist/checks/consolidated/react.d.ts.map +1 -0
  119. package/dist/checks/consolidated/react.js +203 -0
  120. package/dist/checks/consolidated/react.js.map +1 -0
  121. package/dist/checks/consolidated/regression-hygiene.d.ts +17 -0
  122. package/dist/checks/consolidated/regression-hygiene.d.ts.map +1 -0
  123. package/dist/checks/consolidated/regression-hygiene.js +242 -0
  124. package/dist/checks/consolidated/regression-hygiene.js.map +1 -0
  125. package/dist/checks/consolidated/regression.d.ts +20 -0
  126. package/dist/checks/consolidated/regression.d.ts.map +1 -0
  127. package/dist/checks/consolidated/regression.js +121 -0
  128. package/dist/checks/consolidated/regression.js.map +1 -0
  129. package/dist/checks/consolidated/runtime.d.ts +53 -0
  130. package/dist/checks/consolidated/runtime.d.ts.map +1 -0
  131. package/dist/checks/consolidated/runtime.js +160 -0
  132. package/dist/checks/consolidated/runtime.js.map +1 -0
  133. package/dist/checks/consolidated/script-performance.d.ts +17 -0
  134. package/dist/checks/consolidated/script-performance.d.ts.map +1 -0
  135. package/dist/checks/consolidated/script-performance.js +137 -0
  136. package/dist/checks/consolidated/script-performance.js.map +1 -0
  137. package/dist/checks/consolidated/security.d.ts +78 -0
  138. package/dist/checks/consolidated/security.d.ts.map +1 -0
  139. package/dist/checks/consolidated/security.js +404 -0
  140. package/dist/checks/consolidated/security.js.map +1 -0
  141. package/dist/checks/consolidated/seo.d.ts +31 -0
  142. package/dist/checks/consolidated/seo.d.ts.map +1 -0
  143. package/dist/checks/consolidated/seo.js +1438 -0
  144. package/dist/checks/consolidated/seo.js.map +1 -0
  145. package/dist/checks/consolidated/sx-prop-deprecation.d.ts +22 -0
  146. package/dist/checks/consolidated/sx-prop-deprecation.d.ts.map +1 -0
  147. package/dist/checks/consolidated/sx-prop-deprecation.js +280 -0
  148. package/dist/checks/consolidated/sx-prop-deprecation.js.map +1 -0
  149. package/dist/checks/consolidated/tailwind-class-validation.d.ts +25 -0
  150. package/dist/checks/consolidated/tailwind-class-validation.d.ts.map +1 -0
  151. package/dist/checks/consolidated/tailwind-class-validation.js +533 -0
  152. package/dist/checks/consolidated/tailwind-class-validation.js.map +1 -0
  153. package/dist/checks/consolidated/testing.d.ts +54 -0
  154. package/dist/checks/consolidated/testing.d.ts.map +1 -0
  155. package/dist/checks/consolidated/testing.js +163 -0
  156. package/dist/checks/consolidated/testing.js.map +1 -0
  157. package/dist/checks/consolidated/typescript.d.ts +3 -0
  158. package/dist/checks/consolidated/typescript.d.ts.map +1 -0
  159. package/dist/checks/consolidated/typescript.js +31 -0
  160. package/dist/checks/consolidated/typescript.js.map +1 -0
  161. package/dist/checks/consolidated/ui-accessibility-advanced.d.ts +104 -0
  162. package/dist/checks/consolidated/ui-accessibility-advanced.d.ts.map +1 -0
  163. package/dist/checks/consolidated/ui-accessibility-advanced.js +689 -0
  164. package/dist/checks/consolidated/ui-accessibility-advanced.js.map +1 -0
  165. package/dist/checks/consolidated/ui-accessibility.d.ts +121 -0
  166. package/dist/checks/consolidated/ui-accessibility.d.ts.map +1 -0
  167. package/dist/checks/consolidated/ui-accessibility.js +776 -0
  168. package/dist/checks/consolidated/ui-accessibility.js.map +1 -0
  169. package/dist/checks/consolidated/ui-advanced-spacing.d.ts +142 -0
  170. package/dist/checks/consolidated/ui-advanced-spacing.d.ts.map +1 -0
  171. package/dist/checks/consolidated/ui-advanced-spacing.js +1220 -0
  172. package/dist/checks/consolidated/ui-advanced-spacing.js.map +1 -0
  173. package/dist/checks/consolidated/ui-animation-duration.d.ts +108 -0
  174. package/dist/checks/consolidated/ui-animation-duration.d.ts.map +1 -0
  175. package/dist/checks/consolidated/ui-animation-duration.js +531 -0
  176. package/dist/checks/consolidated/ui-animation-duration.js.map +1 -0
  177. package/dist/checks/consolidated/ui-border-radius.d.ts +90 -0
  178. package/dist/checks/consolidated/ui-border-radius.d.ts.map +1 -0
  179. package/dist/checks/consolidated/ui-border-radius.js +519 -0
  180. package/dist/checks/consolidated/ui-border-radius.js.map +1 -0
  181. package/dist/checks/consolidated/ui-buttons.d.ts +32 -0
  182. package/dist/checks/consolidated/ui-buttons.d.ts.map +1 -0
  183. package/dist/checks/consolidated/ui-buttons.js +481 -0
  184. package/dist/checks/consolidated/ui-buttons.js.map +1 -0
  185. package/dist/checks/consolidated/ui-cards.d.ts +29 -0
  186. package/dist/checks/consolidated/ui-cards.d.ts.map +1 -0
  187. package/dist/checks/consolidated/ui-cards.js +504 -0
  188. package/dist/checks/consolidated/ui-cards.js.map +1 -0
  189. package/dist/checks/consolidated/ui-checks.d.ts +48 -0
  190. package/dist/checks/consolidated/ui-checks.d.ts.map +1 -0
  191. package/dist/checks/consolidated/ui-checks.js +264 -0
  192. package/dist/checks/consolidated/ui-checks.js.map +1 -0
  193. package/dist/checks/consolidated/ui-cleanup.d.ts +81 -0
  194. package/dist/checks/consolidated/ui-cleanup.d.ts.map +1 -0
  195. package/dist/checks/consolidated/ui-cleanup.js +650 -0
  196. package/dist/checks/consolidated/ui-cleanup.js.map +1 -0
  197. package/dist/checks/consolidated/ui-components.d.ts +255 -0
  198. package/dist/checks/consolidated/ui-components.d.ts.map +1 -0
  199. package/dist/checks/consolidated/ui-components.js +2008 -0
  200. package/dist/checks/consolidated/ui-components.js.map +1 -0
  201. package/dist/checks/consolidated/ui-consistency-advanced.d.ts +130 -0
  202. package/dist/checks/consolidated/ui-consistency-advanced.d.ts.map +1 -0
  203. package/dist/checks/consolidated/ui-consistency-advanced.js +982 -0
  204. package/dist/checks/consolidated/ui-consistency-advanced.js.map +1 -0
  205. package/dist/checks/consolidated/ui-consistency-comprehensive.d.ts +30 -0
  206. package/dist/checks/consolidated/ui-consistency-comprehensive.d.ts.map +1 -0
  207. package/dist/checks/consolidated/ui-consistency-comprehensive.js +1018 -0
  208. package/dist/checks/consolidated/ui-consistency-comprehensive.js.map +1 -0
  209. package/dist/checks/consolidated/ui-consistency-extended.d.ts +26 -0
  210. package/dist/checks/consolidated/ui-consistency-extended.d.ts.map +1 -0
  211. package/dist/checks/consolidated/ui-consistency-extended.js +606 -0
  212. package/dist/checks/consolidated/ui-consistency-extended.js.map +1 -0
  213. package/dist/checks/consolidated/ui-data-display.d.ts +103 -0
  214. package/dist/checks/consolidated/ui-data-display.d.ts.map +1 -0
  215. package/dist/checks/consolidated/ui-data-display.js +740 -0
  216. package/dist/checks/consolidated/ui-data-display.js.map +1 -0
  217. package/dist/checks/consolidated/ui-deprecated.d.ts +22 -0
  218. package/dist/checks/consolidated/ui-deprecated.d.ts.map +1 -0
  219. package/dist/checks/consolidated/ui-deprecated.js +336 -0
  220. package/dist/checks/consolidated/ui-deprecated.js.map +1 -0
  221. package/dist/checks/consolidated/ui-empty-null-states.d.ts +90 -0
  222. package/dist/checks/consolidated/ui-empty-null-states.d.ts.map +1 -0
  223. package/dist/checks/consolidated/ui-empty-null-states.js +511 -0
  224. package/dist/checks/consolidated/ui-empty-null-states.js.map +1 -0
  225. package/dist/checks/consolidated/ui-error-states.d.ts +99 -0
  226. package/dist/checks/consolidated/ui-error-states.d.ts.map +1 -0
  227. package/dist/checks/consolidated/ui-error-states.js +694 -0
  228. package/dist/checks/consolidated/ui-error-states.js.map +1 -0
  229. package/dist/checks/consolidated/ui-feedback-confirmations.d.ts +90 -0
  230. package/dist/checks/consolidated/ui-feedback-confirmations.d.ts.map +1 -0
  231. package/dist/checks/consolidated/ui-feedback-confirmations.js +596 -0
  232. package/dist/checks/consolidated/ui-feedback-confirmations.js.map +1 -0
  233. package/dist/checks/consolidated/ui-forms.d.ts +32 -0
  234. package/dist/checks/consolidated/ui-forms.d.ts.map +1 -0
  235. package/dist/checks/consolidated/ui-forms.js +568 -0
  236. package/dist/checks/consolidated/ui-forms.js.map +1 -0
  237. package/dist/checks/consolidated/ui-gradient-shadow.d.ts +90 -0
  238. package/dist/checks/consolidated/ui-gradient-shadow.d.ts.map +1 -0
  239. package/dist/checks/consolidated/ui-gradient-shadow.js +568 -0
  240. package/dist/checks/consolidated/ui-gradient-shadow.js.map +1 -0
  241. package/dist/checks/consolidated/ui-grid-responsive.d.ts +27 -0
  242. package/dist/checks/consolidated/ui-grid-responsive.d.ts.map +1 -0
  243. package/dist/checks/consolidated/ui-grid-responsive.js +441 -0
  244. package/dist/checks/consolidated/ui-grid-responsive.js.map +1 -0
  245. package/dist/checks/consolidated/ui-icon-size-tokens.d.ts +104 -0
  246. package/dist/checks/consolidated/ui-icon-size-tokens.d.ts.map +1 -0
  247. package/dist/checks/consolidated/ui-icon-size-tokens.js +514 -0
  248. package/dist/checks/consolidated/ui-icon-size-tokens.js.map +1 -0
  249. package/dist/checks/consolidated/ui-iconography.d.ts +90 -0
  250. package/dist/checks/consolidated/ui-iconography.d.ts.map +1 -0
  251. package/dist/checks/consolidated/ui-iconography.js +565 -0
  252. package/dist/checks/consolidated/ui-iconography.js.map +1 -0
  253. package/dist/checks/consolidated/ui-interactive-states.d.ts +240 -0
  254. package/dist/checks/consolidated/ui-interactive-states.d.ts.map +1 -0
  255. package/dist/checks/consolidated/ui-interactive-states.js +2474 -0
  256. package/dist/checks/consolidated/ui-interactive-states.js.map +1 -0
  257. package/dist/checks/consolidated/ui-layout.d.ts +256 -0
  258. package/dist/checks/consolidated/ui-layout.d.ts.map +1 -0
  259. package/dist/checks/consolidated/ui-layout.js +1371 -0
  260. package/dist/checks/consolidated/ui-layout.js.map +1 -0
  261. package/dist/checks/consolidated/ui-loading-skeletons.d.ts +11 -0
  262. package/dist/checks/consolidated/ui-loading-skeletons.d.ts.map +1 -0
  263. package/dist/checks/consolidated/ui-loading-skeletons.js +145 -0
  264. package/dist/checks/consolidated/ui-loading-skeletons.js.map +1 -0
  265. package/dist/checks/consolidated/ui-loading-state-skeletons.d.ts +9 -0
  266. package/dist/checks/consolidated/ui-loading-state-skeletons.d.ts.map +1 -0
  267. package/dist/checks/consolidated/ui-loading-state-skeletons.js +125 -0
  268. package/dist/checks/consolidated/ui-loading-state-skeletons.js.map +1 -0
  269. package/dist/checks/consolidated/ui-media.d.ts +74 -0
  270. package/dist/checks/consolidated/ui-media.d.ts.map +1 -0
  271. package/dist/checks/consolidated/ui-media.js +408 -0
  272. package/dist/checks/consolidated/ui-media.js.map +1 -0
  273. package/dist/checks/consolidated/ui-micro-interactions.d.ts +107 -0
  274. package/dist/checks/consolidated/ui-micro-interactions.d.ts.map +1 -0
  275. package/dist/checks/consolidated/ui-micro-interactions.js +825 -0
  276. package/dist/checks/consolidated/ui-micro-interactions.js.map +1 -0
  277. package/dist/checks/consolidated/ui-microcopy-consistency.d.ts +114 -0
  278. package/dist/checks/consolidated/ui-microcopy-consistency.d.ts.map +1 -0
  279. package/dist/checks/consolidated/ui-microcopy-consistency.js +566 -0
  280. package/dist/checks/consolidated/ui-microcopy-consistency.js.map +1 -0
  281. package/dist/checks/consolidated/ui-mobile-ux.d.ts +251 -0
  282. package/dist/checks/consolidated/ui-mobile-ux.d.ts.map +1 -0
  283. package/dist/checks/consolidated/ui-mobile-ux.js +2212 -0
  284. package/dist/checks/consolidated/ui-mobile-ux.js.map +1 -0
  285. package/dist/checks/consolidated/ui-motion-accessibility.d.ts +93 -0
  286. package/dist/checks/consolidated/ui-motion-accessibility.d.ts.map +1 -0
  287. package/dist/checks/consolidated/ui-motion-accessibility.js +450 -0
  288. package/dist/checks/consolidated/ui-motion-accessibility.js.map +1 -0
  289. package/dist/checks/consolidated/ui-navigation.d.ts +85 -0
  290. package/dist/checks/consolidated/ui-navigation.d.ts.map +1 -0
  291. package/dist/checks/consolidated/ui-navigation.js +673 -0
  292. package/dist/checks/consolidated/ui-navigation.js.map +1 -0
  293. package/dist/checks/consolidated/ui-patterns.d.ts +174 -0
  294. package/dist/checks/consolidated/ui-patterns.d.ts.map +1 -0
  295. package/dist/checks/consolidated/ui-patterns.js +1532 -0
  296. package/dist/checks/consolidated/ui-patterns.js.map +1 -0
  297. package/dist/checks/consolidated/ui-responsive.d.ts +89 -0
  298. package/dist/checks/consolidated/ui-responsive.d.ts.map +1 -0
  299. package/dist/checks/consolidated/ui-responsive.js +588 -0
  300. package/dist/checks/consolidated/ui-responsive.js.map +1 -0
  301. package/dist/checks/consolidated/ui-spacing-standards.d.ts +43 -0
  302. package/dist/checks/consolidated/ui-spacing-standards.d.ts.map +1 -0
  303. package/dist/checks/consolidated/ui-spacing-standards.js +874 -0
  304. package/dist/checks/consolidated/ui-spacing-standards.js.map +1 -0
  305. package/dist/checks/consolidated/ui-spacing.d.ts +751 -0
  306. package/dist/checks/consolidated/ui-spacing.d.ts.map +1 -0
  307. package/dist/checks/consolidated/ui-spacing.js +4996 -0
  308. package/dist/checks/consolidated/ui-spacing.js.map +1 -0
  309. package/dist/checks/consolidated/ui-standards-auto-fixer.d.ts +70 -0
  310. package/dist/checks/consolidated/ui-standards-auto-fixer.d.ts.map +1 -0
  311. package/dist/checks/consolidated/ui-standards-auto-fixer.js +429 -0
  312. package/dist/checks/consolidated/ui-standards-auto-fixer.js.map +1 -0
  313. package/dist/checks/consolidated/ui-standards-enforcement.d.ts +100 -0
  314. package/dist/checks/consolidated/ui-standards-enforcement.d.ts.map +1 -0
  315. package/dist/checks/consolidated/ui-standards-enforcement.js +935 -0
  316. package/dist/checks/consolidated/ui-standards-enforcement.js.map +1 -0
  317. package/dist/checks/consolidated/ui-state-consistency.d.ts +90 -0
  318. package/dist/checks/consolidated/ui-state-consistency.d.ts.map +1 -0
  319. package/dist/checks/consolidated/ui-state-consistency.js +659 -0
  320. package/dist/checks/consolidated/ui-state-consistency.js.map +1 -0
  321. package/dist/checks/consolidated/ui-style-validation.d.ts +74 -0
  322. package/dist/checks/consolidated/ui-style-validation.d.ts.map +1 -0
  323. package/dist/checks/consolidated/ui-style-validation.js +403 -0
  324. package/dist/checks/consolidated/ui-style-validation.js.map +1 -0
  325. package/dist/checks/consolidated/ui-tokens.d.ts +110 -0
  326. package/dist/checks/consolidated/ui-tokens.d.ts.map +1 -0
  327. package/dist/checks/consolidated/ui-tokens.js +990 -0
  328. package/dist/checks/consolidated/ui-tokens.js.map +1 -0
  329. package/dist/checks/consolidated/ui-typography.d.ts +77 -0
  330. package/dist/checks/consolidated/ui-typography.d.ts.map +1 -0
  331. package/dist/checks/consolidated/ui-typography.js +416 -0
  332. package/dist/checks/consolidated/ui-typography.js.map +1 -0
  333. package/dist/checks/consolidated/ui-visual-hierarchy.d.ts +90 -0
  334. package/dist/checks/consolidated/ui-visual-hierarchy.d.ts.map +1 -0
  335. package/dist/checks/consolidated/ui-visual-hierarchy.js +562 -0
  336. package/dist/checks/consolidated/ui-visual-hierarchy.js.map +1 -0
  337. package/dist/checks/consolidated/woocommerce.d.ts +50 -0
  338. package/dist/checks/consolidated/woocommerce.d.ts.map +1 -0
  339. package/dist/checks/consolidated/woocommerce.js +198 -0
  340. package/dist/checks/consolidated/woocommerce.js.map +1 -0
  341. package/dist/checks/core/api-route-protection.d.ts +2 -0
  342. package/dist/checks/core/api-route-protection.d.ts.map +1 -0
  343. package/dist/checks/core/api-route-protection.js +101 -0
  344. package/dist/checks/core/api-route-protection.js.map +1 -0
  345. package/dist/checks/core/critical.d.ts +8 -0
  346. package/dist/checks/core/critical.d.ts.map +1 -0
  347. package/dist/checks/core/critical.js +200 -0
  348. package/dist/checks/core/critical.js.map +1 -0
  349. package/dist/checks/core/database.d.ts +8 -0
  350. package/dist/checks/core/database.d.ts.map +1 -0
  351. package/dist/checks/core/database.js +699 -0
  352. package/dist/checks/core/database.js.map +1 -0
  353. package/dist/checks/core/development.d.ts +8 -0
  354. package/dist/checks/core/development.d.ts.map +1 -0
  355. package/dist/checks/core/development.js +417 -0
  356. package/dist/checks/core/development.js.map +1 -0
  357. package/dist/checks/core/hydration-mismatch-check.d.ts +38 -0
  358. package/dist/checks/core/hydration-mismatch-check.d.ts.map +1 -0
  359. package/dist/checks/core/hydration-mismatch-check.js +411 -0
  360. package/dist/checks/core/hydration-mismatch-check.js.map +1 -0
  361. package/dist/checks/core/performance.d.ts +8 -0
  362. package/dist/checks/core/performance.d.ts.map +1 -0
  363. package/dist/checks/core/performance.js +474 -0
  364. package/dist/checks/core/performance.js.map +1 -0
  365. package/dist/checks/core/security.d.ts +8 -0
  366. package/dist/checks/core/security.d.ts.map +1 -0
  367. package/dist/checks/core/security.js +275 -0
  368. package/dist/checks/core/security.js.map +1 -0
  369. package/dist/checks/core/standardized-error-handling.d.ts +43 -0
  370. package/dist/checks/core/standardized-error-handling.d.ts.map +1 -0
  371. package/dist/checks/core/standardized-error-handling.js +384 -0
  372. package/dist/checks/core/standardized-error-handling.js.map +1 -0
  373. package/dist/checks/core/supercatch.d.ts +8 -0
  374. package/dist/checks/core/supercatch.d.ts.map +1 -0
  375. package/dist/checks/core/supercatch.js +750 -0
  376. package/dist/checks/core/supercatch.js.map +1 -0
  377. package/dist/checks/core/suppression-check.d.ts +2 -0
  378. package/dist/checks/core/suppression-check.d.ts.map +1 -0
  379. package/dist/checks/core/suppression-check.js +129 -0
  380. package/dist/checks/core/suppression-check.js.map +1 -0
  381. package/dist/checks/core/ui-quality.d.ts +8 -0
  382. package/dist/checks/core/ui-quality.d.ts.map +1 -0
  383. package/dist/checks/core/ui-quality.js +1736 -0
  384. package/dist/checks/core/ui-quality.js.map +1 -0
  385. package/dist/checks/core/unused-assets-check.d.ts +2 -0
  386. package/dist/checks/core/unused-assets-check.d.ts.map +1 -0
  387. package/dist/checks/core/unused-assets-check.js +112 -0
  388. package/dist/checks/core/unused-assets-check.js.map +1 -0
  389. package/dist/checks/core/use-status-ssr-safety.d.ts +34 -0
  390. package/dist/checks/core/use-status-ssr-safety.d.ts.map +1 -0
  391. package/dist/checks/core/use-status-ssr-safety.js +283 -0
  392. package/dist/checks/core/use-status-ssr-safety.js.map +1 -0
  393. package/dist/checks/email/email-flow-validation.d.ts +23 -0
  394. package/dist/checks/email/email-flow-validation.d.ts.map +1 -0
  395. package/dist/checks/email/email-flow-validation.js +468 -0
  396. package/dist/checks/email/email-flow-validation.js.map +1 -0
  397. package/dist/checks/email/email-template-db-verification.d.ts +20 -0
  398. package/dist/checks/email/email-template-db-verification.d.ts.map +1 -0
  399. package/dist/checks/email/email-template-db-verification.js +46 -0
  400. package/dist/checks/email/email-template-db-verification.js.map +1 -0
  401. package/dist/checks/email/email-template-validation.d.ts +24 -0
  402. package/dist/checks/email/email-template-validation.d.ts.map +1 -0
  403. package/dist/checks/email/email-template-validation.js +688 -0
  404. package/dist/checks/email/email-template-validation.js.map +1 -0
  405. package/dist/checks/jsx/comment-placement.d.ts +45 -0
  406. package/dist/checks/jsx/comment-placement.d.ts.map +1 -0
  407. package/dist/checks/jsx/comment-placement.js +316 -0
  408. package/dist/checks/jsx/comment-placement.js.map +1 -0
  409. package/dist/checks/specialized/admin-layout-check.d.ts +19 -0
  410. package/dist/checks/specialized/admin-layout-check.d.ts.map +1 -0
  411. package/dist/checks/specialized/admin-layout-check.js +166 -0
  412. package/dist/checks/specialized/admin-layout-check.js.map +1 -0
  413. package/dist/checks/specialized/client-server-separation.d.ts +14 -0
  414. package/dist/checks/specialized/client-server-separation.d.ts.map +1 -0
  415. package/dist/checks/specialized/client-server-separation.js +197 -0
  416. package/dist/checks/specialized/client-server-separation.js.map +1 -0
  417. package/dist/checks/specialized/cost-optimization.d.ts +18 -0
  418. package/dist/checks/specialized/cost-optimization.d.ts.map +1 -0
  419. package/dist/checks/specialized/cost-optimization.js +78 -0
  420. package/dist/checks/specialized/cost-optimization.js.map +1 -0
  421. package/dist/checks/specialized/database-migration-sync.d.ts +21 -0
  422. package/dist/checks/specialized/database-migration-sync.d.ts.map +1 -0
  423. package/dist/checks/specialized/database-migration-sync.js +150 -0
  424. package/dist/checks/specialized/database-migration-sync.js.map +1 -0
  425. package/dist/checks/specialized/database-model-validation.d.ts +15 -0
  426. package/dist/checks/specialized/database-model-validation.d.ts.map +1 -0
  427. package/dist/checks/specialized/database-model-validation.js +35 -0
  428. package/dist/checks/specialized/database-model-validation.js.map +1 -0
  429. package/dist/checks/specialized/database-schema-migrations-diff.d.ts +27 -0
  430. package/dist/checks/specialized/database-schema-migrations-diff.d.ts.map +1 -0
  431. package/dist/checks/specialized/database-schema-migrations-diff.js +177 -0
  432. package/dist/checks/specialized/database-schema-migrations-diff.js.map +1 -0
  433. package/dist/checks/specialized/database-schema-sync.d.ts +23 -0
  434. package/dist/checks/specialized/database-schema-sync.d.ts.map +1 -0
  435. package/dist/checks/specialized/database-schema-sync.js +77 -0
  436. package/dist/checks/specialized/database-schema-sync.js.map +1 -0
  437. package/dist/checks/specialized/decimal-serialization.d.ts +24 -0
  438. package/dist/checks/specialized/decimal-serialization.d.ts.map +1 -0
  439. package/dist/checks/specialized/decimal-serialization.js +400 -0
  440. package/dist/checks/specialized/decimal-serialization.js.map +1 -0
  441. package/dist/checks/specialized/detect-router-issues.d.ts +14 -0
  442. package/dist/checks/specialized/detect-router-issues.d.ts.map +1 -0
  443. package/dist/checks/specialized/detect-router-issues.js +96 -0
  444. package/dist/checks/specialized/detect-router-issues.js.map +1 -0
  445. package/dist/checks/specialized/enum-validation.d.ts +15 -0
  446. package/dist/checks/specialized/enum-validation.d.ts.map +1 -0
  447. package/dist/checks/specialized/enum-validation.js +35 -0
  448. package/dist/checks/specialized/enum-validation.js.map +1 -0
  449. package/dist/checks/specialized/hash-collision.d.ts +18 -0
  450. package/dist/checks/specialized/hash-collision.d.ts.map +1 -0
  451. package/dist/checks/specialized/hash-collision.js +78 -0
  452. package/dist/checks/specialized/hash-collision.js.map +1 -0
  453. package/dist/checks/specialized/id-generation-enforcement.d.ts +16 -0
  454. package/dist/checks/specialized/id-generation-enforcement.d.ts.map +1 -0
  455. package/dist/checks/specialized/id-generation-enforcement.js +307 -0
  456. package/dist/checks/specialized/id-generation-enforcement.js.map +1 -0
  457. package/dist/checks/specialized/image-data-integrity.d.ts +15 -0
  458. package/dist/checks/specialized/image-data-integrity.d.ts.map +1 -0
  459. package/dist/checks/specialized/image-data-integrity.js +79 -0
  460. package/dist/checks/specialized/image-data-integrity.js.map +1 -0
  461. package/dist/checks/specialized/image-health.d.ts +14 -0
  462. package/dist/checks/specialized/image-health.d.ts.map +1 -0
  463. package/dist/checks/specialized/image-health.js +122 -0
  464. package/dist/checks/specialized/image-health.js.map +1 -0
  465. package/dist/checks/specialized/image-metadata-validation.d.ts +14 -0
  466. package/dist/checks/specialized/image-metadata-validation.d.ts.map +1 -0
  467. package/dist/checks/specialized/image-metadata-validation.js +95 -0
  468. package/dist/checks/specialized/image-metadata-validation.js.map +1 -0
  469. package/dist/checks/specialized/image-optimization.d.ts +16 -0
  470. package/dist/checks/specialized/image-optimization.d.ts.map +1 -0
  471. package/dist/checks/specialized/image-optimization.js +86 -0
  472. package/dist/checks/specialized/image-optimization.js.map +1 -0
  473. package/dist/checks/specialized/invalid-module-imports.d.ts +24 -0
  474. package/dist/checks/specialized/invalid-module-imports.d.ts.map +1 -0
  475. package/dist/checks/specialized/invalid-module-imports.js +209 -0
  476. package/dist/checks/specialized/invalid-module-imports.js.map +1 -0
  477. package/dist/checks/specialized/lint-validation.d.ts +26 -0
  478. package/dist/checks/specialized/lint-validation.d.ts.map +1 -0
  479. package/dist/checks/specialized/lint-validation.js +193 -0
  480. package/dist/checks/specialized/lint-validation.js.map +1 -0
  481. package/dist/checks/specialized/listing-workflow.d.ts +19 -0
  482. package/dist/checks/specialized/listing-workflow.d.ts.map +1 -0
  483. package/dist/checks/specialized/listing-workflow.js +89 -0
  484. package/dist/checks/specialized/listing-workflow.js.map +1 -0
  485. package/dist/checks/specialized/mui-imports-validation.d.ts +18 -0
  486. package/dist/checks/specialized/mui-imports-validation.d.ts.map +1 -0
  487. package/dist/checks/specialized/mui-imports-validation.js +134 -0
  488. package/dist/checks/specialized/mui-imports-validation.js.map +1 -0
  489. package/dist/checks/specialized/nextauth-v5-compliance.d.ts +16 -0
  490. package/dist/checks/specialized/nextauth-v5-compliance.d.ts.map +1 -0
  491. package/dist/checks/specialized/nextauth-v5-compliance.js +164 -0
  492. package/dist/checks/specialized/nextauth-v5-compliance.js.map +1 -0
  493. package/dist/checks/specialized/nextjs-params-check.d.ts +14 -0
  494. package/dist/checks/specialized/nextjs-params-check.d.ts.map +1 -0
  495. package/dist/checks/specialized/nextjs-params-check.js +140 -0
  496. package/dist/checks/specialized/nextjs-params-check.js.map +1 -0
  497. package/dist/checks/specialized/no-legacy-catalog-aliases-validation.d.ts +16 -0
  498. package/dist/checks/specialized/no-legacy-catalog-aliases-validation.d.ts.map +1 -0
  499. package/dist/checks/specialized/no-legacy-catalog-aliases-validation.js +36 -0
  500. package/dist/checks/specialized/no-legacy-catalog-aliases-validation.js.map +1 -0
  501. package/dist/checks/specialized/no-wata-cardgraded-validation.d.ts +22 -0
  502. package/dist/checks/specialized/no-wata-cardgraded-validation.d.ts.map +1 -0
  503. package/dist/checks/specialized/no-wata-cardgraded-validation.js +97 -0
  504. package/dist/checks/specialized/no-wata-cardgraded-validation.js.map +1 -0
  505. package/dist/checks/specialized/parameter-consistency-check.d.ts +20 -0
  506. package/dist/checks/specialized/parameter-consistency-check.d.ts.map +1 -0
  507. package/dist/checks/specialized/parameter-consistency-check.js +115 -0
  508. package/dist/checks/specialized/parameter-consistency-check.js.map +1 -0
  509. package/dist/checks/specialized/prisma-field-names-validation.d.ts +15 -0
  510. package/dist/checks/specialized/prisma-field-names-validation.d.ts.map +1 -0
  511. package/dist/checks/specialized/prisma-field-names-validation.js +35 -0
  512. package/dist/checks/specialized/prisma-field-names-validation.js.map +1 -0
  513. package/dist/checks/specialized/prisma-null-syntax.d.ts +34 -0
  514. package/dist/checks/specialized/prisma-null-syntax.d.ts.map +1 -0
  515. package/dist/checks/specialized/prisma-null-syntax.js +330 -0
  516. package/dist/checks/specialized/prisma-null-syntax.js.map +1 -0
  517. package/dist/checks/specialized/prisma-query-validation.d.ts +15 -0
  518. package/dist/checks/specialized/prisma-query-validation.d.ts.map +1 -0
  519. package/dist/checks/specialized/prisma-query-validation.js +35 -0
  520. package/dist/checks/specialized/prisma-query-validation.js.map +1 -0
  521. package/dist/checks/specialized/product-type-validation.d.ts +17 -0
  522. package/dist/checks/specialized/product-type-validation.d.ts.map +1 -0
  523. package/dist/checks/specialized/product-type-validation.js +129 -0
  524. package/dist/checks/specialized/product-type-validation.js.map +1 -0
  525. package/dist/checks/specialized/responsive-image-validation.d.ts +14 -0
  526. package/dist/checks/specialized/responsive-image-validation.d.ts.map +1 -0
  527. package/dist/checks/specialized/responsive-image-validation.js +101 -0
  528. package/dist/checks/specialized/responsive-image-validation.js.map +1 -0
  529. package/dist/checks/specialized/root-cleanliness.d.ts +21 -0
  530. package/dist/checks/specialized/root-cleanliness.d.ts.map +1 -0
  531. package/dist/checks/specialized/root-cleanliness.js +251 -0
  532. package/dist/checks/specialized/root-cleanliness.js.map +1 -0
  533. package/dist/checks/specialized/rotation-detection-validation.d.ts +16 -0
  534. package/dist/checks/specialized/rotation-detection-validation.d.ts.map +1 -0
  535. package/dist/checks/specialized/rotation-detection-validation.js +113 -0
  536. package/dist/checks/specialized/rotation-detection-validation.js.map +1 -0
  537. package/dist/checks/specialized/script-organization.d.ts +17 -0
  538. package/dist/checks/specialized/script-organization.d.ts.map +1 -0
  539. package/dist/checks/specialized/script-organization.js +487 -0
  540. package/dist/checks/specialized/script-organization.js.map +1 -0
  541. package/dist/checks/specialized/shared-components-migration.d.ts +137 -0
  542. package/dist/checks/specialized/shared-components-migration.d.ts.map +1 -0
  543. package/dist/checks/specialized/shared-components-migration.js +1288 -0
  544. package/dist/checks/specialized/shared-components-migration.js.map +1 -0
  545. package/dist/checks/specialized/store-specialties-normalization.d.ts +10 -0
  546. package/dist/checks/specialized/store-specialties-normalization.d.ts.map +1 -0
  547. package/dist/checks/specialized/store-specialties-normalization.js +126 -0
  548. package/dist/checks/specialized/store-specialties-normalization.js.map +1 -0
  549. package/dist/checks/specialized/two-stage-trim-validation.d.ts +16 -0
  550. package/dist/checks/specialized/two-stage-trim-validation.d.ts.map +1 -0
  551. package/dist/checks/specialized/two-stage-trim-validation.js +115 -0
  552. package/dist/checks/specialized/two-stage-trim-validation.js.map +1 -0
  553. package/dist/checks/specialized/underscore-variable-audit.d.ts +26 -0
  554. package/dist/checks/specialized/underscore-variable-audit.d.ts.map +1 -0
  555. package/dist/checks/specialized/underscore-variable-audit.js +219 -0
  556. package/dist/checks/specialized/underscore-variable-audit.js.map +1 -0
  557. package/dist/checks/specialized/unified-badge-consistency.d.ts +16 -0
  558. package/dist/checks/specialized/unified-badge-consistency.d.ts.map +1 -0
  559. package/dist/checks/specialized/unified-badge-consistency.js +284 -0
  560. package/dist/checks/specialized/unified-badge-consistency.js.map +1 -0
  561. package/dist/checks/specialized/validate-integration-enums.d.ts +15 -0
  562. package/dist/checks/specialized/validate-integration-enums.d.ts.map +1 -0
  563. package/dist/checks/specialized/validate-integration-enums.js +131 -0
  564. package/dist/checks/specialized/validate-integration-enums.js.map +1 -0
  565. package/dist/checks/testing/action-regression.d.ts +23 -0
  566. package/dist/checks/testing/action-regression.d.ts.map +1 -0
  567. package/dist/checks/testing/action-regression.js +192 -0
  568. package/dist/checks/testing/action-regression.js.map +1 -0
  569. package/dist/checks/testing/critical-api-coverage.d.ts +21 -0
  570. package/dist/checks/testing/critical-api-coverage.d.ts.map +1 -0
  571. package/dist/checks/testing/critical-api-coverage.js +158 -0
  572. package/dist/checks/testing/critical-api-coverage.js.map +1 -0
  573. package/dist/checks/testing/data-entry-regression-required.d.ts +24 -0
  574. package/dist/checks/testing/data-entry-regression-required.d.ts.map +1 -0
  575. package/dist/checks/testing/data-entry-regression-required.js +378 -0
  576. package/dist/checks/testing/data-entry-regression-required.js.map +1 -0
  577. package/dist/checks/testing/e2e-best-practices.d.ts +24 -0
  578. package/dist/checks/testing/e2e-best-practices.d.ts.map +1 -0
  579. package/dist/checks/testing/e2e-best-practices.js +791 -0
  580. package/dist/checks/testing/e2e-best-practices.js.map +1 -0
  581. package/dist/checks/testing/e2e-flake-patterns.d.ts +26 -0
  582. package/dist/checks/testing/e2e-flake-patterns.d.ts.map +1 -0
  583. package/dist/checks/testing/e2e-flake-patterns.js +305 -0
  584. package/dist/checks/testing/e2e-flake-patterns.js.map +1 -0
  585. package/dist/checks/testing/e2e-redundant-visibility-checks.d.ts +25 -0
  586. package/dist/checks/testing/e2e-redundant-visibility-checks.d.ts.map +1 -0
  587. package/dist/checks/testing/e2e-redundant-visibility-checks.js +613 -0
  588. package/dist/checks/testing/e2e-redundant-visibility-checks.js.map +1 -0
  589. package/dist/checks/testing/e2e-slow-tests.d.ts +9 -0
  590. package/dist/checks/testing/e2e-slow-tests.d.ts.map +1 -0
  591. package/dist/checks/testing/e2e-slow-tests.js +142 -0
  592. package/dist/checks/testing/e2e-slow-tests.js.map +1 -0
  593. package/dist/checks/testing/e2e-timeouts.d.ts +9 -0
  594. package/dist/checks/testing/e2e-timeouts.d.ts.map +1 -0
  595. package/dist/checks/testing/e2e-timeouts.js +82 -0
  596. package/dist/checks/testing/e2e-timeouts.js.map +1 -0
  597. package/dist/checks/testing/integration-e2e-depth.d.ts +20 -0
  598. package/dist/checks/testing/integration-e2e-depth.d.ts.map +1 -0
  599. package/dist/checks/testing/integration-e2e-depth.js +575 -0
  600. package/dist/checks/testing/integration-e2e-depth.js.map +1 -0
  601. package/dist/checks/testing/playwright-feature-coverage-gaps.d.ts +31 -0
  602. package/dist/checks/testing/playwright-feature-coverage-gaps.d.ts.map +1 -0
  603. package/dist/checks/testing/playwright-feature-coverage-gaps.js +1582 -0
  604. package/dist/checks/testing/playwright-feature-coverage-gaps.js.map +1 -0
  605. package/dist/checks/testing/playwright-mock-inventory.d.ts +24 -0
  606. package/dist/checks/testing/playwright-mock-inventory.d.ts.map +1 -0
  607. package/dist/checks/testing/playwright-mock-inventory.js +380 -0
  608. package/dist/checks/testing/playwright-mock-inventory.js.map +1 -0
  609. package/dist/checks/testing/test-coverage-threshold.d.ts +25 -0
  610. package/dist/checks/testing/test-coverage-threshold.d.ts.map +1 -0
  611. package/dist/checks/testing/test-coverage-threshold.js +166 -0
  612. package/dist/checks/testing/test-coverage-threshold.js.map +1 -0
  613. package/dist/checks/testing/test-flakiness-score.d.ts +27 -0
  614. package/dist/checks/testing/test-flakiness-score.d.ts.map +1 -0
  615. package/dist/checks/testing/test-flakiness-score.js +358 -0
  616. package/dist/checks/testing/test-flakiness-score.js.map +1 -0
  617. package/dist/checks/testing/test-patterns.d.ts +16 -0
  618. package/dist/checks/testing/test-patterns.d.ts.map +1 -0
  619. package/dist/checks/testing/test-patterns.js +156 -0
  620. package/dist/checks/testing/test-patterns.js.map +1 -0
  621. package/dist/checks/workflows/a-plus-rating-validation.d.ts +42 -0
  622. package/dist/checks/workflows/a-plus-rating-validation.d.ts.map +1 -0
  623. package/dist/checks/workflows/a-plus-rating-validation.js +527 -0
  624. package/dist/checks/workflows/a-plus-rating-validation.js.map +1 -0
  625. package/dist/checks/workflows/affected.d.ts +14 -0
  626. package/dist/checks/workflows/affected.d.ts.map +1 -0
  627. package/dist/checks/workflows/affected.js +126 -0
  628. package/dist/checks/workflows/affected.js.map +1 -0
  629. package/dist/checks/workflows/ai.d.ts +6 -0
  630. package/dist/checks/workflows/ai.d.ts.map +1 -0
  631. package/dist/checks/workflows/ai.js +42 -0
  632. package/dist/checks/workflows/ai.js.map +1 -0
  633. package/dist/checks/workflows/all.d.ts +31 -0
  634. package/dist/checks/workflows/all.d.ts.map +1 -0
  635. package/dist/checks/workflows/all.js +2688 -0
  636. package/dist/checks/workflows/all.js.map +1 -0
  637. package/dist/checks/workflows/commit.d.ts +19 -0
  638. package/dist/checks/workflows/commit.d.ts.map +1 -0
  639. package/dist/checks/workflows/commit.js +207 -0
  640. package/dist/checks/workflows/commit.js.map +1 -0
  641. package/dist/checks/workflows/critical.d.ts +9 -0
  642. package/dist/checks/workflows/critical.d.ts.map +1 -0
  643. package/dist/checks/workflows/critical.js +213 -0
  644. package/dist/checks/workflows/critical.js.map +1 -0
  645. package/dist/checks/workflows/database-id-validation.d.ts +9 -0
  646. package/dist/checks/workflows/database-id-validation.d.ts.map +1 -0
  647. package/dist/checks/workflows/database-id-validation.js +13 -0
  648. package/dist/checks/workflows/database-id-validation.js.map +1 -0
  649. package/dist/checks/workflows/deploy.d.ts +20 -0
  650. package/dist/checks/workflows/deploy.d.ts.map +1 -0
  651. package/dist/checks/workflows/deploy.js +107 -0
  652. package/dist/checks/workflows/deploy.js.map +1 -0
  653. package/dist/checks/workflows/deployment-readiness.d.ts +12 -0
  654. package/dist/checks/workflows/deployment-readiness.d.ts.map +1 -0
  655. package/dist/checks/workflows/deployment-readiness.js +403 -0
  656. package/dist/checks/workflows/deployment-readiness.js.map +1 -0
  657. package/dist/checks/workflows/dev.d.ts +19 -0
  658. package/dist/checks/workflows/dev.d.ts.map +1 -0
  659. package/dist/checks/workflows/dev.js +88 -0
  660. package/dist/checks/workflows/dev.js.map +1 -0
  661. package/dist/checks/workflows/development.d.ts +9 -0
  662. package/dist/checks/workflows/development.d.ts.map +1 -0
  663. package/dist/checks/workflows/development.js +65 -0
  664. package/dist/checks/workflows/development.js.map +1 -0
  665. package/dist/checks/workflows/enterprise.d.ts +10 -0
  666. package/dist/checks/workflows/enterprise.d.ts.map +1 -0
  667. package/dist/checks/workflows/enterprise.js +359 -0
  668. package/dist/checks/workflows/enterprise.js.map +1 -0
  669. package/dist/checks/workflows/images.d.ts +6 -0
  670. package/dist/checks/workflows/images.d.ts.map +1 -0
  671. package/dist/checks/workflows/images.js +58 -0
  672. package/dist/checks/workflows/images.js.map +1 -0
  673. package/dist/checks/workflows/naming.d.ts +19 -0
  674. package/dist/checks/workflows/naming.d.ts.map +1 -0
  675. package/dist/checks/workflows/naming.js +42 -0
  676. package/dist/checks/workflows/naming.js.map +1 -0
  677. package/dist/checks/workflows/performance.d.ts +8 -0
  678. package/dist/checks/workflows/performance.d.ts.map +1 -0
  679. package/dist/checks/workflows/performance.js +77 -0
  680. package/dist/checks/workflows/performance.js.map +1 -0
  681. package/dist/checks/workflows/pre-deploy.d.ts +6 -0
  682. package/dist/checks/workflows/pre-deploy.d.ts.map +1 -0
  683. package/dist/checks/workflows/pre-deploy.js +41 -0
  684. package/dist/checks/workflows/pre-deploy.js.map +1 -0
  685. package/dist/checks/workflows/security.d.ts +8 -0
  686. package/dist/checks/workflows/security.d.ts.map +1 -0
  687. package/dist/checks/workflows/security.js +71 -0
  688. package/dist/checks/workflows/security.js.map +1 -0
  689. package/dist/checks/workflows/supercatch.d.ts +8 -0
  690. package/dist/checks/workflows/supercatch.d.ts.map +1 -0
  691. package/dist/checks/workflows/supercatch.js +127 -0
  692. package/dist/checks/workflows/supercatch.js.map +1 -0
  693. package/dist/checks/workflows/ui-quality.d.ts +9 -0
  694. package/dist/checks/workflows/ui-quality.d.ts.map +1 -0
  695. package/dist/checks/workflows/ui-quality.js +264 -0
  696. package/dist/checks/workflows/ui-quality.js.map +1 -0
  697. package/dist/checks/workflows/ui-uniformity.d.ts +18 -0
  698. package/dist/checks/workflows/ui-uniformity.d.ts.map +1 -0
  699. package/dist/checks/workflows/ui-uniformity.js +265 -0
  700. package/dist/checks/workflows/ui-uniformity.js.map +1 -0
  701. package/dist/checks/workflows/vercel.d.ts +16 -0
  702. package/dist/checks/workflows/vercel.d.ts.map +1 -0
  703. package/dist/checks/workflows/vercel.js +173 -0
  704. package/dist/checks/workflows/vercel.js.map +1 -0
  705. package/dist/utils/validation-helpers.d.ts +43 -0
  706. package/dist/utils/validation-helpers.d.ts.map +1 -0
  707. package/dist/utils/validation-helpers.js +370 -0
  708. package/dist/utils/validation-helpers.js.map +1 -0
  709. package/package.json +1 -1
@@ -0,0 +1,1582 @@
1
+ #!/usr/bin/env tsx
2
+ "use strict";
3
+ /**
4
+ * Playwright Feature Coverage Gap Detection Preflight (Proactive)
5
+ *
6
+ * PROACTIVELY discovers missing E2E test coverage by:
7
+ * 1. Scanning source code for features, API endpoints, UI components
8
+ * 2. Analyzing what Playwright tests actually exercise
9
+ * 3. Reporting gaps between implementation and test coverage
10
+ * 4. Tracking coverage trends over time
11
+ * 5. Generating test stubs for uncovered features
12
+ *
13
+ * This is NOT a checklist - it discovers gaps automatically.
14
+ *
15
+ * @blocking true
16
+ * @category testing
17
+ *
18
+ * Usage:
19
+ * pnpm preflight:playwright-feature-gaps
20
+ * pnpm preflight:playwright-feature-gaps --verbose
21
+ * pnpm preflight:playwright-feature-gaps --report
22
+ * pnpm preflight:playwright-feature-gaps --generate-stubs
23
+ * pnpm preflight:playwright-feature-gaps --trend
24
+ */
25
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ var desc = Object.getOwnPropertyDescriptor(m, k);
28
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
29
+ desc = { enumerable: true, get: function() { return m[k]; } };
30
+ }
31
+ Object.defineProperty(o, k2, desc);
32
+ }) : (function(o, m, k, k2) {
33
+ if (k2 === undefined) k2 = k;
34
+ o[k2] = m[k];
35
+ }));
36
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
37
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
38
+ }) : function(o, v) {
39
+ o["default"] = v;
40
+ });
41
+ var __importStar = (this && this.__importStar) || (function () {
42
+ var ownKeys = function(o) {
43
+ ownKeys = Object.getOwnPropertyNames || function (o) {
44
+ var ar = [];
45
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
46
+ return ar;
47
+ };
48
+ return ownKeys(o);
49
+ };
50
+ return function (mod) {
51
+ if (mod && mod.__esModule) return mod;
52
+ var result = {};
53
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
54
+ __setModuleDefault(result, mod);
55
+ return result;
56
+ };
57
+ })();
58
+ Object.defineProperty(exports, "__esModule", { value: true });
59
+ exports.tags = exports.description = exports.blocking = exports.category = exports.name = exports.id = void 0;
60
+ exports.run = run;
61
+ const child_process_1 = require("child_process");
62
+ const fs = __importStar(require("fs"));
63
+ const path = __importStar(require("path"));
64
+ const console_chars_1 = require("../../utils/console-chars");
65
+ const universal_progress_reporter_1 = require("../system/universal-progress-reporter");
66
+ // Check metadata
67
+ exports.id = "testing/playwright-feature-coverage-gaps";
68
+ exports.name = "Playwright Feature Coverage Gaps";
69
+ exports.category = "testing";
70
+ exports.blocking = true;
71
+ exports.description = "Playwright Feature Coverage Gap Detection Preflight (Proactive)";
72
+ exports.tags = ["testing"];
73
+ const isVerbose = process.argv.includes("--verbose");
74
+ const generateReport = process.argv.includes("--fix") || process.argv.includes("--report");
75
+ const generateStubs = process.argv.includes("--generate-stubs");
76
+ const showTrend = process.argv.includes("--trend");
77
+ const warnOnly = process.argv.includes("--warn");
78
+ const TREND_FILE = ".playwright-coverage-trend.json";
79
+ // HELPER: Get recently modified files (last 30 days)
80
+ function getRecentlyModifiedFiles() {
81
+ const recentFiles = new Set();
82
+ try {
83
+ const thirtyDaysAgo = new Date();
84
+ thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
85
+ const since = thirtyDaysAgo.toISOString().split("T")[0];
86
+ const output = (0, child_process_1.execSync)(`git log --since="${since}" --name-only --pretty=format: -- "*.ts" "*.tsx"`, { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
87
+ output
88
+ .split("\n")
89
+ .filter(Boolean)
90
+ .forEach((f) => recentFiles.add(f));
91
+ }
92
+ catch {
93
+ // Git not available or not a git repo
94
+ }
95
+ return recentFiles;
96
+ }
97
+ // TREND TRACKING
98
+ function loadTrendHistory() {
99
+ try {
100
+ if (fs.existsSync(TREND_FILE)) {
101
+ return JSON.parse(fs.readFileSync(TREND_FILE, "utf-8"));
102
+ }
103
+ }
104
+ catch {
105
+ // Ignore parse errors
106
+ }
107
+ return { runs: [] };
108
+ }
109
+ function saveTrendData(totalFeatures, coveredFeatures, byCategory) {
110
+ const history = loadTrendHistory();
111
+ const categoryStats = {};
112
+ for (const [cat, stats] of Object.entries(byCategory)) {
113
+ categoryStats[cat] = {
114
+ ...stats,
115
+ percent: stats.total > 0 ? Math.round((stats.covered / stats.total) * 100) : 100,
116
+ };
117
+ }
118
+ const newEntry = {
119
+ timestamp: new Date().toISOString(),
120
+ totalFeatures,
121
+ coveredFeatures,
122
+ coveragePercent: totalFeatures > 0 ? Math.round((coveredFeatures / totalFeatures) * 100) : 100,
123
+ byCategory: categoryStats,
124
+ };
125
+ history.runs.push(newEntry);
126
+ // Keep last 100 runs
127
+ if (history.runs.length > 100) {
128
+ history.runs = history.runs.slice(-100);
129
+ }
130
+ fs.writeFileSync(TREND_FILE, JSON.stringify(history, null, 2));
131
+ }
132
+ function displayTrend() {
133
+ const history = loadTrendHistory();
134
+ if (history.runs.length === 0) {
135
+ console.log(`\n${console_chars_1.emoji.info} No trend data available yet. Run the preflight a few times to build history.`);
136
+ return;
137
+ }
138
+ console.log(`\n${console_chars_1.emoji.chart} COVERAGE TREND (last ${Math.min(history.runs.length, 10)} runs)`);
139
+ console.log((0, console_chars_1.createDivider)(60, "light"));
140
+ const recentRuns = history.runs.slice(-10);
141
+ for (const run of recentRuns) {
142
+ const date = new Date(run.timestamp).toLocaleDateString();
143
+ const bar = "█".repeat(Math.floor(run.coveragePercent / 5)) +
144
+ "░".repeat(20 - Math.floor(run.coveragePercent / 5));
145
+ console.log(` ${date} ${bar} ${run.coveragePercent}% (${run.coveredFeatures}/${run.totalFeatures})`);
146
+ }
147
+ // Show trend direction
148
+ if (recentRuns.length >= 2) {
149
+ const latest = recentRuns[recentRuns.length - 1];
150
+ const previous = recentRuns[recentRuns.length - 2];
151
+ const diff = latest.coveragePercent - previous.coveragePercent;
152
+ if (diff > 0) {
153
+ console.log(`\n ${console_chars_1.emoji.success} Coverage improved by ${diff}% since last run`);
154
+ }
155
+ else if (diff < 0) {
156
+ console.log(`\n ${console_chars_1.emoji.warning} Coverage decreased by ${Math.abs(diff)}% since last run`);
157
+ }
158
+ else {
159
+ console.log(`\n ${console_chars_1.emoji.info} Coverage unchanged since last run`);
160
+ }
161
+ }
162
+ // Category breakdown for latest run
163
+ const latest = recentRuns[recentRuns.length - 1];
164
+ if (Object.keys(latest.byCategory).length > 0) {
165
+ console.log(`\n ${console_chars_1.emoji.folder} By Category:`);
166
+ for (const [cat, stats] of Object.entries(latest.byCategory)) {
167
+ const catBar = "█".repeat(Math.floor(stats.percent / 10)) +
168
+ "░".repeat(10 - Math.floor(stats.percent / 10));
169
+ console.log(` ${cat.padEnd(15)} ${catBar} ${stats.percent}%`);
170
+ }
171
+ }
172
+ }
173
+ // TEST STUB GENERATION
174
+ function generateTestStub(gap) {
175
+ const { feature } = gap;
176
+ switch (feature.type) {
177
+ case "api-endpoint": {
178
+ const [method, endpoint] = feature.name.split(" ");
179
+ return `import { test, expect } from "@playwright/test";
180
+
181
+ test.describe("${endpoint}", () => {
182
+ test("${method} request returns expected response", async ({ request }) => {
183
+ // TODO: Implement test for ${feature.name}
184
+ // Source: ${feature.sourcePath}
185
+
186
+ const response = await request.${method.toLowerCase()}("${endpoint}", {
187
+ // Add request body/params as needed
188
+ });
189
+
190
+ expect(response.ok()).toBeTruthy();
191
+ // Add more assertions based on expected response
192
+ });
193
+ });
194
+ `;
195
+ }
196
+ case "page-action": {
197
+ return `import { test, expect } from "@playwright/test";
198
+
199
+ test.describe("${feature.name} action", () => {
200
+ test("executes successfully", async ({ page }) => {
201
+ // TODO: Implement test for server action: ${feature.name}
202
+ // Source: ${feature.sourcePath}${feature.line ? `:${feature.line}` : ""}
203
+
204
+ // Navigate to page that uses this action
205
+ await page.goto("/path-to-page");
206
+
207
+ // Trigger the action (e.g., form submission, button click)
208
+ // await page.getByRole("button", { name: "Submit" }).click();
209
+
210
+ // Assert expected outcome
211
+ // await expect(page.getByText("Success")).toBeVisible();
212
+ });
213
+ });
214
+ `;
215
+ }
216
+ case "page":
217
+ case "ui-component": {
218
+ const routePath = feature.name.replace("Page: ", "");
219
+ return `import { test, expect } from "@playwright/test";
220
+
221
+ test.describe("${routePath}", () => {
222
+ test("page loads successfully", async ({ page }) => {
223
+ // TODO: Implement test for ${feature.name}
224
+ // Source: ${feature.sourcePath}
225
+
226
+ await page.goto("${routePath}");
227
+
228
+ // Assert page loaded
229
+ await expect(page).toHaveURL(/${routePath.replace(/\//g, "\\/")}/);
230
+
231
+ // Add more specific assertions
232
+ });
233
+
234
+ test("key interactions work", async ({ page }) => {
235
+ await page.goto("${routePath}");
236
+
237
+ // TODO: Add interaction tests
238
+ });
239
+ });
240
+ `;
241
+ }
242
+ case "middleware": {
243
+ return `import { test, expect } from "@playwright/test";
244
+
245
+ test.describe("Middleware: ${feature.context || feature.name}", () => {
246
+ test("redirects unauthenticated users", async ({ page }) => {
247
+ // TODO: Implement middleware test
248
+ // Source: ${feature.sourcePath}
249
+
250
+ // Test unauthenticated access
251
+ await page.goto("/protected-route");
252
+ await expect(page).toHaveURL(/login/);
253
+ });
254
+
255
+ test("allows authenticated users", async ({ page }) => {
256
+ // TODO: Set up authenticated state
257
+ // await page.goto("/protected-route");
258
+ // await expect(page).toHaveURL("/protected-route");
259
+ });
260
+ });
261
+ `;
262
+ }
263
+ case "error-boundary": {
264
+ const isError = feature.context === "error";
265
+ return `import { test, expect } from "@playwright/test";
266
+
267
+ test.describe("${feature.name}", () => {
268
+ test("${isError ? "error" : "not-found"} boundary renders correctly", async ({ page }) => {
269
+ // TODO: Implement error boundary test
270
+ // Source: ${feature.sourcePath}
271
+
272
+ ${isError
273
+ ? `// Trigger an error condition
274
+ await page.route("**/api/**", (route) => route.abort());
275
+ await page.goto("/path-that-errors");
276
+
277
+ // Assert error UI is shown
278
+ await expect(page.getByText(/error|something went wrong/i)).toBeVisible();`
279
+ : `// Navigate to non-existent route
280
+ await page.goto("/non-existent-page-12345");
281
+
282
+ // Assert 404 UI is shown
283
+ await expect(page.getByText(/not found|404/i)).toBeVisible();`}
284
+ });
285
+ });
286
+ `;
287
+ }
288
+ case "file-upload": {
289
+ return `import { test, expect } from "@playwright/test";
290
+ import path from "path";
291
+ import { createUniversalProgressReporter } from "../system/universal-progress-reporter";
292
+
293
+ test.describe("File upload: ${path.basename(feature.sourcePath)}", () => {
294
+ test("file upload works correctly", async ({ page }) => {
295
+ // TODO: Implement file upload test
296
+ // Source: ${feature.sourcePath}
297
+
298
+ await page.goto("/path-with-upload");
299
+
300
+ // Upload a file
301
+ const fileInput = page.locator('input[type="file"]');
302
+ await fileInput.setInputFiles(path.join(__dirname, "fixtures/test-file.png"));
303
+
304
+ // Assert upload success
305
+ // await expect(page.getByText("Upload complete")).toBeVisible();
306
+ });
307
+ });
308
+ `;
309
+ }
310
+ case "modal-trigger": {
311
+ return `import { test, expect } from "@playwright/test";
312
+
313
+ test.describe("Modal: ${path.basename(feature.sourcePath)}", () => {
314
+ test("modal opens and closes correctly", async ({ page }) => {
315
+ // TODO: Implement modal test
316
+ // Source: ${feature.sourcePath}
317
+
318
+ await page.goto("/path-with-modal");
319
+
320
+ // Open modal
321
+ await page.getByRole("button", { name: /open/i }).click();
322
+ await expect(page.getByRole("dialog")).toBeVisible();
323
+
324
+ // Close modal
325
+ await page.getByRole("button", { name: /close|cancel/i }).click();
326
+ await expect(page.getByRole("dialog")).not.toBeVisible();
327
+ });
328
+ });
329
+ `;
330
+ }
331
+ default:
332
+ return `import { test, expect } from "@playwright/test";
333
+
334
+ test.describe("${feature.name}", () => {
335
+ test("TODO: implement test", async ({ page }) => {
336
+ // TODO: Implement test for ${feature.type}: ${feature.name}
337
+ // Source: ${feature.sourcePath}
338
+
339
+ // Add test implementation
340
+ });
341
+ });
342
+ `;
343
+ }
344
+ }
345
+ function writeTestStubs(gaps) {
346
+ const stubsDir = "tests/e2e/_generated-stubs";
347
+ if (!fs.existsSync(stubsDir)) {
348
+ fs.mkdirSync(stubsDir, { recursive: true });
349
+ }
350
+ let written = 0;
351
+ for (const gap of gaps) {
352
+ if (!gap.suggestedTestFile)
353
+ continue;
354
+ const stubPath = gap.suggestedTestFile.replace("tests/e2e/", `${stubsDir}/`);
355
+ const stubDir = path.dirname(stubPath);
356
+ if (!fs.existsSync(stubDir)) {
357
+ fs.mkdirSync(stubDir, { recursive: true });
358
+ }
359
+ // Don't overwrite existing stubs
360
+ if (fs.existsSync(stubPath))
361
+ continue;
362
+ const stub = generateTestStub(gap);
363
+ fs.writeFileSync(stubPath, stub);
364
+ written++;
365
+ }
366
+ return written;
367
+ }
368
+ // PHASE 1: DISCOVER FEATURES FROM SOURCE CODE
369
+ async function discoverApiEndpoints(recentFiles) {
370
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
371
+ const features = [];
372
+ const apiFiles = await glob("app/api/**/route.ts", { cwd: process.cwd() });
373
+ for (const file of apiFiles) {
374
+ const content = fs.readFileSync(file, "utf-8");
375
+ const routePath = "/" + path.dirname(file).replace(/\\/g, "/").replace("app/", "");
376
+ const hasDynamicSegment = routePath.includes("[");
377
+ const recentlyModified = recentFiles.has(file);
378
+ const methods = ["GET", "POST", "PUT", "PATCH", "DELETE"];
379
+ for (const method of methods) {
380
+ const methodRegex = new RegExp(`export\\s+(async\\s+)?function\\s+${method}\\b`, "i");
381
+ if (methodRegex.test(content)) {
382
+ const isCritical = routePath.includes("/store/") ||
383
+ routePath.includes("/admin/") ||
384
+ routePath.includes("/auth/") ||
385
+ routePath.includes("/checkout/") ||
386
+ routePath.includes("/orders/") ||
387
+ routePath.includes("/payments/") ||
388
+ method === "DELETE" ||
389
+ method === "POST";
390
+ features.push({
391
+ name: `${method} ${routePath}`,
392
+ type: "api-endpoint",
393
+ sourcePath: file,
394
+ context: method,
395
+ priority: isCritical ? "critical" : hasDynamicSegment ? "high" : "medium",
396
+ recentlyModified,
397
+ });
398
+ }
399
+ }
400
+ }
401
+ return features;
402
+ }
403
+ async function discoverPageActions(recentFiles) {
404
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
405
+ const features = [];
406
+ const actionFiles = await glob("app/**/actions.ts", { cwd: process.cwd() });
407
+ actionFiles.push(...(await glob("app/**/actions/*.ts", { cwd: process.cwd() })));
408
+ actionFiles.push(...(await glob("lib/actions/**/*.ts", { cwd: process.cwd() })));
409
+ for (const file of actionFiles) {
410
+ const content = fs.readFileSync(file, "utf-8");
411
+ const recentlyModified = recentFiles.has(file);
412
+ const actionRegex = /export\s+async\s+function\s+(\w+)/g;
413
+ let match;
414
+ while ((match = actionRegex.exec(content)) !== null) {
415
+ const lineNum = content.substring(0, match.index).split("\n").length;
416
+ const actionName = match[1].toLowerCase();
417
+ const isCritical = actionName.includes("delete") ||
418
+ actionName.includes("create") ||
419
+ actionName.includes("update") ||
420
+ actionName.includes("submit") ||
421
+ actionName.includes("approve") ||
422
+ actionName.includes("reject") ||
423
+ actionName.includes("payment") ||
424
+ actionName.includes("order");
425
+ features.push({
426
+ name: match[1],
427
+ type: "page-action",
428
+ sourcePath: file,
429
+ line: lineNum,
430
+ priority: isCritical ? "critical" : "medium",
431
+ recentlyModified,
432
+ });
433
+ }
434
+ }
435
+ return features;
436
+ }
437
+ async function discoverFormFields(recentFiles) {
438
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
439
+ const features = [];
440
+ const componentFiles = await glob("{app,components}/**/*.tsx", { cwd: process.cwd() });
441
+ const formPatterns = [
442
+ { regex: /<TextField[^>]*name=["']([^"']+)["']/g, type: "text-field" },
443
+ { regex: /<Select[^>]*name=["']([^"']+)["']/g, type: "select" },
444
+ { regex: /<input[^>]*name=["']([^"']+)["']/g, type: "input" },
445
+ { regex: /register\(["']([^"']+)["']\)/g, type: "react-hook-form" },
446
+ { regex: /<FormField[^>]*name=["']([^"']+)["']/g, type: "form-field" },
447
+ ];
448
+ const criticalPaths = [
449
+ "app/store/",
450
+ "app/admin/",
451
+ "app/account/",
452
+ "app/(auth)/",
453
+ "components/forms/",
454
+ "components/seller/",
455
+ ];
456
+ for (const file of componentFiles) {
457
+ const normalizedPath = file.replace(/\\/g, "/");
458
+ const isCritical = criticalPaths.some((p) => normalizedPath.includes(p));
459
+ if (!isCritical)
460
+ continue;
461
+ const content = fs.readFileSync(file, "utf-8");
462
+ const recentlyModified = recentFiles.has(file);
463
+ for (const pattern of formPatterns) {
464
+ let match;
465
+ while ((match = pattern.regex.exec(content)) !== null) {
466
+ features.push({
467
+ name: match[1],
468
+ type: "form-field",
469
+ sourcePath: file,
470
+ context: pattern.type,
471
+ recentlyModified,
472
+ });
473
+ }
474
+ }
475
+ }
476
+ return features;
477
+ }
478
+ async function discoverCriticalButtons(recentFiles) {
479
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
480
+ const features = [];
481
+ const componentFiles = await glob("{app,components}/**/*.tsx", { cwd: process.cwd() });
482
+ const criticalPaths = ["app/store/", "app/admin/", "app/account/"];
483
+ for (const file of componentFiles) {
484
+ const normalizedPath = file.replace(/\\/g, "/");
485
+ const isCritical = criticalPaths.some((p) => normalizedPath.includes(p));
486
+ if (!isCritical)
487
+ continue;
488
+ const content = fs.readFileSync(file, "utf-8");
489
+ const recentlyModified = recentFiles.has(file);
490
+ const deleteActions = content.match(/onClick=\{[^}]*(?:delete|remove|handleDelete)/gi) || [];
491
+ for (const _action of deleteActions) {
492
+ features.push({
493
+ name: `Delete action in ${path.basename(file)}`,
494
+ type: "ui-component",
495
+ sourcePath: file,
496
+ context: "destructive-action",
497
+ priority: "critical",
498
+ recentlyModified,
499
+ });
500
+ }
501
+ const submitButtons = content.match(/<Button[^>]*type=["']submit["'][^>]*>/gi) || [];
502
+ for (const _btn of submitButtons) {
503
+ features.push({
504
+ name: `Form submit in ${path.basename(file)}`,
505
+ type: "ui-component",
506
+ sourcePath: file,
507
+ context: "form-submit",
508
+ priority: "high",
509
+ recentlyModified,
510
+ });
511
+ }
512
+ }
513
+ const seen = new Set();
514
+ return features.filter((f) => {
515
+ const key = `${f.sourcePath}:${f.context}`;
516
+ if (seen.has(key))
517
+ return false;
518
+ seen.add(key);
519
+ return true;
520
+ });
521
+ }
522
+ // EXTENDED DISCOVERY: Middleware, Error Boundaries, Loading States, etc.
523
+ async function discoverMiddleware(recentFiles) {
524
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
525
+ const features = [];
526
+ const middlewareFiles = await glob("middleware.ts", { cwd: process.cwd() });
527
+ middlewareFiles.push(...(await glob("app/**/middleware.ts", { cwd: process.cwd() })));
528
+ for (const file of middlewareFiles) {
529
+ const content = fs.readFileSync(file, "utf-8");
530
+ const recentlyModified = recentFiles.has(file);
531
+ const matcherRegex = /matcher:\s*\[([^\]]+)\]/g;
532
+ let match;
533
+ while ((match = matcherRegex.exec(content)) !== null) {
534
+ const patterns = match[1].split(",").map((p) => p.trim().replace(/["']/g, ""));
535
+ for (const pattern of patterns) {
536
+ features.push({
537
+ name: `Middleware: ${pattern}`,
538
+ type: "middleware",
539
+ sourcePath: file,
540
+ context: pattern,
541
+ priority: "high",
542
+ recentlyModified,
543
+ });
544
+ }
545
+ }
546
+ if (content.includes("NextResponse.redirect") || content.includes("NextResponse.rewrite")) {
547
+ features.push({
548
+ name: `Middleware redirects in ${path.basename(file)}`,
549
+ type: "middleware",
550
+ sourcePath: file,
551
+ context: "redirect-logic",
552
+ priority: "high",
553
+ recentlyModified,
554
+ });
555
+ }
556
+ if (content.includes("getToken") || content.includes("auth(") || content.includes("session")) {
557
+ features.push({
558
+ name: `Auth middleware in ${path.basename(file)}`,
559
+ type: "middleware",
560
+ sourcePath: file,
561
+ context: "auth-check",
562
+ priority: "critical",
563
+ recentlyModified,
564
+ });
565
+ }
566
+ }
567
+ return features;
568
+ }
569
+ async function discoverErrorBoundaries(recentFiles) {
570
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
571
+ const features = [];
572
+ const errorFiles = await glob("app/**/error.tsx", { cwd: process.cwd() });
573
+ const notFoundFiles = await glob("app/**/not-found.tsx", { cwd: process.cwd() });
574
+ for (const file of [...errorFiles, ...notFoundFiles]) {
575
+ const routePath = path.dirname(file).replace(/\\/g, "/").replace("app/", "/");
576
+ const isError = file.includes("error.tsx");
577
+ const recentlyModified = recentFiles.has(file);
578
+ features.push({
579
+ name: `${isError ? "Error" : "NotFound"} boundary: ${routePath}`,
580
+ type: "error-boundary",
581
+ sourcePath: file,
582
+ context: isError ? "error" : "not-found",
583
+ priority: "medium",
584
+ recentlyModified,
585
+ });
586
+ }
587
+ return features;
588
+ }
589
+ async function discoverLoadingStates(recentFiles) {
590
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
591
+ const features = [];
592
+ const loadingFiles = await glob("app/**/loading.tsx", { cwd: process.cwd() });
593
+ for (const file of loadingFiles) {
594
+ const routePath = path.dirname(file).replace(/\\/g, "/").replace("app/", "/");
595
+ const recentlyModified = recentFiles.has(file);
596
+ features.push({
597
+ name: `Loading state: ${routePath}`,
598
+ type: "loading-state",
599
+ sourcePath: file,
600
+ priority: "low",
601
+ recentlyModified,
602
+ });
603
+ }
604
+ return features;
605
+ }
606
+ async function discoverDynamicRoutes(recentFiles) {
607
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
608
+ const features = [];
609
+ const pageFiles = await glob("app/**/\\[*\\]/**/page.tsx", { cwd: process.cwd() });
610
+ pageFiles.push(...(await glob("app/**/\\[*\\]/page.tsx", { cwd: process.cwd() })));
611
+ for (const file of pageFiles) {
612
+ const routePath = path.dirname(file).replace(/\\/g, "/").replace("app/", "/");
613
+ const recentlyModified = recentFiles.has(file);
614
+ const segments = routePath.match(/\[([^\]]+)\]/g) || [];
615
+ features.push({
616
+ name: `Dynamic route: ${routePath}`,
617
+ type: "dynamic-route",
618
+ sourcePath: file,
619
+ context: segments.join(", "),
620
+ priority: "high",
621
+ recentlyModified,
622
+ });
623
+ }
624
+ return features;
625
+ }
626
+ async function discoverDataTestIds(recentFiles) {
627
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
628
+ const features = [];
629
+ const componentFiles = await glob("{app,components}/**/*.tsx", { cwd: process.cwd() });
630
+ for (const file of componentFiles) {
631
+ const content = fs.readFileSync(file, "utf-8");
632
+ const recentlyModified = recentFiles.has(file);
633
+ const testIdRegex = /data-testid=["']([^"']+)["']/g;
634
+ let match;
635
+ while ((match = testIdRegex.exec(content)) !== null) {
636
+ features.push({
637
+ name: match[1],
638
+ type: "data-testid",
639
+ sourcePath: file,
640
+ priority: "medium",
641
+ recentlyModified,
642
+ });
643
+ }
644
+ }
645
+ return features;
646
+ }
647
+ async function discoverSideEffects(recentFiles) {
648
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
649
+ const features = [];
650
+ const componentFiles = await glob("{app,components}/**/*.tsx", { cwd: process.cwd() });
651
+ const criticalPaths = ["app/store/", "app/admin/", "app/account/", "app/checkout/"];
652
+ for (const file of componentFiles) {
653
+ const normalizedPath = file.replace(/\\/g, "/");
654
+ const isCritical = criticalPaths.some((p) => normalizedPath.includes(p));
655
+ if (!isCritical)
656
+ continue;
657
+ const content = fs.readFileSync(file, "utf-8");
658
+ const recentlyModified = recentFiles.has(file);
659
+ const useEffectWithFetch = /useEffect\s*\(\s*(?:async\s*)?\(\)\s*=>\s*\{[^}]*(?:fetch|axios|api\.|\.get\(|\.post\()/gi;
660
+ if (useEffectWithFetch.test(content)) {
661
+ features.push({
662
+ name: `Side effect with API call in ${path.basename(file)}`,
663
+ type: "side-effect",
664
+ sourcePath: file,
665
+ context: "api-call",
666
+ priority: "high",
667
+ recentlyModified,
668
+ });
669
+ }
670
+ }
671
+ const seen = new Set();
672
+ return features.filter((f) => {
673
+ const key = `${f.sourcePath}:${f.type}`;
674
+ if (seen.has(key))
675
+ return false;
676
+ seen.add(key);
677
+ return true;
678
+ });
679
+ }
680
+ async function discoverModalTriggers(recentFiles) {
681
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
682
+ const features = [];
683
+ const componentFiles = await glob("{app,components}/**/*.tsx", { cwd: process.cwd() });
684
+ for (const file of componentFiles) {
685
+ const content = fs.readFileSync(file, "utf-8");
686
+ const recentlyModified = recentFiles.has(file);
687
+ const modalPatterns = [
688
+ /<Dialog[^>]*open=/gi,
689
+ /<Modal[^>]*open=/gi,
690
+ /setOpen\(true\)/gi,
691
+ /setIsOpen\(true\)/gi,
692
+ /setShowModal\(true\)/gi,
693
+ /openModal\(/gi,
694
+ ];
695
+ for (const pattern of modalPatterns) {
696
+ if (pattern.test(content)) {
697
+ features.push({
698
+ name: `Modal/Dialog in ${path.basename(file)}`,
699
+ type: "modal-trigger",
700
+ sourcePath: file,
701
+ priority: "medium",
702
+ recentlyModified,
703
+ });
704
+ break;
705
+ }
706
+ }
707
+ }
708
+ return features;
709
+ }
710
+ async function discoverToastTriggers(recentFiles) {
711
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
712
+ const features = [];
713
+ const componentFiles = await glob("{app,components}/**/*.tsx", { cwd: process.cwd() });
714
+ for (const file of componentFiles) {
715
+ const content = fs.readFileSync(file, "utf-8");
716
+ const recentlyModified = recentFiles.has(file);
717
+ const toastPatterns = [
718
+ /toast\(/gi,
719
+ /toast\.success\(/gi,
720
+ /toast\.error\(/gi,
721
+ /showNotification\(/gi,
722
+ /enqueueSnackbar\(/gi,
723
+ /addToast\(/gi,
724
+ ];
725
+ for (const pattern of toastPatterns) {
726
+ if (pattern.test(content)) {
727
+ features.push({
728
+ name: `Toast/Notification in ${path.basename(file)}`,
729
+ type: "toast-trigger",
730
+ sourcePath: file,
731
+ priority: "low",
732
+ recentlyModified,
733
+ });
734
+ break;
735
+ }
736
+ }
737
+ }
738
+ return features;
739
+ }
740
+ async function discoverFileUploads(recentFiles) {
741
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
742
+ const features = [];
743
+ const componentFiles = await glob("{app,components}/**/*.tsx", { cwd: process.cwd() });
744
+ for (const file of componentFiles) {
745
+ const content = fs.readFileSync(file, "utf-8");
746
+ const recentlyModified = recentFiles.has(file);
747
+ const uploadPatterns = [
748
+ /<input[^>]*type=["']file["']/gi,
749
+ /useDropzone/gi,
750
+ /FileUpload/gi,
751
+ /UploadButton/gi,
752
+ /setInputFiles/gi,
753
+ /FormData.*append.*file/gi,
754
+ ];
755
+ for (const pattern of uploadPatterns) {
756
+ if (pattern.test(content)) {
757
+ features.push({
758
+ name: `File upload in ${path.basename(file)}`,
759
+ type: "file-upload",
760
+ sourcePath: file,
761
+ priority: "high",
762
+ recentlyModified,
763
+ });
764
+ break;
765
+ }
766
+ }
767
+ }
768
+ return features;
769
+ }
770
+ async function discoverWebSockets(recentFiles) {
771
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
772
+ const features = [];
773
+ const files = await glob("{app,components,lib}/**/*.{ts,tsx}", { cwd: process.cwd() });
774
+ for (const file of files) {
775
+ const content = fs.readFileSync(file, "utf-8");
776
+ const recentlyModified = recentFiles.has(file);
777
+ const wsPatterns = [
778
+ /new WebSocket\(/gi,
779
+ /useWebSocket/gi,
780
+ /socket\.io/gi,
781
+ /pusher/gi,
782
+ /ably/gi,
783
+ ];
784
+ for (const pattern of wsPatterns) {
785
+ if (pattern.test(content)) {
786
+ features.push({
787
+ name: `WebSocket in ${path.basename(file)}`,
788
+ type: "websocket",
789
+ sourcePath: file,
790
+ priority: "high",
791
+ recentlyModified,
792
+ });
793
+ break;
794
+ }
795
+ }
796
+ }
797
+ return features;
798
+ }
799
+ async function discoverStorageUsage(recentFiles) {
800
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
801
+ const features = [];
802
+ const files = await glob("{app,components,lib}/**/*.{ts,tsx}", { cwd: process.cwd() });
803
+ for (const file of files) {
804
+ const content = fs.readFileSync(file, "utf-8");
805
+ const recentlyModified = recentFiles.has(file);
806
+ if (/localStorage\./gi.test(content)) {
807
+ features.push({
808
+ name: `localStorage in ${path.basename(file)}`,
809
+ type: "storage-usage",
810
+ sourcePath: file,
811
+ context: "localStorage",
812
+ priority: "medium",
813
+ recentlyModified,
814
+ });
815
+ }
816
+ if (/sessionStorage\./gi.test(content)) {
817
+ features.push({
818
+ name: `sessionStorage in ${path.basename(file)}`,
819
+ type: "storage-usage",
820
+ sourcePath: file,
821
+ context: "sessionStorage",
822
+ priority: "medium",
823
+ recentlyModified,
824
+ });
825
+ }
826
+ }
827
+ const seen = new Set();
828
+ return features.filter((f) => {
829
+ const key = `${f.sourcePath}:${f.context}`;
830
+ if (seen.has(key))
831
+ return false;
832
+ seen.add(key);
833
+ return true;
834
+ });
835
+ }
836
+ // PHASE 2: ANALYZE WHAT TESTS ACTUALLY COVER
837
+ async function analyzeTestCoverage() {
838
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
839
+ const coverageMap = new Map();
840
+ const testFiles = await glob("tests/e2e/**/*.spec.ts", { cwd: process.cwd() });
841
+ for (const testFile of testFiles) {
842
+ const content = fs.readFileSync(testFile, "utf-8");
843
+ const coverage = {
844
+ testPath: testFile,
845
+ coveredEndpoints: new Set(),
846
+ coveredActions: new Set(),
847
+ coveredComponents: new Set(),
848
+ mockedApis: new Set(),
849
+ interactions: new Set(),
850
+ testIds: new Set(),
851
+ dynamicParams: new Set(),
852
+ };
853
+ // Extract API endpoints being tested or mocked
854
+ const apiPatterns = [
855
+ /page\.route\(["']\*\*([^"']+)["']/g,
856
+ /request\.(?:get|post|put|patch|delete)\(["']([^"']+)["']/g,
857
+ /fetch\(["']([^"']+)["']/g,
858
+ /goto\([^,]*,\s*["']([^"']+)["']/g,
859
+ /page\.goto\(["']([^"']+)["']/g,
860
+ ];
861
+ for (const pattern of apiPatterns) {
862
+ let match;
863
+ while ((match = pattern.exec(content)) !== null) {
864
+ const endpoint = match[1].replace(/\*\*/g, "").replace(/\*/g, "");
865
+ if (endpoint.includes("/api/")) {
866
+ coverage.mockedApis.add(endpoint);
867
+ }
868
+ coverage.coveredEndpoints.add(endpoint);
869
+ }
870
+ }
871
+ // Extract UI interactions
872
+ const interactionPatterns = [
873
+ /\.click\(\)/g,
874
+ /\.fill\(["']([^"']+)["']/g,
875
+ /\.type\(["']([^"']+)["']/g,
876
+ /\.check\(\)/g,
877
+ /\.selectOption\(/g,
878
+ /\.setInputFiles\(/g,
879
+ /getByRole\(["']([^"']+)["']/g,
880
+ /getByLabel\(["']([^"']+)["']/g,
881
+ /getByText\(["']([^"']+)["']/g,
882
+ /getByTestId\(["']([^"']+)["']/g,
883
+ ];
884
+ for (const pattern of interactionPatterns) {
885
+ let match;
886
+ while ((match = pattern.exec(content)) !== null) {
887
+ coverage.interactions.add(match[1] || match[0]);
888
+ }
889
+ }
890
+ // Extract data-testid usage
891
+ const testIdPattern = /getByTestId\(["']([^"']+)["']\)/g;
892
+ let testIdMatch;
893
+ while ((testIdMatch = testIdPattern.exec(content)) !== null) {
894
+ coverage.testIds.add(testIdMatch[1]);
895
+ }
896
+ // Extract dynamic route params being tested
897
+ const dynamicParamPatterns = [
898
+ /\/\w+\/([a-f0-9-]{36})/gi, // UUIDs
899
+ /\/\w+\/(\d+)/g, // Numeric IDs
900
+ /params\.\w+/g, // params.id, params.slug
901
+ ];
902
+ for (const pattern of dynamicParamPatterns) {
903
+ let match;
904
+ while ((match = pattern.exec(content)) !== null) {
905
+ coverage.dynamicParams.add(match[1] || match[0]);
906
+ }
907
+ }
908
+ // Extract action names being tested
909
+ const actionMentions = content.match(/["'](\w+Action|handle\w+|on\w+|submit\w+)["']/gi) || [];
910
+ for (const action of actionMentions) {
911
+ coverage.coveredActions.add(action.replace(/["']/g, ""));
912
+ }
913
+ coverageMap.set(testFile, coverage);
914
+ }
915
+ return coverageMap;
916
+ }
917
+ function aggregateCoverage(coverageMap) {
918
+ const result = {
919
+ allEndpoints: new Set(),
920
+ allMockedApis: new Set(),
921
+ allInteractions: new Set(),
922
+ allActions: new Set(),
923
+ allTestIds: new Set(),
924
+ allDynamicParams: new Set(),
925
+ testFilesByRoute: new Map(),
926
+ };
927
+ for (const [testPath, coverage] of coverageMap) {
928
+ coverage.coveredEndpoints.forEach((e) => {
929
+ result.allEndpoints.add(e);
930
+ const existing = result.testFilesByRoute.get(e) || [];
931
+ existing.push(testPath);
932
+ result.testFilesByRoute.set(e, existing);
933
+ });
934
+ coverage.mockedApis.forEach((e) => result.allMockedApis.add(e));
935
+ coverage.interactions.forEach((i) => result.allInteractions.add(i.toLowerCase()));
936
+ coverage.coveredActions.forEach((a) => result.allActions.add(a.toLowerCase()));
937
+ coverage.testIds.forEach((t) => result.allTestIds.add(t));
938
+ coverage.dynamicParams.forEach((p) => result.allDynamicParams.add(p));
939
+ }
940
+ return result;
941
+ }
942
+ // STRUCTURAL GAP DETECTION: Match source files to test files
943
+ async function findStructuralGaps(recentFiles) {
944
+ const { glob } = await Promise.resolve().then(() => __importStar(require("glob")));
945
+ const gaps = [];
946
+ const pageFiles = await glob("app/**/page.tsx", { cwd: process.cwd() });
947
+ const testFiles = await glob("tests/e2e/**/*.spec.ts", { cwd: process.cwd() });
948
+ // Build a map of test file coverage by route pattern
949
+ const testRoutePatterns = new Set();
950
+ const testFileContents = new Map();
951
+ for (const testFile of testFiles) {
952
+ const routePattern = testFile
953
+ .replace("tests/e2e/", "")
954
+ .replace(".spec.ts", "")
955
+ .replace(/\\/g, "/");
956
+ testRoutePatterns.add(routePattern);
957
+ testRoutePatterns.add(routePattern.replace(/-/g, "/"));
958
+ // Also read test file content to check for route references
959
+ try {
960
+ const content = fs.readFileSync(testFile, "utf-8");
961
+ testFileContents.set(testFile, content);
962
+ }
963
+ catch {
964
+ // Ignore read errors
965
+ }
966
+ }
967
+ // Build a set of all routes referenced in test files
968
+ const routesInTests = new Set();
969
+ for (const [_testFile, content] of testFileContents) {
970
+ // Extract goto URLs
971
+ const gotoMatches = content.matchAll(/goto\s*\(\s*["'`]([^"'`]+)["'`]/g);
972
+ for (const match of gotoMatches) {
973
+ const route = match[1].replace(/^\//, "").split("?")[0];
974
+ routesInTests.add(route);
975
+ // Also add parent routes
976
+ const parts = route.split("/");
977
+ for (let i = 1; i <= parts.length; i++) {
978
+ routesInTests.add(parts.slice(0, i).join("/"));
979
+ }
980
+ }
981
+ // Extract route patterns from comments and test descriptions
982
+ const routeComments = content.matchAll(/\/([a-z][a-z0-9-]*(?:\/[a-z][a-z0-9-]*)*)/gi);
983
+ for (const match of routeComments) {
984
+ routesInTests.add(match[1]);
985
+ }
986
+ }
987
+ for (const pageFile of pageFiles) {
988
+ const routePattern = path
989
+ .dirname(pageFile)
990
+ .replace(/\\/g, "/")
991
+ .replace("app/", "")
992
+ .replace(/\(.*?\)\//g, "") // Remove route groups like (auth)/
993
+ .replace(/\[.*?\]/g, "[param]"); // Normalize dynamic segments
994
+ // Check 1: Test file name matches route pattern
995
+ const hasTestFile = [...testRoutePatterns].some((testPattern) => {
996
+ return (testPattern.includes(routePattern) ||
997
+ routePattern.includes(testPattern) ||
998
+ testPattern.replace(/-/g, "").includes(routePattern.replace(/-/g, "")));
999
+ });
1000
+ // Check 2: Route is referenced in any test file content
1001
+ const routeWithoutParams = routePattern.replace(/\[param\]/g, "");
1002
+ const hasRouteReference = [...routesInTests].some((testedRoute) => {
1003
+ const normalizedTested = testedRoute.toLowerCase().replace(/[^a-z0-9]/g, "");
1004
+ const normalizedRoute = routeWithoutParams.toLowerCase().replace(/[^a-z0-9]/g, "");
1005
+ return (normalizedTested.includes(normalizedRoute) ||
1006
+ normalizedRoute.includes(normalizedTested) ||
1007
+ testedRoute.includes(routePattern.replace(/\[param\]/g, "")));
1008
+ });
1009
+ if (!hasTestFile && !hasRouteReference && !routePattern.includes("api/")) {
1010
+ const isCritical = routePattern.includes("store/") ||
1011
+ routePattern.includes("admin/") ||
1012
+ routePattern.includes("checkout/") ||
1013
+ routePattern.includes("account/");
1014
+ const recentlyModified = recentFiles.has(pageFile);
1015
+ gaps.push({
1016
+ feature: {
1017
+ name: `Page: /${routePattern}`,
1018
+ type: "page",
1019
+ sourcePath: pageFile,
1020
+ priority: isCritical ? "critical" : "medium",
1021
+ recentlyModified,
1022
+ },
1023
+ severity: isCritical ? "error" : "warning",
1024
+ reason: `No test file found matching route pattern: ${routePattern}${recentlyModified ? " (recently modified)" : ""}`,
1025
+ suggestedTestFile: `tests/e2e/${routePattern.replace(/\[param\]/g, "dynamic")}.spec.ts`,
1026
+ });
1027
+ }
1028
+ }
1029
+ return gaps;
1030
+ }
1031
+ // PHASE 3: COMPARE AND FIND GAPS
1032
+ function findApiGaps(discoveredApis, testedEndpoints, mockedApis) {
1033
+ const gaps = [];
1034
+ for (const api of discoveredApis) {
1035
+ const endpoint = api.name.split(" ")[1];
1036
+ const _method = api.name.split(" ")[0];
1037
+ const isTested = [...testedEndpoints, ...mockedApis].some((tested) => tested.includes(endpoint) || endpoint.includes(tested.replace(/\*/g, "")));
1038
+ if (!isTested) {
1039
+ gaps.push({
1040
+ feature: api,
1041
+ severity: api.priority === "critical" ? "error" : "warning",
1042
+ reason: `API endpoint ${api.name} has no E2E test coverage${api.recentlyModified ? " (recently modified)" : ""}`,
1043
+ suggestedTestFile: `tests/e2e/api/${endpoint.replace("/api/", "").replace(/\//g, "-")}.spec.ts`,
1044
+ });
1045
+ }
1046
+ }
1047
+ return gaps;
1048
+ }
1049
+ function findActionGaps(discoveredActions, testedActions, testedInteractions) {
1050
+ const gaps = [];
1051
+ for (const action of discoveredActions) {
1052
+ const actionName = action.name.toLowerCase();
1053
+ // Check if action name is directly referenced
1054
+ const isDirectlyTested = [...testedActions].some((tested) => tested.includes(actionName) || actionName.includes(tested));
1055
+ // Check if action functionality is tested through UI interactions
1056
+ // Extract key words from action name (e.g., "updateProfileVisibility" -> ["update", "profile", "visibility"])
1057
+ const actionWords = actionName
1058
+ .replace(/([A-Z])/g, " $1")
1059
+ .toLowerCase()
1060
+ .split(/\s+/)
1061
+ .filter((w) => w.length > 3); // Filter out short words like "get", "set"
1062
+ const isFunctionallyTested = actionWords.some((word) => [...testedInteractions].some((interaction) => interaction.includes(word) || word.includes(interaction)));
1063
+ // Also check if the action's source file path suggests a tested area
1064
+ const sourcePath = action.sourcePath.toLowerCase().replace(/\\/g, "/");
1065
+ const interactionsLower = [...testedInteractions].map((i) => i.toLowerCase());
1066
+ const isInTestedArea = (sourcePath.includes("profile") &&
1067
+ interactionsLower.some((i) => i.includes("profile") || i.includes("setting") || i.includes("visibility"))) ||
1068
+ (sourcePath.includes("cart") &&
1069
+ interactionsLower.some((i) => i.includes("cart") ||
1070
+ i.includes("quantity") ||
1071
+ i.includes("increase") ||
1072
+ i.includes("decrease"))) ||
1073
+ (sourcePath.includes("collection") &&
1074
+ interactionsLower.some((i) => i.includes("collection") || i.includes("quantity"))) ||
1075
+ // Wishlist actions - check for wishlist-related interactions
1076
+ (sourcePath.includes("wishlist") &&
1077
+ interactionsLower.some((i) => i.includes("wishlist") ||
1078
+ i.includes("save") ||
1079
+ i.includes("heart") ||
1080
+ i.includes("favorite") ||
1081
+ i.includes("remove"))) ||
1082
+ (actionName.includes("wishlist") &&
1083
+ interactionsLower.some((i) => i.includes("wishlist") ||
1084
+ i.includes("save") ||
1085
+ i.includes("heart") ||
1086
+ i.includes("favorite"))) ||
1087
+ // Social actions - check for social-related interactions
1088
+ (sourcePath.includes("social") &&
1089
+ interactionsLower.some((i) => i.includes("follow") ||
1090
+ i.includes("like") ||
1091
+ i.includes("feed") ||
1092
+ i.includes("social"))) ||
1093
+ (actionName.includes("follow") &&
1094
+ interactionsLower.some((i) => i.includes("follow") || i.includes("unfollow"))) ||
1095
+ (actionName.includes("like") &&
1096
+ interactionsLower.some((i) => i.includes("like") || i.includes("unlike") || i.includes("heart"))) ||
1097
+ (actionName.includes("feed") &&
1098
+ interactionsLower.some((i) => i.includes("feed") || i.includes("collection"))) ||
1099
+ // Price history actions
1100
+ (actionName.includes("pricehistory") &&
1101
+ interactionsLower.some((i) => i.includes("price") ||
1102
+ i.includes("history") ||
1103
+ i.includes("trend") ||
1104
+ i.includes("chart"))) ||
1105
+ (actionName.includes("price") &&
1106
+ actionName.includes("history") &&
1107
+ interactionsLower.some((i) => i.includes("price") || i.includes("drop"))) ||
1108
+ // Public collections actions
1109
+ (actionName.includes("publiccollection") &&
1110
+ interactionsLower.some((i) => i.includes("collection") || i.includes("public") || i.includes("explore"))) ||
1111
+ (actionName.includes("public") &&
1112
+ actionName.includes("collection") &&
1113
+ interactionsLower.some((i) => i.includes("collection") || i.includes("profile")));
1114
+ if (!isDirectlyTested && !isFunctionallyTested && !isInTestedArea) {
1115
+ gaps.push({
1116
+ feature: action,
1117
+ severity: action.priority === "critical" ? "error" : "warning",
1118
+ reason: `Server action "${action.name}" has no E2E test coverage${action.recentlyModified ? " (recently modified)" : ""}`,
1119
+ suggestedTestFile: `tests/e2e/actions/${action.name
1120
+ .replace(/([A-Z])/g, "-$1")
1121
+ .toLowerCase()
1122
+ .replace(/^-/, "")}.spec.ts`,
1123
+ });
1124
+ }
1125
+ }
1126
+ return gaps;
1127
+ }
1128
+ function findFormFieldGaps(discoveredFields, testedInteractions) {
1129
+ const gaps = [];
1130
+ const fieldsByFile = new Map();
1131
+ for (const field of discoveredFields) {
1132
+ const existing = fieldsByFile.get(field.sourcePath) || [];
1133
+ existing.push(field);
1134
+ fieldsByFile.set(field.sourcePath, existing);
1135
+ }
1136
+ for (const [file, fields] of fieldsByFile) {
1137
+ const untestedFields = fields.filter((f) => {
1138
+ const fieldName = f.name.toLowerCase();
1139
+ return ![...testedInteractions].some((tested) => tested.includes(fieldName) || fieldName.includes(tested));
1140
+ });
1141
+ if (untestedFields.length > 0 && untestedFields.length >= fields.length * 0.5) {
1142
+ const hasRecentlyModified = untestedFields.some((f) => f.recentlyModified);
1143
+ gaps.push({
1144
+ feature: {
1145
+ name: `${untestedFields.length} form fields`,
1146
+ type: "form-field",
1147
+ sourcePath: file,
1148
+ context: untestedFields
1149
+ .map((f) => f.name)
1150
+ .slice(0, 5)
1151
+ .join(", "),
1152
+ recentlyModified: hasRecentlyModified,
1153
+ },
1154
+ severity: "warning",
1155
+ reason: `Form in ${path.basename(file)} has ${untestedFields.length}/${fields.length} untested fields${hasRecentlyModified ? " (recently modified)" : ""}`,
1156
+ });
1157
+ }
1158
+ }
1159
+ return gaps;
1160
+ }
1161
+ function findDestructiveActionGaps(discoveredButtons, testedInteractions) {
1162
+ const gaps = [];
1163
+ const destructiveActions = discoveredButtons.filter((b) => b.context === "destructive-action");
1164
+ for (const action of destructiveActions) {
1165
+ const _fileName = path.basename(action.sourcePath).toLowerCase();
1166
+ const hasDeleteTest = [...testedInteractions].some((i) => i.includes("delete") || i.includes("remove") || i.includes("confirm"));
1167
+ if (!hasDeleteTest) {
1168
+ gaps.push({
1169
+ feature: action,
1170
+ severity: "error",
1171
+ reason: `Destructive action in ${path.basename(action.sourcePath)} has no E2E test${action.recentlyModified ? " (recently modified)" : ""}`,
1172
+ suggestedTestFile: `tests/e2e/destructive/${path.basename(action.sourcePath).replace(".tsx", "")}.spec.ts`,
1173
+ });
1174
+ }
1175
+ }
1176
+ return gaps;
1177
+ }
1178
+ function findMiddlewareGaps(discoveredMiddleware, testedEndpoints) {
1179
+ const gaps = [];
1180
+ for (const mw of discoveredMiddleware) {
1181
+ // Check if middleware routes are tested
1182
+ const hasTest = [...testedEndpoints].some((e) => {
1183
+ if (mw.context && mw.context !== "auth-check" && mw.context !== "redirect-logic") {
1184
+ return e.includes(mw.context.replace(/\*/g, ""));
1185
+ }
1186
+ return false;
1187
+ });
1188
+ if (!hasTest) {
1189
+ if (mw.context === "auth-check") {
1190
+ gaps.push({
1191
+ feature: mw,
1192
+ severity: "error",
1193
+ reason: `Auth middleware needs tests for authenticated/unauthenticated states`,
1194
+ suggestedTestFile: "tests/e2e/auth/middleware-auth.spec.ts",
1195
+ });
1196
+ }
1197
+ else if (mw.context === "redirect-logic") {
1198
+ gaps.push({
1199
+ feature: mw,
1200
+ severity: "warning",
1201
+ reason: `Middleware redirect logic should be tested`,
1202
+ suggestedTestFile: "tests/e2e/middleware/redirects.spec.ts",
1203
+ });
1204
+ }
1205
+ }
1206
+ }
1207
+ return gaps;
1208
+ }
1209
+ function findErrorBoundaryGaps(discoveredBoundaries, testedEndpoints, testedInteractions) {
1210
+ const gaps = [];
1211
+ // Check if there's a dedicated error boundary test file
1212
+ const hasErrorBoundaryTests = [...testedEndpoints].some((e) => e.includes("error") || e.includes("boundary") || e.includes("404") || e.includes("not-found"));
1213
+ // Check if error-related interactions are tested
1214
+ const hasErrorInteractions = [...testedInteractions].some((i) => i.includes("error") ||
1215
+ i.includes("retry") ||
1216
+ i.includes("reload") ||
1217
+ i.includes("try again") ||
1218
+ i.includes("failed"));
1219
+ // If we have error boundary tests, consider all boundaries covered
1220
+ if (hasErrorBoundaryTests || hasErrorInteractions) {
1221
+ return gaps;
1222
+ }
1223
+ for (const boundary of discoveredBoundaries) {
1224
+ const routePath = boundary.name
1225
+ .replace("Error boundary: ", "")
1226
+ .replace("NotFound boundary: ", "");
1227
+ const hasErrorTest = [...testedEndpoints].some((e) => e.includes(routePath) &&
1228
+ (e.includes("error") || e.includes("404") || e.includes("not-found")));
1229
+ if (!hasErrorTest) {
1230
+ gaps.push({
1231
+ feature: boundary,
1232
+ severity: "warning",
1233
+ reason: `${boundary.context === "error" ? "Error" : "NotFound"} boundary at ${routePath} has no E2E test`,
1234
+ suggestedTestFile: `tests/e2e/error-states/${routePath.replace(/\//g, "-").replace(/^-/, "")}-${boundary.context}.spec.ts`,
1235
+ });
1236
+ }
1237
+ }
1238
+ return gaps;
1239
+ }
1240
+ function findFileUploadGaps(discoveredUploads, testedInteractions) {
1241
+ const gaps = [];
1242
+ const hasUploadTest = [...testedInteractions].some((i) => i.includes("file") || i.includes("upload") || i.includes("setinputfiles"));
1243
+ if (!hasUploadTest && discoveredUploads.length > 0) {
1244
+ for (const upload of discoveredUploads) {
1245
+ gaps.push({
1246
+ feature: upload,
1247
+ severity: "warning",
1248
+ reason: `File upload in ${path.basename(upload.sourcePath)} has no E2E test`,
1249
+ suggestedTestFile: `tests/e2e/uploads/${path.basename(upload.sourcePath).replace(".tsx", "")}.spec.ts`,
1250
+ });
1251
+ }
1252
+ }
1253
+ return gaps;
1254
+ }
1255
+ function findModalGaps(discoveredModals, testedInteractions) {
1256
+ const gaps = [];
1257
+ const hasModalTest = [...testedInteractions].some((i) => i.includes("dialog") || i.includes("modal") || i.includes("close") || i.includes("cancel"));
1258
+ // Only flag critical path modals
1259
+ const criticalModals = discoveredModals.filter((m) => {
1260
+ const filePath = m.sourcePath.replace(/\\/g, "/");
1261
+ return (filePath.includes("store/") || filePath.includes("admin/") || filePath.includes("checkout/"));
1262
+ });
1263
+ if (!hasModalTest && criticalModals.length > 0) {
1264
+ // Group by file to reduce noise
1265
+ const byFile = new Map();
1266
+ for (const modal of criticalModals) {
1267
+ if (!byFile.has(modal.sourcePath)) {
1268
+ byFile.set(modal.sourcePath, modal);
1269
+ }
1270
+ }
1271
+ for (const modal of byFile.values()) {
1272
+ gaps.push({
1273
+ feature: modal,
1274
+ severity: "warning",
1275
+ reason: `Modal in critical path ${path.basename(modal.sourcePath)} has no E2E test`,
1276
+ suggestedTestFile: `tests/e2e/modals/${path.basename(modal.sourcePath).replace(".tsx", "")}.spec.ts`,
1277
+ });
1278
+ }
1279
+ }
1280
+ return gaps;
1281
+ }
1282
+ function findDataTestIdGaps(discoveredTestIds, usedTestIds) {
1283
+ const gaps = [];
1284
+ // Only check critical path test IDs
1285
+ const criticalTestIds = discoveredTestIds.filter((t) => {
1286
+ const filePath = t.sourcePath.replace(/\\/g, "/");
1287
+ return (filePath.includes("store/") || filePath.includes("admin/") || filePath.includes("checkout/"));
1288
+ });
1289
+ for (const testId of criticalTestIds) {
1290
+ if (!usedTestIds.has(testId.name)) {
1291
+ gaps.push({
1292
+ feature: testId,
1293
+ severity: "warning",
1294
+ reason: `data-testid="${testId.name}" defined but never used in tests`,
1295
+ });
1296
+ }
1297
+ }
1298
+ return gaps;
1299
+ }
1300
+ // MAIN EXECUTION
1301
+ async function run() {
1302
+ const reporter = (0, universal_progress_reporter_1.createUniversalProgressReporter)(exports.name);
1303
+ console.log(`\n${console_chars_1.emoji.testTube} PLAYWRIGHT FEATURE COVERAGE GAP DETECTION (Proactive)`);
1304
+ console.log((0, console_chars_1.createDivider)(60, "heavy"));
1305
+ // Show trend if requested
1306
+ if (showTrend) {
1307
+ displayTrend();
1308
+ process.exit(0);
1309
+ }
1310
+ console.log(`${console_chars_1.emoji.info} Scanning source code to discover features...`);
1311
+ // Get recently modified files for priority flagging
1312
+ const recentFiles = getRecentlyModifiedFiles();
1313
+ // Phase 1: Discover ALL features from source (core + extended)
1314
+ const [apiEndpoints, pageActions, formFields, criticalButtons, middleware, errorBoundaries, loadingStates, dynamicRoutes, dataTestIds, sideEffects, modalTriggers, toastTriggers, fileUploads, webSockets, storageUsage,] = await Promise.all([
1315
+ discoverApiEndpoints(recentFiles),
1316
+ discoverPageActions(recentFiles),
1317
+ discoverFormFields(recentFiles),
1318
+ discoverCriticalButtons(recentFiles),
1319
+ discoverMiddleware(recentFiles),
1320
+ discoverErrorBoundaries(recentFiles),
1321
+ discoverLoadingStates(recentFiles),
1322
+ discoverDynamicRoutes(recentFiles),
1323
+ discoverDataTestIds(recentFiles),
1324
+ discoverSideEffects(recentFiles),
1325
+ discoverModalTriggers(recentFiles),
1326
+ discoverToastTriggers(recentFiles),
1327
+ discoverFileUploads(recentFiles),
1328
+ discoverWebSockets(recentFiles),
1329
+ discoverStorageUsage(recentFiles),
1330
+ ]);
1331
+ // Structural gaps (page.tsx without matching test files)
1332
+ const structuralGaps = await findStructuralGaps(recentFiles);
1333
+ if (isVerbose) {
1334
+ console.log(`\n${console_chars_1.emoji.search} Discovered:`);
1335
+ console.log(` ${console_chars_1.emoji.globe} ${apiEndpoints.length} API endpoints`);
1336
+ console.log(` ${console_chars_1.emoji.lightning} ${pageActions.length} server actions`);
1337
+ console.log(` ${console_chars_1.emoji.clipboard} ${formFields.length} form fields (critical paths)`);
1338
+ console.log(` ${console_chars_1.emoji.warning} ${criticalButtons.length} destructive actions`);
1339
+ console.log(` ${console_chars_1.emoji.lock} ${middleware.length} middleware rules`);
1340
+ console.log(` ${console_chars_1.emoji.error} ${errorBoundaries.length} error boundaries`);
1341
+ console.log(` ${console_chars_1.emoji.clock} ${loadingStates.length} loading states`);
1342
+ console.log(` ${console_chars_1.emoji.link} ${dynamicRoutes.length} dynamic routes`);
1343
+ console.log(` ${console_chars_1.emoji.target} ${dataTestIds.length} data-testid attributes`);
1344
+ console.log(` ${console_chars_1.emoji.refresh} ${sideEffects.length} side effects with API calls`);
1345
+ console.log(` ${console_chars_1.emoji.components} ${modalTriggers.length} modal/dialog triggers`);
1346
+ console.log(` ${console_chars_1.emoji.bell} ${toastTriggers.length} toast/notification triggers`);
1347
+ console.log(` ${console_chars_1.emoji.file} ${fileUploads.length} file upload components`);
1348
+ console.log(` ${console_chars_1.emoji.link} ${webSockets.length} WebSocket connections`);
1349
+ console.log(` ${console_chars_1.emoji.database} ${storageUsage.length} storage usage (local/session)`);
1350
+ console.log(` ${console_chars_1.emoji.folder} ${structuralGaps.length} pages without test files`);
1351
+ }
1352
+ // Phase 2: Analyze test coverage
1353
+ console.log(`\n${console_chars_1.emoji.search} Analyzing Playwright test coverage...`);
1354
+ const coverageMap = await analyzeTestCoverage();
1355
+ const aggregated = aggregateCoverage(coverageMap);
1356
+ if (isVerbose) {
1357
+ console.log(`\n${console_chars_1.emoji.chart} Test coverage found:`);
1358
+ console.log(` ${console_chars_1.emoji.check} ${aggregated.allEndpoints.size} endpoints referenced`);
1359
+ console.log(` ${console_chars_1.emoji.check} ${aggregated.allMockedApis.size} APIs mocked`);
1360
+ console.log(` ${console_chars_1.emoji.check} ${aggregated.allInteractions.size} unique interactions`);
1361
+ console.log(` ${console_chars_1.emoji.check} ${aggregated.allActions.size} actions referenced`);
1362
+ console.log(` ${console_chars_1.emoji.check} ${aggregated.allTestIds.size} test IDs used`);
1363
+ }
1364
+ // Phase 3: Find ALL gaps
1365
+ console.log(`\n${console_chars_1.emoji.magnifier} Comparing implementation vs tests...`);
1366
+ const apiGaps = findApiGaps(apiEndpoints, aggregated.allEndpoints, aggregated.allMockedApis);
1367
+ const actionGaps = findActionGaps(pageActions, aggregated.allActions, aggregated.allInteractions);
1368
+ const formGaps = findFormFieldGaps(formFields, aggregated.allInteractions);
1369
+ const destructiveGaps = findDestructiveActionGaps(criticalButtons, aggregated.allInteractions);
1370
+ const middlewareGaps = findMiddlewareGaps(middleware, aggregated.allEndpoints);
1371
+ const errorBoundaryGaps = findErrorBoundaryGaps(errorBoundaries, aggregated.allEndpoints, aggregated.allInteractions);
1372
+ const fileUploadGaps = findFileUploadGaps(fileUploads, aggregated.allInteractions);
1373
+ const modalGaps = findModalGaps(modalTriggers, aggregated.allInteractions);
1374
+ const testIdGaps = findDataTestIdGaps(dataTestIds, aggregated.allTestIds);
1375
+ const allGaps = [
1376
+ ...apiGaps,
1377
+ ...actionGaps,
1378
+ ...formGaps,
1379
+ ...destructiveGaps,
1380
+ ...structuralGaps,
1381
+ ...middlewareGaps,
1382
+ ...errorBoundaryGaps,
1383
+ ...fileUploadGaps,
1384
+ ...modalGaps,
1385
+ ...testIdGaps,
1386
+ ];
1387
+ const errors = allGaps.filter((g) => g.severity === "error");
1388
+ const warnings = allGaps.filter((g) => g.severity === "warning");
1389
+ // Calculate coverage stats for trend tracking
1390
+ const totalFeatures = apiEndpoints.length +
1391
+ pageActions.length +
1392
+ criticalButtons.length +
1393
+ middleware.length +
1394
+ errorBoundaries.length +
1395
+ fileUploads.length;
1396
+ const coveredFeatures = totalFeatures -
1397
+ (apiGaps.length +
1398
+ actionGaps.length +
1399
+ destructiveGaps.length +
1400
+ middlewareGaps.length +
1401
+ errorBoundaryGaps.length +
1402
+ fileUploadGaps.length);
1403
+ const byCategory = {
1404
+ "api-endpoints": { total: apiEndpoints.length, covered: apiEndpoints.length - apiGaps.length },
1405
+ "server-actions": {
1406
+ total: pageActions.length,
1407
+ covered: pageActions.length - actionGaps.length,
1408
+ },
1409
+ "destructive-actions": {
1410
+ total: criticalButtons.length,
1411
+ covered: criticalButtons.length - destructiveGaps.length,
1412
+ },
1413
+ middleware: { total: middleware.length, covered: middleware.length - middlewareGaps.length },
1414
+ "error-boundaries": {
1415
+ total: errorBoundaries.length,
1416
+ covered: errorBoundaries.length - errorBoundaryGaps.length,
1417
+ },
1418
+ "file-uploads": {
1419
+ total: fileUploads.length,
1420
+ covered: fileUploads.length - fileUploadGaps.length,
1421
+ },
1422
+ };
1423
+ // Save trend data
1424
+ saveTrendData(totalFeatures, coveredFeatures, byCategory);
1425
+ // Report results
1426
+ console.log((0, console_chars_1.createDivider)(60, "light"));
1427
+ if (allGaps.length === 0) {
1428
+ console.log(`\n${console_chars_1.emoji.success} All discovered features have E2E test coverage!`);
1429
+ process.exit(0);
1430
+ }
1431
+ // Group gaps by type for cleaner output
1432
+ const gapsByType = new Map();
1433
+ for (const gap of allGaps) {
1434
+ const type = gap.feature.type;
1435
+ const existing = gapsByType.get(type) || [];
1436
+ existing.push(gap);
1437
+ gapsByType.set(type, existing);
1438
+ }
1439
+ const typeLabels = {
1440
+ "api-endpoint": "API Endpoints",
1441
+ "page-action": "Server Actions",
1442
+ "form-field": "Form Fields",
1443
+ "ui-component": "UI Components",
1444
+ "service-method": "Service Methods",
1445
+ middleware: "Middleware",
1446
+ "error-boundary": "Error Boundaries",
1447
+ "loading-state": "Loading States",
1448
+ "dynamic-route": "Dynamic Routes",
1449
+ "data-testid": "Test IDs",
1450
+ "side-effect": "Side Effects",
1451
+ "modal-trigger": "Modals/Dialogs",
1452
+ "toast-trigger": "Toasts/Notifications",
1453
+ "file-upload": "File Uploads",
1454
+ websocket: "WebSockets",
1455
+ "storage-usage": "Storage Usage",
1456
+ page: "Pages",
1457
+ };
1458
+ if (errors.length > 0) {
1459
+ console.log(`\n${console_chars_1.emoji.error} CRITICAL GAPS (${errors.length}):\n`);
1460
+ for (const [type, gaps] of gapsByType) {
1461
+ const typeErrors = gaps.filter((g) => g.severity === "error");
1462
+ if (typeErrors.length === 0)
1463
+ continue;
1464
+ console.log(` ${console_chars_1.emoji.folder} ${typeLabels[type] || type}:`);
1465
+ for (const gap of typeErrors.slice(0, 10)) {
1466
+ console.log(` ${console_chars_1.chars.cross} ${gap.feature.name}`);
1467
+ if (isVerbose) {
1468
+ console.log(` File: ${gap.feature.sourcePath}`);
1469
+ console.log(` ${gap.reason}`);
1470
+ if (gap.suggestedTestFile) {
1471
+ console.log(` Suggested: ${gap.suggestedTestFile}`);
1472
+ }
1473
+ }
1474
+ }
1475
+ if (typeErrors.length > 10) {
1476
+ console.log(` ... and ${typeErrors.length - 10} more`);
1477
+ }
1478
+ console.log("");
1479
+ }
1480
+ }
1481
+ if (warnings.length > 0 && isVerbose) {
1482
+ console.log(`\n${console_chars_1.emoji.warning} WARNINGS (${warnings.length}):\n`);
1483
+ for (const [type, gaps] of gapsByType) {
1484
+ const typeWarnings = gaps.filter((g) => g.severity === "warning");
1485
+ if (typeWarnings.length === 0)
1486
+ continue;
1487
+ console.log(` ${console_chars_1.emoji.folder} ${typeLabels[type] || type}: ${typeWarnings.length} gaps`);
1488
+ for (const gap of typeWarnings.slice(0, 5)) {
1489
+ console.log(` ${console_chars_1.emoji.warning} ${gap.feature.name}`);
1490
+ }
1491
+ if (typeWarnings.length > 5) {
1492
+ console.log(` ... and ${typeWarnings.length - 5} more`);
1493
+ }
1494
+ console.log("");
1495
+ }
1496
+ }
1497
+ // Generate test stubs if requested
1498
+ if (generateStubs) {
1499
+ const gapsWithSuggestions = allGaps.filter((g) => g.suggestedTestFile);
1500
+ const stubsWritten = writeTestStubs(gapsWithSuggestions);
1501
+ console.log(`\n${console_chars_1.emoji.file} Generated ${stubsWritten} test stub(s) in tests/e2e/_generated-stubs/`);
1502
+ console.log(` Review and move stubs to appropriate locations, then implement tests.`);
1503
+ }
1504
+ // Generate report if requested
1505
+ if (generateReport) {
1506
+ const coveragePercent = totalFeatures > 0 ? Math.round((coveredFeatures / totalFeatures) * 100) : 100;
1507
+ const reportLines = [
1508
+ "# Playwright Coverage Gap Report (Auto-Discovered)",
1509
+ "",
1510
+ `Generated: ${new Date().toISOString()}`,
1511
+ "",
1512
+ "## Summary",
1513
+ "",
1514
+ `- **Total Features Discovered:** ${totalFeatures}`,
1515
+ `- **Features with Coverage:** ${coveredFeatures}`,
1516
+ `- **Coverage Percentage:** ${coveragePercent}%`,
1517
+ "",
1518
+ "### By Category",
1519
+ "",
1520
+ "| Category | Total | Covered | % |",
1521
+ "|----------|-------|---------|---|",
1522
+ ];
1523
+ for (const [cat, stats] of Object.entries(byCategory)) {
1524
+ const pct = stats.total > 0 ? Math.round((stats.covered / stats.total) * 100) : 100;
1525
+ reportLines.push(`| ${cat} | ${stats.total} | ${stats.covered} | ${pct}% |`);
1526
+ }
1527
+ reportLines.push("");
1528
+ reportLines.push(`- **Critical Gaps:** ${errors.length}`);
1529
+ reportLines.push(`- **Warnings:** ${warnings.length}`);
1530
+ reportLines.push("");
1531
+ reportLines.push("## Critical Gaps");
1532
+ reportLines.push("");
1533
+ for (const gap of errors) {
1534
+ reportLines.push(`### ${gap.feature.name}`);
1535
+ reportLines.push(`- **Type:** ${gap.feature.type}`);
1536
+ reportLines.push(`- **File:** \`${gap.feature.sourcePath}\``);
1537
+ reportLines.push(`- **Issue:** ${gap.reason}`);
1538
+ if (gap.suggestedTestFile) {
1539
+ reportLines.push(`- **Suggested Test:** \`${gap.suggestedTestFile}\``);
1540
+ }
1541
+ reportLines.push("");
1542
+ }
1543
+ if (warnings.length > 0) {
1544
+ reportLines.push("## Warnings");
1545
+ reportLines.push("");
1546
+ for (const gap of warnings.slice(0, 20)) {
1547
+ reportLines.push(`- **${gap.feature.name}** (${gap.feature.type}): ${gap.reason}`);
1548
+ }
1549
+ if (warnings.length > 20) {
1550
+ reportLines.push(`- ... and ${warnings.length - 20} more warnings`);
1551
+ }
1552
+ }
1553
+ const reportPath = "reports/playwright-coverage-gaps.md";
1554
+ const reportDir = path.dirname(reportPath);
1555
+ if (!fs.existsSync(reportDir)) {
1556
+ fs.mkdirSync(reportDir, { recursive: true });
1557
+ }
1558
+ fs.writeFileSync(reportPath, reportLines.join("\n"));
1559
+ console.log(`\n${console_chars_1.emoji.file} Report written to: ${reportPath}`);
1560
+ }
1561
+ // Summary
1562
+ console.log((0, console_chars_1.createDivider)(60, "heavy"));
1563
+ const coveragePercent = totalFeatures > 0 ? Math.round((coveredFeatures / totalFeatures) * 100) : 100;
1564
+ console.log(`\n${console_chars_1.emoji.chart} Coverage: ${coveragePercent}% (${coveredFeatures}/${totalFeatures} features)`);
1565
+ if (errors.length > 0) {
1566
+ if (warnOnly) {
1567
+ console.log(`\n${console_chars_1.emoji.warning} ${errors.length} critical gap(s), ${warnings.length} warning(s) (--warn mode, not blocking)`);
1568
+ console.log(`\nRun with --verbose for details, --report for markdown, --generate-stubs for test templates, --trend for history\n`);
1569
+ process.exit(0);
1570
+ }
1571
+ console.log(`\n${console_chars_1.emoji.error} FAILED: ${errors.length} critical gap(s), ${warnings.length} warning(s)`);
1572
+ console.log(`\nRun with --verbose for details, --report for markdown, --generate-stubs for test templates, --trend for history\n`);
1573
+ process.exit(1);
1574
+ }
1575
+ console.log(`\n${console_chars_1.emoji.success} PASSED with ${warnings.length} warning(s)`);
1576
+ process.exit(0);
1577
+ }
1578
+ // Allow direct execution
1579
+ if (require.main === module) {
1580
+ run().catch(console.error);
1581
+ }
1582
+ //# sourceMappingURL=playwright-feature-coverage-gaps.js.map