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,104 +1,26 @@
1
1
  'use client'
2
2
 
3
- import { useEffect, useState, type ReactNode } from 'react'
4
- import { useRouter } from 'next/navigation'
3
+ import { useEffect } from 'react'
5
4
  import {
6
- CircleHelp,
7
- Code,
8
- Component,
9
- Group,
10
- LayoutTemplate,
11
- Puzzle,
12
5
  RefreshCw,
13
- Server,
14
- Tag,
15
- TestTubeDiagonal,
16
- TestTubes,
17
6
  } from 'lucide-react'
18
- import { getSyncPendingCountsAction, runSyncAction } from '@/actions/settings/sync-actions'
19
7
  import { AppDrawerItemColor } from '@/app/(dashboard-components)/app-drawer'
20
8
  import { Button } from '@/components/ui/button'
21
9
  import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
22
10
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
23
- import { toast } from '@/hooks/use-toast'
24
11
  import {
25
12
  SYNC_ALL_REQUEST_ID,
26
- getSyncScriptDefinition,
27
- resolveRequestedSyncExecutionOrder,
28
- syncScriptDefinitions,
29
13
  type SyncRequestId,
30
- type SyncScriptId,
31
14
  type SyncScriptDefinition,
15
+ syncScriptDefinitions,
32
16
  } from '@/lib/sync/sync-registry'
33
17
  import type { SyncPendingCounts } from '@/lib/sync/sync-pending-counts'
34
-
35
- type SyncRunResult = Awaited<ReturnType<typeof runSyncAction>>
36
- type SyncTileColor = keyof typeof AppDrawerItemColor
37
-
38
- const syncPresentation: Record<SyncScriptId, { icon: ReactNode; colorKey: SyncTileColor }> = {
39
- 'sync-modules': {
40
- icon: <Puzzle />,
41
- colorKey: 'indigo',
42
- },
43
- 'sync-environments': {
44
- icon: <Server />,
45
- colorKey: 'sky',
46
- },
47
- 'sync-tags': {
48
- icon: <Tag />,
49
- colorKey: 'yellow',
50
- },
51
- 'sync-template-step-groups': {
52
- icon: <Component />,
53
- colorKey: 'violet',
54
- },
55
- 'sync-template-steps': {
56
- icon: <LayoutTemplate />,
57
- colorKey: 'purple',
58
- },
59
- 'sync-locator-groups': {
60
- icon: <Group />,
61
- colorKey: 'blue',
62
- },
63
- 'sync-locators': {
64
- icon: <Code />,
65
- colorKey: 'emerald',
66
- },
67
- 'sync-test-suites': {
68
- icon: <TestTubes />,
69
- colorKey: 'orange',
70
- },
71
- 'sync-test-cases': {
72
- icon: <TestTubeDiagonal />,
73
- colorKey: 'rose',
74
- },
75
- }
76
-
77
- function formatExecutionSummary(result: SyncRunResult): string {
78
- if (result.requestedScriptId === SYNC_ALL_REQUEST_ID) {
79
- return `Completed ${result.executedScriptIds.length} sync scripts successfully.`
80
- }
81
-
82
- if (result.executedScriptIds.length <= 1) {
83
- return `${result.requestedScriptId} completed successfully.`
84
- }
85
-
86
- return `${result.requestedScriptId} completed after running ${result.executedScriptIds.join(' -> ')}.`
87
- }
88
-
89
- function formatFailureSummary(result: SyncRunResult): string {
90
- if ('failedScriptId' in result && result.failedScriptId) {
91
- const exitCode = typeof result.exitCode === 'number' ? ` (exit code ${result.exitCode})` : ''
92
- const cause = result.cause ?? 'No cause was reported.'
93
- return `${result.failedScriptId}${exitCode} failed: ${cause}`
94
- }
95
-
96
- return result.cause ?? `Unable to run ${result.requestedScriptId}.`
97
- }
98
-
99
- function formatExecutionOrder(scriptIds: SyncScriptId[]): string {
100
- return scriptIds.map(scriptId => getSyncScriptDefinition(scriptId).orderLabel).join(' -> ')
101
- }
18
+ import {
19
+ getSyncTooltipCopy,
20
+ syncPanelInfo,
21
+ syncPresentation,
22
+ } from './settings-sync-panel-helpers'
23
+ import { useSettingsSync } from './use-settings-sync'
102
24
 
