create-appraise 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/README.md +52 -0
  2. package/package.json +63 -0
  3. package/templates/default/.env.example +2 -0
  4. package/templates/default/README.md +51 -0
  5. package/templates/default/appraise.config.json +4 -0
  6. package/templates/default/components.json +24 -0
  7. package/templates/default/eslint.config.mjs +15 -0
  8. package/templates/default/next-env.d.ts +6 -0
  9. package/templates/default/next.config.ts +7 -0
  10. package/templates/default/package-lock.json +14321 -0
  11. package/templates/default/package.json +124 -0
  12. package/templates/default/postcss.config.mjs +8 -0
  13. package/templates/default/prisma/migrations/20251026202316_migrate_back_to_sqlite/migration.sql +257 -0
  14. package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -0
  15. package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -0
  16. package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -0
  17. package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -0
  18. package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -0
  19. package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -0
  20. package/templates/default/prisma/migrations/20251130190737_add_trace_path_to_test_run_test_case/migration.sql +2 -0
  21. package/templates/default/prisma/migrations/20251213074835_add_log_path_to_test_run/migration.sql +2 -0
  22. package/templates/default/prisma/migrations/20251213183952_add_name_property_for_the_test_run_entities/migration.sql +30 -0
  23. package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -0
  24. package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -0
  25. package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -0
  26. package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -0
  27. package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -0
  28. package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -0
  29. package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -0
  30. package/templates/default/prisma/migrations/migration_lock.toml +3 -0
  31. package/templates/default/prisma/schema.prisma +554 -0
  32. package/templates/default/public/favicon.ico +0 -0
  33. package/templates/default/public/file.svg +1 -0
  34. package/templates/default/public/globe.svg +1 -0
  35. package/templates/default/public/next.svg +1 -0
  36. package/templates/default/public/vercel.svg +1 -0
  37. package/templates/default/public/window.svg +1 -0
  38. package/templates/default/scripts/regenerate-features.ts +94 -0
  39. package/templates/default/scripts/setup-env.ts +19 -0
  40. package/templates/default/scripts/sync-all.ts +341 -0
  41. package/templates/default/scripts/sync-environments.ts +323 -0
  42. package/templates/default/scripts/sync-locator-groups.ts +413 -0
  43. package/templates/default/scripts/sync-locators.ts +402 -0
  44. package/templates/default/scripts/sync-modules.ts +349 -0
  45. package/templates/default/scripts/sync-tags.ts +292 -0
  46. package/templates/default/scripts/sync-template-step-groups.ts +399 -0
  47. package/templates/default/scripts/sync-template-steps.ts +806 -0
  48. package/templates/default/scripts/sync-test-cases.ts +905 -0
  49. package/templates/default/scripts/sync-test-suites.ts +411 -0
  50. package/templates/default/src/actions/conflict/conflict.action.ts +33 -0
  51. package/templates/default/src/actions/dashboard/dashboard-actions.ts +241 -0
  52. package/templates/default/src/actions/environments/environment-actions.ts +205 -0
  53. package/templates/default/src/actions/locator/locator-actions.ts +547 -0
  54. package/templates/default/src/actions/locator-groups/locator-group-actions.ts +344 -0
  55. package/templates/default/src/actions/modules/module-actions.ts +133 -0
  56. package/templates/default/src/actions/reports/report-actions.ts +614 -0
  57. package/templates/default/src/actions/review/review-actions.ts +147 -0
  58. package/templates/default/src/actions/tags/tag-actions.ts +104 -0
  59. package/templates/default/src/actions/template-step/template-step-actions.ts +332 -0
  60. package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +278 -0
  61. package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -0
  62. package/templates/default/src/actions/test-case/test-case-actions.ts +419 -0
  63. package/templates/default/src/actions/test-run/test-run-actions.ts +1185 -0
  64. package/templates/default/src/actions/test-suite/test-suite-actions.ts +253 -0
  65. package/templates/default/src/actions/user/user-actions.ts +13 -0
  66. package/templates/default/src/app/(base)/environments/create/page.tsx +28 -0
  67. package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -0
  68. package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -0
  69. package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -0
  70. package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -0
  71. package/templates/default/src/app/(base)/environments/page.tsx +59 -0
  72. package/templates/default/src/app/(base)/layout.tsx +10 -0
  73. package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -0
  74. package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -0
  75. package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -0
  76. package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -0
  77. package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -0
  78. package/templates/default/src/app/(base)/locator-groups/page.tsx +61 -0
  79. package/templates/default/src/app/(base)/locators/create/page.tsx +38 -0
  80. package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -0
  81. package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +90 -0
  82. package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -0
  83. package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +45 -0
  84. package/templates/default/src/app/(base)/locators/page.tsx +65 -0
  85. package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -0
  86. package/templates/default/src/app/(base)/modules/create/page.tsx +34 -0
  87. package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -0
  88. package/templates/default/src/app/(base)/modules/module-form.tsx +126 -0
  89. package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -0
  90. package/templates/default/src/app/(base)/modules/module-table.tsx +24 -0
  91. package/templates/default/src/app/(base)/modules/page.tsx +59 -0
  92. package/templates/default/src/app/(base)/reports/[id]/page.tsx +517 -0
  93. package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -0
  94. package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -0
  95. package/templates/default/src/app/(base)/reports/overview-chart.tsx +46 -0
  96. package/templates/default/src/app/(base)/reports/page.tsx +98 -0
  97. package/templates/default/src/app/(base)/reports/report-metric-card.tsx +16 -0
  98. package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -0
  99. package/templates/default/src/app/(base)/reports/report-table.tsx +72 -0
  100. package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +131 -0
  101. package/templates/default/src/app/(base)/reports/report-view-table.tsx +82 -0
  102. package/templates/default/src/app/(base)/reports/test-cases/page.tsx +42 -0
  103. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -0
  104. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -0
  105. package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -0
  106. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -0
  107. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -0
  108. package/templates/default/src/app/(base)/reports/view-logs-button.tsx +60 -0
  109. package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -0
  110. package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -0
  111. package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -0
  112. package/templates/default/src/app/(base)/reviews/page.tsx +26 -0
  113. package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -0
  114. package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -0
  115. package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -0
  116. package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -0
  117. package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -0
  118. package/templates/default/src/app/(base)/tags/create/page.tsx +39 -0
  119. package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -0
  120. package/templates/default/src/app/(base)/tags/page.tsx +58 -0
  121. package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -0
  122. package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -0
  123. package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -0
  124. package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -0
  125. package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -0
  126. package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -0
  127. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -0
  128. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -0
  129. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -0
  130. package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -0
  131. package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -0
  132. package/templates/default/src/app/(base)/template-steps/page.tsx +59 -0
  133. package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -0
  134. package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -0
  135. package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -0
  136. package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -0
  137. package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -0
  138. package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -0
  139. package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -0
  140. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -0
  141. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -0
  142. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -0
  143. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -0
  144. package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -0
  145. package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -0
  146. package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -0
  147. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -0
  148. package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -0
  149. package/templates/default/src/app/(base)/test-cases/page.tsx +60 -0
  150. package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -0
  151. package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -0
  152. package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +90 -0
  153. package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +35 -0
  154. package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +56 -0
  155. package/templates/default/src/app/(base)/test-runs/create/page.tsx +47 -0
  156. package/templates/default/src/app/(base)/test-runs/page.tsx +60 -0
  157. package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +512 -0
  158. package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -0
  159. package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -0
  160. package/templates/default/src/app/(base)/test-suites/create/page.tsx +45 -0
  161. package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +55 -0
  162. package/templates/default/src/app/(base)/test-suites/page.tsx +82 -0
  163. package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +269 -0
  164. package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +97 -0
  165. package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -0
  166. package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -0
  167. package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +13 -0
  168. package/templates/default/src/app/(dashboard-components)/data-card.tsx +27 -0
  169. package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +57 -0
  170. package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -0
  171. package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +45 -0
  172. package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +133 -0
  173. package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +420 -0
  174. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -0
  175. package/templates/default/src/app/favicon.ico +0 -0
  176. package/templates/default/src/app/globals.css +147 -0
  177. package/templates/default/src/app/layout.tsx +171 -0
  178. package/templates/default/src/app/page.tsx +64 -0
  179. package/templates/default/src/assets/icons/empty-tube.tsx +23 -0
  180. package/templates/default/src/assets/icons/tube-plus.tsx +29 -0
  181. package/templates/default/src/components/base-node.tsx +21 -0
  182. package/templates/default/src/components/chart/pie-chart.tsx +73 -0
  183. package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -0
  184. package/templates/default/src/components/data-state/empty-state.tsx +40 -0
  185. package/templates/default/src/components/data-visualization/info-card.tsx +70 -0
  186. package/templates/default/src/components/data-visualization/info-grid.tsx +22 -0
  187. package/templates/default/src/components/devtools/providers.tsx +13 -0
  188. package/templates/default/src/components/diagram/button-edge.tsx +54 -0
  189. package/templates/default/src/components/diagram/dynamic-parameters.tsx +438 -0
  190. package/templates/default/src/components/diagram/edit-header-option.tsx +36 -0
  191. package/templates/default/src/components/diagram/flow-diagram.tsx +470 -0
  192. package/templates/default/src/components/diagram/node-form.tsx +262 -0
  193. package/templates/default/src/components/diagram/options-header-node.tsx +57 -0
  194. package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -0
  195. package/templates/default/src/components/form/error-message.tsx +7 -0
  196. package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -0
  197. package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -0
  198. package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -0
  199. package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -0
  200. package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -0
  201. package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -0
  202. package/templates/default/src/components/logo.tsx +15 -0
  203. package/templates/default/src/components/navigation/command-badge.tsx +34 -0
  204. package/templates/default/src/components/navigation/command-chain-input.tsx +51 -0
  205. package/templates/default/src/components/navigation/entity-search-command.tsx +116 -0
  206. package/templates/default/src/components/navigation/nav-card.tsx +31 -0
  207. package/templates/default/src/components/navigation/nav-command.tsx +508 -0
  208. package/templates/default/src/components/navigation/nav-link.tsx +60 -0
  209. package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -0
  210. package/templates/default/src/components/node-header.tsx +159 -0
  211. package/templates/default/src/components/reports/test-case-logs-modal.tsx +253 -0
  212. package/templates/default/src/components/table/table-actions.tsx +172 -0
  213. package/templates/default/src/components/test-run/download-logs-button.tsx +99 -0
  214. package/templates/default/src/components/test-run/log-viewer.tsx +445 -0
  215. package/templates/default/src/components/test-run/test-run-details.tsx +611 -0
  216. package/templates/default/src/components/test-run/test-run-header.tsx +149 -0
  217. package/templates/default/src/components/test-run/view-report-button.tsx +102 -0
  218. package/templates/default/src/components/theme/mode-toggle.tsx +54 -0
  219. package/templates/default/src/components/theme/theme-provider.tsx +8 -0
  220. package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -0
  221. package/templates/default/src/components/typography/page-header.tsx +7 -0
  222. package/templates/default/src/components/ui/alert-dialog.tsx +106 -0
  223. package/templates/default/src/components/ui/alert.tsx +43 -0
  224. package/templates/default/src/components/ui/avatar.tsx +40 -0
  225. package/templates/default/src/components/ui/badge.tsx +29 -0
  226. package/templates/default/src/components/ui/button.tsx +47 -0
  227. package/templates/default/src/components/ui/calendar.tsx +158 -0
  228. package/templates/default/src/components/ui/card.tsx +43 -0
  229. package/templates/default/src/components/ui/chart.tsx +369 -0
  230. package/templates/default/src/components/ui/checkbox.tsx +28 -0
  231. package/templates/default/src/components/ui/command.tsx +135 -0
  232. package/templates/default/src/components/ui/data-table-column-header.tsx +61 -0
  233. package/templates/default/src/components/ui/data-table-pagination.tsx +87 -0
  234. package/templates/default/src/components/ui/data-table-view-options.tsx +50 -0
  235. package/templates/default/src/components/ui/data-table.tsx +267 -0
  236. package/templates/default/src/components/ui/dialog.tsx +97 -0
  237. package/templates/default/src/components/ui/dropdown-menu.tsx +182 -0
  238. package/templates/default/src/components/ui/empty.tsx +104 -0
  239. package/templates/default/src/components/ui/input.tsx +22 -0
  240. package/templates/default/src/components/ui/kbd.tsx +28 -0
  241. package/templates/default/src/components/ui/label.tsx +19 -0
  242. package/templates/default/src/components/ui/loading.tsx +12 -0
  243. package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -0
  244. package/templates/default/src/components/ui/multi-select.tsx +142 -0
  245. package/templates/default/src/components/ui/navigation-menu.tsx +120 -0
  246. package/templates/default/src/components/ui/popover.tsx +33 -0
  247. package/templates/default/src/components/ui/progress.tsx +25 -0
  248. package/templates/default/src/components/ui/radio-group.tsx +44 -0
  249. package/templates/default/src/components/ui/scroll-area.tsx +40 -0
  250. package/templates/default/src/components/ui/select.tsx +144 -0
  251. package/templates/default/src/components/ui/separator.tsx +22 -0
  252. package/templates/default/src/components/ui/skeleton.tsx +7 -0
  253. package/templates/default/src/components/ui/table.tsx +76 -0
  254. package/templates/default/src/components/ui/tabs.tsx +55 -0
  255. package/templates/default/src/components/ui/textarea.tsx +21 -0
  256. package/templates/default/src/components/ui/toast.tsx +113 -0
  257. package/templates/default/src/components/ui/toaster.tsx +26 -0
  258. package/templates/default/src/components/ui/tooltip.tsx +32 -0
  259. package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -0
  260. package/templates/default/src/config/db-config.ts +10 -0
  261. package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -0
  262. package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -0
  263. package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -0
  264. package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -0
  265. package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -0
  266. package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -0
  267. package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -0
  268. package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -0
  269. package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -0
  270. package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -0
  271. package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -0
  272. package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -0
  273. package/templates/default/src/constants/form-opts/test-run-form-opts.ts +31 -0
  274. package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -0
  275. package/templates/default/src/hooks/use-toast.ts +187 -0
  276. package/templates/default/src/lib/bidirectional-sync.ts +432 -0
  277. package/templates/default/src/lib/database-sync.ts +531 -0
  278. package/templates/default/src/lib/environment-file-utils.ts +221 -0
  279. package/templates/default/src/lib/feature-file-generator.ts +411 -0
  280. package/templates/default/src/lib/gherkin-parser.ts +259 -0
  281. package/templates/default/src/lib/locator-group-file-utils.ts +370 -0
  282. package/templates/default/src/lib/metrics/metric-calculator.ts +613 -0
  283. package/templates/default/src/lib/module-hierarchy-builder.ts +205 -0
  284. package/templates/default/src/lib/path-helpers/module-path.ts +71 -0
  285. package/templates/default/src/lib/test-case-utils.ts +6 -0
  286. package/templates/default/src/lib/test-run/log-formatter.ts +83 -0
  287. package/templates/default/src/lib/test-run/process-manager.ts +191 -0
  288. package/templates/default/src/lib/test-run/report-parser.ts +316 -0
  289. package/templates/default/src/lib/test-run/test-run-executor.ts +144 -0
  290. package/templates/default/src/lib/test-run/winston-logger.ts +95 -0
  291. package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -0
  292. package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -0
  293. package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -0
  294. package/templates/default/src/lib/utils/node-param-validation.ts +81 -0
  295. package/templates/default/src/lib/utils/template-step-file-generator.ts +167 -0
  296. package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +723 -0
  297. package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -0
  298. package/templates/default/src/lib/utils.ts +31 -0
  299. package/templates/default/src/tests/config/environments/environments.json +14 -0
  300. package/templates/default/src/tests/config/executor/world.ts +41 -0
  301. package/templates/default/src/tests/executor.ts +80 -0
  302. package/templates/default/src/tests/hooks/hooks.ts +99 -0
  303. package/templates/default/src/tests/mapping/locator-map.json +1 -0
  304. package/templates/default/src/tests/steps/actions/click.step.ts +62 -0
  305. package/templates/default/src/tests/steps/actions/hover.step.ts +31 -0
  306. package/templates/default/src/tests/steps/actions/input.step.ts +149 -0
  307. package/templates/default/src/tests/steps/actions/navigation.step.ts +72 -0
  308. package/templates/default/src/tests/steps/actions/random_data.step.ts +146 -0
  309. package/templates/default/src/tests/steps/actions/store.step.ts +90 -0
  310. package/templates/default/src/tests/steps/actions/wait.step.ts +107 -0
  311. package/templates/default/src/tests/steps/validations/active_state_assertion.step.ts +34 -0
  312. package/templates/default/src/tests/steps/validations/navigation_assertion.step.ts +23 -0
  313. package/templates/default/src/tests/steps/validations/text_assertion.step.ts +111 -0
  314. package/templates/default/src/tests/steps/validations/visibility_assertion.step.ts +30 -0
  315. package/templates/default/src/tests/support/parameter-types.ts +12 -0
  316. package/templates/default/src/tests/utils/cache.util.ts +260 -0
  317. package/templates/default/src/tests/utils/cli.util.ts +177 -0
  318. package/templates/default/src/tests/utils/environment.util.ts +65 -0
  319. package/templates/default/src/tests/utils/locator.util.ts +248 -0
  320. package/templates/default/src/tests/utils/random-data.util.ts +45 -0
  321. package/templates/default/src/tests/utils/spawner.util.ts +617 -0
  322. package/templates/default/src/types/diagram/diagram.ts +34 -0
  323. package/templates/default/src/types/diagram/template-step.ts +11 -0
  324. package/templates/default/src/types/executor/browser.type.ts +1 -0
  325. package/templates/default/src/types/form/actionHandler.ts +6 -0
  326. package/templates/default/src/types/locator/locator.type.ts +11 -0
  327. package/templates/default/src/types/step/step.type.ts +1 -0
  328. package/templates/default/src/types/table/data-table.ts +6 -0
  329. package/templates/default/tailwind.config.ts +62 -0
  330. package/templates/default/tsconfig.json +28 -0
