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,253 @@
1
+ // action.ts
2
+ 'use server'
3
+
4
+ import prisma from '@/config/db-config'
5
+ import { testSuiteSchema } from '@/constants/form-opts/test-suite-form-opts'
6
+ import { ActionResponse } from '@/types/form/actionHandler'
7
+ import { Prisma } from '@prisma/client'
8
+ import { revalidatePath } from 'next/cache'
9
+ import { z, ZodError } from 'zod'
10
+ import { generateFeatureFile, deleteFeatureFile } from '@/lib/feature-file-generator'
11
+
12
+ const generateSafeFileName = (testSuiteName: string): string => {
13
+ return testSuiteName
14
+ .toLowerCase()
15
+ .replace(/[^a-z0-9]+/g, '-')
16
+ .replace(/^-+|-+$/g, '')
17
+ .replace(/-+/g, '-')
18
+ }
19
+
20
+ /**
21
+ * Get all test suites
22
+ * @returns ActionResponse
23
+ */
24
+ export async function getAllTestSuitesAction(): Promise<ActionResponse> {
25
+ try {
26
+ const testSuites = await prisma.testSuite.findMany({
27
+ include: {
28
+ module: true,
29
+ testCases: true,
30
+ tags: true,
31
+ },
32
+ })
33
+ return {
34
+ status: 200,
35
+ data: testSuites,
36
+ }
37
+ } catch (e) {
38
+ return {
39
+ status: 500,
40
+ error: `Server error occurred: ${e}`,
41
+ }
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Create a new test suite
47
+ * @param _prev - Previous state
48
+ * @param value - Test suite data
49
+ * @returns ActionResponse
50
+ */
51
+ export async function createTestSuiteAction(
52
+ _prev: unknown,
53
+ value: z.infer<typeof testSuiteSchema>,
54
+ ): Promise<ActionResponse> {
55
+ try {
56
+ testSuiteSchema.parse(value)
57
+
58
+ // Create the test suite
59
+ const newTestSuite = await prisma.testSuite.create({
60
+ data: {
61
+ name: value.name,
62
+ description: value.description,
63
+ module: {
64
+ connect: {
65
+ id: value.moduleId,
66
+ },
67
+ },
68
+ testCases: {
69
+ connect: value.testCases?.map(id => ({ id })),
70
+ },
71
+ tags: {
72
+ connect: value.tagIds?.map(id => ({ id })) || [],
73
+ },
74
+ },
75
+ include: {
76
+ module: true,
77
+ },
78
+ })
79
+
80
+ const sanitizedTestSuiteName = generateSafeFileName(newTestSuite.name)
81
+ // Generate feature file for the new test suite
82
+ try {
83
+ await generateFeatureFile(newTestSuite.id, sanitizedTestSuiteName, newTestSuite.description || undefined)
84
+ } catch (featureFileError) {
85
+ console.error('Error generating feature file:', featureFileError)
86
+ // Don't fail the test suite creation if feature file generation fails
87
+ }
88
+
89
+ revalidatePath('/test-suites')
90
+ return {
91
+ status: 200,
92
+ message: 'Test suite created successfully',
93
+ }
94
+ } catch (e) {
95
+ if (e instanceof ZodError) {
96
+ return {
97
+ status: 400,
98
+ error: e.message,
99
+ }
100
+ }
101
+ if (e instanceof Prisma.PrismaClientKnownRequestError) {
102
+ return {
103
+ status: 500,
104
+ error: e.message,
105
+ }
106
+ }
107
+ return {
108
+ status: 500,
109
+ error: 'Server error occurred',
110
+ }
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Delete a test suite
116
+ * @param id - Test suite id
117
+ * @returns ActionResponse
118
+ */
119
+ export async function deleteTestSuiteAction(id: string[]): Promise<ActionResponse> {
120
+ try {
121
+ // Delete corresponding feature files before deleting test suites
122
+ for (const testSuiteId of id) {
123
+ try {
124
+ await deleteFeatureFile(testSuiteId)
125
+ } catch (featureFileError) {
126
+ console.error(`Error deleting feature file for test suite ${testSuiteId}:`, featureFileError)
127
+ // Don't fail the test suite deletion if feature file deletion fails
128
+ }
129
+ }
130
+
131
+ await prisma.testSuite.deleteMany({
132
+ where: { id: { in: id } },
133
+ })
134
+ revalidatePath('/test-suites')
135
+ return {
136
+ status: 200,
137
+ message: 'Test suite(s) deleted successfully',
138
+ }
139
+ } catch (e) {
140
+ return {
141
+ status: 500,
142
+ error: `Server error occurred: ${e}`,
143
+ }
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Get a test suite by id
149
+ * @param id - Test suite id
150
+ * @returns ActionResponse
151
+ */
152
+ export async function getTestSuiteByIdAction(id: string): Promise<ActionResponse> {
153
+ try {
154
+ const testSuite = await prisma.testSuite.findUnique({
155
+ where: { id },
156
+ include: { testCases: true, tags: true },
157
+ })
158
+ return {
159
+ status: 200,
160
+ data: testSuite,
161
+ }
162
+ } catch (e) {
163
+ console.error(e)
164
+ throw e
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Update a test suite
170
+ * @param _prev - Previous state
171
+ * @param value - Test suite data
172
+ * @param id - Test suite id
173
+ * @returns ActionResponse
174
+ */
175
+ export async function updateTestSuiteAction(
176
+ _prev: unknown,
177
+ value: z.infer<typeof testSuiteSchema>,
178
+ id?: string,
179
+ ): Promise<ActionResponse> {
180
+ try {
181
+ testSuiteSchema.parse(value)
182
+
183
+ // Get the current test suite to check if name or module changed
184
+ const currentTestSuite = await prisma.testSuite.findUnique({
185
+ where: { id },
186
+ include: {
187
+ module: true,
188
+ },
189
+ })
190
+
191
+ if (!currentTestSuite) {
192
+ return {
193
+ status: 404,
194
+ error: 'Test suite not found',
195
+ }
196
+ }
197
+
198
+ // Check if name or module changed - if so, delete old feature file
199
+ const nameChanged = currentTestSuite.name !== value.name
200
+ const moduleChanged = currentTestSuite.moduleId !== value.moduleId
201
+
202
+ if (nameChanged || moduleChanged) {
203
+ try {
204
+ await deleteFeatureFile(currentTestSuite.id)
205
+ } catch (featureFileError) {
206
+ console.error('Error deleting old feature file:', featureFileError)
207
+ // Don't fail the update if old file deletion fails
208
+ }
209
+ }
210
+
211
+ // Update the test suite
212
+ const updatedTestSuite = await prisma.testSuite.update({
213
+ where: { id },
214
+ data: {
215
+ name: value.name,
216
+ description: value.description,
217
+ testCases: {
218
+ set: value.testCases?.map(id => ({ id })),
219
+ },
220
+ tags: {
221
+ set: value.tagIds?.map(id => ({ id })) || [],
222
+ },
223
+ module: {
224
+ connect: {
225
+ id: value.moduleId,
226
+ },
227
+ },
228
+ },
229
+ include: {
230
+ module: true,
231
+ },
232
+ })
233
+
234
+ // Generate new feature file with updated information
235
+ try {
236
+ await generateFeatureFile(updatedTestSuite.id, updatedTestSuite.name, updatedTestSuite.description || undefined)
237
+ } catch (featureFileError) {
238
+ console.error('Error generating updated feature file:', featureFileError)
239
+ // Don't fail the test suite update if feature file generation fails
240
+ }
241
+
242
+ revalidatePath('/test-suites')
243
+ return {
244
+ status: 200,
245
+ message: 'Test suite updated successfully',
246
+ }
247
+ } catch (e) {
248
+ return {
249
+ status: 500,
250
+ error: `Server error occurred: ${e}`,
251
+ }
252
+ }
253
+ }
@@ -0,0 +1,13 @@
1
+ // User actions removed since authentication system was removed
2
+ // This file is kept for potential future use but all user-related functionality is disabled
3
+
4
+ import { ActionResponse } from '@/types/form/actionHandler'
5
+
6
+ export async function getAllUsersAction(): Promise<ActionResponse> {
7
+ // Since User model was removed, return empty array
8
+ return {
9
+ status: 200,
10
+ data: [],
11
+ message: 'No users available - authentication system removed',
12
+ }
13
+ }
@@ -0,0 +1,28 @@
1
+ import { createEnvironmentAction } from '@/actions/environments/environment-actions'
2
+ import EnvironmentForm from '../environment-form'
3
+ import PageHeader from '@/components/typography/page-header'
4
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
5
+ import { Metadata } from 'next'
6
+
7
+ export const metadata: Metadata = {
8
+ title: 'Appraise | Create Environment',
9
+ description: 'Create a new environment configuration for your test runs',
10
+ }
11
+
12
+ const CreateEnvironment = async () => {
13
+ return (
14
+ <>
15
+ <div className="mb-8">
16
+ <PageHeader>Create Environment</PageHeader>
17
+ <HeaderSubtitle>Create a new environment configuration for your test runs.</HeaderSubtitle>
18
+ </div>
19
+ <EnvironmentForm
20
+ successTitle="Environment created"
21
+ successMessage="Environment created successfully"
22
+ onSubmitAction={createEnvironmentAction}
23
+ />
24
+ </>
25
+ )
26
+ }
27
+
28
+ export default CreateEnvironment
@@ -0,0 +1,219 @@
1
+ 'use client'
2
+
3
+ import { Button } from '@/components/ui/button'
4
+ import { Input } from '@/components/ui/input'
5
+ import { Label } from '@/components/ui/label'
6
+ import { formOpts, type Environment } from '@/constants/form-opts/environment-form-opts'
7
+ import { toast } from '@/hooks/use-toast'
8
+ import { ActionResponse } from '@/types/form/actionHandler'
9
+ import { useForm } from '@tanstack/react-form'
10
+ import { useRouter } from 'next/navigation'
11
+ import React, { useState } from 'react'
12
+ import { z } from 'zod'
13
+ import { Eye, EyeOff } from 'lucide-react'
14
+
15
+ const EnvironmentForm = ({
16
+ defaultValues,
17
+ successTitle,
18
+ successMessage,
19
+ id,
20
+ onSubmitAction,
21
+ }: {
22
+ defaultValues?: Environment
23
+ successTitle: string
24
+ successMessage: string
25
+ id?: string
26
+ onSubmitAction: (
27
+ _prev: unknown,
28
+ value: Environment,
29
+ id?: string,
30
+ ) => Promise<ActionResponse>
31
+ }) => {
32
+ const router = useRouter()
33
+ const [showPassword, setShowPassword] = useState(false)
34
+ const form = useForm({
35
+ defaultValues: defaultValues ?? formOpts?.defaultValues,
36
+ validators: formOpts?.validators,
37
+ onSubmit: async ({ value }) => {
38
+ const res = await onSubmitAction(undefined, value, id)
39
+ if (res.status === 200) {
40
+ toast({
41
+ title: successTitle,
42
+ description: successMessage,
43
+ })
44
+ router.push('/environments')
45
+ }
46
+ if (res.status === 400) {
47
+ toast({
48
+ title: 'Error',
49
+ description: res.error,
50
+ variant: 'destructive',
51
+ })
52
+ }
53
+ if (res.status === 500) {
54
+ toast({
55
+ title: 'Error',
56
+ description: res.error,
57
+ variant: 'destructive',
58
+ })
59
+ }
60
+ },
61
+ })
62
+ return (
63
+ <form
64
+ onSubmit={e => {
65
+ e.preventDefault()
66
+ e.stopPropagation()
67
+ form.handleSubmit()
68
+ }}
69
+ >
70
+ <form.Field
71
+ name="name"
72
+ validators={{
73
+ onChange: z.string().min(1, { message: 'Name is required' }),
74
+ }}
75
+ >
76
+ {field => {
77
+ return (
78
+ <div className="mb-4 flex flex-col gap-2 lg:w-1/3">
79
+ <Label htmlFor={field.name}>Name</Label>
80
+ <Input id={field.name} value={field.state.value} onChange={e => field.handleChange(e.target.value)} />
81
+ {field.state.meta.isTouched &&
82
+ field.state.meta.errors.map((error, index) => (
83
+ <p key={index} className="text-xs text-pink-500">
84
+ {typeof error === 'string' ? error : error?.message || String(error)}
85
+ </p>
86
+ ))}
87
+ </div>
88
+ )
89
+ }}
90
+ </form.Field>
91
+ <form.Field
92
+ name="baseUrl"
93
+ validators={{
94
+ onChange: z.string().url({ message: 'Base URL must be a valid URL' }),
95
+ }}
96
+ >
97
+ {field => {
98
+ return (
99
+ <div className="mb-4 flex flex-col gap-2 lg:w-1/3">
100
+ <Label htmlFor={field.name}>Base URL</Label>
101
+ <Input
102
+ id={field.name}
103
+ value={field.state.value}
104
+ onChange={e => field.handleChange(e.target.value)}
105
+ placeholder="https://example.com"
106
+ />
107
+ {field.state.meta.isTouched &&
108
+ field.state.meta.errors.map((error, index) => (
109
+ <p key={index} className="text-xs text-pink-500">
110
+ {typeof error === 'string' ? error : error?.message || String(error)}
111
+ </p>
112
+ ))}
113
+ </div>
114
+ )
115
+ }}
116
+ </form.Field>
117
+ <form.Field
118
+ name="apiBaseUrl"
119
+ validators={{
120
+ onChange: z.string().url({ message: 'API Base URL must be a valid URL' }).optional().or(z.literal('')),
121
+ }}
122
+ >
123
+ {field => {
124
+ return (
125
+ <div className="mb-4 flex flex-col gap-2 lg:w-1/3">
126
+ <Label htmlFor={field.name}>API Base URL (Optional)</Label>
127
+ <Input
128
+ id={field.name}
129
+ value={field.state.value}
130
+ onChange={e => field.handleChange(e.target.value)}
131
+ placeholder="https://api.example.com"
132
+ />
133
+ {field.state.meta.isTouched &&
134
+ field.state.meta.errors.map((error, index) => (
135
+ <p key={index} className="text-xs text-pink-500">
136
+ {typeof error === 'string' ? error : error?.message || String(error)}
137
+ </p>
138
+ ))}
139
+ </div>
140
+ )
141
+ }}
142
+ </form.Field>
143
+ <form.Field
144
+ name="username"
145
+ validators={{
146
+ onChange: z.string().optional().or(z.literal('')),
147
+ }}
148
+ >
149
+ {field => {
150
+ return (
151
+ <div className="mb-4 flex flex-col gap-2 lg:w-1/3">
152
+ <Label htmlFor={field.name}>Username (Optional)</Label>
153
+ <Input
154
+ id={field.name}
155
+ value={field.state.value}
156
+ onChange={e => field.handleChange(e.target.value)}
157
+ placeholder="Enter username"
158
+ />
159
+ {field.state.meta.isTouched &&
160
+ field.state.meta.errors.map((error, index) => (
161
+ <p key={index} className="text-xs text-pink-500">
162
+ {typeof error === 'string' ? error : error?.message || String(error)}
163
+ </p>
164
+ ))}
165
+ </div>
166
+ )
167
+ }}
168
+ </form.Field>
169
+ <form.Field
170
+ name="password"
171
+ validators={{
172
+ onChange: z.string().optional().or(z.literal('')),
173
+ }}
174
+ >
175
+ {field => {
176
+ return (
177
+ <div className="mb-4 flex flex-col gap-2 lg:w-1/3">
178
+ <Label htmlFor={field.name}>Password (Optional)</Label>
179
+ <div className="relative">
180
+ <Input
181
+ id={field.name}
182
+ type={showPassword ? 'text' : 'password'}
183
+ value={field.state.value}
184
+ onChange={e => field.handleChange(e.target.value)}
185
+ placeholder="Enter password"
186
+ className="pr-10"
187
+ />
188
+ <Button
189
+ type="button"
190
+ variant="ghost"
191
+ size="sm"
192
+ className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
193
+ onClick={() => setShowPassword(!showPassword)}
194
+ >
195
+ {showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
196
+ </Button>
197
+ </div>
198
+ {field.state.meta.isTouched &&
199
+ field.state.meta.errors.map((error, index) => (
200
+ <p key={index} className="text-xs text-pink-500">
201
+ {typeof error === 'string' ? error : error?.message || String(error)}
202
+ </p>
203
+ ))}
204
+ </div>
205
+ )
206
+ }}
207
+ </form.Field>
208
+ <form.Subscribe selector={formState => [formState.canSubmit, formState.isSubmitting]}>
209
+ {([canSubmit, isSubmitting]) => (
210
+ <Button type="submit" disabled={!canSubmit}>
211
+ {isSubmitting ? '...' : 'Save'}
212
+ </Button>
213
+ )}
214
+ </form.Subscribe>
215
+ </form>
216
+ )
217
+ }
218
+
219
+ export default EnvironmentForm
@@ -0,0 +1,96 @@
1
+ 'use client'
2
+
3
+ import { DataTableColumnHeader } from '@/components/ui/data-table-column-header'
4
+ import { ColumnDef } from '@tanstack/react-table'
5
+
6
+ import { Checkbox } from '@/components/ui/checkbox'
7
+ import TableActions from '@/components/table/table-actions'
8
+ import { Environment } from '@prisma/client'
9
+ import { deleteEnvironmentAction } from '@/actions/environments/environment-actions'
10
+ import { formatDateTime } from '@/lib/utils'
11
+
12
+ export const environmentTableCols: ColumnDef<Environment>[] = [
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: 'baseUrl',
40
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Base URL" />,
41
+ cell: ({ row }) => {
42
+ const baseUrl = row.original.baseUrl
43
+ return (
44
+ <div className="max-w-[200px] truncate font-mono text-sm" title={baseUrl}>
45
+ {baseUrl}
46
+ </div>
47
+ )
48
+ },
49
+ },
50
+ {
51
+ accessorKey: 'apiBaseUrl',
52
+ header: ({ column }) => <DataTableColumnHeader column={column} title="API Base URL" />,
53
+ cell: ({ row }) => {
54
+ const apiBaseUrl = row.original.apiBaseUrl
55
+ return (
56
+ <div className="max-w-[200px] truncate font-mono text-sm" title={apiBaseUrl || ''}>
57
+ {apiBaseUrl || '-'}
58
+ </div>
59
+ )
60
+ },
61
+ },
62
+ {
63
+ accessorKey: 'username',
64
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Username" />,
65
+ cell: ({ row }) => {
66
+ const username = row.original.username
67
+ return <div className="max-w-[150px] truncate">{username || '-'}</div>
68
+ },
69
+ },
70
+ {
71
+ accessorKey: 'createdAt',
72
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Created At" />,
73
+ cell: ({ row }) => {
74
+ return formatDateTime(row.original.createdAt)
75
+ },
76
+ },
77
+ {
78
+ accessorKey: 'updatedAt',
79
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Updated At" />,
80
+ cell: ({ row }) => {
81
+ return formatDateTime(row.original.updatedAt)
82
+ },
83
+ },
84
+ {
85
+ id: 'actions',
86
+ cell: ({ row }) => {
87
+ const environmentData = row.original
88
+ return (
89
+ <TableActions
90
+ modifyLink={`/environments/modify/${environmentData.id}`}
91
+ deleteHandler={() => deleteEnvironmentAction([environmentData.id])}
92
+ />
93
+ )
94
+ },
95
+ },
96
+ ]
@@ -0,0 +1,24 @@
1
+ import { DataTable } from '@/components/ui/data-table'
2
+ import { Environment } from '@prisma/client'
3
+ import { getAllEnvironmentsAction, deleteEnvironmentAction } from '@/actions/environments/environment-actions'
4
+ import { environmentTableCols } from './environment-table-columns'
5
+
6
+ const EnvironmentTable = async () => {
7
+ const { data: environments } = await getAllEnvironmentsAction()
8
+
9
+ return (
10
+ <>
11
+ <DataTable
12
+ columns={environmentTableCols}
13
+ data={environments as Environment[]}
14
+ filterColumn="name"
15
+ filterPlaceholder="Filter by name..."
16
+ createLink="/environments/create"
17
+ modifyLink="/environments/modify"
18
+ deleteAction={deleteEnvironmentAction}
19
+ />
20
+ </>
21
+ )
22
+ }
23
+
24
+ export default EnvironmentTable
@@ -0,0 +1,46 @@
1
+ import { getEnvironmentByIdAction, updateEnvironmentAction } from '@/actions/environments/environment-actions'
2
+ import { Environment } from '@prisma/client'
3
+ import EnvironmentForm from '../../environment-form'
4
+ import PageHeader from '@/components/typography/page-header'
5
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
6
+ import { Metadata } from 'next'
7
+
8
+ export const metadata: Metadata = {
9
+ title: 'Appraise | Modify Environment',
10
+ description: 'Update the environment configuration',
11
+ }
12
+
13
+ const ModifyEnvironment = async ({ params }: { params: Promise<{ id: string }> }) => {
14
+ const { id } = await params
15
+ const { data: environmentToBeEditedData, error: environmentToBeEditedError } = await getEnvironmentByIdAction(id)
16
+
17
+ if (environmentToBeEditedError) {
18
+ return <div>Error: {environmentToBeEditedError}</div>
19
+ }
20
+
21
+ const environmentData = environmentToBeEditedData as Environment
22
+
23
+ return (
24
+ <>
25
+ <div className="mb-8">
26
+ <PageHeader>Modify Environment</PageHeader>
27
+ <HeaderSubtitle>Update the environment configuration.</HeaderSubtitle>
28
+ </div>
29
+ <EnvironmentForm
30
+ id={id}
31
+ defaultValues={{
32
+ name: environmentData.name,
33
+ baseUrl: environmentData.baseUrl,
34
+ apiBaseUrl: environmentData.apiBaseUrl || '',
35
+ username: environmentData.username || '',
36
+ password: environmentData.password || '',
37
+ }}
38
+ successTitle="Environment updated"
39
+ successMessage="Environment updated successfully"
40
+ onSubmitAction={updateEnvironmentAction}
41
+ />
42
+ </>
43
+ )
44
+ }
45
+
46
+ export default ModifyEnvironment