create-appraisejs 0.1.10-alpha.8 → 0.2.0-alpha.1

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 (414) hide show
  1. package/README.md +52 -52
  2. package/dist/cli.e2e.test.d.ts +2 -0
  3. package/dist/cli.e2e.test.d.ts.map +1 -0
  4. package/dist/cli.e2e.test.js +73 -0
  5. package/dist/cli.e2e.test.js.map +1 -0
  6. package/dist/config.test.d.ts +2 -0
  7. package/dist/config.test.d.ts.map +1 -0
  8. package/dist/config.test.js +65 -0
  9. package/dist/config.test.js.map +1 -0
  10. package/dist/copy-template.test.d.ts +2 -0
  11. package/dist/copy-template.test.d.ts.map +1 -0
  12. package/dist/copy-template.test.js +71 -0
  13. package/dist/copy-template.test.js.map +1 -0
  14. package/dist/download-repo.test.d.ts +2 -0
  15. package/dist/download-repo.test.d.ts.map +1 -0
  16. package/dist/download-repo.test.js +14 -0
  17. package/dist/download-repo.test.js.map +1 -0
  18. package/dist/install.test.d.ts +2 -0
  19. package/dist/install.test.d.ts.map +1 -0
  20. package/dist/install.test.js +119 -0
  21. package/dist/install.test.js.map +1 -0
  22. package/dist/prepare-template-utils.d.ts.map +1 -1
  23. package/dist/prepare-template-utils.js +5 -0
  24. package/dist/prepare-template-utils.js.map +1 -1
  25. package/dist/prompts.test.d.ts +2 -0
  26. package/dist/prompts.test.d.ts.map +1 -0
  27. package/dist/prompts.test.js +58 -0
  28. package/dist/prompts.test.js.map +1 -0
  29. package/dist/scaffold-gitignore.d.ts +1 -0
  30. package/dist/scaffold-gitignore.d.ts.map +1 -1
  31. package/dist/scaffold-gitignore.js +3 -0
  32. package/dist/scaffold-gitignore.js.map +1 -1
  33. package/package.json +3 -2
  34. package/templates/default/.appraise-template-meta.json +2 -2
  35. package/templates/default/.env.example +2 -2
  36. package/templates/default/.vscode/settings.json +2 -1
  37. package/templates/default/README.md +53 -53
  38. package/templates/default/automation/mapping/locator-map.json +1 -14
  39. package/templates/default/automation/steps/actions/click.step.ts +58 -58
  40. package/templates/default/automation/steps/actions/hover.step.ts +27 -27
  41. package/templates/default/automation/steps/actions/input.step.ts +84 -84
  42. package/templates/default/automation/steps/actions/navigation.step.ts +70 -70
  43. package/templates/default/automation/steps/actions/random_data.step.ts +142 -142
  44. package/templates/default/automation/steps/actions/store.step.ts +86 -86
  45. package/templates/default/automation/steps/actions/wait.step.ts +90 -90
  46. package/templates/default/automation/steps/validations/active_state_assertion.step.ts +30 -30
  47. package/templates/default/automation/steps/validations/navigation_assertion.step.ts +22 -22
  48. package/templates/default/automation/steps/validations/text_assertion.step.ts +107 -107
  49. package/templates/default/automation/steps/validations/visibility_assertion.step.ts +26 -26
  50. package/templates/default/components.json +24 -24
  51. package/templates/default/cucumber.mjs +16 -16
  52. package/templates/default/eslint.config.mjs +16 -16
  53. package/templates/default/gitignore +3 -0
  54. package/templates/default/next-env.d.ts +6 -6
  55. package/templates/default/next.config.ts +11 -11
  56. package/templates/default/package-lock.json +146 -75
  57. package/templates/default/package.json +2 -1
  58. package/templates/default/packages/cucumber-runtime/package.json +13 -13
  59. package/templates/default/packages/cucumber-runtime/src/cache.util.ts +93 -93
  60. package/templates/default/packages/cucumber-runtime/src/cli.ts +68 -68
  61. package/templates/default/packages/cucumber-runtime/src/environment.util.ts +21 -21
  62. package/templates/default/packages/cucumber-runtime/src/executor.ts +32 -32
  63. package/templates/default/packages/cucumber-runtime/src/hooks.ts +25 -3
  64. package/templates/default/packages/cucumber-runtime/src/index.ts +17 -17
  65. package/templates/default/packages/cucumber-runtime/src/locator.util.ts +234 -234
  66. package/templates/default/packages/cucumber-runtime/src/parameter-types.ts +7 -7
  67. package/templates/default/packages/cucumber-runtime/src/paths.ts +66 -1
  68. package/templates/default/packages/cucumber-runtime/src/random-data.util.ts +35 -35
  69. package/templates/default/packages/cucumber-runtime/src/types.ts +13 -13
  70. package/templates/default/packages/cucumber-runtime/src/world.ts +44 -44
  71. package/templates/default/packages/cucumber-runtime/tsconfig.json +11 -11
  72. package/templates/default/packages/locator-picker-companion/dist/cli.d.ts +1 -0
  73. package/templates/default/packages/locator-picker-companion/dist/cli.js +302 -0
  74. package/templates/default/packages/locator-picker-companion/dist/index.d.ts +3 -0
  75. package/templates/default/packages/locator-picker-companion/dist/index.js +3 -0
  76. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.d.ts +1 -0
  77. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.js +615 -0
  78. package/templates/default/packages/locator-picker-companion/dist/launcher.d.ts +11 -0
  79. package/templates/default/packages/locator-picker-companion/dist/launcher.js +59 -0
  80. package/templates/default/packages/locator-picker-companion/dist/selector-generator.d.ts +3 -0
  81. package/templates/default/packages/locator-picker-companion/dist/selector-generator.js +257 -0
  82. package/templates/default/packages/locator-picker-companion/dist/session-file.d.ts +22 -0
  83. package/templates/default/packages/locator-picker-companion/dist/session-file.js +150 -0
  84. package/templates/default/packages/locator-picker-companion/dist/types.d.ts +31 -0
  85. package/templates/default/packages/locator-picker-companion/dist/types.js +1 -0
  86. package/templates/default/packages/locator-picker-companion/package.json +17 -0
  87. package/templates/default/packages/locator-picker-companion/src/cli.ts +428 -0
  88. package/templates/default/packages/locator-picker-companion/src/index.ts +3 -0
  89. package/templates/default/packages/locator-picker-companion/src/injected-picker-script.ts +771 -0
  90. package/templates/default/packages/locator-picker-companion/src/launcher.ts +77 -0
  91. package/templates/default/packages/locator-picker-companion/src/selector-generator.ts +339 -0
  92. package/templates/default/packages/locator-picker-companion/src/session-file.ts +226 -0
  93. package/templates/default/packages/locator-picker-companion/src/types.ts +42 -0
  94. package/templates/default/packages/locator-picker-companion/tsconfig.json +14 -0
  95. package/templates/default/postcss.config.mjs +8 -8
  96. package/templates/default/prisma/dev.db +0 -0
  97. package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
  98. package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
  99. package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
  100. package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
  101. package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
  102. package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
  103. package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
  104. package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
  105. package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
  106. package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
  107. package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
  108. package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
  109. package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
  110. package/templates/default/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -0
  111. package/templates/default/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +20 -0
  112. package/templates/default/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +2 -0
  113. package/templates/default/prisma/schema.prisma +4 -0
  114. package/templates/default/scripts/install-playwright.ts +20 -0
  115. package/templates/default/scripts/protect-seeded-files.ts +38 -38
  116. package/templates/default/scripts/regenerate-features.ts +94 -94
  117. package/templates/default/scripts/setup-env.ts +19 -19
  118. package/templates/default/scripts/sync-all.ts +22 -66
  119. package/templates/default/scripts/sync-appraise-base-template.ts +57 -19
  120. package/templates/default/scripts/sync-environments.ts +40 -21
  121. package/templates/default/scripts/sync-locator-groups.ts +410 -410
  122. package/templates/default/scripts/sync-locators.ts +398 -398
  123. package/templates/default/scripts/sync-modules.ts +341 -341
  124. package/templates/default/scripts/sync-tags.ts +2 -3
  125. package/templates/default/scripts/sync-template-step-groups.ts +0 -3
  126. package/templates/default/scripts/sync-template-steps.ts +37 -11
  127. package/templates/default/scripts/sync-test-cases.ts +68 -16
  128. package/templates/default/scripts/sync-test-suites.ts +7 -5
  129. package/templates/default/src/actions/conflict/conflict.action.ts +33 -33
  130. package/templates/default/src/actions/dashboard/dashboard-actions.ts +240 -240
  131. package/templates/default/src/actions/environments/environment-actions.ts +188 -188
  132. package/templates/default/src/actions/locator/locator-actions.ts +490 -490
  133. package/templates/default/src/actions/locator-groups/locator-group-actions.ts +6 -3
  134. package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +243 -0
  135. package/templates/default/src/actions/modules/module-actions.ts +135 -135
  136. package/templates/default/src/actions/reports/report-actions.ts +51 -49
  137. package/templates/default/src/actions/review/review-actions.ts +147 -147
  138. package/templates/default/src/actions/settings/sync-actions.ts +46 -0
  139. package/templates/default/src/actions/tags/tag-actions.ts +107 -107
  140. package/templates/default/src/actions/template-step/template-step-actions.ts +38 -4
  141. package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +10 -3
  142. package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -238
  143. package/templates/default/src/actions/test-case/test-case-actions.ts +356 -356
  144. package/templates/default/src/actions/test-run/test-run-actions.ts +222 -129
  145. package/templates/default/src/actions/test-suite/test-suite-actions.ts +95 -17
  146. package/templates/default/src/actions/user/user-actions.ts +13 -13
  147. package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
  148. package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -219
  149. package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
  150. package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -24
  151. package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -46
  152. package/templates/default/src/app/(base)/environments/page.tsx +59 -59
  153. package/templates/default/src/app/(base)/layout.tsx +10 -10
  154. package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
  155. package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
  156. package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
  157. package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
  158. package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
  159. package/templates/default/src/app/(base)/locator-groups/page.tsx +20 -8
  160. package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +542 -0
  161. package/templates/default/src/app/(base)/locators/create/page.tsx +32 -19
  162. package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
  163. package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -73
  164. package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
  165. package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +56 -27
  166. package/templates/default/src/app/(base)/locators/page.tsx +13 -13
  167. package/templates/default/src/app/(base)/locators/picker/page.tsx +7 -0
  168. package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -66
  169. package/templates/default/src/app/(base)/modules/create/page.tsx +34 -34
  170. package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -46
  171. package/templates/default/src/app/(base)/modules/module-form.tsx +126 -126
  172. package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -85
  173. package/templates/default/src/app/(base)/modules/module-table.tsx +24 -24
  174. package/templates/default/src/app/(base)/modules/page.tsx +59 -59
  175. package/templates/default/src/app/(base)/reports/[id]/page.tsx +40 -33
  176. package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
  177. package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -78
  178. package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -46
  179. package/templates/default/src/app/(base)/reports/page.tsx +98 -98
  180. package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -16
  181. package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
  182. package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
  183. package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +12 -1
  184. package/templates/default/src/app/(base)/reports/report-view-table.tsx +1 -0
  185. package/templates/default/src/app/(base)/reports/test-cases/page.tsx +40 -42
  186. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
  187. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
  188. package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
  189. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
  190. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
  191. package/templates/default/src/app/(base)/reports/view-logs-button.tsx +58 -60
  192. package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -26
  193. package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -15
  194. package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -26
  195. package/templates/default/src/app/(base)/reviews/page.tsx +26 -26
  196. package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -26
  197. package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -11
  198. package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -9
  199. package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -9
  200. package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -15
  201. package/templates/default/src/app/(base)/settings/page.tsx +30 -0
  202. package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +261 -0
  203. package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
  204. package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
  205. package/templates/default/src/app/(base)/tags/page.tsx +58 -58
  206. package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -147
  207. package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
  208. package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
  209. package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
  210. package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -45
  211. package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
  212. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -167
  213. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
  214. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -32
  215. package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -37
  216. package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -49
  217. package/templates/default/src/app/(base)/template-steps/page.tsx +58 -58
  218. package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -213
  219. package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -384
  220. package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -158
  221. package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -24
  222. package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
  223. package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
  224. package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
  225. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -84
  226. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -262
  227. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
  228. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
  229. package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -76
  230. package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -96
  231. package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -38
  232. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -73
  233. package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
  234. package/templates/default/src/app/(base)/test-cases/page.tsx +2 -2
  235. package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -82
  236. package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -395
  237. package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +6 -71
  238. package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +2 -2
  239. package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +4 -1
  240. package/templates/default/src/app/(base)/test-runs/create/page.tsx +11 -9
  241. package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
  242. package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +37 -44
  243. package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
  244. package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
  245. package/templates/default/src/app/(base)/test-suites/create/page.tsx +3 -2
  246. package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +2 -1
  247. package/templates/default/src/app/(base)/test-suites/page.tsx +57 -21
  248. package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +16 -17
  249. package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +2 -1
  250. package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -29
  251. package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
  252. package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
  253. package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
  254. package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
  255. package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
  256. package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
  257. package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -0
  258. package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +97 -34
  259. package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +4 -1
  260. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -147
  261. package/templates/default/src/app/globals.css +147 -147
  262. package/templates/default/src/app/layout.tsx +4 -0
  263. package/templates/default/src/app/page.tsx +2 -0
  264. package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
  265. package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
  266. package/templates/default/src/components/base-node.tsx +21 -21
  267. package/templates/default/src/components/chart/pie-chart.tsx +73 -73
  268. package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -460
  269. package/templates/default/src/components/data-state/empty-state.tsx +40 -40
  270. package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
  271. package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
  272. package/templates/default/src/components/diagram/button-edge.tsx +54 -54
  273. package/templates/default/src/components/diagram/dynamic-parameters.tsx +474 -474
  274. package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
  275. package/templates/default/src/components/diagram/flow-diagram.tsx +470 -470
  276. package/templates/default/src/components/diagram/node-form.tsx +262 -262
  277. package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
  278. package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
  279. package/templates/default/src/components/form/error-message.tsx +7 -7
  280. package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
  281. package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
  282. package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
  283. package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
  284. package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
  285. package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
  286. package/templates/default/src/components/logo.tsx +15 -15
  287. package/templates/default/src/components/navigation/command-badge.tsx +34 -34
  288. package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
  289. package/templates/default/src/components/navigation/entity-search-command.tsx +116 -116
  290. package/templates/default/src/components/navigation/nav-card.tsx +31 -31
  291. package/templates/default/src/components/navigation/nav-command.tsx +13 -0
  292. package/templates/default/src/components/navigation/nav-link.tsx +60 -60
  293. package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
  294. package/templates/default/src/components/node-header.tsx +159 -159
  295. package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -253
  296. package/templates/default/src/components/table/table-actions.tsx +172 -172
  297. package/templates/default/src/components/test-case/test-case-columns.tsx +76 -0
  298. package/templates/default/src/components/test-case/test-case-picker.tsx +244 -0
  299. package/templates/default/src/components/test-run/download-logs-button.tsx +92 -99
  300. package/templates/default/src/components/test-run/log-viewer.tsx +1 -14
  301. package/templates/default/src/components/test-run/test-run-details.tsx +15 -2
  302. package/templates/default/src/components/test-run/test-run-header.tsx +149 -149
  303. package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
  304. package/templates/default/src/components/test-suite/test-suite-picker.tsx +444 -0
  305. package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
  306. package/templates/default/src/components/theme/theme-provider.tsx +8 -8
  307. package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
  308. package/templates/default/src/components/typography/page-header.tsx +7 -7
  309. package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
  310. package/templates/default/src/components/ui/alert.tsx +43 -43
  311. package/templates/default/src/components/ui/avatar.tsx +40 -40
  312. package/templates/default/src/components/ui/badge.tsx +29 -29
  313. package/templates/default/src/components/ui/button.tsx +47 -47
  314. package/templates/default/src/components/ui/calendar.tsx +158 -158
  315. package/templates/default/src/components/ui/card.tsx +43 -43
  316. package/templates/default/src/components/ui/checkbox.tsx +28 -28
  317. package/templates/default/src/components/ui/command.tsx +135 -135
  318. package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
  319. package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
  320. package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
  321. package/templates/default/src/components/ui/data-table.tsx +261 -261
  322. package/templates/default/src/components/ui/dialog.tsx +97 -97
  323. package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
  324. package/templates/default/src/components/ui/input.tsx +22 -22
  325. package/templates/default/src/components/ui/kbd.tsx +28 -28
  326. package/templates/default/src/components/ui/label.tsx +19 -19
  327. package/templates/default/src/components/ui/loading.tsx +12 -12
  328. package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
  329. package/templates/default/src/components/ui/multi-select.tsx +142 -142
  330. package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
  331. package/templates/default/src/components/ui/popover.tsx +33 -33
  332. package/templates/default/src/components/ui/progress.tsx +25 -25
  333. package/templates/default/src/components/ui/radio-group.tsx +44 -44
  334. package/templates/default/src/components/ui/scroll-area.tsx +40 -40
  335. package/templates/default/src/components/ui/select.tsx +151 -151
  336. package/templates/default/src/components/ui/separator.tsx +22 -22
  337. package/templates/default/src/components/ui/skeleton.tsx +7 -7
  338. package/templates/default/src/components/ui/table.tsx +76 -76
  339. package/templates/default/src/components/ui/tabs.tsx +55 -55
  340. package/templates/default/src/components/ui/textarea.tsx +21 -21
  341. package/templates/default/src/components/ui/toast.tsx +113 -113
  342. package/templates/default/src/components/ui/toaster.tsx +26 -26
  343. package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -87
  344. package/templates/default/src/config/db-config.ts +10 -10
  345. package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
  346. package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
  347. package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -20
  348. package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
  349. package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
  350. package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -23
  351. package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
  352. package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
  353. package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
  354. package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
  355. package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
  356. package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
  357. package/templates/default/src/constants/form-opts/test-run-form-opts.ts +5 -3
  358. package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
  359. package/templates/default/src/hooks/use-toast.ts +187 -187
  360. package/templates/default/src/lib/automation/paths.ts +42 -12
  361. package/templates/default/src/lib/automation/projection-service.ts +2 -1
  362. package/templates/default/src/lib/bidirectional-sync.ts +432 -432
  363. package/templates/default/src/lib/database-sync.ts +2 -7
  364. package/templates/default/src/lib/environment-file-utils.ts +184 -184
  365. package/templates/default/src/lib/executor/local-executor-adapter.ts +24 -25
  366. package/templates/default/src/lib/executor/types.ts +2 -2
  367. package/templates/default/src/lib/feature-file-generator.ts +5 -66
  368. package/templates/default/src/lib/gherkin-parser.ts +259 -259
  369. package/templates/default/src/lib/locator-group-file-utils.ts +307 -307
  370. package/templates/default/src/lib/locator-picker/session-manager.ts +452 -0
  371. package/templates/default/src/lib/locator-picker/suggestions.ts +124 -0
  372. package/templates/default/src/lib/metrics/metric-calculator.ts +5 -0
  373. package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
  374. package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
  375. package/templates/default/src/lib/process/task-spawner.ts +39 -2
  376. package/templates/default/src/lib/sync/projected-feature-utils.ts +113 -0
  377. package/templates/default/src/lib/sync/sync-executor.ts +130 -0
  378. package/templates/default/src/lib/sync/sync-pending-counts.test.ts +239 -0
  379. package/templates/default/src/lib/sync/sync-pending-counts.ts +1358 -0
  380. package/templates/default/src/lib/sync/sync-registry.ts +149 -0
  381. package/templates/default/src/lib/tag-utils.ts +28 -0
  382. package/templates/default/src/lib/template-sync-utils.d.ts +6 -6
  383. package/templates/default/src/lib/template-sync-utils.js +46 -46
  384. package/templates/default/src/lib/template-sync-utils.ts +63 -63
  385. package/templates/default/src/lib/test-case-utils.ts +6 -6
  386. package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
  387. package/templates/default/src/lib/test-run/matching.ts +117 -0
  388. package/templates/default/src/lib/test-run/process-manager.ts +2 -0
  389. package/templates/default/src/lib/test-run/report-parser.ts +352 -316
  390. package/templates/default/src/lib/test-run/test-run-executor.ts +13 -15
  391. package/templates/default/src/lib/test-run/winston-logger.ts +64 -66
  392. package/templates/default/src/lib/test-suite-identifier-service.ts +76 -0
  393. package/templates/default/src/lib/test-suite-utils.ts +6 -0
  394. package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
  395. package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
  396. package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
  397. package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
  398. package/templates/default/src/lib/utils/template-step-file-generator.ts +104 -104
  399. package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +0 -8
  400. package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
  401. package/templates/default/src/lib/utils.ts +31 -31
  402. package/templates/default/src/types/diagram/diagram.ts +34 -34
  403. package/templates/default/src/types/diagram/template-step.ts +11 -11
  404. package/templates/default/src/types/executor/browser.type.ts +1 -1
  405. package/templates/default/src/types/form/actionHandler.ts +6 -6
  406. package/templates/default/src/types/locator/locator.type.ts +11 -11
  407. package/templates/default/src/types/locator-picker.ts +65 -0
  408. package/templates/default/src/types/step/step.type.ts +1 -1
  409. package/templates/default/src/types/table/data-table.ts +6 -6
  410. package/templates/default/src/types/test-case-picker.ts +6 -0
  411. package/templates/default/src/types/test-suite-picker.ts +18 -0
  412. package/templates/default/tailwind.config.ts +62 -62
  413. package/templates/default/tsconfig.json +4 -1
  414. package/templates/default/appraisejs.config.json +0 -1