103
25
  function SyncRow({
104
26
  definition,
@@ -115,7 +37,6 @@ function SyncRow({
115
37
  }) {
116
38
  const { icon, colorKey } = syncPresentation[definition.id]
117
39
  const color = AppDrawerItemColor[colorKey]
118
- const executionOrder = resolveRequestedSyncExecutionOrder(definition.id)
119
40
 
120
41
  return (
121
42
  <Tooltip>
@@ -123,6 +44,7 @@ function SyncRow({
123
44
  <Button
124
45
  variant="outline"
125
46
  disabled={disabled}
47
+ aria-label={definition.label}
126
48
  onClick={() => onRun(definition.id)}
127
49
  className={`inline-flex h-24 w-44 flex-none flex-col items-start justify-start whitespace-normal rounded-2xl border-none px-3 py-2.5 text-left hover:text-gray-200 ${color.buttonColor}`}
128
50
  >
@@ -145,59 +67,21 @@ function SyncRow({
145
67
  </TooltipTrigger>
146
68
  <TooltipContent className="max-w-xs">
147
69
  <p>{definition.description}</p>
148
- <p className="mt-1 text-primary-foreground/80">Runs synchronization in order: {formatExecutionOrder(executionOrder)}</p>
70
+ <p className="mt-1 text-primary-foreground/80">{getSyncTooltipCopy(definition.id)}</p>
149
71
  </TooltipContent>
150
72
  </Tooltip>
151
73
  )
152
74
  }
153
75
 
154
76
  export function SettingsSyncPanel({ pendingCounts }: { pendingCounts: SyncPendingCounts }) {
155
- const router = useRouter()
156
- const [activeRequestId, setActiveRequestId] = useState<SyncRequestId | null>(null)
157
- const [currentPendingCounts, setCurrentPendingCounts] = useState<SyncPendingCounts>(pendingCounts)
77
+ const { activeRequestId, isRunning, pendingCounts: currentPendingCounts, runSync, setPendingCounts } =
78
+ useSettingsSync({
79
+ initialPendingCounts: pendingCounts,
80
+ })
158
81
 
159
82
  useEffect(() => {
160
- setCurrentPendingCounts(pendingCounts)
161
- }, [pendingCounts])
162
-
163
- const runSync = async (requestId: SyncRequestId) => {
164
- if (activeRequestId) {
165
- return
166
- }
167
-
168
- setActiveRequestId(requestId)
169
-
170
- try {
171
- const result = await runSyncAction(requestId)
172
-
173
- if (result.success) {
174
- const refreshedCounts = await getSyncPendingCountsAction()
175
- setCurrentPendingCounts(refreshedCounts)
176
- toast({
177
- title: 'Sync completed',
178
- description: formatExecutionSummary(result),
179
- })
180
- } else {
181
- toast({
182
- variant: 'destructive',
183
- title: 'Sync failed',
184
- description: formatFailureSummary(result),
185
- })
186
- }
187
-
188
- router.refresh()
189
- } catch (error) {
190
- toast({
191
- variant: 'destructive',
192
- title: 'Sync failed',
193
- description: error instanceof Error ? error.message : String(error),
194
- })
195
- } finally {
196
- setActiveRequestId(null)
197
- }
198
- }
199
-
200
- const isRunning = activeRequestId !== null
83
+ setPendingCounts(pendingCounts)
84
+ }, [pendingCounts, setPendingCounts])
201
85
 
202
86
  return (
203
87
  <TooltipProvider>
@@ -208,7 +92,7 @@ export function SettingsSyncPanel({ pendingCounts }: { pendingCounts: SyncPendin
208
92
  <Tooltip>
209
93
  <TooltipTrigger asChild>
210
94
  <span className="cursor-help text-muted-foreground">
211
- <CircleHelp className="h-4 w-4" />
95
+ {syncPanelInfo.helpIcon}
212
96
  </span>
213
97
  </TooltipTrigger>
214
98
  <TooltipContent className="max-w-xs">
@@ -222,6 +106,7 @@ export function SettingsSyncPanel({ pendingCounts }: { pendingCounts: SyncPendin
222
106
  <TooltipTrigger asChild>
223
107
  <Button
224
108
  disabled={isRunning}
109
+ aria-label="Sync All"
225
110
  onClick={() => runSync(SYNC_ALL_REQUEST_ID)}
226
111
  className="inline-flex h-24 w-44 flex-none flex-col items-start justify-start whitespace-normal rounded-2xl border-none bg-emerald-500/10 px-3 py-2.5 text-left text-gray-100 hover:bg-emerald-500/20 hover:text-gray-100"
227
112
  >
@@ -239,7 +124,7 @@ export function SettingsSyncPanel({ pendingCounts }: { pendingCounts: SyncPendin
239
124
  </Button>
240
125
  </TooltipTrigger>
241
126
  <TooltipContent className="max-w-xs">
242
- Runs synchronization in order: {formatExecutionOrder(resolveRequestedSyncExecutionOrder(SYNC_ALL_REQUEST_ID))}
127
+ {getSyncTooltipCopy(SYNC_ALL_REQUEST_ID)}
243
128
  </TooltipContent>
244
129
  </Tooltip>
245
130
  <div className="flex flex-wrap items-start gap-4">
@@ -0,0 +1,66 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { useRouter } from 'next/navigation'
5
+
6
+ import { getSyncPendingCountsAction, runSyncAction } from '@/actions/settings/sync-actions'
7
+ import { toast } from '@/hooks/use-toast'
8
+ import type { SyncPendingCounts } from '@/lib/sync/sync-pending-counts'
9
+ import type { SyncRequestId } from '@/lib/sync/sync-registry'
10
+
11
+ import { formatExecutionSummary, formatFailureSummary, type SyncRunResult } from './settings-sync-panel-helpers'
12
+
13
+ type UseSettingsSyncOptions = {
14
+ initialPendingCounts: SyncPendingCounts
15
+ }
16
+
17
+ export function useSettingsSync({ initialPendingCounts }: UseSettingsSyncOptions) {
18
+ const router = useRouter()
19
+ const [activeRequestId, setActiveRequestId] = useState<SyncRequestId | null>(null)
20
+ const [pendingCounts, setPendingCounts] = useState<SyncPendingCounts>(initialPendingCounts)
21
+
22
+ const runSync = async (requestId: SyncRequestId) => {
23
+ if (activeRequestId) {
24
+ return
25
+ }
26
+
27
+ setActiveRequestId(requestId)
28
+
29
+ try {
30
+ const result = (await runSyncAction(requestId)) as SyncRunResult
31
+
32
+ if (result.success) {
33
+ const refreshedCounts = await getSyncPendingCountsAction()
34
+ setPendingCounts(refreshedCounts)
35
+ toast({
36
+ title: 'Sync completed',
37
+ description: formatExecutionSummary(result),
38
+ })
39
+ } else {
40
+ toast({
41
+ variant: 'destructive',
42
+ title: 'Sync failed',
43
+ description: formatFailureSummary(result),
44
+ })
45
+ }
46
+
47
+ router.refresh()
48
+ } catch (error) {
49
+ toast({
50
+ variant: 'destructive',
51
+ title: 'Sync failed',
52
+ description: error instanceof Error ? error.message : String(error),
53
+ })
54
+ } finally {
55
+ setActiveRequestId(null)
56
+ }
57
+ }
58
+
59
+ return {
60
+ activeRequestId,
61
+ isRunning: activeRequestId !== null,
62
+ pendingCounts,
63
+ runSync,
64
+ setPendingCounts,
65
+ }
66
+ }
@@ -1,39 +1,39 @@
1
- import { createTagAction } from '@/actions/tags/tag-actions'
2
- import PageHeader from '@/components/typography/page-header'
3
- import HeaderSubtitle from '@/components/typography/page-header-subtitle'
4
- import { Tag } from 'lucide-react'
5
- import React from 'react'
6
- import TagForm from '../tag-form'
7
- import { Metadata } from 'next'
8
-
9
- export const metadata: Metadata = {
10
- title: 'Appraise | Create Tag',
11
- description: 'Create a new tag to be used in your test cases',
12
- }
13
-
14
- const CreateTag = () => {
15
- return (
16
- <>
17
- <div className="mb-8">
18
- <PageHeader>
19
- <span className="flex items-center">
20
- <Tag className="mr-2 h-8 w-8" />
21
- Create Tag
22
- </span>
23
- </PageHeader>
24
- <HeaderSubtitle>Create a new tag to be used in your test cases.</HeaderSubtitle>
25
- </div>
26
- <TagForm
27
- successTitle="Tag created"
28
- successMessage="Tag created successfully"
29
- onSubmitAction={createTagAction}
30
- defaultValues={{
31
- name: '',
32
- tagExpression: '',
33
- }}
34
- />
35
- </>
36
- )
37
- }
38
-
39
- export default CreateTag
1
+ import { createTagAction } from '@/actions/tags/tag-actions'
2
+ import PageHeader from '@/components/typography/page-header'
3
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
4
+ import { Tag } from 'lucide-react'
5
+ import React from 'react'
6
+ import TagForm from '../tag-form'
7
+ import { Metadata } from 'next'
8
+
9
+ export const metadata: Metadata = {
10
+ title: 'Appraise | Create Tag',
11
+ description: 'Create a new tag to be used in your test cases',
12
+ }
13
+
14
+ const CreateTag = () => {
15
+ return (
16
+ <>
17
+ <div className="mb-8">
18
+ <PageHeader>
19
+ <span className="flex items-center">
20
+ <Tag className="mr-2 h-8 w-8" />
21
+ Create Tag
22
+ </span>
23
+ </PageHeader>
24
+ <HeaderSubtitle>Create a new tag to be used in your test cases.</HeaderSubtitle>
25
+ </div>
26
+ <TagForm
27
+ successTitle="Tag created"
28
+ successMessage="Tag created successfully"
29
+ onSubmitAction={createTagAction}
30
+ defaultValues={{
31
+ name: '',
32
+ tagExpression: '',
33
+ }}
34
+ />
35
+ </>
36
+ )
37
+ }
38
+
39
+ export default CreateTag
@@ -1,50 +1,50 @@
1
- import PageHeader from '@/components/typography/page-header'
2
- import HeaderSubtitle from '@/components/typography/page-header-subtitle'
3
- import React from 'react'
4
- import TagForm from '../../tag-form'
5
- import { getTagByIdAction, updateTagAction } from '@/actions/tags/tag-actions'
6
- import { Tag } from 'lucide-react'
7
- import { Tag as TagType } from '@prisma/client'
8
- import { Metadata } from 'next'
9
-
10
- export const metadata: Metadata = {
11
- title: 'Appraise | Modify Tag',
12
- description: 'Modify a tag',
13
- }
14
-
15
- const ModifyTag = async ({ params }: { params: Promise<{ id: string }> }) => {
16
- const { id } = await params
17
- const { data: tagToBeEditedData, error: tagToBeEditedError } = await getTagByIdAction(id)
18
-
19
- if (tagToBeEditedError) {
20
- return <div>Error: {tagToBeEditedError}</div>
21
- }
22
-
23
- const tagData = tagToBeEditedData as TagType
24
-
25
- return (
26
- <>
27
- <div className="mb-8">
28
- <PageHeader>
29
- <span className="flex items-center">
30
- <Tag className="mr-2 h-8 w-8" />
31
- Modify Tag
32
- </span>
33
- </PageHeader>
34
- <HeaderSubtitle>Modify a tag.</HeaderSubtitle>
35
- </div>
36
- <TagForm
37
- successTitle="Tag modified"
38
- successMessage="Tag modified successfully"
39
- onSubmitAction={updateTagAction}
40
- defaultValues={{
41
- name: tagData.name,
42
- tagExpression: tagData.tagExpression,
43
- }}
44
- id={id}
45
- />
46
- </>
47
- )
48
- }
49
-
50
- export default ModifyTag
1
+ import PageHeader from '@/components/typography/page-header'
2
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
3
+ import React from 'react'
4
+ import TagForm from '../../tag-form'
5
+ import { getTagByIdAction, updateTagAction } from '@/actions/tags/tag-actions'
6
+ import { Tag } from 'lucide-react'
7
+ import { Tag as TagType } from '@prisma/client'
8
+ import { Metadata } from 'next'
9
+
10
+ export const metadata: Metadata = {
11
+ title: 'Appraise | Modify Tag',
12
+ description: 'Modify a tag',
13
+ }
14
+
15
+ const ModifyTag = async ({ params }: { params: Promise<{ id: string }> }) => {
16
+ const { id } = await params
17
+ const { data: tagToBeEditedData, error: tagToBeEditedError } = await getTagByIdAction(id)
18
+
19
+ if (tagToBeEditedError) {
20
+ return <div>Error: {tagToBeEditedError}</div>
21
+ }
22
+
23
+ const tagData = tagToBeEditedData as TagType
24
+
25
+ return (
26
+ <>
27
+ <div className="mb-8">
28
+ <PageHeader>
29
+ <span className="flex items-center">
30
+ <Tag className="mr-2 h-8 w-8" />
31
+ Modify Tag
32
+ </span>
33
+ </PageHeader>
34
+ <HeaderSubtitle>Modify a tag.</HeaderSubtitle>
35
+ </div>
36
+ <TagForm
37
+ successTitle="Tag modified"
38
+ successMessage="Tag modified successfully"
39
+ onSubmitAction={updateTagAction}
40
+ defaultValues={{
41
+ name: tagData.name,
42
+ tagExpression: tagData.tagExpression,
43
+ }}
44
+ id={id}
45
+ />
46
+ </>
47
+ )
48
+ }
49
+
50
+ export default ModifyTag
@@ -1,58 +1,58 @@
1
- import DataTableSkeleton from '@/components/loading-skeleton/data-table/data-table-skeleton'
2
- import PageHeader from '@/components/typography/page-header'
3
- import HeaderSubtitle from '@/components/typography/page-header-subtitle'
4
- import { Tag } from 'lucide-react'
5
- import { Suspense } from 'react'
6
- import TagTable from './tag-table'
7
- import { getAllTagsAction } from '@/actions/tags/tag-actions'
8
- import EmptyState from '@/components/data-state/empty-state'
9
- import { Tag as TagModel } from '@prisma/client'
10
- import { Metadata } from 'next'
11
-
12
- export const metadata: Metadata = {
13
- title: 'Appraise | Tags',
14
- description: 'Manage tags for categorizing test cases and test runs',
15
- }
16
-
17
- const Tags = async () => {
18
- const { data: tags, error: tagsError } = await getAllTagsAction()
19
-
20
- if (tagsError) {
21
- return <div>Error: {tagsError}</div>
22
- }
23
-
24
- const tagsData = tags as TagModel[]
25
-
26
- if (!tagsData || tagsData.length === 0) {
27
- return (
28
- <div className="flex min-h-[calc(100vh-20rem)] items-center justify-center">
29
- <EmptyState
30
- icon={<Tag className="h-8 w-8" />}
31
- title="No tags found"
32
- description="Get started by creating a tag to categorize your test cases and test runs"
33
- createRoute="/tags/create"
34
- createText="Create Tag"
35
- />
36
- </div>
37
- )
38
- }
39
-
40
- return (
41
- <>
42
- <div className="mb-8">
43
- <PageHeader>
44
- <span className="flex items-center">
45
- <Tag className="mr-2 h-8 w-8" />
46
- Tags
47
- </span>
48
- </PageHeader>
49
- <HeaderSubtitle>Categorize test cases and test runs for better organization and filtering</HeaderSubtitle>
50
- </div>
51
- <Suspense fallback={<DataTableSkeleton />}>
52
- <TagTable />
53
- </Suspense>
54
- </>
55
- )
56
- }
57
-
58
- export default Tags
1
+ import DataTableSkeleton from '@/components/loading-skeleton/data-table/data-table-skeleton'
2
+ import PageHeader from '@/components/typography/page-header'
3
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
4
+ import { Tag } from 'lucide-react'
5
+ import { Suspense } from 'react'
6
+ import TagTable from './tag-table'
7
+ import { getAllTagsAction } from '@/actions/tags/tag-actions'
8
+ import EmptyState from '@/components/data-state/empty-state'
9
+ import { Tag as TagModel } from '@prisma/client'
10
+ import { Metadata } from 'next'
11
+
12
+ export const metadata: Metadata = {
13
+ title: 'Appraise | Tags',
14
+ description: 'Manage tags for categorizing test cases and test runs',
15
+ }
16
+
17
+ const Tags = async () => {
18
+ const { data: tags, error: tagsError } = await getAllTagsAction()
19
+
20
+ if (tagsError) {
21
+ return <div>Error: {tagsError}</div>
22
+ }
23
+
24
+ const tagsData = tags as TagModel[]
25
+
26
+ if (!tagsData || tagsData.length === 0) {
27
+ return (
28
+ <div className="flex min-h-[calc(100vh-20rem)] items-center justify-center">
29
+ <EmptyState
30
+ icon={<Tag className="h-8 w-8" />}
31
+ title="No tags found"
32
+ description="Get started by creating a tag to categorize your test cases and test runs"
33
+ createRoute="/tags/create"
34
+ createText="Create Tag"
35
+ />
36
+ </div>
37
+ )
38
+ }
39
+
40
+ return (
41
+ <>
42
+ <div className="mb-8">
43
+ <PageHeader>
44
+ <span className="flex items-center">
45
+ <Tag className="mr-2 h-8 w-8" />
46
+ Tags
47
+ </span>
48
+ </PageHeader>
49
+ <HeaderSubtitle>Categorize test cases and test runs for better organization and filtering</HeaderSubtitle>
50
+ </div>
51
+ <Suspense fallback={<DataTableSkeleton />}>
52
+ <TagTable />
53
+ </Suspense>
54
+ </>
55
+ )
56
+ }
57
+
58
+ export default Tags
@@ -0,0 +1,13 @@
1
+ import { tagSchema, type Tag } from '@/constants/form-opts/tag-form-opts'
2
+ import { type ActionResponse } from '@/types/form/actionHandler'
3
+
4
+ export type TagFormSubmitAction = (_prev: unknown, value: Tag, id?: string) => Promise<ActionResponse>
5
+
6
+ export const tagFieldValidators = {
7
+ name: tagSchema.shape.name,
8
+ tagExpression: tagSchema.shape.tagExpression,
9
+ }
10
+
11
+ export function getActionErrorMessage(response: ActionResponse) {
12
+ return response.error || response.message || 'Unable to save tag.'
13
+ }
@@ -0,0 +1,83 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { render, screen, waitFor } from '@testing-library/react'
4
+ import userEvent from '@testing-library/user-event'
5
+ import { describe, expect, it, vi } from 'vitest'
6
+
7
+ import TagForm from './tag-form'
8
+
9
+ const { push, toast } = vi.hoisted(() => ({
10
+ push: vi.fn(),
11
+ toast: vi.fn(),
12
+ }))
13
+
14
+ vi.mock('next/navigation', () => ({
15
+ useRouter: () => ({
16
+ push,
17
+ }),
18
+ }))
19
+
20
+ vi.mock('@/hooks/use-toast', () => ({
21
+ toast,
22
+ }))
23
+
24
+ describe('TagForm', () => {
25
+ it('submits valid values, shows a toast, and navigates back to the tags list', async () => {
26
+ const user = userEvent.setup()
27
+ const onSubmitAction = vi.fn().mockResolvedValue({
28
+ status: 200,
29
+ })
30
+
31
+ render(
32
+ <TagForm
33
+ successTitle="Tag created"
34
+ successMessage="Tag created successfully"
35
+ onSubmitAction={onSubmitAction}
36
+ />,
37
+ )
38
+
39
+ await user.type(screen.getByLabelText('Name'), 'Smoke')
40
+ await user.type(screen.getByLabelText('Tag Expression'), '@smoke')
41
+ await user.click(screen.getByRole('button', { name: 'Save' }))
42
+
43
+ await waitFor(() => {
44
+ expect(onSubmitAction).toHaveBeenCalledWith(
45
+ undefined,
46
+ {
47
+ name: 'Smoke',
48
+ tagExpression: '@smoke',
49
+ },
50
+ undefined,
51
+ )
52
+ })
53
+
54
+ expect(toast).toHaveBeenCalledWith({
55
+ title: 'Tag created',
56
+ description: 'Tag created successfully',
57
+ })
58
+ expect(push).toHaveBeenCalledWith('/tags')
59
+ })
60
+
61
+ it('shows validation feedback for an invalid tag expression and does not submit', async () => {
62
+ const user = userEvent.setup()
63
+ const onSubmitAction = vi.fn()
64
+
65
+ render(
66
+ <TagForm
67
+ successTitle="Tag created"
68
+ successMessage="Tag created successfully"
69
+ onSubmitAction={onSubmitAction}
70
+ />,
71
+ )
72
+
73
+ await user.type(screen.getByLabelText('Name'), 'Smoke')
74
+ await user.type(screen.getByLabelText('Tag Expression'), 'smoke')
75
+
76
+ expect(
77
+ screen.getByText('Tag expression must be a single tag starting with @ and contain no spaces (e.g., "@smoke")'),
78
+ ).toBeInTheDocument()
79
+
80
+ expect(screen.getByRole('button', { name: 'Save' })).toBeDisabled()
81
+ expect(onSubmitAction).not.toHaveBeenCalled()
82
+ })
83
+ })