create-appraise 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/README.md +52 -0
  2. package/package.json +63 -0
  3. package/templates/default/.env.example +2 -0
  4. package/templates/default/README.md +51 -0
  5. package/templates/default/appraise.config.json +4 -0
  6. package/templates/default/components.json +24 -0
  7. package/templates/default/eslint.config.mjs +15 -0
  8. package/templates/default/next-env.d.ts +6 -0
  9. package/templates/default/next.config.ts +7 -0
  10. package/templates/default/package-lock.json +14321 -0
  11. package/templates/default/package.json +124 -0
  12. package/templates/default/postcss.config.mjs +8 -0
  13. package/templates/default/prisma/migrations/20251026202316_migrate_back_to_sqlite/migration.sql +257 -0
  14. package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -0
  15. package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -0
  16. package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -0
  17. package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -0
  18. package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -0
  19. package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -0
  20. package/templates/default/prisma/migrations/20251130190737_add_trace_path_to_test_run_test_case/migration.sql +2 -0
  21. package/templates/default/prisma/migrations/20251213074835_add_log_path_to_test_run/migration.sql +2 -0
  22. package/templates/default/prisma/migrations/20251213183952_add_name_property_for_the_test_run_entities/migration.sql +30 -0
  23. package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -0
  24. package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -0
  25. package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -0
  26. package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -0
  27. package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -0
  28. package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -0
  29. package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -0
  30. package/templates/default/prisma/migrations/migration_lock.toml +3 -0
  31. package/templates/default/prisma/schema.prisma +554 -0
  32. package/templates/default/public/favicon.ico +0 -0
  33. package/templates/default/public/file.svg +1 -0
  34. package/templates/default/public/globe.svg +1 -0
  35. package/templates/default/public/next.svg +1 -0
  36. package/templates/default/public/vercel.svg +1 -0
  37. package/templates/default/public/window.svg +1 -0
  38. package/templates/default/scripts/regenerate-features.ts +94 -0
  39. package/templates/default/scripts/setup-env.ts +19 -0
  40. package/templates/default/scripts/sync-all.ts +341 -0
  41. package/templates/default/scripts/sync-environments.ts +323 -0
  42. package/templates/default/scripts/sync-locator-groups.ts +413 -0
  43. package/templates/default/scripts/sync-locators.ts +402 -0
  44. package/templates/default/scripts/sync-modules.ts +349 -0
  45. package/templates/default/scripts/sync-tags.ts +292 -0
  46. package/templates/default/scripts/sync-template-step-groups.ts +399 -0
  47. package/templates/default/scripts/sync-template-steps.ts +806 -0
  48. package/templates/default/scripts/sync-test-cases.ts +905 -0
  49. package/templates/default/scripts/sync-test-suites.ts +411 -0
  50. package/templates/default/src/actions/conflict/conflict.action.ts +33 -0
  51. package/templates/default/src/actions/dashboard/dashboard-actions.ts +241 -0
  52. package/templates/default/src/actions/environments/environment-actions.ts +205 -0
  53. package/templates/default/src/actions/locator/locator-actions.ts +547 -0
  54. package/templates/default/src/actions/locator-groups/locator-group-actions.ts +344 -0
  55. package/templates/default/src/actions/modules/module-actions.ts +133 -0
  56. package/templates/default/src/actions/reports/report-actions.ts +614 -0
  57. package/templates/default/src/actions/review/review-actions.ts +147 -0
  58. package/templates/default/src/actions/tags/tag-actions.ts +104 -0
  59. package/templates/default/src/actions/template-step/template-step-actions.ts +332 -0
  60. package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +278 -0
  61. package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -0
  62. package/templates/default/src/actions/test-case/test-case-actions.ts +419 -0
  63. package/templates/default/src/actions/test-run/test-run-actions.ts +1185 -0
  64. package/templates/default/src/actions/test-suite/test-suite-actions.ts +253 -0
  65. package/templates/default/src/actions/user/user-actions.ts +13 -0
  66. package/templates/default/src/app/(base)/environments/create/page.tsx +28 -0
  67. package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -0
  68. package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -0
  69. package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -0
  70. package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -0
  71. package/templates/default/src/app/(base)/environments/page.tsx +59 -0
  72. package/templates/default/src/app/(base)/layout.tsx +10 -0
  73. package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -0
  74. package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -0
  75. package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -0
  76. package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -0
  77. package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -0
  78. package/templates/default/src/app/(base)/locator-groups/page.tsx +61 -0
  79. package/templates/default/src/app/(base)/locators/create/page.tsx +38 -0
  80. package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -0
  81. package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +90 -0
  82. package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -0
  83. package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +45 -0
  84. package/templates/default/src/app/(base)/locators/page.tsx +65 -0
  85. package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -0
  86. package/templates/default/src/app/(base)/modules/create/page.tsx +34 -0
  87. package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -0
  88. package/templates/default/src/app/(base)/modules/module-form.tsx +126 -0
  89. package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -0
  90. package/templates/default/src/app/(base)/modules/module-table.tsx +24 -0
  91. package/templates/default/src/app/(base)/modules/page.tsx +59 -0
  92. package/templates/default/src/app/(base)/reports/[id]/page.tsx +517 -0
  93. package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -0
  94. package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -0
  95. package/templates/default/src/app/(base)/reports/overview-chart.tsx +46 -0
  96. package/templates/default/src/app/(base)/reports/page.tsx +98 -0
  97. package/templates/default/src/app/(base)/reports/report-metric-card.tsx +16 -0
  98. package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -0
  99. package/templates/default/src/app/(base)/reports/report-table.tsx +72 -0
  100. package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +131 -0
  101. package/templates/default/src/app/(base)/reports/report-view-table.tsx +82 -0
  102. package/templates/default/src/app/(base)/reports/test-cases/page.tsx +42 -0
  103. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -0
  104. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -0
  105. package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -0
  106. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -0
  107. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -0
  108. package/templates/default/src/app/(base)/reports/view-logs-button.tsx +60 -0
  109. package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -0
  110. package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -0
  111. package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -0
  112. package/templates/default/src/app/(base)/reviews/page.tsx +26 -0
  113. package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -0
  114. package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -0
  115. package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -0
  116. package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -0
  117. package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -0
  118. package/templates/default/src/app/(base)/tags/create/page.tsx +39 -0
  119. package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -0
  120. package/templates/default/src/app/(base)/tags/page.tsx +58 -0
  121. package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -0
  122. package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -0
  123. package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -0
  124. package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -0
  125. package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -0
  126. package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -0
  127. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -0
  128. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -0
  129. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -0
  130. package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -0
  131. package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -0
  132. package/templates/default/src/app/(base)/template-steps/page.tsx +59 -0
  133. package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -0
  134. package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -0
  135. package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -0
  136. package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -0
  137. package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -0
  138. package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -0
  139. package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -0
  140. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -0
  141. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -0
  142. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -0
  143. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -0
  144. package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -0
  145. package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -0
  146. package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -0
  147. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -0
  148. package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -0
  149. package/templates/default/src/app/(base)/test-cases/page.tsx +60 -0
  150. package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -0
  151. package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -0
  152. package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +90 -0
  153. package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +35 -0
  154. package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +56 -0
  155. package/templates/default/src/app/(base)/test-runs/create/page.tsx +47 -0
  156. package/templates/default/src/app/(base)/test-runs/page.tsx +60 -0
  157. package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +512 -0
  158. package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -0
  159. package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -0
  160. package/templates/default/src/app/(base)/test-suites/create/page.tsx +45 -0
  161. package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +55 -0
  162. package/templates/default/src/app/(base)/test-suites/page.tsx +82 -0
  163. package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +269 -0
  164. package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +97 -0
  165. package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -0
  166. package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -0
  167. package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +13 -0
  168. package/templates/default/src/app/(dashboard-components)/data-card.tsx +27 -0
  169. package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +57 -0
  170. package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -0
  171. package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +45 -0
  172. package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +133 -0
  173. package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +420 -0
  174. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -0
  175. package/templates/default/src/app/favicon.ico +0 -0
  176. package/templates/default/src/app/globals.css +147 -0
  177. package/templates/default/src/app/layout.tsx +171 -0
  178. package/templates/default/src/app/page.tsx +64 -0
  179. package/templates/default/src/assets/icons/empty-tube.tsx +23 -0
  180. package/templates/default/src/assets/icons/tube-plus.tsx +29 -0
  181. package/templates/default/src/components/base-node.tsx +21 -0
  182. package/templates/default/src/components/chart/pie-chart.tsx +73 -0
  183. package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -0
  184. package/templates/default/src/components/data-state/empty-state.tsx +40 -0
  185. package/templates/default/src/components/data-visualization/info-card.tsx +70 -0
  186. package/templates/default/src/components/data-visualization/info-grid.tsx +22 -0
  187. package/templates/default/src/components/devtools/providers.tsx +13 -0
  188. package/templates/default/src/components/diagram/button-edge.tsx +54 -0
  189. package/templates/default/src/components/diagram/dynamic-parameters.tsx +438 -0
  190. package/templates/default/src/components/diagram/edit-header-option.tsx +36 -0
  191. package/templates/default/src/components/diagram/flow-diagram.tsx +470 -0
  192. package/templates/default/src/components/diagram/node-form.tsx +262 -0
  193. package/templates/default/src/components/diagram/options-header-node.tsx +57 -0
  194. package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -0
  195. package/templates/default/src/components/form/error-message.tsx +7 -0
  196. package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -0
  197. package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -0
  198. package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -0
  199. package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -0
  200. package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -0
  201. package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -0
  202. package/templates/default/src/components/logo.tsx +15 -0
  203. package/templates/default/src/components/navigation/command-badge.tsx +34 -0
  204. package/templates/default/src/components/navigation/command-chain-input.tsx +51 -0
  205. package/templates/default/src/components/navigation/entity-search-command.tsx +116 -0
  206. package/templates/default/src/components/navigation/nav-card.tsx +31 -0
  207. package/templates/default/src/components/navigation/nav-command.tsx +508 -0
  208. package/templates/default/src/components/navigation/nav-link.tsx +60 -0
  209. package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -0
  210. package/templates/default/src/components/node-header.tsx +159 -0
  211. package/templates/default/src/components/reports/test-case-logs-modal.tsx +253 -0
  212. package/templates/default/src/components/table/table-actions.tsx +172 -0
  213. package/templates/default/src/components/test-run/download-logs-button.tsx +99 -0
  214. package/templates/default/src/components/test-run/log-viewer.tsx +445 -0
  215. package/templates/default/src/components/test-run/test-run-details.tsx +611 -0
  216. package/templates/default/src/components/test-run/test-run-header.tsx +149 -0
  217. package/templates/default/src/components/test-run/view-report-button.tsx +102 -0
  218. package/templates/default/src/components/theme/mode-toggle.tsx +54 -0
  219. package/templates/default/src/components/theme/theme-provider.tsx +8 -0
  220. package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -0
  221. package/templates/default/src/components/typography/page-header.tsx +7 -0
  222. package/templates/default/src/components/ui/alert-dialog.tsx +106 -0
  223. package/templates/default/src/components/ui/alert.tsx +43 -0
  224. package/templates/default/src/components/ui/avatar.tsx +40 -0
  225. package/templates/default/src/components/ui/badge.tsx +29 -0
  226. package/templates/default/src/components/ui/button.tsx +47 -0
  227. package/templates/default/src/components/ui/calendar.tsx +158 -0
  228. package/templates/default/src/components/ui/card.tsx +43 -0
  229. package/templates/default/src/components/ui/chart.tsx +369 -0
  230. package/templates/default/src/components/ui/checkbox.tsx +28 -0
  231. package/templates/default/src/components/ui/command.tsx +135 -0
  232. package/templates/default/src/components/ui/data-table-column-header.tsx +61 -0
  233. package/templates/default/src/components/ui/data-table-pagination.tsx +87 -0
  234. package/templates/default/src/components/ui/data-table-view-options.tsx +50 -0
  235. package/templates/default/src/components/ui/data-table.tsx +267 -0
  236. package/templates/default/src/components/ui/dialog.tsx +97 -0
  237. package/templates/default/src/components/ui/dropdown-menu.tsx +182 -0
  238. package/templates/default/src/components/ui/empty.tsx +104 -0
  239. package/templates/default/src/components/ui/input.tsx +22 -0
  240. package/templates/default/src/components/ui/kbd.tsx +28 -0
  241. package/templates/default/src/components/ui/label.tsx +19 -0
  242. package/templates/default/src/components/ui/loading.tsx +12 -0
  243. package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -0
  244. package/templates/default/src/components/ui/multi-select.tsx +142 -0
  245. package/templates/default/src/components/ui/navigation-menu.tsx +120 -0
  246. package/templates/default/src/components/ui/popover.tsx +33 -0
  247. package/templates/default/src/components/ui/progress.tsx +25 -0
  248. package/templates/default/src/components/ui/radio-group.tsx +44 -0
  249. package/templates/default/src/components/ui/scroll-area.tsx +40 -0
  250. package/templates/default/src/components/ui/select.tsx +144 -0
  251. package/templates/default/src/components/ui/separator.tsx +22 -0
  252. package/templates/default/src/components/ui/skeleton.tsx +7 -0
  253. package/templates/default/src/components/ui/table.tsx +76 -0
  254. package/templates/default/src/components/ui/tabs.tsx +55 -0
  255. package/templates/default/src/components/ui/textarea.tsx +21 -0
  256. package/templates/default/src/components/ui/toast.tsx +113 -0
  257. package/templates/default/src/components/ui/toaster.tsx +26 -0
  258. package/templates/default/src/components/ui/tooltip.tsx +32 -0
  259. package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -0
  260. package/templates/default/src/config/db-config.ts +10 -0
  261. package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -0
  262. package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -0
  263. package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -0
  264. package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -0
  265. package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -0
  266. package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -0
  267. package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -0
  268. package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -0
  269. package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -0
  270. package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -0
  271. package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -0
  272. package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -0
  273. package/templates/default/src/constants/form-opts/test-run-form-opts.ts +31 -0
  274. package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -0
  275. package/templates/default/src/hooks/use-toast.ts +187 -0
  276. package/templates/default/src/lib/bidirectional-sync.ts +432 -0
  277. package/templates/default/src/lib/database-sync.ts +531 -0
  278. package/templates/default/src/lib/environment-file-utils.ts +221 -0
  279. package/templates/default/src/lib/feature-file-generator.ts +411 -0
  280. package/templates/default/src/lib/gherkin-parser.ts +259 -0
  281. package/templates/default/src/lib/locator-group-file-utils.ts +370 -0
  282. package/templates/default/src/lib/metrics/metric-calculator.ts +613 -0
  283. package/templates/default/src/lib/module-hierarchy-builder.ts +205 -0
  284. package/templates/default/src/lib/path-helpers/module-path.ts +71 -0
  285. package/templates/default/src/lib/test-case-utils.ts +6 -0
  286. package/templates/default/src/lib/test-run/log-formatter.ts +83 -0
  287. package/templates/default/src/lib/test-run/process-manager.ts +191 -0
  288. package/templates/default/src/lib/test-run/report-parser.ts +316 -0
  289. package/templates/default/src/lib/test-run/test-run-executor.ts +144 -0
  290. package/templates/default/src/lib/test-run/winston-logger.ts +95 -0
  291. package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -0
  292. package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -0
  293. package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -0
  294. package/templates/default/src/lib/utils/node-param-validation.ts +81 -0
  295. package/templates/default/src/lib/utils/template-step-file-generator.ts +167 -0
  296. package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +723 -0
  297. package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -0
  298. package/templates/default/src/lib/utils.ts +31 -0
  299. package/templates/default/src/tests/config/environments/environments.json +14 -0
  300. package/templates/default/src/tests/config/executor/world.ts +41 -0
  301. package/templates/default/src/tests/executor.ts +80 -0
  302. package/templates/default/src/tests/hooks/hooks.ts +99 -0
  303. package/templates/default/src/tests/mapping/locator-map.json +1 -0
  304. package/templates/default/src/tests/steps/actions/click.step.ts +62 -0
  305. package/templates/default/src/tests/steps/actions/hover.step.ts +31 -0
  306. package/templates/default/src/tests/steps/actions/input.step.ts +149 -0
  307. package/templates/default/src/tests/steps/actions/navigation.step.ts +72 -0
  308. package/templates/default/src/tests/steps/actions/random_data.step.ts +146 -0
  309. package/templates/default/src/tests/steps/actions/store.step.ts +90 -0
  310. package/templates/default/src/tests/steps/actions/wait.step.ts +107 -0
  311. package/templates/default/src/tests/steps/validations/active_state_assertion.step.ts +34 -0
  312. package/templates/default/src/tests/steps/validations/navigation_assertion.step.ts +23 -0
  313. package/templates/default/src/tests/steps/validations/text_assertion.step.ts +111 -0
  314. package/templates/default/src/tests/steps/validations/visibility_assertion.step.ts +30 -0
  315. package/templates/default/src/tests/support/parameter-types.ts +12 -0
  316. package/templates/default/src/tests/utils/cache.util.ts +260 -0
  317. package/templates/default/src/tests/utils/cli.util.ts +177 -0
  318. package/templates/default/src/tests/utils/environment.util.ts +65 -0
  319. package/templates/default/src/tests/utils/locator.util.ts +248 -0
  320. package/templates/default/src/tests/utils/random-data.util.ts +45 -0
  321. package/templates/default/src/tests/utils/spawner.util.ts +617 -0
  322. package/templates/default/src/types/diagram/diagram.ts +34 -0
  323. package/templates/default/src/types/diagram/template-step.ts +11 -0
  324. package/templates/default/src/types/executor/browser.type.ts +1 -0
  325. package/templates/default/src/types/form/actionHandler.ts +6 -0
  326. package/templates/default/src/types/locator/locator.type.ts +11 -0
  327. package/templates/default/src/types/step/step.type.ts +1 -0
  328. package/templates/default/src/types/table/data-table.ts +6 -0
  329. package/templates/default/tailwind.config.ts +62 -0
  330. package/templates/default/tsconfig.json +28 -0