@@ -1,127 +1,127 @@
1
- 'use client'
2
-
3
- import { deleteTestRunAction, getTestRunByIdAction } from '@/actions/test-run/test-run-actions'
4
- import { DataTable } from '@/components/ui/data-table'
5
- import { Environment, Tag, TestRun, TestRunTestCase, TestRunStatus } from '@prisma/client'
6
- import React, { useEffect, useState, useRef, useMemo } from 'react'
7
- import { testRunTableCols } from './test-run-table-columns'
8
-
9
- type TestRunData = TestRun & { testCases: TestRunTestCase[]; tags: Tag[]; environment: Environment }
10
-
11
- interface TestRunTableProps {
12
- initialData: TestRunData[]
13
- filter: 'recentFailed' | 'all'
14
- }
15
-
16
- const TestRunTable = ({ initialData, filter = 'all' }: TestRunTableProps) => {
17
- const [testRuns, setTestRuns] = useState<TestRunData[]>(initialData)
18
- const pollingRef = useRef<NodeJS.Timeout | null>(null)
19
-
20
- // Memoize running test run IDs to avoid unnecessary effect re-runs
21
- // Include RUNNING, QUEUED, and CANCELLING statuses for polling
22
- const runningTestRunIds = useMemo(() => {
23
- return testRuns
24
- .filter(
25
- tr =>
26
- tr.status === TestRunStatus.RUNNING ||
27
- tr.status === TestRunStatus.QUEUED ||
28
- tr.status === TestRunStatus.CANCELLING,
29
- )
30
- .map(tr => tr.id)
31
- }, [testRuns])
32
-
33
- // Create a stable dependency string for useEffect
34
- const runningTestRunIdsKey = useMemo(() => runningTestRunIds.join(','), [runningTestRunIds])
35
-
36
- // Poll for status updates while test runs are running
37
- useEffect(() => {
38
- // Clear any existing polling interval
39
- if (pollingRef.current) {
40
- clearInterval(pollingRef.current)
41
- pollingRef.current = null
42
- }
43
-
44
- // If no running test runs, don't poll
45
- if (runningTestRunIds.length === 0) {
46
- return
47
- }
48
-
49
- pollingRef.current = setInterval(async () => {
50
- try {
51
- // Poll only running test runs in parallel
52
- const updatePromises = runningTestRunIds.map(async id => {
53
- const { data, error } = await getTestRunByIdAction(id)
54
- if (error || !data) {
55
- return null
56
- }
57
- // getTestRunByIdAction returns testCases with nested testCase, but we need to flatten it
58
- const testRun = data as TestRun & {
59
- testCases: (TestRunTestCase & { testCase: { title: string } })[]
60
- tags: Tag[]
61
- environment: Environment
62
- }
63
- // Convert to the format expected by the table (flatten testCases)
64
- return {
65
- ...testRun,
66
- testCases: testRun.testCases.map(tc => ({
67
- id: tc.id,
68
- testRunId: tc.testRunId,
69
- testCaseId: tc.testCaseId,
70
- status: tc.status,
71
- result: tc.result,
72
- })) as TestRunTestCase[],
73
- } as TestRunData
74
- })
75
-
76
- const updates = await Promise.all(updatePromises)
77
- const validUpdates = updates.filter((u): u is TestRunData => u !== null)
78
-
79
- // Update only the changed test runs
80
- setTestRuns(prev =>
81
- prev.map(tr => {
82
- const update = validUpdates.find(u => u.id === tr.id)
83
- return update || tr
84
- }),
85
- )
86
-
87
- // Check if any are still running (including CANCELLING)
88
- const stillRunning = validUpdates.filter(
89
- u =>
90
- u.status === TestRunStatus.RUNNING ||
91
- u.status === TestRunStatus.QUEUED ||
92
- u.status === TestRunStatus.CANCELLING,
93
- )
94
-
95
- // If no test runs are running anymore, stop polling
96
- if (stillRunning.length === 0 && pollingRef.current) {
97
- clearInterval(pollingRef.current)
98
- pollingRef.current = null
99
- }
100
- } catch (error) {
101
- console.error('Error polling test runs status:', error)
102
- }
103
- }, 2000) // Poll every 2 seconds
104
-
105
- return () => {
106
- if (pollingRef.current) {
107
- clearInterval(pollingRef.current)
108
- pollingRef.current = null
109
- }
110
- }
111
- }, [runningTestRunIdsKey, runningTestRunIds])
112
-
113
- return (
114
- <>
115
- <DataTable
116
- columns={testRunTableCols}
117
- data={testRuns}
118
- filterColumn="name"
119
- filterPlaceholder="Filter by name..."
120
- deleteAction={deleteTestRunAction}
121
- createLink={filter === 'all' ? '/test-runs/create' : undefined}
122
- />
123
- </>
124
- )
125
- }
126
-
127
- export default TestRunTable
1
+ 'use client'
2
+
3
+ import { deleteTestRunAction, getTestRunByIdAction } from '@/actions/test-run/test-run-actions'
4
+ import { DataTable } from '@/components/ui/data-table'
5
+ import { Environment, Tag, TestRun, TestRunTestCase, TestRunStatus } from '@prisma/client'
6
+ import React, { useEffect, useState, useRef, useMemo } from 'react'
7
+ import { testRunTableCols } from './test-run-table-columns'
8
+
9
+ type TestRunData = TestRun & { testCases: TestRunTestCase[]; tags: Tag[]; environment: Environment }
10
+
11
+ interface TestRunTableProps {
12
+ initialData: TestRunData[]
13
+ filter: 'recentFailed' | 'all'
14
+ }
15
+
16
+ const TestRunTable = ({ initialData, filter = 'all' }: TestRunTableProps) => {
17
+ const [testRuns, setTestRuns] = useState<TestRunData[]>(initialData)
18
+ const pollingRef = useRef<NodeJS.Timeout | null>(null)
19
+
20
+ // Memoize running test run IDs to avoid unnecessary effect re-runs
21
+ // Include RUNNING, QUEUED, and CANCELLING statuses for polling
22
+ const runningTestRunIds = useMemo(() => {
23
+ return testRuns
24
+ .filter(
25
+ tr =>
26
+ tr.status === TestRunStatus.RUNNING ||
27
+ tr.status === TestRunStatus.QUEUED ||
28
+ tr.status === TestRunStatus.CANCELLING,
29
+ )
30
+ .map(tr => tr.id)
31
+ }, [testRuns])
32
+
33
+ // Create a stable dependency string for useEffect
34
+ const runningTestRunIdsKey = useMemo(() => runningTestRunIds.join(','), [runningTestRunIds])
35
+
36
+ // Poll for status updates while test runs are running
37
+ useEffect(() => {
38
+ // Clear any existing polling interval
39
+ if (pollingRef.current) {
40
+ clearInterval(pollingRef.current)
41
+ pollingRef.current = null
42
+ }
43
+
44
+ // If no running test runs, don't poll
45
+ if (runningTestRunIds.length === 0) {
46
+ return
47
+ }
48
+
49
+ pollingRef.current = setInterval(async () => {
50
+ try {
51
+ // Poll only running test runs in parallel
52
+ const updatePromises = runningTestRunIds.map(async id => {
53
+ const { data, error } = await getTestRunByIdAction(id)
54
+ if (error || !data) {
55
+ return null
56
+ }
57
+ // getTestRunByIdAction returns testCases with nested testCase, but we need to flatten it
58
+ const testRun = data as TestRun & {
59
+ testCases: (TestRunTestCase & { testCase: { title: string } })[]
60
+ tags: Tag[]
61
+ environment: Environment
62
+ }
63
+ // Convert to the format expected by the table (flatten testCases)
64
+ return {
65
+ ...testRun,
66
+ testCases: testRun.testCases.map(tc => ({
67
+ id: tc.id,
68
+ testRunId: tc.testRunId,
69
+ testCaseId: tc.testCaseId,
70
+ status: tc.status,
71
+ result: tc.result,
72
+ })) as TestRunTestCase[],
73
+ } as TestRunData
74
+ })
75
+
76
+ const updates = await Promise.all(updatePromises)
77
+ const validUpdates = updates.filter((u): u is TestRunData => u !== null)
78
+
79
+ // Update only the changed test runs
80
+ setTestRuns(prev =>
81
+ prev.map(tr => {
82
+ const update = validUpdates.find(u => u.id === tr.id)
83
+ return update || tr
84
+ }),
85
+ )
86
+
87
+ // Check if any are still running (including CANCELLING)
88
+ const stillRunning = validUpdates.filter(
89
+ u =>
90
+ u.status === TestRunStatus.RUNNING ||
91
+ u.status === TestRunStatus.QUEUED ||
92
+ u.status === TestRunStatus.CANCELLING,
93
+ )
94
+
95
+ // If no test runs are running anymore, stop polling
96
+ if (stillRunning.length === 0 && pollingRef.current) {
97
+ clearInterval(pollingRef.current)
98
+ pollingRef.current = null
99
+ }
100
+ } catch (error) {
101
+ console.error('Error polling test runs status:', error)
102
+ }
103
+ }, 2000) // Poll every 2 seconds
104
+
105
+ return () => {
106
+ if (pollingRef.current) {
107
+ clearInterval(pollingRef.current)
108
+ pollingRef.current = null
109
+ }
110
+ }
111
+ }, [runningTestRunIdsKey, runningTestRunIds])
112
+
113
+ return (
114
+ <>
115
+ <DataTable
116
+ columns={testRunTableCols}
117
+ data={testRuns}
118
+ filterColumn="name"
119
+ filterPlaceholder="Filter by name..."
120
+ deleteAction={deleteTestRunAction}
121
+ createLink={filter === 'all' ? '/test-runs/create' : undefined}
122
+ />
123
+ </>
124
+ )
125
+ }
126
+
127
+ export default TestRunTable
@@ -3,7 +3,8 @@ import { TestSuiteForm } from '../test-suite-form'
3
3
  import PageHeader from '@/components/typography/page-header'