@@ -0,0 +1,316 @@
1
+ import { readFile } from 'fs/promises'
2
+ import { StepStatus, StepKeyword } from '@prisma/client'
3
+
4
+ /**
5
+ * Parsed report structure matching cucumber.json format
6
+ */
7
+ export interface ParsedReport {
8
+ features: Array<{
9
+ name: string
10
+ description: string
11
+ uri: string
12
+ line: number
13
+ keyword: string
14
+ tags: Array<{ name: string; line: number }>
15
+ scenarios: Array<{
16
+ name: string
17
+ description: string
18
+ line: number
19
+ keyword: string
20
+ type: string
21
+ cucumberId: string
22
+ tags: Array<{ name: string; line: number }>
23
+ steps: Array<{
24
+ keyword: string
25
+ line: number | null
26
+ name: string
27
+ matchLocation?: string
28
+ status: string
29
+ duration: number
30
+ errorMessage?: string
31
+ errorTrace?: string
32
+ hidden: boolean
33
+ order: number
34
+ }>
35
+ hooks: Array<{
36
+ keyword: string
37
+ status: string
38
+ duration: number
39
+ errorMessage?: string
40
+ errorTrace?: string
41
+ hidden: boolean
42
+ }>
43
+ }>
44
+ }>
45
+ }
46
+
47
+ /**
48
+ * Cucumber JSON report structure (as received from cucumber-js)
49
+ */
50
+ interface CucumberJsonFeature {
51
+ description: string
52
+ elements: Array<{
53
+ description: string
54
+ id: string
55
+ keyword: string
56
+ line: number
57
+ name: string
58
+ steps: Array<{
59
+ keyword: string
60
+ line?: number
61
+ name?: string
62
+ hidden?: boolean
63
+ match?: {
64
+ location: string
65
+ }
66
+ result?: {
67
+ status: string
68
+ duration?: number
69
+ error_message?: string
70
+ }
71
+ }>
72
+ tags: Array<{
73
+ name: string
74
+ line: number
75
+ }>
76
+ type: string
77
+ }>
78
+ id: string
79
+ line: number
80
+ keyword: string
81
+ name: string
82
+ tags: Array<{
83
+ name: string
84
+ line: number
85
+ }>
86
+ uri: string
87
+ }
88
+
89
+ /**
90
+ * Maps cucumber step status to Prisma StepStatus enum
91
+ */
92
+ function mapStepStatus(status: string): StepStatus {
93
+ const upperStatus = status.toUpperCase()
94
+ switch (upperStatus) {
95
+ case 'PASSED':
96
+ return StepStatus.PASSED
97
+ case 'FAILED':
98
+ return StepStatus.FAILED
99
+ case 'SKIPPED':
100
+ return StepStatus.SKIPPED
101
+ case 'PENDING':
102
+ return StepStatus.PENDING
103
+ case 'UNDEFINED':
104
+ return StepStatus.UNDEFINED
105
+ default:
106
+ return StepStatus.PENDING
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Maps cucumber step keyword to Prisma StepKeyword enum
112
+ */
113
+ function mapStepKeyword(keyword: string): StepKeyword {
114
+ const trimmedKeyword = keyword.trim()
115
+ const upperKeyword = trimmedKeyword.toUpperCase()
116
+ switch (upperKeyword) {
117
+ case 'GIVEN':
118
+ return StepKeyword.GIVEN
119
+ case 'WHEN':
120
+ return StepKeyword.WHEN
121
+ case 'THEN':
122
+ return StepKeyword.THEN
123
+ case 'AND':
124
+ return StepKeyword.AND
125
+ case 'BUT':
126
+ return StepKeyword.BUT
127
+ case 'BEFORE':
128
+ return StepKeyword.BEFORE
129
+ case 'AFTER':
130
+ return StepKeyword.AFTER
131
+ default:
132
+ // Default to GIVEN for unknown keywords
133
+ return StepKeyword.GIVEN
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Separates error message from stack trace
139
+ * Cucumber's error_message typically contains both the error message and stack trace
140
+ * The stack trace usually starts with "at" or contains file paths
141
+ *
142
+ * @param errorMessage - The full error message from Cucumber
143
+ * @returns Object with separated message and trace
144
+ */
145
+ function separateErrorMessageAndTrace(errorMessage: string | undefined): {
146
+ message: string | undefined
147
+ trace: string | undefined
148
+ } {
149
+ if (!errorMessage) {
150
+ return { message: undefined, trace: undefined }
151
+ }
152
+
153
+ // Look for common stack trace indicators
154
+ // Stack traces typically start with "at", " at", or contain file paths with line numbers
155
+ const stackTracePatterns = [
156
+ /\n\s*at\s/, // "at" at the start of a line (with optional whitespace)
157
+ /\n\s+at\s/, // "at" with leading whitespace
158
+ /Error:\s*$/m, // Error: at end of line (message ends, trace starts)
159
+ ]
160
+
161
+ // Find the first occurrence of a stack trace pattern
162
+ let splitIndex = -1
163
+ for (const pattern of stackTracePatterns) {
164
+ const match = errorMessage.match(pattern)
165
+ if (match && match.index !== undefined) {
166
+ // If we find "at" pattern, split before it (include the newline before "at")
167
+ // If we find "Error:" pattern, split after it
168
+ if (pattern.source.includes('Error:')) {
169
+ splitIndex = match.index + match[0].length
170
+ } else {
171
+ splitIndex = match.index
172
+ }
173
+ break
174
+ }
175
+ }
176
+
177
+ // If no stack trace pattern found, check if it looks like just a message (short, no file paths)
178
+ if (splitIndex === -1) {
179
+ // Check if it contains file paths (common in stack traces)
180
+ const hasFilePath = /[\/\\][\w\-\.]+:\d+/.test(errorMessage)
181
+ if (hasFilePath && errorMessage.length > 200) {
182
+ // Likely contains a trace, try to find where message ends
183
+ // Usually the first few lines are the message, rest is trace
184
+ const lines = errorMessage.split('\n')
185
+ // Look for the first line that starts with whitespace and "at" or contains a file path
186
+ for (let i = 0; i < lines.length; i++) {
187
+ if (/^\s*at\s/.test(lines[i]) || /[\/\\][\w\-\.]+:\d+/.test(lines[i])) {
188
+ splitIndex = errorMessage.indexOf(lines[i])
189
+ break
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ if (splitIndex > 0) {
196
+ const message = errorMessage.substring(0, splitIndex).trim()
197
+ const trace = errorMessage.substring(splitIndex).trim()
198
+ return {
199
+ message: message || undefined,
200
+ trace: trace || undefined,
201
+ }
202
+ }
203
+
204
+ // If we can't separate them, treat the whole thing as the message
205
+ // and leave trace as undefined (better than duplicating)
206
+ return {
207
+ message: errorMessage.trim() || undefined,
208
+ trace: undefined,
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Parses a cucumber.json report file into a structured ParsedReport object
214
+ *
215
+ * @param reportPath - Path to the cucumber.json file
216
+ * @returns Parsed report structure
217
+ * @throws Error if file cannot be read or parsed
218
+ */
219
+ export async function parseCucumberReport(reportPath: string): Promise<ParsedReport> {
220
+ try {
221
+ // Read the report file
222
+ const fileContent = await readFile(reportPath, 'utf-8')
223
+ const cucumberData: CucumberJsonFeature[] = JSON.parse(fileContent)
224
+
225
+ // Parse features
226
+ const features = cucumberData.map(feature => {
227
+ // Separate steps into regular steps and hooks
228
+ const scenarios = feature.elements.map(element => {
229
+ const steps: ParsedReport['features'][0]['scenarios'][0]['steps'] = []
230
+ const hooks: ParsedReport['features'][0]['scenarios'][0]['hooks'] = []
231
+
232
+ element.steps.forEach((step, index) => {
233
+ const isHook = step.keyword === 'Before' || step.keyword === 'After'
234
+ const stepStatus = step.result?.status || 'pending'
235
+ const duration = step.result?.duration || 0
236
+
237
+ // Separate error message from stack trace
238
+ const { message: errorMessage, trace: errorTrace } = separateErrorMessageAndTrace(step.result?.error_message)
239
+
240
+ if (isHook) {
241
+ hooks.push({
242
+ keyword: step.keyword,
243
+ status: stepStatus,
244
+ duration,
245
+ errorMessage,
246
+ errorTrace,
247
+ hidden: step.hidden || false,
248
+ })
249
+ } else {
250
+ steps.push({
251
+ keyword: step.keyword.trim(),
252
+ line: step.line || null,
253
+ name: step.name || '',
254
+ matchLocation: step.match?.location,
255
+ status: stepStatus,
256
+ duration,
257
+ errorMessage,
258
+ errorTrace,
259
+ hidden: step.hidden || false,
260
+ order: index,
261
+ })
262
+ }
263
+ })
264
+
265
+ return {
266
+ name: element.name,
267
+ description: element.description || '',
268
+ line: element.line,
269
+ keyword: element.keyword,
270
+ type: element.type,
271
+ cucumberId: element.id,
272
+ tags: element.tags.map(tag => ({
273
+ name: tag.name,
274
+ line: tag.line,
275
+ })),
276
+ steps,
277
+ hooks,
278
+ }
279
+ })
280
+
281
+ return {
282
+ name: feature.name,
283
+ description: feature.description || '',
284
+ uri: feature.uri,
285
+ line: feature.line,
286
+ keyword: feature.keyword,
287
+ tags: feature.tags.map(tag => ({
288
+ name: tag.name,
289
+ line: tag.line,
290
+ })),
291
+ scenarios,
292
+ }
293
+ })
294
+
295
+ return { features }
296
+ } catch (error) {
297
+ if (error instanceof Error) {
298
+ throw new Error(`Failed to parse cucumber report at ${reportPath}: ${error.message}`)
299
+ }
300
+ throw new Error(`Failed to parse cucumber report at ${reportPath}: Unknown error`)
301
+ }
302
+ }
303
+
304
+ /**
305
+ * Helper function to convert parsed step status to Prisma enum
306
+ */
307
+ export function getStepStatusEnum(status: string): StepStatus {
308
+ return mapStepStatus(status)
309
+ }
310
+
311
+ /**
312
+ * Helper function to convert parsed step keyword to Prisma enum
313
+ */
314
+ export function getStepKeywordEnum(keyword: string): StepKeyword {
315
+ return mapStepKeyword(keyword)
316
+ }
@@ -0,0 +1,144 @@
1
+ import { BrowserEngine, Environment, Tag } from '@prisma/client'
2
+ import { spawnTask } from '@/tests/utils/spawner.util'
3
+ import { processManager } from './process-manager'
4
+ import type { SpawnedProcess } from '@/tests/utils/spawner.util'
5
+ import { join } from 'path'
6
+
7
+ /**
8
+ * Configuration for executing a test run
9
+ */
10
+ export interface TestRunExecutionConfig {
11
+ testRunId: string
12
+ environment: Environment
13
+ tags: Tag[]
14
+ testWorkersCount: number
15
+ browserEngine: BrowserEngine
16
+ headless?: boolean
17
+ }
18
+
19
+ /**
20
+ * Maps BrowserEngine enum to browser name string for CLI
21
+ */
22
+ function mapBrowserEngineToName(browserEngine: BrowserEngine): 'chromium' | 'firefox' | 'webkit' {
23
+ switch (browserEngine) {
24
+ case BrowserEngine.CHROMIUM:
25
+ return 'chromium'
26
+ case BrowserEngine.FIREFOX:
27
+ return 'firefox'
28
+ case BrowserEngine.WEBKIT:
29
+ return 'webkit'
30
+ default:
31
+ return 'chromium'
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Combines multiple tag expressions into a single Cucumber tag expression
37
+ * Uses OR logic to combine tags: (@tag1 or @tag2 or @tag3)
38
+ */
39
+ function combineTagExpressions(tags: Tag[]): string | null {
40
+ if (tags.length === 0) {
41
+ return null
42
+ }
43
+
44
+ if (tags.length === 1) {
45
+ return tags[0].tagExpression
46
+ }
47
+
48
+ // Combine multiple tag expressions with OR
49
+ return tags.map(tag => `(${tag.tagExpression})`).join(' or ')
50
+ }
51
+
52
+ /**
53
+ * Generates a unique report path for a test run
54
+ * Format: src/tests/reports/cucumber-{testRunId}-{timestamp}.json
55
+ *
56
+ * @param testRunId - The test run ID (runId, not id)
57
+ * @returns The full path to the report file
58
+ */
59
+ export function generateReportPath(testRunId: string): string {
60
+ const timestamp = Date.now()
61
+ const reportFileName = `cucumber-${testRunId}-${timestamp}.json`
62
+ const reportPath = join(process.cwd(), 'src', 'tests', 'reports', reportFileName)
63
+ return reportPath
64
+ }
65
+
66
+ /**
67
+ * Sets environment variables for the test execution
68
+ */
69
+ function setEnvironmentVariables(
70
+ environment: Environment,
71
+ headless: boolean,
72
+ browser: string,
73
+ reportPath?: string,
74
+ ): void {
75
+ process.env.ENVIRONMENT = environment.name
76
+ process.env.HEADLESS = headless.toString()
77
+ process.env.BROWSER = browser
78
+ if (reportPath) {
79
+ process.env.REPORT_PATH = reportPath
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Executes a test run by spawning a cucumber process
85
+ *
86
+ * @param config - Test run execution configuration
87
+ * @returns Promise that resolves to an object containing the spawned process and report path
88
+ */
89
+ export async function executeTestRun(config: TestRunExecutionConfig): Promise<{
90
+ process: SpawnedProcess
91
+ reportPath: string
92
+ }> {
93
+ const { testRunId, environment, tags, testWorkersCount, browserEngine, headless = true } = config
94
+
95
+ // Generate unique report path
96
+ const reportPath = generateReportPath(testRunId)
97
+
98
+ // Map browser engine to browser name
99
+ const browserName = mapBrowserEngineToName(browserEngine)
100
+
101
+ // Set environment variables including report path
102
+ setEnvironmentVariables(environment, headless, browserName, reportPath)
103
+
104
+ // Build cucumber command arguments
105
+ const cucumberArgs: string[] = []
106
+
107
+ // Add tag expression if tags are provided
108
+ const tagExpression = combineTagExpressions(tags)
109
+ if (tagExpression) {
110
+ cucumberArgs.push('-t', tagExpression)
111
+ }
112
+
113
+ // Add parallel flag if workers > 1
114
+ if (testWorkersCount > 1) {
115
+ cucumberArgs.push('--parallel', testWorkersCount.toString())
116
+ }
117
+
118
+ // Spawn the cucumber test process
119
+ // Enable streamLogs to see output in console for debugging
120
+ // Use captureOutput: true to capture logs for streaming
121
+ const process = await spawnTask('npx', ['cucumber-js', ...cucumberArgs], {
122
+ streamLogs: true, // Enable console output to verify logs are being generated
123
+ prefixLogs: true, // Add prefix to identify logs
124
+ logPrefix: `test-run-${testRunId}`,
125
+ captureOutput: true, // Capture output for streaming
126
+ })
127
+
128
+ // Register the process in ProcessManager
129
+ console.log(`[TestRunExecutor] Registering process for testRunId: ${testRunId}, process name: ${process.name}`)
130
+ processManager.register(testRunId, process)
131
+ console.log(`[TestRunExecutor] Process registered. ProcessManager now has ${processManager.size()} processes`)
132
+
133
+ // Set up exit handler - Immediately unregister process to free up memory
134
+ process.process.on('exit', code => {
135
+ // Immediately unregister the process to free up memory
136
+ // Log storage will be handled in createTestRunAction after process completion
137
+ processManager.unregister(testRunId)
138
+ console.log(
139
+ `[TestRunExecutor] Process exited for testRunId: ${testRunId} with code ${code}, unregistered from ProcessManager`,
140
+ )
141
+ })
142
+
143
+ return { process, reportPath }
144
+ }
@@ -0,0 +1,95 @@
1
+ import winston from 'winston'
2
+ import path from 'path'
3
+ import { promises as fs } from 'fs'
4
+
5
+ const LOGS_DIR = path.join(process.cwd(), 'src', 'tests', 'reports', 'logs')
6
+
7
+ /**
8
+ * Ensures the logs directory exists, creating it if necessary
9
+ */
10
+ async function ensureLogsDirectory(): Promise<void> {
11
+ try {
12
+ await fs.access(LOGS_DIR)
13
+ } catch {
14
+ // Directory doesn't exist, create it
15
+ await fs.mkdir(LOGS_DIR, { recursive: true })
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Creates a Winston logger instance for a specific test run
21
+ * @param testRunId - The unique test run ID (runId, not id)
22
+ * @returns A configured Winston logger instance
23
+ */
24
+ export async function createTestRunLogger(testRunId: string): Promise<winston.Logger> {
25
+ // Ensure logs directory exists
26
+ await ensureLogsDirectory()
27
+
28
+ // Create log file path
29
+ const logFilePath = path.join(LOGS_DIR, `${testRunId}.log`)
30
+
31
+ // Define log format
32
+ const logFormat = winston.format.combine(
33
+ winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
34
+ winston.format.errors({ stack: true }),
35
+ winston.format.printf(({ timestamp, level, message, stack }) => {
36
+ if (stack) {
37
+ return `${timestamp} [${level.toUpperCase()}]: ${message}\n${stack}`
38
+ }
39
+ return `${timestamp} [${level.toUpperCase()}]: ${message}`
40
+ }),
41
+ )
42
+
43
+ // Create logger with console and file transports
44
+ const logger = winston.createLogger({
45
+ level: 'info',
46
+ format: logFormat,
47
+ transports: [
48
+ // Console transport (stdout)
49
+ new winston.transports.Console({
50
+ format: winston.format.combine(
51
+ winston.format.colorize(),
52
+ winston.format.printf(({ timestamp, level, message, stack }) => {
53
+ if (stack) {
54
+ return `${timestamp} [${level}]: ${message}\n${stack}`
55
+ }
56
+ return `${timestamp} [${level}]: ${message}`
57
+ }),
58
+ ),
59
+ }),
60
+ // File transport
61
+ new winston.transports.File({
62
+ filename: logFilePath,
63
+ maxsize: 10 * 1024 * 1024, // 10MB
64
+ maxFiles: 5,
65
+ }),
66
+ ],
67
+ })
68
+
69
+ return logger
70
+ }
71
+
72
+ /**
73
+ * Closes a Winston logger instance, ensuring all logs are flushed
74
+ * @param logger - The logger instance to close
75
+ */
76
+ export async function closeLogger(logger: winston.Logger): Promise<void> {
77
+ return new Promise((resolve, reject) => {
78
+ logger.end((err: Error | null) => {
79
+ if (err) {
80
+ reject(err)
81
+ } else {
82
+ resolve()
83
+ }
84
+ })
85
+ })
86
+ }
87
+
88
+ /**
89
+ * Gets the log file path for a test run
90
+ * @param testRunId - The unique test run ID (runId, not id)
91
+ * @returns The absolute path to the log file
92
+ */
93
+ export function getLogFilePath(testRunId: string): string {
94
+ return path.join(LOGS_DIR, `${testRunId}.log`)
95
+ }
@@ -0,0 +1,42 @@
1
+ import { TemplateStepType } from '@prisma/client'
2
+
3
+ export const generateGherkinStep = (
4
+ type: TemplateStepType,
5
+ signature: string,
6
+ parameters: { value: string; order: number }[],
7
+ ) => {
8
+ const signatureParts = signature.split(' ')
9
+ const sortedParameters = parameters.sort((a, b) => a.order - b.order)
10
+
11
+ const gherkinStep = signatureParts
12
+ .map(part => {
13
+ // Check if this part is a parameter placeholder
14
+ if (part.startsWith('{') && part.endsWith('}')) {
15
+ const parameter = sortedParameters.shift()
16
+
17
+ // If no parameter or missing value, return the placeholder to indicate incompleteness
18
+ if (!parameter || !parameter.value || parameter.value.trim() === '') {
19
+ return part
20
+ }
21
+
22
+ // Format the parameter value based on its type
23
+ switch (part) {
24
+ case '{string}':
25
+ return `"${parameter.value}"`
26
+ case '{int}':
27
+ return parameter.value
28
+ case '{boolean}':
29
+ return parameter.value
30
+ default:
31
+ return parameter.value
32
+ }
33
+ }
34
+
35
+ return part
36
+ })
37
+ .join(' ')
38
+
39
+ // Prepend the appropriate Gherkin keyword based on type
40
+ const keyword = type === 'ACTION' ? 'When' : 'Then'
41
+ return `${keyword} ${gherkinStep}`
42
+ }
@@ -0,0 +1,95 @@
1
+ import { TemplateStepIcon } from '@prisma/client'
2
+ import {
3
+ ALargeSmall,
4
+ BugPlay,
5
+ Database,
6
+ Download,
7
+ Globe,
8
+ Keyboard,
9
+ MousePointerClick,
10
+ Save,
11
+ Server,
12
+ Upload,
13
+ Loader,
14
+ CheckCheck,
15
+ LucideIcon,
16
+ } from 'lucide-react'
17
+ import { ReactElement } from 'react'
18
+
19
+ export const KeyToIconTransformer = (key: TemplateStepIcon, className?: string) => {
20
+ switch (key) {
21
+ case 'MOUSE':
22
+ return <MousePointerClick className={className} />
23
+ case 'NAVIGATION':
24
+ return <Globe className={className} />
25
+ case 'INPUT':
26
+ return <Keyboard className={className} />
27
+ case 'DOWNLOAD':
28
+ return <Download className={className} />
29
+ case 'API':
30
+ return <Server className={className} />
31
+ case 'STORE':
32
+ return <Save className={className} />
33
+ case 'FORMAT':
34
+ return <ALargeSmall className={className} />
35
+ case 'DATA':
36
+ return <Database className={className} />
37
+ case 'UPLOAD':
38
+ return <Upload className={className} />
39
+ case 'WAIT':
40
+ return <Loader className={className} />
41
+ case 'VALIDATION':
42
+ return <CheckCheck className={className} />
43
+ case 'DEBUG':
44
+ return <BugPlay className={className} />
45
+ }
46
+ }
47
+
48
+ // Map of component types to TemplateStepIcon values
49
+ const componentToIconMap = new Map<LucideIcon, TemplateStepIcon>([
50
+ [MousePointerClick, 'MOUSE'],
51
+ [Globe, 'NAVIGATION'],
52
+ [Keyboard, 'INPUT'],
53
+ [Download, 'DOWNLOAD'],
54
+ [Server, 'API'],
55
+ [Save, 'STORE'],
56
+ [ALargeSmall, 'FORMAT'],
57
+ [Database, 'DATA'],
58
+ [Upload, 'UPLOAD'],
59
+ [Loader, 'WAIT'],
60
+ [CheckCheck, 'VALIDATION'],
61
+ [BugPlay, 'DEBUG'],
62
+ ])
63
+
64
+ // Map of string values to TemplateStepIcon values
65
+ const stringToIconMap = new Map<string, TemplateStepIcon>([
66
+ ['MOUSE', 'MOUSE'],
67
+ ['NAVIGATION', 'NAVIGATION'],
68
+ ['INPUT', 'INPUT'],
69
+ ['DOWNLOAD', 'DOWNLOAD'],
70
+ ['API', 'API'],
71
+ ['STORE', 'STORE'],
72
+ ['FORMAT', 'FORMAT'],
73
+ ['DATA', 'DATA'],
74
+ ['UPLOAD', 'UPLOAD'],
75
+ ['WAIT', 'WAIT'],
76
+ ['VALIDATION', 'VALIDATION'],
77
+ ['DEBUG', 'DEBUG'],
78
+ ])
79
+
80
+ export const IconToKeyTransformer = (icon: React.ReactNode | string): TemplateStepIcon | undefined => {
81
+ // Handle string input
82
+ if (typeof icon === 'string') {
83
+ return stringToIconMap.get(icon)
84
+ }
85
+
86
+ // Handle React component input
87
+ if (!icon || typeof icon !== 'object') return undefined
88
+
89
+ // Get the component type from the React element
90
+ const componentType = (icon as ReactElement)?.type
91
+ if (!componentType) return undefined
92
+
93
+ // Look up the icon in our map
94
+ return componentToIconMap.get(componentType as LucideIcon)
95
+ }