create-appraisejs 0.2.0 → 0.3.0-alpha.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 (485) hide show
  1. package/README.md +12 -1
  2. package/package.json +1 -1
  3. package/templates/default/.appraise-template-meta.json +2 -2
  4. package/templates/default/.env.example +2 -2
  5. package/templates/default/README.md +57 -53
  6. package/templates/default/automation/steps/actions/click.step.ts +58 -58
  7. package/templates/default/automation/steps/actions/hover.step.ts +27 -27
  8. package/templates/default/automation/steps/actions/navigation.step.ts +70 -70
  9. package/templates/default/automation/steps/actions/random_data.step.ts +142 -142
  10. package/templates/default/automation/steps/actions/store.step.ts +86 -86
  11. package/templates/default/automation/steps/actions/wait.step.ts +110 -90
  12. package/templates/default/automation/steps/validations/active_state_assertion.step.ts +30 -30
  13. package/templates/default/automation/steps/validations/navigation_assertion.step.ts +22 -22
  14. package/templates/default/automation/steps/validations/text_assertion.step.ts +107 -107
  15. package/templates/default/automation/steps/validations/visibility_assertion.step.ts +26 -26
  16. package/templates/default/components.json +24 -24
  17. package/templates/default/cucumber.mjs +16 -16
  18. package/templates/default/eslint.config.mjs +20 -16
  19. package/templates/default/next-env.d.ts +6 -6
  20. package/templates/default/next.config.ts +20 -11
  21. package/templates/default/package-lock.json +1775 -74
  22. package/templates/default/package.json +8 -1
  23. package/templates/default/packages/cucumber-runtime/package.json +13 -13
  24. package/templates/default/packages/cucumber-runtime/src/cache.util.ts +93 -93
  25. package/templates/default/packages/cucumber-runtime/src/cli.ts +68 -68
  26. package/templates/default/packages/cucumber-runtime/src/environment.util.ts +21 -21
  27. package/templates/default/packages/cucumber-runtime/src/executor.ts +32 -32
  28. package/templates/default/packages/cucumber-runtime/src/index.ts +17 -17
  29. package/templates/default/packages/cucumber-runtime/src/locator.util.ts +234 -234
  30. package/templates/default/packages/cucumber-runtime/src/parameter-types.ts +7 -7
  31. package/templates/default/packages/cucumber-runtime/src/random-data.util.ts +35 -35
  32. package/templates/default/packages/cucumber-runtime/src/types.ts +13 -13
  33. package/templates/default/packages/cucumber-runtime/src/world.ts +44 -44
  34. package/templates/default/packages/cucumber-runtime/tsconfig.json +11 -11
  35. package/templates/default/postcss.config.mjs +8 -8
  36. package/templates/default/prisma/dev.db +0 -0
  37. package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
  38. package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
  39. package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
  40. package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
  41. package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
  42. package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
  43. package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
  44. package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
  45. package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
  46. package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
  47. package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
  48. package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
  49. package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
  50. package/templates/default/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -1
  51. package/templates/default/scripts/build-step-registry.ts +33 -0
  52. package/templates/default/scripts/install-playwright.ts +17 -8
  53. package/templates/default/scripts/install-template-step.ts +128 -0
  54. package/templates/default/scripts/lib/filename-utils.test.ts +24 -0
  55. package/templates/default/scripts/lib/filename-utils.ts +24 -0
  56. package/templates/default/scripts/lib/jsdoc-parser.test.ts +63 -0
  57. package/templates/default/scripts/lib/jsdoc-parser.ts +88 -0
  58. package/templates/default/scripts/lib/step-file-parser.test.ts +71 -0
  59. package/templates/default/scripts/lib/step-file-parser.ts +315 -0
  60. package/templates/default/scripts/lib/step-matcher.test.ts +86 -0
  61. package/templates/default/scripts/lib/step-matcher.ts +120 -0
  62. package/templates/default/scripts/lib/sync-script-runner.ts +23 -0
  63. package/templates/default/scripts/lib/sync-summary.ts +29 -0
  64. package/templates/default/scripts/lib/tag-parsing.test.ts +20 -0
  65. package/templates/default/scripts/lib/tag-parsing.ts +10 -0
  66. package/templates/default/scripts/lib/template-step-installer.test.ts +225 -0
  67. package/templates/default/scripts/lib/template-step-installer.ts +404 -0
  68. package/templates/default/scripts/lib/template-step-registry.test.ts +118 -0
  69. package/templates/default/scripts/lib/template-step-registry.ts +137 -0
  70. package/templates/default/scripts/protect-seeded-files.ts +51 -38
  71. package/templates/default/scripts/regenerate-features.ts +98 -94
  72. package/templates/default/scripts/run-vitest.ts +59 -0
  73. package/templates/default/scripts/setup-env.ts +26 -19
  74. package/templates/default/scripts/sync-all.ts +44 -54
  75. package/templates/default/scripts/sync-appraise-base-template.ts +44 -16
  76. package/templates/default/scripts/sync-environments.ts +22 -66
  77. package/templates/default/scripts/sync-locator-groups.ts +358 -410
  78. package/templates/default/scripts/sync-locators.ts +348 -398
  79. package/templates/default/scripts/sync-modules.ts +302 -341
  80. package/templates/default/scripts/sync-tags.ts +29 -65
  81. package/templates/default/scripts/sync-template-step-groups.ts +24 -182
  82. package/templates/default/scripts/sync-template-steps.ts +36 -493
  83. package/templates/default/scripts/sync-test-cases.ts +296 -539
  84. package/templates/default/scripts/sync-test-suites.ts +32 -79
  85. package/templates/default/src/actions/dashboard/dashboard-actions.ts +70 -241
  86. package/templates/default/src/actions/environments/environment-actions.ts +102 -188
  87. package/templates/default/src/actions/locator/locator-actions.ts +77 -490
  88. package/templates/default/src/actions/locator-groups/locator-group-actions.ts +34 -212
  89. package/templates/default/src/actions/locator-picker/locator-picker-actions.test.ts +81 -0
  90. package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +20 -161
  91. package/templates/default/src/actions/modules/module-actions.ts +99 -135
  92. package/templates/default/src/actions/reports/report-actions.ts +28 -565
  93. package/templates/default/src/actions/settings/sync-actions.test.ts +58 -0
  94. package/templates/default/src/actions/tags/tag-actions.ts +99 -107
  95. package/templates/default/src/actions/template-step/template-step-actions.ts +33 -194
  96. package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +35 -92
  97. package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +98 -238
  98. package/templates/default/src/actions/test-case/test-case-actions.ts +108 -356
  99. package/templates/default/src/actions/test-run/test-run-actions.ts +74 -1081
  100. package/templates/default/src/actions/test-suite/test-suite-actions.ts +35 -202
  101. package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
  102. package/templates/default/src/app/(base)/environments/environment-form.test.tsx +92 -0
  103. package/templates/default/src/app/(base)/environments/environment-form.tsx +228 -219
  104. package/templates/default/src/app/(base)/environments/environment-helpers.ts +58 -0
  105. package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
  106. package/templates/default/src/app/(base)/environments/environment-table.tsx +25 -24
  107. package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +49 -46
  108. package/templates/default/src/app/(base)/environments/page.tsx +59 -59
  109. package/templates/default/src/app/(base)/layout.tsx +10 -10
  110. package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
  111. package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
  112. package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
  113. package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
  114. package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
  115. package/templates/default/src/app/(base)/locators/create/create-locator-workspace-helpers.test.ts +71 -0
  116. package/templates/default/src/app/(base)/locators/create/create-locator-workspace-helpers.ts +333 -0
  117. package/templates/default/src/app/(base)/locators/create/create-locator-workspace.test.tsx +125 -0
  118. package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +56 -274
  119. package/templates/default/src/app/(base)/locators/create/page.tsx +8 -4
  120. package/templates/default/src/app/(base)/locators/create/use-locator-workspace.ts +183 -0
  121. package/templates/default/src/app/(base)/locators/locator-helpers.test.ts +28 -0
  122. package/templates/default/src/app/(base)/locators/locator-helpers.ts +59 -0
  123. package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +74 -73
  124. package/templates/default/src/app/(base)/locators/locator-table.tsx +30 -28
  125. package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +20 -8
  126. package/templates/default/src/app/(base)/locators/page.tsx +3 -6
  127. package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +67 -66
  128. package/templates/default/src/app/(base)/modules/create/page.tsx +33 -34
  129. package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +43 -46
  130. package/templates/default/src/app/(base)/modules/module-form.test.tsx +84 -0
  131. package/templates/default/src/app/(base)/modules/module-form.tsx +159 -126
  132. package/templates/default/src/app/(base)/modules/module-helpers.ts +64 -0
  133. package/templates/default/src/app/(base)/modules/module-table-columns.tsx +81 -85
  134. package/templates/default/src/app/(base)/modules/module-table.tsx +25 -24
  135. package/templates/default/src/app/(base)/modules/page.tsx +59 -59
  136. package/templates/default/src/app/(base)/reports/[id]/page.tsx +20 -260
  137. package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
  138. package/templates/default/src/app/(base)/reports/feature-chart.tsx +79 -78
  139. package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -49
  140. package/templates/default/src/app/(base)/reports/page.tsx +98 -98
  141. package/templates/default/src/app/(base)/reports/report-detail-helpers.test.ts +109 -0
  142. package/templates/default/src/app/(base)/reports/report-detail-helpers.ts +247 -0
  143. package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -78
  144. package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
  145. package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
  146. package/templates/default/src/app/(base)/reports/test-cases/page.tsx +40 -40
  147. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
  148. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
  149. package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
  150. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
  151. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
  152. package/templates/default/src/app/(base)/reports/view-logs-button.tsx +58 -58
  153. package/templates/default/src/app/(base)/settings/settings-sync-panel-helpers.test.tsx +40 -0
  154. package/templates/default/src/app/(base)/settings/settings-sync-panel-helpers.tsx +110 -0
  155. package/templates/default/src/app/(base)/settings/settings-sync-panel.test.tsx +127 -0
  156. package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +19 -134
  157. package/templates/default/src/app/(base)/settings/use-settings-sync.ts +66 -0
  158. package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
  159. package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
  160. package/templates/default/src/app/(base)/tags/page.tsx +58 -58
  161. package/templates/default/src/app/(base)/tags/tag-form-helpers.ts +13 -0
  162. package/templates/default/src/app/(base)/tags/tag-form.test.tsx +83 -0
  163. package/templates/default/src/app/(base)/tags/tag-form.tsx +143 -147
  164. package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
  165. package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
  166. package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
  167. package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +43 -45
  168. package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
  169. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.test.tsx +82 -0
  170. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +181 -167
  171. package/templates/default/src/app/(base)/template-step-groups/template-step-group-helpers.ts +54 -0
  172. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
  173. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +34 -32
  174. package/templates/default/src/app/(base)/template-steps/create/page.tsx +40 -37
  175. package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +54 -49
  176. package/templates/default/src/app/(base)/template-steps/page.tsx +59 -58
  177. package/templates/default/src/app/(base)/template-steps/paramChip.tsx +233 -213
  178. package/templates/default/src/app/(base)/template-steps/template-step-form.test.tsx +132 -0
  179. package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +342 -384
  180. package/templates/default/src/app/(base)/template-steps/template-step-helpers.test.ts +99 -0
  181. package/templates/default/src/app/(base)/template-steps/template-step-helpers.ts +176 -0
  182. package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +153 -158
  183. package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +26 -24
  184. package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
  185. package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
  186. package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
  187. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.test.tsx +109 -0
  188. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +45 -84
  189. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.test.tsx +140 -0
  190. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +154 -262
  191. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
  192. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
  193. package/templates/default/src/app/(base)/test-cases/create/page.tsx +90 -76
  194. package/templates/default/src/app/(base)/test-cases/create-from-template/create-from-template-helpers.test.ts +94 -0
  195. package/templates/default/src/app/(base)/test-cases/create-from-template/create-from-template-helpers.ts +171 -0
  196. package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +105 -96
  197. package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +40 -38
  198. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.test.tsx +87 -0
  199. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +83 -73
  200. package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
  201. package/templates/default/src/app/(base)/test-cases/page.tsx +3 -2
  202. package/templates/default/src/app/(base)/test-cases/test-case-flow.test.tsx +108 -0
  203. package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +43 -82
  204. package/templates/default/src/app/(base)/test-cases/test-case-form.test.tsx +202 -0
  205. package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +263 -395
  206. package/templates/default/src/app/(base)/test-cases/test-case-route-helpers.test.ts +95 -0
  207. package/templates/default/src/app/(base)/test-cases/test-case-route-helpers.ts +147 -0
  208. package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +4 -2
  209. package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +11 -10
  210. package/templates/default/src/app/(base)/test-runs/create/page.tsx +4 -5
  211. package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
  212. package/templates/default/src/app/(base)/test-runs/test-run-form-helpers.test.ts +50 -0
  213. package/templates/default/src/app/(base)/test-runs/test-run-form-helpers.ts +168 -0
  214. package/templates/default/src/app/(base)/test-runs/test-run-form.test.tsx +138 -0
  215. package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +111 -256
  216. package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
  217. package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
  218. package/templates/default/src/app/(base)/test-runs/use-test-run-name-validation.ts +74 -0
  219. package/templates/default/src/app/(base)/test-suites/create/page.tsx +17 -12
  220. package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +22 -19
  221. package/templates/default/src/app/(base)/test-suites/page.tsx +14 -56
  222. package/templates/default/src/app/(base)/test-suites/test-suite-form.test.tsx +127 -0
  223. package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +45 -64
  224. package/templates/default/src/app/(base)/test-suites/test-suite-helpers.test.ts +67 -0
  225. package/templates/default/src/app/(base)/test-suites/test-suite-helpers.ts +215 -0
  226. package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +32 -29
  227. package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
  228. package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
  229. package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
  230. package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
  231. package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
  232. package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
  233. package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.test.ts +83 -0
  234. package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -52
  235. package/templates/default/src/app/api/test-runs/[runId]/download/route.test.ts +169 -0
  236. package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +1 -1
  237. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.test.ts +135 -0
  238. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -146
  239. package/templates/default/src/app/globals.css +147 -147
  240. package/templates/default/src/app/page.tsx +1 -1
  241. package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
  242. package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
  243. package/templates/default/src/components/base-node.tsx +21 -21
  244. package/templates/default/src/components/chart/pie-chart.tsx +73 -73
  245. package/templates/default/src/components/data-extraction/locator-inspector-helpers.test.ts +32 -0
  246. package/templates/default/src/components/data-extraction/locator-inspector-helpers.ts +183 -0
  247. package/templates/default/src/components/data-extraction/locator-inspector.tsx +349 -460
  248. package/templates/default/src/components/data-state/empty-state.tsx +40 -40
  249. package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
  250. package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
  251. package/templates/default/src/components/diagram/button-edge.tsx +54 -54
  252. package/templates/default/src/components/diagram/dynamic-parameters-helpers.test.ts +83 -0
  253. package/templates/default/src/components/diagram/dynamic-parameters-helpers.ts +158 -0
  254. package/templates/default/src/components/diagram/dynamic-parameters.tsx +350 -474
  255. package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
  256. package/templates/default/src/components/diagram/flow-diagram-helpers.test.ts +117 -0
  257. package/templates/default/src/components/diagram/flow-diagram-helpers.ts +251 -0
  258. package/templates/default/src/components/diagram/flow-diagram.tsx +247 -470
  259. package/templates/default/src/components/diagram/flow-host-helpers.test.ts +74 -0
  260. package/templates/default/src/components/diagram/flow-host-helpers.ts +51 -0
  261. package/templates/default/src/components/diagram/node-form-helpers.test.ts +92 -0
  262. package/templates/default/src/components/diagram/node-form-helpers.ts +100 -0
  263. package/templates/default/src/components/diagram/node-form.test.tsx +168 -0
  264. package/templates/default/src/components/diagram/node-form.tsx +199 -262
  265. package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
  266. package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
  267. package/templates/default/src/components/diagram/use-flow-node-order.ts +49 -0
  268. package/templates/default/src/components/form/error-message.tsx +7 -7
  269. package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
  270. package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
  271. package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
  272. package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
  273. package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
  274. package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
  275. package/templates/default/src/components/navigation/command-badge.tsx +34 -34
  276. package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
  277. package/templates/default/src/components/navigation/entity-search-command.tsx +118 -116
  278. package/templates/default/src/components/navigation/nav-card.tsx +31 -31
  279. package/templates/default/src/components/navigation/nav-command-helpers.ts +122 -0
  280. package/templates/default/src/components/navigation/nav-command-search.tsx +125 -0
  281. package/templates/default/src/components/navigation/nav-command.test.tsx +106 -0
  282. package/templates/default/src/components/navigation/nav-command.tsx +49 -472
  283. package/templates/default/src/components/navigation/nav-link.tsx +60 -60
  284. package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
  285. package/templates/default/src/components/navigation/use-nav-command.ts +58 -0
  286. package/templates/default/src/components/node-header.tsx +159 -159
  287. package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -310
  288. package/templates/default/src/components/table/table-actions.tsx +174 -172
  289. package/templates/default/src/components/test-case/test-case-form-helpers.test.ts +100 -0
  290. package/templates/default/src/components/test-case/test-case-form-helpers.ts +140 -0
  291. package/templates/default/src/components/test-case/test-case-picker-helpers.test.ts +40 -0
  292. package/templates/default/src/components/test-case/test-case-picker-helpers.ts +41 -0
  293. package/templates/default/src/components/test-case/test-case-picker.test.tsx +44 -0
  294. package/templates/default/src/components/test-case/test-case-picker.tsx +16 -35
  295. package/templates/default/src/components/test-case/test-scenario-preview.tsx +34 -0
  296. package/templates/default/src/components/test-run/download-logs-button.tsx +92 -92
  297. package/templates/default/src/components/test-run/log-viewer-helpers.test.ts +37 -0
  298. package/templates/default/src/components/test-run/log-viewer-helpers.ts +80 -0
  299. package/templates/default/src/components/test-run/log-viewer.test.tsx +118 -0
  300. package/templates/default/src/components/test-run/log-viewer.tsx +51 -350
  301. package/templates/default/src/components/test-run/test-run-details-helpers.test.ts +31 -0
  302. package/templates/default/src/components/test-run/test-run-details-helpers.ts +208 -0
  303. package/templates/default/src/components/test-run/test-run-details.test.tsx +174 -0
  304. package/templates/default/src/components/test-run/test-run-details.tsx +155 -457
  305. package/templates/default/src/components/test-run/test-run-header-helpers.test.ts +31 -0
  306. package/templates/default/src/components/test-run/test-run-header-helpers.ts +23 -0
  307. package/templates/default/src/components/test-run/test-run-header.test.tsx +103 -0
  308. package/templates/default/src/components/test-run/test-run-header.tsx +27 -149
  309. package/templates/default/src/components/test-run/use-log-viewer.ts +213 -0
  310. package/templates/default/src/components/test-run/use-test-run-details.ts +184 -0
  311. package/templates/default/src/components/test-run/use-test-run-header.ts +89 -0
  312. package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
  313. package/templates/default/src/components/test-suite/test-suite-picker-helpers.test.ts +68 -0
  314. package/templates/default/src/components/test-suite/test-suite-picker-helpers.ts +76 -0
  315. package/templates/default/src/components/test-suite/test-suite-picker.test.tsx +65 -0
  316. package/templates/default/src/components/test-suite/test-suite-picker.tsx +4 -72
  317. package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
  318. package/templates/default/src/components/theme/theme-provider.tsx +8 -8
  319. package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
  320. package/templates/default/src/components/typography/page-header.tsx +7 -7
  321. package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
  322. package/templates/default/src/components/ui/alert.tsx +43 -43
  323. package/templates/default/src/components/ui/avatar.tsx +40 -40
  324. package/templates/default/src/components/ui/badge.tsx +29 -29
  325. package/templates/default/src/components/ui/button.tsx +47 -47
  326. package/templates/default/src/components/ui/calendar.tsx +158 -158
  327. package/templates/default/src/components/ui/card.tsx +43 -43
  328. package/templates/default/src/components/ui/checkbox.tsx +28 -28
  329. package/templates/default/src/components/ui/command.tsx +135 -135
  330. package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
  331. package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
  332. package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
  333. package/templates/default/src/components/ui/data-table.test.tsx +122 -0
  334. package/templates/default/src/components/ui/data-table.tsx +298 -261
  335. package/templates/default/src/components/ui/dialog.tsx +97 -97
  336. package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
  337. package/templates/default/src/components/ui/input.tsx +22 -22
  338. package/templates/default/src/components/ui/kbd.tsx +28 -28
  339. package/templates/default/src/components/ui/label.tsx +19 -19
  340. package/templates/default/src/components/ui/loading.tsx +12 -12
  341. package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
  342. package/templates/default/src/components/ui/multi-select.test.tsx +45 -0
  343. package/templates/default/src/components/ui/multi-select.tsx +158 -142
  344. package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
  345. package/templates/default/src/components/ui/popover.tsx +33 -33
  346. package/templates/default/src/components/ui/progress.tsx +25 -25
  347. package/templates/default/src/components/ui/radio-group.tsx +44 -44
  348. package/templates/default/src/components/ui/scroll-area.tsx +40 -40
  349. package/templates/default/src/components/ui/select.tsx +151 -151
  350. package/templates/default/src/components/ui/separator.tsx +22 -22
  351. package/templates/default/src/components/ui/skeleton.tsx +7 -7
  352. package/templates/default/src/components/ui/table.tsx +76 -76
  353. package/templates/default/src/components/ui/tabs.tsx +55 -55
  354. package/templates/default/src/components/ui/textarea.tsx +21 -21
  355. package/templates/default/src/components/ui/toast.tsx +113 -113
  356. package/templates/default/src/components/ui/toaster.tsx +26 -26
  357. package/templates/default/src/components/user-prompt/delete-prompt.test.tsx +60 -0
  358. package/templates/default/src/components/user-prompt/delete-prompt.tsx +118 -87
  359. package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
  360. package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
  361. package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
  362. package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
  363. package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
  364. package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
  365. package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
  366. package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
  367. package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
  368. package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
  369. package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
  370. package/templates/default/src/hooks/use-toast.ts +187 -187
  371. package/templates/default/src/lib/automation/automation-path-roots.ts +95 -0
  372. package/templates/default/src/lib/automation/automation-workspace.ts +147 -0
  373. package/templates/default/src/lib/automation/paths.ts +6 -211
  374. package/templates/default/src/lib/bidirectional-sync.ts +432 -432
  375. package/templates/default/src/lib/environment-file-utils.ts +2 -1
  376. package/templates/default/src/lib/executor/local-executor-adapter.ts +2 -5
  377. package/templates/default/src/lib/feature-file-generator.ts +2 -1
  378. package/templates/default/src/lib/gherkin-parser.ts +0 -2
  379. package/templates/default/src/lib/locator-group-file-utils.ts +304 -307
  380. package/templates/default/src/lib/locator-picker/session-manager.ts +0 -21
  381. package/templates/default/src/lib/locator-picker/suggestions.ts +4 -2
  382. package/templates/default/src/lib/metrics/metric-calculator.ts +2 -6
  383. package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
  384. package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
  385. package/templates/default/src/lib/sync/sync-executor.test.ts +76 -0
  386. package/templates/default/src/lib/sync/sync-pending-counts.test.ts +227 -226
  387. package/templates/default/src/lib/sync/sync-pending-counts.ts +2 -5
  388. package/templates/default/src/lib/template-sync-utils.d.ts +6 -6
  389. package/templates/default/src/lib/template-sync-utils.js +46 -46
  390. package/templates/default/src/lib/template-sync-utils.ts +63 -63
  391. package/templates/default/src/lib/test-case-utils.ts +6 -6
  392. package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
  393. package/templates/default/src/lib/test-run/report-parser.ts +352 -352
  394. package/templates/default/src/lib/test-run/test-run-executor.ts +13 -13
  395. package/templates/default/src/lib/test-run/winston-logger.ts +65 -64
  396. package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
  397. package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
  398. package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
  399. package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
  400. package/templates/default/src/lib/utils/template-step-file-generator.ts +2 -2
  401. package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
  402. package/templates/default/src/lib/utils.ts +31 -31
  403. package/templates/default/src/services/dashboard/dashboard-service.test.ts +106 -0
  404. package/templates/default/src/services/dashboard/dashboard-service.ts +173 -0
  405. package/templates/default/src/services/environment/environment-service.test.ts +137 -0
  406. package/templates/default/src/services/environment/environment-service.ts +96 -0
  407. package/templates/default/src/services/locator/locator-path-utils.test.ts +14 -0
  408. package/templates/default/src/services/locator/locator-path-utils.ts +14 -0
  409. package/templates/default/src/services/locator/locator-service.test.ts +63 -0
  410. package/templates/default/src/services/locator/locator-service.ts +479 -0
  411. package/templates/default/src/services/locator/locator-sync-utils.test.ts +19 -0
  412. package/templates/default/src/services/locator/locator-sync-utils.ts +21 -0
  413. package/templates/default/src/services/locator-group/locator-group-service.test.ts +123 -0
  414. package/templates/default/src/services/locator-group/locator-group-service.ts +180 -0
  415. package/templates/default/src/services/module/module-service.test.ts +89 -0
  416. package/templates/default/src/services/module/module-service.ts +66 -0
  417. package/templates/default/src/services/report/report-service.test.ts +244 -0
  418. package/templates/default/src/services/report/report-service.ts +438 -0
  419. package/templates/default/src/services/shared/constants.ts +2 -0
  420. package/templates/default/src/services/shared/errors.test.ts +38 -0
  421. package/templates/default/src/services/shared/errors.ts +44 -0
  422. package/templates/default/src/services/shared/index.ts +7 -0
  423. package/templates/default/src/services/tag/tag-service.test.ts +22 -0
  424. package/templates/default/src/services/tag/tag-service.ts +41 -0
  425. package/templates/default/src/services/template-step/template-step-service.test.ts +22 -0
  426. package/templates/default/src/services/template-step/template-step-service.ts +171 -0
  427. package/templates/default/src/services/template-step-group/template-step-group-service.test.ts +22 -0
  428. package/templates/default/src/services/template-step-group/template-step-group-service.ts +81 -0
  429. package/templates/default/src/services/template-test-case/template-test-case-service.test.ts +22 -0
  430. package/templates/default/src/services/template-test-case/template-test-case-service.ts +128 -0
  431. package/templates/default/src/services/test-case/test-case-service.test.ts +175 -0
  432. package/templates/default/src/services/test-case/test-case-service.ts +298 -0
  433. package/templates/default/src/services/test-run/test-run-helpers.ts +61 -0
  434. package/templates/default/src/services/test-run/test-run-service.test.ts +647 -0
  435. package/templates/default/src/services/test-run/test-run-service.ts +917 -0
  436. package/templates/default/src/services/test-suite/test-suite-service.test.ts +127 -0
  437. package/templates/default/src/services/test-suite/test-suite-service.ts +197 -0
  438. package/templates/default/src/types/diagram/diagram.ts +34 -34
  439. package/templates/default/src/types/diagram/template-step.ts +11 -11
  440. package/templates/default/src/types/executor/browser.type.ts +1 -1
  441. package/templates/default/src/types/form/actionHandler.ts +19 -6
  442. package/templates/default/src/types/locator/locator.type.ts +11 -11
  443. package/templates/default/src/types/step/step.type.ts +1 -1
  444. package/templates/default/src/types/table/data-table.ts +6 -6
  445. package/templates/default/tailwind.config.ts +62 -62
  446. package/templates/default/tsconfig.json +1 -1
  447. package/dist/cli.e2e.test.d.ts +0 -2
  448. package/dist/cli.e2e.test.d.ts.map +0 -1
  449. package/dist/cli.e2e.test.js +0 -73
  450. package/dist/cli.e2e.test.js.map +0 -1
  451. package/dist/config.test.d.ts +0 -2
  452. package/dist/config.test.d.ts.map +0 -1
  453. package/dist/config.test.js +0 -65
  454. package/dist/config.test.js.map +0 -1
  455. package/dist/copy-template.test.d.ts +0 -2
  456. package/dist/copy-template.test.d.ts.map +0 -1
  457. package/dist/copy-template.test.js +0 -71
  458. package/dist/copy-template.test.js.map +0 -1
  459. package/dist/download-repo.test.d.ts +0 -2
  460. package/dist/download-repo.test.d.ts.map +0 -1
  461. package/dist/download-repo.test.js +0 -14
  462. package/dist/download-repo.test.js.map +0 -1
  463. package/dist/install.test.d.ts +0 -2
  464. package/dist/install.test.d.ts.map +0 -1
  465. package/dist/install.test.js +0 -119
  466. package/dist/install.test.js.map +0 -1
  467. package/dist/prompts.test.d.ts +0 -2
  468. package/dist/prompts.test.d.ts.map +0 -1
  469. package/dist/prompts.test.js +0 -58
  470. package/dist/prompts.test.js.map +0 -1
  471. package/templates/default/src/actions/conflict/conflict.action.ts +0 -33
  472. package/templates/default/src/actions/review/review-actions.ts +0 -147
  473. package/templates/default/src/actions/user/user-actions.ts +0 -13
  474. package/templates/default/src/app/(base)/locators/locator-form.tsx +0 -163
  475. package/templates/default/src/app/(base)/reviews/create/page.tsx +0 -26
  476. package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +0 -15
  477. package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +0 -26
  478. package/templates/default/src/app/(base)/reviews/page.tsx +0 -26
  479. package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +0 -26
  480. package/templates/default/src/app/(base)/reviews/review-form.tsx +0 -11
  481. package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +0 -9
  482. package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +0 -9
  483. package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +0 -15
  484. package/templates/default/src/constants/form-opts/locator-form-opts.ts +0 -20
  485. package/templates/default/src/constants/form-opts/review-form-opts.ts +0 -23