4
4
  import HeaderSubtitle from '@/components/typography/page-header-subtitle'
5
5
  import { getAllTestCasesAction } from '@/actions/test-case/test-case-actions'
6
- import { Module, TestCase, Tag } from '@prisma/client'
6
+ import { TestCasePickerRow } from '@/types/test-case-picker'
7
+ import { Module, Tag } from '@prisma/client'
7
8
  import { getAllModulesAction } from '@/actions/modules/module-actions'
8
9
  import { getAllTagsAction } from '@/actions/tags/tag-actions'
9
10
  import { Metadata } from 'next'
@@ -34,7 +35,7 @@ const CreateTestSuite = async () => {
34
35
  successTitle="Suite created"
35
36
  successMessage="Test suite created successfully"
36
37
  onSubmitAction={createTestSuiteAction}
37
- testCases={testCases as TestCase[]}
38
+ testCases={testCases as TestCasePickerRow[]}
38
39
  moduleList={moduleList as Module[]}
39
40
  tags={tags as Tag[]}
40
41
  />
@@ -7,6 +7,7 @@ import { Module, TestCase } from '@prisma/client'
7
7
  import { getAllModulesAction } from '@/actions/modules/module-actions'
8
8
  import { getAllTagsAction } from '@/actions/tags/tag-actions'
9
9
  import { Metadata } from 'next'
10
+ import { TestCasePickerRow } from '@/types/test-case-picker'
10
11
 
11
12
  export const metadata: Metadata = {
12
13
  title: 'Appraise | Modify Test Suite',
@@ -45,7 +46,7 @@ const ModifyTestSuite = async ({ params }: { params: Promise<{ id: string }> })
45
46
  successMessage="Test suite updated successfully"
46
47
  onSubmitAction={updateTestSuiteAction}
47
48
  id={id}
48
- testCases={testCases as TestCase[]}
49
+ testCases={testCases as TestCasePickerRow[]}
49
50
  moduleList={moduleList as Module[]}
50
51
  tags={tags as Tag[]}
51
52
  />
@@ -5,12 +5,14 @@ import TestSuiteTable from './test-suite-table'
5
5
  import { Suspense } from 'react'
6
6
  import DataTableSkeleton from '@/components/loading-skeleton/data-table/data-table-skeleton'
7
7
  import { getAllTestSuitesAction } from '@/actions/test-suite/test-suite-actions'
8
- import { TestCase, TestSuite } from '@prisma/client'
8
+ import { Tag, TestCase, TestSuite } from '@prisma/client'
9
9
  import InfoGrid from '@/components/data-visualization/info-grid'
10
10
  import EmptyState from '@/components/data-state/empty-state'
11
11
  import { Metadata } from 'next'
12
12
  import { TubePlus } from '@/assets/icons/tube-plus'
13
13
  import EmptyTube from '@/assets/icons/empty-tube'
14
+ import { Tag as TagIcon } from 'lucide-react'
15
+ import { getFilterTags } from '@/lib/tag-utils'
14
16
 
15
17
  export const metadata: Metadata = {
16
18
  title: 'Appraise | Test Suites',
@@ -24,9 +26,60 @@ const TestSuites = async () => {
24
26
  return <div>Error: {testSuitesError}</div>
25
27
  }
26
28
 
27
- const testSuitesData = testSuites as (TestSuite & { testCases: TestCase[] })[]
29
+ const testSuitesData = testSuites as (TestSuite & { testCases: TestCase[]; tags: Tag[] })[]
28
30
  const emptyTestSuites = testSuitesData.filter(testSuite => testSuite.testCases.length === 0)
29
- const latestCreatedTestSuite = testSuitesData.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0]
31
+ const latestCreatedTestSuite = [...testSuitesData].sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0]
32
+ const tagSuiteCountMap = new Map<string, { name: string; suiteCount: number }>()
33
+
34
+ for (const testSuite of testSuitesData) {
35
+ for (const tag of getFilterTags(testSuite.tags)) {
36
+ const currentTag = tagSuiteCountMap.get(tag.id)
37
+
38
+ if (currentTag) {
39
+ currentTag.suiteCount += 1
40
+ } else {
41
+ tagSuiteCountMap.set(tag.id, {
42
+ name: tag.name,
43
+ suiteCount: 1,
44
+ })
45
+ }
46
+ }
47
+ }
48
+
49
+ const mostCommonTagWithSuites = [...tagSuiteCountMap.values()].sort((a, b) => {
50
+ if (b.suiteCount !== a.suiteCount) {
51
+ return b.suiteCount - a.suiteCount
52
+ }
53
+
54
+ return a.name.localeCompare(b.name)
55
+ })[0]
56
+ const infoCards = [
57
+ {
58
+ showHighlightGroup: testSuitesData.length > 0,
59
+ highlight: emptyTestSuites.length.toString(),
60
+ legend: 'Empty test suite(s)',
61
+ defaultText: 'Empty test suites count. Will update when test suites are created.',
62
+ icon: <EmptyTube className="h-12 w-12 rounded-sm bg-muted p-2" />,
63
+ },
64
+ {
65
+ showHighlightGroup: testSuitesData.length > 0,
66
+ highlight: latestCreatedTestSuite ? latestCreatedTestSuite.name : 'N/A',
67
+ legend: 'Latest test suite',
68
+ defaultText: 'Latest created test suite. Will update when test suites are created.',
69
+ icon: <TubePlus className="h-12 w-12 rounded-sm bg-muted p-2" />,
70
+ },
71
+ ...(mostCommonTagWithSuites
72
+ ? [
73
+ {
74
+ showHighlightGroup: true,
75
+ highlight: mostCommonTagWithSuites.name,
76
+ legend: 'Most common tag',
77
+ defaultText: 'Most common suite tag will appear here when test suites have tags.',
78
+ icon: <TagIcon className="h-12 w-12 rounded-sm bg-muted p-2" />,
79
+ },
80
+ ]
81
+ : []),
82
+ ]
30
83
 
31
84
  if (testSuitesData.length === 0) {
32
85
  return (
@@ -53,24 +106,7 @@ const TestSuites = async () => {
53
106
  <HeaderSubtitle>
54
107
  Test suites are collections of tests that are used to test a specific feature or functionality
55
108
  </HeaderSubtitle>
56
- <InfoGrid
57
- infoCards={[
58
- {
59
- showHighlightGroup: testSuitesData.length > 0,
60
- highlight: emptyTestSuites.length.toString(),
61
- legend: 'Empty test suite(s)',
62
- defaultText: 'Empty test suites count. Will update when test suites are created.',
63
- icon: <EmptyTube className="h-12 w-12 rounded-sm bg-muted p-2" />,
64
- },
65
- {
66
- showHighlightGroup: testSuitesData.length > 0,
67
- highlight: latestCreatedTestSuite ? latestCreatedTestSuite.name : 'N/A',
68
- legend: 'Latest test suite',
69
- defaultText: 'Latest created test suite. Will update when test suites are created.',
70
- icon: <TubePlus className="h-12 w-12 rounded-sm bg-muted p-2" />,
71
- },
72
- ]}
73
- />
109
+ <InfoGrid infoCards={infoCards} />
74
110
  </div>
75
111
  <Suspense fallback={<DataTableSkeleton />}>
76
112
  <TestSuiteTable />
@@ -1,6 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import { Button } from '@/components/ui/button'
4
+ import TestCasePicker from '@/components/test-case/test-case-picker'
4
5
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
5
6
  import { Input } from '@/components/ui/input'
6
7
  import { Label } from '@/components/ui/label'
@@ -9,8 +10,9 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
9
10
  import { Textarea } from '@/components/ui/textarea'
10
11
  import { formOpts, TestSuite } from '@/constants/form-opts/test-suite-form-opts'
11
12
  import { toast } from '@/hooks/use-toast'
13
+ import { TestCasePickerRow } from '@/types/test-case-picker'
12
14
  import { ActionResponse } from '@/types/form/actionHandler'
13
- import { Module, TestCase, Tag } from '@prisma/client'
15
+ import { Module, Tag } from '@prisma/client'
14
16
  import { useForm } from '@tanstack/react-form'
15
17
  import { Info, Save } from 'lucide-react'
16
18
  import { useRouter } from 'next/navigation'
@@ -31,7 +33,7 @@ export const TestSuiteForm = ({
31
33
  successMessage: string
32
34
  id?: string
33
35
  onSubmitAction: (_prev: unknown, value: TestSuite, id?: string) => Promise<ActionResponse>
34
- testCases: TestCase[]
36
+ testCases: TestCasePickerRow[]
35
37
  moduleList: Module[]
36
38
  tags: Tag[]
37
39
  }) => {
@@ -134,28 +136,25 @@ export const TestSuiteForm = ({
134
136
  </form.Field>
135
137
  <form.Field name="testCases">
136
138
  {field => {
137
- const testCasesOptions = testCases.map(testCase => ({
138
- value: testCase.id,
139
- label: testCase.title,
140
- }))
141
139
  return (
142
140
  <div className="mb-6 flex flex-col gap-2">
143
141
  <Label htmlFor={field.name} className="font-bold">
144
142
  Test Cases
145
143
  </Label>
146
- <MultiSelectWithPreview
147
- id={field.name}
148
- className="w-full"
149
- options={testCasesOptions}
150
- onSelectChange={value => {
151
- field.handleChange(value)
152
- }}
153
- defaultSelectedValues={field.state.value}
154
- placeholder="Select test case(s)"
155
- emptyMessage="No test case(s) found"
144
+ <TestCasePicker
145
+ testCases={testCases}
146
+ selectedIds={field.state.value ?? []}
147
+ onSave={value => field.handleChange(value)}
148
+ triggerPlaceholder="Select test case(s)"
149
+ dialogTitle="Select Test Cases"
150
+ dialogDescription="Search and select the test cases to include in this suite."
156
151
  selectedLabel="Selected test case(s)"
157
- searchPlaceholder="Search test cases..."
158
152
  />
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
+ ))}
159
158
  </div>
160
159
  )
161
160
  }}
@@ -9,6 +9,7 @@ import TableActions from '@/components/table/table-actions'
9
9
  import { deleteTestSuiteAction } from '@/actions/test-suite/test-suite-actions'
10
10
  import { formatDateTime } from '@/lib/utils'
11
11
  import { Badge } from '@/components/ui/badge'
12
+ import { getFilterTags } from '@/lib/tag-utils'
12
13
  export const testSuiteTableCols: ColumnDef<TestSuite & { tags?: Tag[]; module: Module; testCases: TestCase[] }>[] = [
13
14
  {
14
15
  id: 'select',
@@ -60,7 +61,7 @@ export const testSuiteTableCols: ColumnDef<TestSuite & { tags?: Tag[]; module: M
60
61
  header: ({ column }) => <DataTableColumnHeader column={column} title="Tags" />,
61
62
  cell: ({ row }) => {
62
63
  const testSuite = row.original
63
- const tags = testSuite.tags || []
64
+ const tags = getFilterTags(testSuite.tags || [])
64
65
  return (
65
66
  <div className="flex flex-wrap gap-1">
66
67
  {tags.length > 0 ? tags.map(tag => <Badge key={tag.id}>{tag.name}</Badge>) : '-'}
@@ -1,29 +1,29 @@
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
+ 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