@@ -0,0 +1,89 @@
1
+ import {
2
+ Locator,
3
+ LocatorGroup,
4
+ TemplateStep,
5
+ TemplateStepParameter,
6
+ TemplateTestCase,
7
+ TemplateTestCaseStep,
8
+ TemplateTestCaseStepParameter,
9
+ } from '@prisma/client'
10
+ import React from 'react'
11
+ import TemplateTestCaseForm from '../../template-test-case-form'
12
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
13
+ import PageHeader from '@/components/typography/page-header'
14
+ import {
15
+ getAllTemplateStepParamsAction,
16
+ getAllTemplateStepsAction,
17
+ } from '@/actions/template-step/template-step-actions'
18
+ import { getAllLocatorGroupsAction } from '@/actions/locator-groups/locator-group-actions'
19
+ import { TemplateTestCaseNodeOrderMap } from '@/types/diagram/diagram'
20
+ import {
21
+ getTemplateTestCaseByIdAction,
22
+ updateTemplateTestCaseAction,
23
+ } from '@/actions/template-test-case/template-test-case-actions'
24
+ import { getAllLocatorsAction } from '@/actions/locator/locator-actions'
25
+ import { Metadata } from 'next'
26
+
27
+ export const metadata: Metadata = {
28
+ title: 'Appraise | Modify Template Test Case',
29
+ description: 'Modify a template test case',
30
+ }
31
+
32
+ const ModifyTemplateTestCase = async ({ params }: { params: Promise<{ id: string }> }) => {
33
+ const { id } = await params
34
+ const { data, error } = await getTemplateTestCaseByIdAction(id)
35
+
36
+ if (error) {
37
+ return <div>Error: {error}</div>
38
+ }
39
+ const templateTestCase = data as TemplateTestCase & {
40
+ steps: (TemplateTestCaseStep & {
41
+ parameters: TemplateTestCaseStepParameter[]
42
+ })[]
43
+ }
44
+ const { data: templateStepParams, error: templateStepParamsError } = await getAllTemplateStepParamsAction()
45
+ const { data: templateSteps, error: templateStepsError } = await getAllTemplateStepsAction()
46
+ const { data: locators, error: locatorsError } = await getAllLocatorsAction()
47
+ const { data: locatorGroups, error: locatorGroupsError } = await getAllLocatorGroupsAction()
48
+ if (templateStepParamsError || templateStepsError || locatorsError || locatorGroupsError) {
49
+ return <div>Error: {templateStepParamsError || templateStepsError || locatorsError || locatorGroupsError}</div>
50
+ }
51
+ return (
52
+ <>
53
+ <div className="mb-8">
54
+ <PageHeader>Modify Template Test Case</PageHeader>
55
+ <HeaderSubtitle>Modify a template test case</HeaderSubtitle>
56
+ </div>
57
+ <TemplateTestCaseForm
58
+ onSubmitAction={updateTemplateTestCaseAction}
59
+ id={id}
60
+ defaultTitle={templateTestCase.name}
61
+ defaultDescription={templateTestCase.description || ''}
62
+ templateStepParams={templateStepParams as TemplateStepParameter[]}
63
+ templateSteps={templateSteps as TemplateStep[]}
64
+ locators={locators as Locator[]}
65
+ locatorGroups={locatorGroups as LocatorGroup[]}
66
+ defaultNodesOrder={templateTestCase.steps.reduce((acc, step) => {
67
+ acc[step.id] = {
68
+ order: step.order,
69
+ label: step.label,
70
+ gherkinStep: step.gherkinStep,
71
+ icon: step.icon,
72
+ parameters: ((step.parameters || []) as TemplateTestCaseStepParameter[]).map(
73
+ (param: TemplateTestCaseStepParameter) => ({
74
+ name: param.name,
75
+ defaultValue: param.defaultValue,
76
+ type: param.type,
77
+ order: param.order,
78
+ }),
79
+ ),
80
+ templateStepId: step.templateStepId,
81
+ }
82
+ return acc
83
+ }, {} as TemplateTestCaseNodeOrderMap)}
84
+ />
85
+ </>
86
+ )
87
+ }
88
+
89
+ export default ModifyTemplateTestCase
@@ -0,0 +1,58 @@
1
+ import PageHeader from '@/components/typography/page-header'
2
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
3
+ import { Blocks } from 'lucide-react'
4
+ import React, { Suspense } from 'react'
5
+ import TemplateTestCaseTable from './template-test-case-table'
6
+ import DataTableSkeleton from '@/components/loading-skeleton/data-table/data-table-skeleton'
7
+ import { getAllTemplateTestCasesAction } from '@/actions/template-test-case/template-test-case-actions'
8
+ import EmptyState from '@/components/data-state/empty-state'
9
+ import { TemplateTestCase, TemplateTestCaseStep } from '@prisma/client'
10
+ import { Metadata } from 'next'
11
+
12
+ export const metadata: Metadata = {
13
+ title: 'Appraise | Template Test Cases',
14
+ description: 'Manage template test cases for quickly creating test cases',
15
+ }
16
+
17
+ const TemplateTestCasesPage = async () => {
18
+ const { data: templateTestCases, error: templateTestCasesError } = await getAllTemplateTestCasesAction()
19
+
20
+ if (templateTestCasesError) {
21
+ return <div>Error: {templateTestCasesError}</div>
22
+ }
23
+
24
+ const templateTestCasesData = templateTestCases as (TemplateTestCase & { steps: TemplateTestCaseStep[] })[]
25
+
26
+ if (!templateTestCasesData || templateTestCasesData.length === 0) {
27
+ return (
28
+ <div className="flex min-h-[calc(100vh-20rem)] items-center justify-center">
29
+ <EmptyState
30
+ icon={<Blocks className="h-8 w-8" />}
31
+ title="No template test cases found"
32
+ description="Get started by creating a template test case to quickly create test cases"
33
+ createRoute="/template-test-cases/create"
34
+ createText="Create Template Test Case"
35
+ />
36
+ </div>
37
+ )
38
+ }
39
+
40
+ return (
41
+ <>
42
+ <div className="mb-8">
43
+ <PageHeader>
44
+ <span className="flex items-center">
45
+ <Blocks className="mr-2 h-8 w-8" />
46
+ Template Test Cases
47
+ </span>
48
+ </PageHeader>
49
+ <HeaderSubtitle>A collection of templates to quickly create test cases</HeaderSubtitle>
50
+ </div>
51
+ <Suspense fallback={<DataTableSkeleton />}>
52
+ <TemplateTestCaseTable />
53
+ </Suspense>
54
+ </>
55
+ )
56
+ }
57
+
58
+ export default TemplateTestCasesPage
@@ -0,0 +1,84 @@
1
+ import FlowDiagram from '@/components/diagram/flow-diagram'
2
+ import { TemplateTestCaseNodeOrderMap, NodeOrderMap } from '@/types/diagram/diagram'
3
+ import { Locator, TemplateStep, TemplateStepParameter, StepParameterType, LocatorGroup } from '@prisma/client'
4
+ import React, { useCallback, useState, useEffect, useRef } from 'react'
5
+
6
+ function useDebouncedCallback<T extends unknown[]>(callback: (...args: T) => void, delay: number) {
7
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null)
8
+
9
+ return (...args: T) => {
10
+ if (timeoutRef.current) clearTimeout(timeoutRef.current)
11
+ timeoutRef.current = setTimeout(() => {
12
+ callback(...args)
13
+ }, delay)
14
+ }
15
+ }
16
+
17
+ const TemplateTestCaseFlow = ({
18
+ initialNodesOrder,
19
+ templateStepParams,
20
+ templateSteps,
21
+ locators,
22
+ locatorGroups,
23
+ onNodeOrderChange,
24
+ defaultValueInput = false,
25
+ }: {
26
+ initialNodesOrder: TemplateTestCaseNodeOrderMap
27
+ templateStepParams: TemplateStepParameter[]
28
+ templateSteps: TemplateStep[]
29
+ locators: Locator[]
30
+ locatorGroups: LocatorGroup[]
31
+ onNodeOrderChange: (nodesOrder: TemplateTestCaseNodeOrderMap) => void
32
+ defaultValueInput?: boolean
33
+ }) => {
34
+ const [nodesOrder, setNodesOrder] = useState<TemplateTestCaseNodeOrderMap>(initialNodesOrder)
35
+
36
+ const handleNodeOrderChange = useCallback(
37
+ (nodeOrder: NodeOrderMap | TemplateTestCaseNodeOrderMap) => {
38
+ // Convert NodeOrderMap to TemplateTestCaseNodeOrderMap if needed
39
+ const convertedNodeOrder: TemplateTestCaseNodeOrderMap = {}
40
+ Object.entries(nodeOrder).forEach(([key, nodeData]) => {
41
+ convertedNodeOrder[key] = {
42
+ ...nodeData,
43
+ parameters: nodeData.parameters.map(
44
+ (param: {
45
+ name: string
46
+ value?: string
47
+ defaultValue?: string
48
+ type: StepParameterType
49
+ order: number
50
+ }) => ({
51
+ ...param,
52
+ defaultValue: 'value' in param ? param.value : param.defaultValue,
53
+ }),
54
+ ),
55
+ }
56
+ })
57
+ setNodesOrder(convertedNodeOrder)
58
+ },
59
+ [setNodesOrder],
60
+ )
61
+
62
+ const debouncedSaveNodesOrder = useDebouncedCallback(onNodeOrderChange, 200)
63
+
64
+ useEffect(() => {
65
+ debouncedSaveNodesOrder(nodesOrder)
66
+ // eslint-disable-next-line react-hooks/exhaustive-deps
67
+ }, [nodesOrder])
68
+
69
+ return (
70
+ <>
71
+ <FlowDiagram
72
+ nodeOrder={nodesOrder}
73
+ templateStepParams={templateStepParams}
74
+ onNodeOrderChange={handleNodeOrderChange}
75
+ templateSteps={templateSteps}
76
+ locators={locators}
77
+ locatorGroups={locatorGroups}
78
+ defaultValueInput={defaultValueInput}
79
+ />
80
+ </>
81
+ )
82
+ }
83
+
84
+ export default TemplateTestCaseFlow
@@ -0,0 +1,262 @@
1
+ 'use client'
2
+ import React, { useCallback, useState } from 'react'
3
+ import TemplateTestCaseFlow from './template-test-case-flow'
4
+ import { TemplateTestCaseNodeOrderMap } from '@/types/diagram/diagram'
5
+ import {
6
+ Locator,
7
+ LocatorGroup,
8
+ StepParameterType,
9
+ TemplateStep,
10
+ TemplateStepIcon,
11
+ TemplateStepParameter,
12
+ } from '@prisma/client'
13
+ import { Input } from '@/components/ui/input'
14
+ import { Label } from '@/components/ui/label'
15
+ import { Textarea } from '@/components/ui/textarea'
16
+ import { Button } from '@/components/ui/button'
17
+ import ErrorMessage from '@/components/form/error-message'
18
+ import { z } from 'zod'
19
+ import { toast } from '@/hooks/use-toast'
20
+ import { useRouter } from 'next/navigation'
21
+ import { IconToKeyTransformer } from '@/lib/transformers/key-to-icon-transformer'
22
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
23
+ import CodeMirror, { EditorView } from '@uiw/react-codemirror'
24
+ import { langs } from '@uiw/codemirror-extensions-langs'
25
+ import { githubDark } from '@uiw/codemirror-theme-github'
26
+ import { ActionResponse } from '@/types/form/actionHandler'
27
+ import { templateTestCaseSchema } from '@/constants/form-opts/template-test-case-form-opts'
28
+
29
+ const errorSchema = z.object({
30
+ title: z.string().min(3, { message: 'Title must be at least 3 characters' }),
31
+ description: z.string().optional(),
32
+ steps: z
33
+ .array(
34
+ z.object({
35
+ gherkinStep: z.string(),
36
+ label: z.string(),
37
+ icon: z.nativeEnum(TemplateStepIcon),
38
+ parameters: z.array(
39
+ z.object({
40
+ name: z.string(),
41
+ value: z.string(),
42
+ type: z.nativeEnum(StepParameterType),
43
+ order: z.number(),
44
+ }),
45
+ ),
46
+ order: z.number(),
47
+ templateStepId: z.string(),
48
+ }),
49
+ )
50
+ .min(1, { message: 'At least one step is required' }),
51
+ })
52
+
53
+ const TemplateTestCaseForm = ({
54
+ defaultNodesOrder,
55
+ templateStepParams,
56
+ templateSteps,
57
+ locators,
58
+ locatorGroups,
59
+ id,
60
+ defaultTitle,
61
+ defaultDescription,
62
+ defaultValueInput = false,
63
+ onSubmitAction,
64
+ }: {
65
+ defaultNodesOrder: TemplateTestCaseNodeOrderMap
66
+ templateStepParams: TemplateStepParameter[]
67
+ templateSteps: TemplateStep[]
68
+ locators: Locator[]
69
+ locatorGroups: LocatorGroup[]
70
+ onSubmitAction: (value: z.infer<typeof templateTestCaseSchema>, id?: string) => Promise<ActionResponse>
71
+ id?: string
72
+ defaultTitle?: string
73
+ defaultDescription?: string
74
+ defaultValueInput?: boolean
75
+ }) => {
76
+ const router = useRouter()
77
+ // states
78
+ const [nodesOrder, setNodesOrder] = useState<TemplateTestCaseNodeOrderMap>(defaultNodesOrder)
79
+ const [title, setTitle] = useState<string>(defaultTitle || '')
80
+ const [description, setDescription] = useState<string>(defaultDescription || '')
81
+ const [errors, setErrors] = useState<{
82
+ title?: string[]
83
+ description?: string[]
84
+ steps?: string[]
85
+ }>({})
86
+
87
+ const generateGherkinSyntax = useCallback(() => {
88
+ if (!title) return ''
89
+
90
+ const scenarioHeader = `Scenario: [${title}] ${description || ''}`
91
+
92
+ // Filter out nodes with order -1 and sort the remaining nodes
93
+ const validSteps = Object.entries(nodesOrder)
94
+ .map(([, value]) => value)
95
+ .filter(step => step.order !== -1)
96
+ .sort((a, b) => a.order - b.order)
97
+
98
+ // Generate Gherkin steps with proper keywords
99
+ let hasThenInPrevious = false
100
+ let hasWhenInPrevious = false
101
+
102
+ const gherkinSteps = validSteps.map((step, index) => {
103
+ const gherkinStep = step.gherkinStep?.trim() || ''
104
+ const firstWord = gherkinStep.split(' ')[0].toLowerCase()
105
+ const hasGherkinKeyword = ['given', 'when', 'then', 'and', 'but'].includes(firstWord)
106
+ const stepWithoutKeyword = hasGherkinKeyword ? gherkinStep.split(' ').slice(1).join(' ') : gherkinStep
107
+
108
+ // First step always starts with Given
109
+ if (index === 0) {
110
+ return `Given ${stepWithoutKeyword}`
111
+ }
112
+
113
+ // Check if this step should be a Then statement
114
+ const isThenStatement =
115
+ firstWord === 'then' ||
116
+ stepWithoutKeyword.toLowerCase().startsWith('should') ||
117
+ stepWithoutKeyword.toLowerCase().startsWith('must') ||
118
+ stepWithoutKeyword.toLowerCase().startsWith('will')
119
+
120
+ // If we haven't seen a Then yet
121
+ if (!hasThenInPrevious) {
122
+ // If this is a Then statement
123
+ if (isThenStatement) {
124
+ hasThenInPrevious = true
125
+ return `Then ${stepWithoutKeyword}`
126
+ }
127
+
128
+ // If we haven't seen a When yet, use When
129
+ if (!hasWhenInPrevious) {
130
+ hasWhenInPrevious = true
131
+ return `When ${stepWithoutKeyword}`
132
+ }
133
+ // After When, use And
134
+ return `And ${stepWithoutKeyword}`
135
+ }
136
+
137
+ // After Then
138
+ if (isThenStatement) {
139
+ // If it's another Then statement, use And
140
+ return `And ${stepWithoutKeyword}`
141
+ }
142
+ // After Then, use When for new actions
143
+ hasThenInPrevious = false
144
+ hasWhenInPrevious = false
145
+ return `When ${stepWithoutKeyword}`
146
+ })
147
+
148
+ // Update the flags after processing all steps
149
+ hasThenInPrevious = gherkinSteps.some(step => step.toLowerCase().startsWith('then'))
150
+ hasWhenInPrevious = gherkinSteps.some(step => step.toLowerCase().startsWith('when'))
151
+
152
+ return [scenarioHeader, ...gherkinSteps].join('\n')
153
+ }, [title, description, nodesOrder])
154
+
155
+ // handlers
156
+ const onNodeOrderChange = useCallback((nodesOrder: TemplateTestCaseNodeOrderMap) => {
157
+ setNodesOrder(nodesOrder)
158
+ }, [])
159
+
160
+ const onTitleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
161
+ setTitle(e.target.value)
162
+ }, [])
163
+
164
+ const onDescriptionChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
165
+ setDescription(e.target.value)
166
+ }, [])
167
+
168
+ const handleSubmit = useCallback(async () => {
169
+ const result = errorSchema.safeParse({
170
+ title,
171
+ description,
172
+ steps: Object.entries(nodesOrder).map(([, value]) => ({
173
+ gherkinStep: value.gherkinStep || '',
174
+ label: value.label,
175
+ icon: IconToKeyTransformer(value.icon),
176
+ parameters: value.parameters,
177
+ order: value.order,
178
+ templateStepId: value.templateStepId,
179
+ })),
180
+ })
181
+
182
+ if (!result.success) {
183
+ setErrors(result.error.flatten().fieldErrors)
184
+ return
185
+ }
186
+ setErrors({})
187
+ const response = await onSubmitAction(result.data, id)
188
+ if (response.status === 200) {
189
+ toast({
190
+ title: 'Success',
191
+ description: 'Test case saved successfully',
192
+ variant: 'default',
193
+ })
194
+ router.push(`/template-test-cases`)
195
+ }
196
+ if (response.status === 500) {
197
+ toast({
198
+ title: 'Error',
199
+ description: response.error || 'An error occurred',
200
+ variant: 'destructive',
201
+ })
202
+ }
203
+ }, [description, nodesOrder, title, router, onSubmitAction, id])
204
+
205
+ return (
206
+ <div className="flex flex-col gap-4">
207
+ <div className="flex justify-between gap-8" id="meta">
208
+ <div className="w-1/2">
209
+ <div className="mb-4 flex flex-col gap-2">
210
+ <Label htmlFor="title">Title</Label>
211
+ <Input id="title" name="title" value={title} onChange={onTitleChange} />
212
+ <ErrorMessage message={errors.title?.[0] || ''} visible={!!errors.title} />
213
+ </div>
214
+ <div className="mb-4 flex flex-col gap-2">
215
+ <Label htmlFor="description">Description</Label>
216
+ <Textarea id="description" name="description" value={description} onChange={onDescriptionChange} />
217
+ <ErrorMessage message={errors.description?.[0] || ''} visible={!!errors.description} />
218
+ </div>
219
+ </div>
220
+ <div className="w-1/2">
221
+ <div className="mb-4 flex flex-col gap-2">
222
+ <Card>
223
+ <CardHeader>
224
+ <CardTitle>Test Scenario(Preview)</CardTitle>
225
+ </CardHeader>
226
+ <CardContent>
227
+ <CodeMirror
228
+ editable={false}
229
+ value={generateGherkinSyntax()}
230
+ onChange={() => {}}
231
+ height="200px"
232
+ extensions={[langs.gherkin(), EditorView.lineWrapping]}
233
+ theme={githubDark}
234
+ />
235
+ </CardContent>
236
+ </Card>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ <div className="mb-4 flex h-[500px] flex-col gap-2">
241
+ <Label htmlFor="test-case-flow">Test Case Flow</Label>
242
+ <TemplateTestCaseFlow
243
+ initialNodesOrder={nodesOrder}
244
+ templateStepParams={templateStepParams}
245
+ templateSteps={templateSteps}
246
+ onNodeOrderChange={onNodeOrderChange}
247
+ locators={locators}
248
+ locatorGroups={locatorGroups}
249
+ defaultValueInput={defaultValueInput}
250
+ />
251
+ </div>
252
+ <ErrorMessage message={errors.steps?.[0] || ''} visible={!!errors.steps} />
253
+ <div className="mb-4 flex flex-col gap-2">
254
+ <Button onClick={handleSubmit} className="w-fit px-6">
255
+ Save
256
+ </Button>
257
+ </div>
258
+ </div>
259
+ )
260
+ }
261
+
262
+ export default TemplateTestCaseForm
@@ -0,0 +1,76 @@
1
+ 'use client'
2
+
3
+ import { DataTableColumnHeader } from '@/components/ui/data-table-column-header'
4
+ import { TemplateTestCase, TemplateTestCaseStep } from '@prisma/client'
5
+ import { ColumnDef } from '@tanstack/react-table'
6
+
7
+ import { Checkbox } from '@/components/ui/checkbox'
8
+ import TableActions from '@/components/table/table-actions'
9
+ import { deleteTemplateTestCaseAction } from '@/actions/template-test-case/template-test-case-actions'
10
+ import { formatDateTime } from '@/lib/utils'
11
+
12
+ export const templateTestCaseTableCols: ColumnDef<TemplateTestCase & { steps: TemplateTestCaseStep[] }>[] = [
13
+ {
14
+ id: 'select',
15
+ header: ({ table }) => (
16
+ <Checkbox
17
+ checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate')}
18
+ onCheckedChange={value => table.toggleAllPageRowsSelected(!!value)}
19
+ aria-label="Select all"
20
+ className="mr-2"
21
+ />
22
+ ),
23
+ cell: ({ row }) => (
24
+ <Checkbox
25
+ checked={row.getIsSelected()}
26
+ onCheckedChange={value => row.toggleSelected(!!value)}
27
+ aria-label="Select row"
28
+ className="mr-2"
29
+ />
30
+ ),
31
+ enableSorting: false,
32
+ enableHiding: false,
33
+ },
34
+ {
35
+ accessorKey: 'name',
36
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Name" />,
37
+ },
38
+ {
39
+ accessorKey: 'description',
40
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Description" />,
41
+ },
42
+ {
43
+ accessorKey: 'steps',
44
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Steps" />,
45
+ cell: ({ row }) => {
46
+ const templateTestCase = row.original
47
+ return <div>{templateTestCase.steps.length}</div>
48
+ },
49
+ },
50
+ {
51
+ accessorKey: 'createdAt',
52
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Created At" />,
53
+ cell: ({ row }) => {
54
+ return formatDateTime(row.original.createdAt)
55
+ },
56
+ },
57
+ {
58
+ accessorKey: 'updatedAt',
59
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Updated At" />,
60
+ cell: ({ row }) => {
61
+ return formatDateTime(row.original.updatedAt)
62
+ },
63
+ },
64
+ {
65
+ id: 'actions',
66
+ cell: ({ row }) => {
67
+ const templateTestCase = row.original
68
+ return (
69
+ <TableActions
70
+ modifyLink={`/template-test-cases/modify/${templateTestCase.id}`}
71
+ deleteHandler={() => deleteTemplateTestCaseAction([templateTestCase.id])}
72
+ />
73
+ )
74
+ },
75
+ },
76
+ ]
@@ -0,0 +1,32 @@
1
+ import { DataTable } from '@/components/ui/data-table'
2
+ import React from 'react'
3
+ import { templateTestCaseTableCols } from './template-test-case-table-columns'
4
+ import {
5
+ getAllTemplateTestCasesAction,
6
+ deleteTemplateTestCaseAction,
7
+ } from '@/actions/template-test-case/template-test-case-actions'
8
+ import { TemplateTestCase, TemplateTestCaseStep } from '@prisma/client'
9
+
10
+ type TemplateTestCaseWithSteps = TemplateTestCase & {
11
+ steps: TemplateTestCaseStep[]
12
+ }
13
+
14
+ const TemplateTestCaseTable = async () => {
15
+ const { data: templateTestCases } = await getAllTemplateTestCasesAction()
16
+
17
+ return (
18
+ <>
19
+ <DataTable
20
+ columns={templateTestCaseTableCols}
21
+ data={templateTestCases as TemplateTestCaseWithSteps[]}
22
+ filterColumn="name"
23
+ filterPlaceholder="Filter by name..."
24
+ createLink="/template-test-cases/create"
25
+ modifyLink="/template-test-cases/modify"
26
+ deleteAction={deleteTemplateTestCaseAction}
27
+ />
28
+ </>
29
+ )
30
+ }
31
+
32
+ export default TemplateTestCaseTable
@@ -0,0 +1,76 @@
1
+ import PageHeader from '@/components/typography/page-header'
2
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
3
+ import React from 'react'
4
+ import TestCaseForm from '../test-case-form'
5
+ import {
6
+ getAllTemplateStepParamsAction,
7
+ getAllTemplateStepsAction,
8
+ } from '@/actions/template-step/template-step-actions'
9
+ import { Locator, LocatorGroup, TemplateStep, TemplateStepParameter, TestSuite, Tag } from '@prisma/client'
10
+ import { getAllLocatorsAction } from '@/actions/locator/locator-actions'
11
+ import { getAllTestSuitesAction } from '@/actions/test-suite/test-suite-actions'
12
+ import { createTestCaseAction } from '@/actions/test-case/test-case-actions'
13
+ import { getAllLocatorGroupsAction } from '@/actions/locator-groups/locator-group-actions'
14
+ import { getAllTagsAction } from '@/actions/tags/tag-actions'
15
+ import { Metadata } from 'next'
16
+
17
+ export const metadata: Metadata = {
18
+ title: 'Appraise | Create Test Case',
19
+ description: 'Create a new test from scratch to execute against your application',
20
+ }
21
+
22
+ const CreateTestCase = async () => {
23
+ const { data: templateStepParams, error: templateStepParamsError } = await getAllTemplateStepParamsAction()
24
+
25
+ const { data: templateSteps, error: templateStepsError } = await getAllTemplateStepsAction()
26
+
27
+ const { data: testSuites, error: testSuitesError } = await getAllTestSuitesAction()
28
+
29
+ const { data: locators, error: locatorsError } = await getAllLocatorsAction()
30
+
31
+ const { data: locatorGroups, error: locatorGroupsError } = await getAllLocatorGroupsAction()
32
+
33
+ const { data: tags, error: tagsError } = await getAllTagsAction()
34
+
35
+ if (
36
+ templateStepParamsError ||
37
+ templateStepsError ||
38
+ locatorsError ||
39
+ testSuitesError ||
40
+ locatorGroupsError ||
41
+ tagsError
42
+ ) {
43
+ return (
44
+ <div>
45
+ Error:{' '}
46
+ {templateStepParamsError ||
47
+ templateStepsError ||
48
+ locatorsError ||
49
+ testSuitesError ||
50
+ locatorGroupsError ||
51
+ tagsError}
52
+ </div>
53
+ )
54
+ }
55
+
56
+ return (
57
+ <div>
58
+ <div className="mb-8">
59
+ <PageHeader>Create New Test Case</PageHeader>
60
+ <HeaderSubtitle>Create a new test from scratch to execute against your application</HeaderSubtitle>
61
+ </div>
62
+ <TestCaseForm
63
+ defaultNodesOrder={{}}
64
+ templateStepParams={templateStepParams as TemplateStepParameter[]}
65
+ templateSteps={templateSteps as TemplateStep[]}
66
+ locators={locators as Locator[]}
67
+ locatorGroups={locatorGroups as LocatorGroup[]}
68
+ testSuites={testSuites as TestSuite[]}
69
+ tags={tags as Tag[]}
70
+ onSubmitAction={createTestCaseAction}
71
+ />
72
+ </div>
73
+ )
74
+ }
75
+
76
+ export default CreateTestCase