@@ -1,22 +1,31 @@
1
1
  'use client'
2
2
 
3
3
  import { Button } from '@/components/ui/button'
4
- import TestCasePicker from '@/components/test-case/test-case-picker'
5
4
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
6
5
  import { Input } from '@/components/ui/input'
7
6
  import { Label } from '@/components/ui/label'
8
7
  import MultiSelectWithPreview from '@/components/ui/multi-select-with-preview'
9
8
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
10
9
  import { Textarea } from '@/components/ui/textarea'
11
- import { formOpts, TestSuite } from '@/constants/form-opts/test-suite-form-opts'
10
+ import { formOpts, type TestSuite } from '@/constants/form-opts/test-suite-form-opts'
12
11
  import { toast } from '@/hooks/use-toast'
13
- import { TestCasePickerRow } from '@/types/test-case-picker'
14
- import { ActionResponse } from '@/types/form/actionHandler'
15
- import { Module, Tag } from '@prisma/client'
12
+ import type { TestCasePickerRow } from '@/types/test-case-picker'
13
+ import type { Module, Tag } from '@prisma/client'
16
14
  import { useForm } from '@tanstack/react-form'
17
15
  import { Info, Save } from 'lucide-react'
18
16
  import { useRouter } from 'next/navigation'
19
- import { z } from 'zod'
17
+
18
+ import TestCasePicker from '@/components/test-case/test-case-picker'
19
+
20
+ import {
21
+ getActionErrorMessage,
22
+ getFieldErrorMessage,
23
+ getModuleOptions,
24
+ getTagOptions,
25
+ testSuiteFieldValidators,
26
+ testSuiteQuickTips,
27
+ type TestSuiteFormSubmitAction,
28
+ } from './test-suite-helpers'
20
29
 
21
30
  export const TestSuiteForm = ({
22
31
  defaultValues,
@@ -32,7 +41,7 @@ export const TestSuiteForm = ({
32
41
  successTitle: string
33
42
  successMessage: string
34
43
  id?: string
35
- onSubmitAction: (_prev: unknown, value: TestSuite, id?: string) => Promise<ActionResponse>
44
+ onSubmitAction: TestSuiteFormSubmitAction
36
45
  testCases: TestCasePickerRow[]
37
46
  moduleList: Module[]
38
47
  tags: Tag[]
@@ -53,19 +62,26 @@ export const TestSuiteForm = ({
53
62
  if (res.status === 400) {
54
63
  toast({
55
64
  title: 'Error',
56
- description: res.error,
65
+ description: getActionErrorMessage(res),
57
66
  variant: 'destructive',
58
67
  })
59
68
  }
60
69
  if (res.status === 500) {
61
70
  toast({
62
71
  title: 'Error',
63
- description: res.error,
72
+ description: getActionErrorMessage(res),
64
73
  variant: 'destructive',
65
74
  })
66
75
  }
67
76
  },
68
77
  })
78
+ const moduleOptions = getModuleOptions(moduleList)
79
+ const tagOptions = getTagOptions(tags)
80
+ const renderError = (error: unknown, index: number) => (
81
+ <p key={index} className="text-xs text-pink-500">
82
+ {getFieldErrorMessage(error)}
83
+ </p>
84
+ )
69
85
  return (
70
86
  <div className="flex justify-between gap-20 overflow-x-hidden">
71
87
  <Card className="w-2/3 border-gray-700 bg-gray-500/10">
@@ -84,7 +100,7 @@ export const TestSuiteForm = ({
84
100
  <form.Field
85
101
  name="name"
86
102
  validators={{
87
- onChange: z.string().min(3, { message: 'Name must be at least 3 characters' }),
103
+ onChange: testSuiteFieldValidators.name,
88
104
  }}
89
105
  >
90
106
  {field => {
@@ -101,11 +117,7 @@ export const TestSuiteForm = ({
101
117
  onChange={e => field.handleChange(e.target.value)}
102
118
  placeholder="Enter name for your test suite"
103
119
  />
104
- {field.state.meta.errors.map((error, index) => (
105
- <p key={index} className="text-xs text-pink-500">
106
- {typeof error === 'string' ? error : error?.message || String(error)}
107
- </p>
108
- ))}
120
+ {field.state.meta.errors.map(renderError)}
109
121
  </div>
110
122
  )
111
123
  }}
@@ -125,11 +137,7 @@ export const TestSuiteForm = ({
125
137
  onChange={e => field.handleChange(e.target.value)}
126
138
  placeholder="Enter description for your test suite"
127
139
  />
128
- {field.state.meta.errors.map((error, index) => (
129
- <p key={index} className="text-xs text-pink-500">
130
- {typeof error === 'string' ? error : error?.message || String(error)}
131
- </p>
132
- ))}
140
+ {field.state.meta.errors.map(renderError)}
133
141
  </div>
134
142
  )
135
143
  }}
@@ -150,11 +158,7 @@ export const TestSuiteForm = ({
150
158
  dialogDescription="Search and select the test cases to include in this suite."
151
159
  selectedLabel="Selected test case(s)"
152
160
  />
153
- {field.state.meta.errors.map((error, index) => (
154
- <p key={index} className="text-xs text-pink-500">
155
- {typeof error === 'string' ? error : error?.message || String(error)}
156
- </p>
157
- ))}
161
+ {field.state.meta.errors.map(renderError)}
158
162
  </div>
159
163
  )
160
164
  }}
@@ -167,27 +171,24 @@ export const TestSuiteForm = ({
167
171
  Module
168
172
  </Label>
169
173
  <Select value={field.state.value} onValueChange={value => field.handleChange(value)}>
170
- <SelectTrigger className="w-full bg-background">
174
+ <SelectTrigger id={field.name} className="w-full bg-background">
171
175
  <SelectValue placeholder="Select a module" />
172
176
  </SelectTrigger>
173
- <SelectContent className="w-full" isEmpty={moduleList.length === 0}>
174
- {moduleList.map(module => (
175
- <SelectItem key={module.id} value={module.id}>
176
- {module.name}
177
+ <SelectContent className="w-full" isEmpty={moduleOptions.length === 0}>
178
+ {moduleOptions.map(moduleOption => (
179
+ <SelectItem key={moduleOption.value} value={moduleOption.value}>
180
+ {moduleOption.label}
177
181
  </SelectItem>
178
182
  ))}
179
183
  </SelectContent>
180
184
  </Select>
185
+ {field.state.meta.errors.map(renderError)}
181
186
  </div>
182
187
  )
183
188
  }}
184
189
  </form.Field>
185
190
  <form.Field name="tagIds">
186
191
  {field => {
187
- const tagsOptions = tags.map(tag => ({
188
- value: tag.id,
189
- label: tag.name,
190
- }))
191
192
  return (
192
193
  <div className="mb-6 flex flex-col gap-2">
193
194
  <Label htmlFor={field.name} className="font-bold">
@@ -195,7 +196,7 @@ export const TestSuiteForm = ({
195
196
  </Label>
196
197
  <MultiSelectWithPreview
197
198
  id={field.name}
198
- options={tagsOptions}
199
+ options={tagOptions}
199
200
  onSelectChange={value => {
200
201
  field.handleChange(value)
201
202
  }}
@@ -229,37 +230,17 @@ export const TestSuiteForm = ({
229
230
  </CardTitle>
230
231
  </CardHeader>
231
232
  <CardContent className="flex flex-col gap-6">
232
- <div className="flex items-start gap-4">
233
- <span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
234
- 1
235
- </span>
236
- <div className="flex flex-col gap-1">
237
- <span className="text-base font-bold">Choose a descriptive name</span>
238
- <span className="text-sm text-muted-foreground">
239
- Use clear, specific names that indicate the purpose
240
- </span>
241
- </div>
242
- </div>
243
- <div className="flex items-start gap-4">
244
- <span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
245
- 2
246
- </span>
247
- <div className="flex flex-col gap-1">
248
- <span className="text-base font-bold">Group related tests</span>
249
- <span className="text-sm text-muted-foreground">
250
- Organize tests that validate the same feature together
233
+ {testSuiteQuickTips.map((tip, index) => (
234
+ <div key={tip.title} className="flex items-start gap-4">
235
+ <span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
236
+ {index + 1}
251
237
  </span>
238
+ <div className="flex flex-col gap-1">
239
+ <span className="text-base font-bold">{tip.title}</span>
240
+ <span className="text-sm text-muted-foreground">{tip.description}</span>
241
+ </div>
252
242
  </div>
253
- </div>
254
- <div className="flex items-start gap-4">
255
- <span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
256
- 3
257
- </span>
258
- <div className="flex flex-col gap-1">
259
- <span className="text-base font-bold">Use meaningful tags</span>
260
- <span className="text-sm text-muted-foreground">Tags help filter and categorize effectively</span>
261
- </div>
262
- </div>
243
+ ))}
263
244
  </CardContent>
264
245
  </Card>
265
246
  </div>
@@ -0,0 +1,67 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import {
4
+ buildTestSuiteInfoCards,
5
+ getEditableTestSuite,
6
+ getModuleOptions,
7
+ getTestCasePickerRows,
8
+ getTestSuiteTableRows,
9
+ } from './test-suite-helpers'
10
+
11
+ describe('test-suite helpers', () => {
12
+ it('formats module options and narrows test case picker rows', () => {
13
+ expect(getModuleOptions([{ id: 'module-1', name: 'Payments' } as never])).toEqual([
14
+ { label: 'Payments', value: 'module-1' },
15
+ ])
16
+
17
+ expect(
18
+ getTestCasePickerRows([
19
+ {
20
+ id: 'case-1',
21
+ title: 'Login',
22
+ steps: [],
23
+ tags: [{ id: 'tag-1', name: 'smoke' }],
24
+ },
25
+ {
26
+ id: 'broken',
27
+ title: 'Broken',
28
+ steps: [],
29
+ tags: ['bad'],
30
+ },
31
+ ]),
32
+ ).toEqual([
33
+ {
34
+ id: 'case-1',
35
+ title: 'Login',
36
+ steps: [],
37
+ tags: [{ id: 'tag-1', name: 'smoke' }],
38
+ },
39
+ ])
40
+ })
41
+
42
+ it('narrows test suite table and editable rows', () => {
43
+ const tableRows = getTestSuiteTableRows([
44
+ {
45
+ id: 'suite-1',
46
+ name: 'Smoke',
47
+ module: { id: 'module-1', name: 'Payments' },
48
+ testCases: [{ id: 'case-1', title: 'Login' }],
49
+ tags: [{ id: 'tag-1', name: 'smoke' }],
50
+ },
51
+ ])
52
+
53
+ expect(tableRows).toHaveLength(1)
54
+ expect(buildTestSuiteInfoCards(tableRows).map(card => card.legend)).toContain('Latest test suite')
55
+
56
+ expect(
57
+ getEditableTestSuite({
58
+ id: 'suite-1',
59
+ name: 'Smoke',
60
+ module: { id: 'module-1', name: 'Payments' },
61
+ moduleId: 'module-1',
62
+ testCases: [{ id: 'case-1', title: 'Login' }],
63
+ tags: [{ id: 'tag-1', name: 'smoke' }],
64
+ }),
65
+ ).not.toBeNull()
66
+ })
67
+ })
@@ -0,0 +1,215 @@
1
+ import type { Module, Tag, TestCase, TestSuite as PrismaTestSuite } from '@prisma/client'
2
+
3
+ import { testSuiteSchema, type TestSuite } from '@/constants/form-opts/test-suite-form-opts'
4
+ import { getFilterTags } from '@/lib/tag-utils'
5
+ import type { ActionResponse, ActionResponseData } from '@/types/form/actionHandler'
6
+ import type { TestCasePickerRow } from '@/types/test-case-picker'
7
+
8
+ export type TestSuiteTableRow = PrismaTestSuite & {
9
+ tags?: Tag[]
10
+ module: Module
11
+ testCases: TestCase[]
12
+ }
13
+
14
+ export type EditableTestSuite = PrismaTestSuite & {
15
+ testCases: TestCase[]
16
+ module: Module
17
+ tags: Tag[]
18
+ }
19
+
20
+ export type TestSuiteGroupOption = {
21
+ id: string
22
+ name: string
23
+ }
24
+
25
+ export type TestSuiteFormSubmitAction = (_prev: unknown, value: TestSuite, id?: string) => Promise<ActionResponse>
26
+
27
+ export const testSuiteFieldValidators = {
28
+ name: testSuiteSchema.shape.name,
29
+ moduleId: testSuiteSchema.shape.moduleId,
30
+ }
31
+
32
+ export const testSuiteQuickTips = [
33
+ {
34
+ title: 'Choose a descriptive name',
35
+ description: 'Use clear, specific names that indicate the purpose',
36
+ },
37
+ {
38
+ title: 'Group related tests',
39
+ description: 'Organize tests that validate the same feature together',
40
+ },
41
+ {
42
+ title: 'Use meaningful tags',
43
+ description: 'Tags help filter and categorize effectively',
44
+ },
45
+ ] as const
46
+
47
+ export type TestSuiteInfoCard = {
48
+ showHighlightGroup: boolean
49
+ highlight: string
50
+ legend: string
51
+ defaultText: string
52
+ }
53
+
54
+ export function getFieldErrorMessage(error: unknown) {
55
+ if (typeof error === 'string') {
56
+ return error
57
+ }
58
+
59
+ if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {
60
+ return error.message
61
+ }
62
+
63
+ return String(error)
64
+ }
65
+
66
+ export function getActionErrorMessage(response: ActionResponse) {
67
+ return response.error || 'An error occurred'
68
+ }
69
+
70
+ export function getModuleOptions(modules: Module[]) {
71
+ return modules.map(module => ({
72
+ label: module.name,
73
+ value: module.id,
74
+ }))
75
+ }
76
+
77
+ export function getTagOptions(tags: Tag[]) {
78
+ return tags.map(tag => ({
79
+ label: tag.name,
80
+ value: tag.id,
81
+ }))
82
+ }
83
+
84
+ function isNamedRow(value: unknown): value is { id: string; name: string } {
85
+ return typeof value === 'object' && value !== null && 'id' in value && 'name' in value
86
+ }
87
+
88
+ function isTagRow(value: unknown): value is Tag {
89
+ return isNamedRow(value)
90
+ }
91
+
92
+ function isTestCaseRow(value: unknown): value is TestCase {
93
+ return typeof value === 'object' && value !== null && 'id' in value && 'title' in value
94
+ }
95
+
96
+ function isTestSuitePickerRow(value: unknown): value is TestCasePickerRow {
97
+ return (
98
+ isTestCaseRow(value) &&
99
+ 'steps' in value &&
100
+ Array.isArray(value.steps) &&
101
+ 'tags' in value &&
102
+ Array.isArray(value.tags) &&
103
+ value.tags.every(isTagRow)
104
+ )
105
+ }
106
+
107
+ function isModuleRow(value: unknown): value is Module {
108
+ return isNamedRow(value)
109
+ }
110
+
111
+ function isTestSuiteTableRow(value: unknown): value is TestSuiteTableRow {
112
+ return (
113
+ typeof value === 'object' &&
114
+ value !== null &&
115
+ 'id' in value &&
116
+ 'name' in value &&
117
+ 'module' in value &&
118
+ isModuleRow(value.module) &&
119
+ 'testCases' in value &&
120
+ Array.isArray(value.testCases) &&
121
+ value.testCases.every(isTestCaseRow) &&
122
+ (!('tags' in value) || value.tags === undefined || (Array.isArray(value.tags) && value.tags.every(isTagRow)))
123
+ )
124
+ }
125
+
126
+ function isEditableTestSuite(value: unknown): value is EditableTestSuite {
127
+ return (
128
+ isTestSuiteTableRow(value) &&
129
+ 'tags' in value &&
130
+ Array.isArray(value.tags) &&
131
+ value.tags.every(isTagRow)
132
+ )
133
+ }
134
+
135
+ function isGroupOption(value: unknown): value is TestSuiteGroupOption {
136
+ return isNamedRow(value)
137
+ }
138
+
139
+ export function getTestCasePickerRows(data: ActionResponseData | undefined): TestCasePickerRow[] {
140
+ return Array.isArray(data) ? data.filter(isTestSuitePickerRow) : []
141
+ }
142
+
143
+ export function getModuleRows(data: ActionResponseData | undefined): Module[] {
144
+ return Array.isArray(data) ? data.filter(isModuleRow) : []
145
+ }
146
+
147
+ export function getTagRows(data: ActionResponseData | undefined): Tag[] {
148
+ return Array.isArray(data) ? data.filter(isTagRow) : []
149
+ }
150
+
151
+ export function getTestSuiteTableRows(data: ActionResponseData | undefined): TestSuiteTableRow[] {
152
+ return Array.isArray(data) ? data.filter(isTestSuiteTableRow) : []
153
+ }
154
+
155
+ export function buildTestSuiteInfoCards(testSuites: TestSuiteTableRow[]): TestSuiteInfoCard[] {
156
+ const emptyTestSuites = testSuites.filter(testSuite => testSuite.testCases.length === 0)
157
+ const latestCreatedTestSuite = [...testSuites].sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0]
158
+ const tagSuiteCountMap = new Map<string, { name: string; suiteCount: number }>()
159
+
160
+ for (const testSuite of testSuites) {
161
+ for (const tag of getFilterTags(testSuite.tags || [])) {
162
+ const currentTag = tagSuiteCountMap.get(tag.id)
163
+
164
+ if (currentTag) {
165
+ currentTag.suiteCount += 1
166
+ } else {
167
+ tagSuiteCountMap.set(tag.id, {
168
+ name: tag.name,
169
+ suiteCount: 1,
170
+ })
171
+ }
172
+ }
173
+ }
174
+
175
+ const mostCommonTagWithSuites = [...tagSuiteCountMap.values()].sort((a, b) => {
176
+ if (b.suiteCount !== a.suiteCount) {
177
+ return b.suiteCount - a.suiteCount
178
+ }
179
+
180
+ return a.name.localeCompare(b.name)
181
+ })[0]
182
+
183
+ return [
184
+ {
185
+ showHighlightGroup: testSuites.length > 0,
186
+ highlight: emptyTestSuites.length.toString(),
187
+ legend: 'Empty test suite(s)',
188
+ defaultText: 'Empty test suites count. Will update when test suites are created.',
189
+ },
190
+ {
191
+ showHighlightGroup: testSuites.length > 0,
192
+ highlight: latestCreatedTestSuite ? latestCreatedTestSuite.name : 'N/A',
193
+ legend: 'Latest test suite',
194
+ defaultText: 'Latest created test suite. Will update when test suites are created.',
195
+ },
196
+ ...(mostCommonTagWithSuites
197
+ ? [
198
+ {
199
+ showHighlightGroup: true,
200
+ highlight: mostCommonTagWithSuites.name,
201
+ legend: 'Most common tag',
202
+ defaultText: 'Most common suite tag will appear here when test suites have tags.',
203
+ },
204
+ ]
205
+ : []),
206
+ ]
207
+ }
208
+
209
+ export function getEditableTestSuite(data: ActionResponseData | undefined) {
210
+ return isEditableTestSuite(data) ? data : null
211
+ }
212
+
213
+ export function getTemplateStepGroupRows(data: ActionResponseData | undefined): TestSuiteGroupOption[] {
214
+ return Array.isArray(data) ? data.filter(isGroupOption) : []
215
+ }
@@ -1,29 +1,32 @@
1
- import { DataTable } from '@/components/ui/data-table'
2
- import React from 'react'
3
- import { testSuiteTableCols } from './test-suite-table-columns'
4
- import { getAllTestSuitesAction, deleteTestSuiteAction } from '@/actions/test-suite/test-suite-actions'
5
- import { Module, TestCase, TestSuite, Tag } from '@prisma/client'
6
-
7
- const TestSuiteTable = async () => {
8
- const { data: testSuites, error: testSuitesError } = await getAllTestSuitesAction()
9
-
10
- if (testSuitesError) {
11
- return <div>Error: {testSuitesError}</div>
12
- }
13
-
14
- return (
15
- <>
16
- <DataTable
17
- columns={testSuiteTableCols}
18
- data={testSuites as (TestSuite & { tags?: Tag[]; module: Module; testCases: TestCase[] })[]}
19
- filterColumn="name"
20
- filterPlaceholder="Filter by name..."
21
- createLink="/test-suites/create"
22
- modifyLink="/test-suites/modify"
23
- deleteAction={deleteTestSuiteAction}
24
- />
25
- </>
26
- )
27
- }
28
-
29
- export default TestSuiteTable
1
+ import { DataTable } from '@/components/ui/data-table'
2
+ import React from 'react'
3
+ import { testSuiteTableCols } from './test-suite-table-columns'
4
+ import { getAllTestSuitesAction, deleteTestSuiteAction } from '@/actions/test-suite/test-suite-actions'
5
+
6
+ import { getTestSuiteTableRows } from './test-suite-helpers'
7
+
8
+ const TestSuiteTable = async () => {
9
+ const { data: testSuites, error: testSuitesError } = await getAllTestSuitesAction()
10
+
11
+ if (testSuitesError) {
12
+ return <div>Error: {testSuitesError}</div>
13
+ }
14
+
15
+ const rows = getTestSuiteTableRows(testSuites)
16
+
17
+ return (
18
+ <>
19
+ <DataTable
20
+ columns={testSuiteTableCols}
21
+ data={rows}
22
+ filterColumn="name"
23
+ filterPlaceholder="Filter by name..."
24
+ createLink="/test-suites/create"
25
+ modifyLink="/test-suites/modify"
26
+ deleteAction={deleteTestSuiteAction}
27
+ />
28
+ </>
29
+ )
30
+ }
31
+
32
+ export default TestSuiteTable