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,59 @@
1
+ import PageHeader from '@/components/typography/page-header'
2
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
3
+ import React from 'react'
4
+ import { Server } from 'lucide-react'
5
+ import EnvironmentTable from './environment-table'
6
+ import { Suspense } from 'react'
7
+ import DataTableSkeleton from '@/components/loading-skeleton/data-table/data-table-skeleton'
8
+ import { getAllEnvironmentsAction } from '@/actions/environments/environment-actions'
9
+ import EmptyState from '@/components/data-state/empty-state'
10
+ import { Environment } from '@prisma/client'
11
+ import { Metadata } from 'next'
12
+
13
+ export const metadata: Metadata = {
14
+ title: 'Appraise | Environments',
15
+ description: 'Manage test environments and their configurations',
16
+ }
17
+
18
+ const Environments = async () => {
19
+ const { data: environments, error: environmentsError } = await getAllEnvironmentsAction()
20
+
21
+ if (environmentsError) {
22
+ return <div>Error: {environmentsError}</div>
23
+ }
24
+
25
+ const environmentsData = environments as Environment[]
26
+
27
+ if (!environmentsData || environmentsData.length === 0) {
28
+ return (
29
+ <div className="flex min-h-[calc(100vh-20rem)] items-center justify-center">
30
+ <EmptyState
31
+ icon={<Server className="h-8 w-8" />}
32
+ title="No environments found"
33
+ description="Get started by creating an environment to manage your test configurations"
34
+ createRoute="/environments/create"
35
+ createText="Create Environment"
36
+ />
37
+ </div>
38
+ )
39
+ }
40
+
41
+ return (
42
+ <>
43
+ <div className="mb-8">
44
+ <PageHeader>
45
+ <span className="flex items-center">
46
+ <Server className="mr-2 h-8 w-8" />
47
+ Environments
48
+ </span>
49
+ </PageHeader>
50
+ <HeaderSubtitle>Manage test environments and their configurations</HeaderSubtitle>
51
+ </div>
52
+ <Suspense fallback={<DataTableSkeleton />}>
53
+ <EnvironmentTable />
54
+ </Suspense>
55
+ </>
56
+ )
57
+ }
58
+
59
+ export default Environments
@@ -0,0 +1,10 @@
1
+ /**
2
+ * All (base) routes depend on server data (Prisma). Force dynamic rendering
3
+ * so these pages are not statically generated at build time (e.g. in CI where
4
+ * no database is available).
5
+ */
6
+ export const dynamic = 'force-dynamic'
7
+
8
+ export default function BaseLayout({ children }: { children: React.ReactNode }) {
9
+ return <>{children}</>
10
+ }
@@ -0,0 +1,44 @@
1
+ import { createLocatorGroupAction } from '@/actions/locator-groups/locator-group-actions'
2
+ import PageHeader from '@/components/typography/page-header'
3
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
4
+ import { Group } from 'lucide-react'
5
+ import React from 'react'
6
+ import LocatorGroupForm from '../locator-group-form'
7
+ import { getAllModulesAction } from '@/actions/modules/module-actions'
8
+ import { Module } from '@prisma/client'
9
+ import { Metadata } from 'next'
10
+
11
+ export const metadata: Metadata = {
12
+ title: 'Appraise | Create Locator Group',
13
+ description: 'Create a new locator group',
14
+ }
15
+
16
+ const CreateLocatorGroup = async () => {
17
+ const { data: moduleList, error: moduleListError } = await getAllModulesAction()
18
+
19
+ if (moduleListError) {
20
+ return <div>Error: {moduleListError}</div>
21
+ }
22
+
23
+ return (
24
+ <>
25
+ <div className="mb-8">
26
+ <PageHeader>
27
+ <span className="flex items-center">
28
+ <Group className="mr-2 h-8 w-8" />
29
+ Create Locator Group
30
+ </span>
31
+ </PageHeader>
32
+ <HeaderSubtitle>Create a new locator group.</HeaderSubtitle>
33
+ </div>
34
+ <LocatorGroupForm
35
+ moduleList={moduleList as Module[]}
36
+ onSubmitAction={createLocatorGroupAction}
37
+ successTitle="Locator Group Created"
38
+ successMessage="The locator group has been created successfully."
39
+ />
40
+ </>
41
+ )
42
+ }
43
+
44
+ export default CreateLocatorGroup
@@ -0,0 +1,215 @@
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, LocatorGroup } from '@/constants/form-opts/locator-group-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 React, { useCallback, useRef } from 'react'
11
+ import { z } from 'zod'
12
+ import { useRouter } from 'next/navigation'
13
+ import { Module } from '@prisma/client'
14
+ import { checkLocatorGroupNameUniqueAction } from '@/actions/locator-groups/locator-group-actions'
15
+
16
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
17
+
18
+ const LocatorGroupForm = ({
19
+ defaultValues,
20
+ successTitle,
21
+ successMessage,
22
+ id,
23
+ onSubmitAction,
24
+ moduleList,
25
+ }: {
26
+ defaultValues?: LocatorGroup
27
+ successTitle: string
28
+ successMessage: string
29
+ moduleList: Module[]
30
+ id?: string
31
+ onSubmitAction: (
32
+ _prev: unknown,
33
+ value: LocatorGroup,
34
+ id?: string,
35
+ ) => Promise<ActionResponse>
36
+ }) => {
37
+ const router = useRouter()
38
+ const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null)
39
+
40
+ // Debounced function to check name uniqueness
41
+ const checkNameUniqueness = useCallback(
42
+ async (name: string) => {
43
+ if (!name || name.length < 1) return true
44
+
45
+ try {
46
+ const response = await checkLocatorGroupNameUniqueAction(name, id)
47
+ return response.status === 200 && (response.data as { isUnique: boolean })?.isUnique
48
+ } catch (error) {
49
+ console.error('Error checking name uniqueness:', error)
50
+ return true // Allow submission if check fails
51
+ }
52
+ },
53
+ [id],
54
+ )
55
+
56
+ // Debounced validation function
57
+ const debouncedNameValidation = useCallback(
58
+ (name: string): Promise<boolean> => {
59
+ return new Promise(resolve => {
60
+ if (debounceTimeoutRef.current) {
61
+ clearTimeout(debounceTimeoutRef.current)
62
+ }
63
+
64
+ debounceTimeoutRef.current = setTimeout(async () => {
65
+ const isValid = await checkNameUniqueness(name)
66
+ resolve(isValid)
67
+ }, 500) // 500ms debounce
68
+ })
69
+ },
70
+ [checkNameUniqueness],
71
+ )
72
+
73
+ const form = useForm({
74
+ defaultValues: defaultValues ?? formOpts?.defaultValues,
75
+ validators: formOpts?.validators,
76
+ onSubmit: async ({ value }) => {
77
+ const res = await onSubmitAction(undefined, value, id)
78
+ if (res.status === 200) {
79
+ toast({
80
+ title: successTitle,
81
+ description: successMessage,
82
+ })
83
+ router.push('/locator-groups')
84
+ }
85
+ if (res.status === 400) {
86
+ toast({
87
+ title: 'Error',
88
+ description: res.error,
89
+ variant: 'destructive',
90
+ })
91
+ }
92
+ if (res.status === 500) {
93
+ toast({
94
+ title: 'Error',
95
+ description: res.error,
96
+ variant: 'destructive',
97
+ })
98
+ }
99
+ },
100
+ })
101
+ return (
102
+ <form
103
+ onSubmit={e => {
104
+ e.preventDefault()
105
+ e.stopPropagation()
106
+ form.handleSubmit()
107
+ }}
108
+ >
109
+ <form.Field
110
+ name="name"
111
+ validators={{
112
+ onChange: z.string().min(1, { message: 'Name is required' }),
113
+ onChangeAsync: async ({ value }) => {
114
+ if (!value || value.length < 1) return undefined
115
+ const isValid = await debouncedNameValidation(value)
116
+ return isValid
117
+ ? undefined
118
+ : 'A locator group with this name already exists. Please choose a different name.'
119
+ },
120
+ }}
121
+ >
122
+ {field => {
123
+ return (
124
+ <div className="mb-4 flex flex-col gap-2 lg:w-1/3">
125
+ <Label htmlFor={field.name}>Name</Label>
126
+ <Input
127
+ id={field.name}
128
+ value={field.state.value}
129
+ onChange={e => field.handleChange(e.target.value)}
130
+ placeholder="Enter locator group name"
131
+ />
132
+ {field.state.meta.isTouched &&
133
+ field.state.meta.errors.map((error, index) => (
134
+ <p key={index} className="text-xs text-pink-500">
135
+ {typeof error === 'string' ? error : error?.message || String(error)}
136
+ </p>
137
+ ))}
138
+ {field.state.meta.isTouched && field.state.meta.errors.length === 0 && field.state.meta.isValidating && (
139
+ <p className="text-xs text-blue-500">Checking name availability...</p>
140
+ )}
141
+ </div>
142
+ )
143
+ }}
144
+ </form.Field>
145
+ <form.Field
146
+ name="moduleId"
147
+ validators={{
148
+ onChange: z.string().min(1, { message: 'Module is required' }),
149
+ }}
150
+ >
151
+ {field => {
152
+ return (
153
+ <div className="mb-4 flex flex-col gap-2 lg:w-1/3">
154
+ <Label htmlFor={field.name}>Module</Label>
155
+ <Select value={field.state.value} onValueChange={value => field.handleChange(value)}>
156
+ <SelectTrigger>
157
+ <SelectValue placeholder="Select a module" />
158
+ </SelectTrigger>
159
+ <SelectContent>
160
+ {moduleList.map(moduleData => (
161
+ <SelectItem key={moduleData.id} value={moduleData.id}>
162
+ {moduleData.name}
163
+ </SelectItem>
164
+ ))}
165
+ </SelectContent>
166
+ </Select>
167
+ {field.state.meta.isTouched &&
168
+ field.state.meta.errors.map((error, index) => (
169
+ <p key={index} className="text-xs text-pink-500">
170
+ {typeof error === 'string' ? error : error?.message || String(error)}
171
+ </p>
172
+ ))}
173
+ </div>
174
+ )
175
+ }}
176
+ </form.Field>
177
+ <form.Field
178
+ name="route"
179
+ validators={{
180
+ onChange: z.string().optional(),
181
+ }}
182
+ >
183
+ {field => {
184
+ return (
185
+ <div className="mb-4 flex flex-col gap-2 lg:w-1/3">
186
+ <Label htmlFor={field.name}>Route</Label>
187
+ <Input
188
+ id={field.name}
189
+ value={field.state.value}
190
+ onChange={e => field.handleChange(e.target.value)}
191
+ placeholder="Enter the route of page the locator group is for. Default is '/' (root)"
192
+ />
193
+ {field.state.meta.isTouched &&
194
+ field.state.meta.errors.map((error, index) => (
195
+ <p key={index} className="text-xs text-pink-500">
196
+ {typeof error === 'string' ? error : error?.message || String(error)}
197
+ </p>
198
+ ))}
199
+ </div>
200
+ )
201
+ }}
202
+ </form.Field>
203
+
204
+ <form.Subscribe selector={formState => [formState.canSubmit, formState.isSubmitting]}>
205
+ {([canSubmit, isSubmitting]) => (
206
+ <Button type="submit" disabled={!canSubmit}>
207
+ {isSubmitting ? '...' : 'Save'}
208
+ </Button>
209
+ )}
210
+ </form.Subscribe>
211
+ </form>
212
+ )
213
+ }
214
+
215
+ export default LocatorGroupForm
@@ -0,0 +1,77 @@
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 { LocatorGroup, Module } from '@prisma/client'
9
+ import { formatDateTime } from '@/lib/utils'
10
+ import { deleteLocatorGroupAction } from '@/actions/locator-groups/locator-group-actions'
11
+ import { Badge } from '@/components/ui/badge'
12
+
13
+ export const locatorGroupTableCols: ColumnDef<LocatorGroup & { module: Module }>[] = [
14
+ {
15
+ id: 'select',
16
+ header: ({ table }) => (
17
+ <Checkbox
18
+ checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate')}
19
+ onCheckedChange={value => table.toggleAllPageRowsSelected(!!value)}
20
+ aria-label="Select all"
21
+ className="mr-2"
22
+ />
23
+ ),
24
+ cell: ({ row }) => (
25
+ <Checkbox
26
+ checked={row.getIsSelected()}
27
+ onCheckedChange={value => row.toggleSelected(!!value)}
28
+ aria-label="Select row"
29
+ className="mr-2"
30
+ />
31
+ ),
32
+ enableSorting: false,
33
+ enableHiding: false,
34
+ },
35
+ {
36
+ accessorKey: 'name',
37
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Name" />,
38
+ },
39
+ {
40
+ accessorKey: 'module.name',
41
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Module" />,
42
+ cell: ({ row }) => {
43
+ const locatorGroup = row.original
44
+ return <Badge variant="outline">{locatorGroup.module?.name}</Badge>
45
+ },
46
+ },
47
+ {
48
+ accessorKey: 'route',
49
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Route" />,
50
+ },
51
+ {
52
+ accessorKey: 'createdAt',
53
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Created At" />,
54
+ cell: ({ row }) => {
55
+ return formatDateTime(row.original.createdAt)
56
+ },
57
+ },
58
+ {
59
+ accessorKey: 'updatedAt',
60
+ header: ({ column }) => <DataTableColumnHeader column={column} title="Updated At" />,
61
+ cell: ({ row }) => {
62
+ return formatDateTime(row.original.updatedAt)
63
+ },
64
+ },
65
+ {
66
+ id: 'actions',
67
+ cell: ({ row }) => {
68
+ const locatorGroup = row.original
69
+ return (
70
+ <TableActions
71
+ modifyLink={`/locator-groups/modify/${locatorGroup.id}`}
72
+ deleteHandler={() => deleteLocatorGroupAction([locatorGroup.id])}
73
+ />
74
+ )
75
+ },
76
+ },
77
+ ]
@@ -0,0 +1,28 @@
1
+ import { deleteLocatorGroupAction, getAllLocatorGroupsAction } from '@/actions/locator-groups/locator-group-actions'
2
+ import { DataTable } from '@/components/ui/data-table'
3
+ import { LocatorGroup, Module } from '@prisma/client'
4
+ import { locatorGroupTableCols } from './locator-group-table-columns'
5
+
6
+ const LocatorGroupTable = async () => {
7
+ const { data: locatorGroups, error: locatorGroupsError } = await getAllLocatorGroupsAction()
8
+
9
+ if (locatorGroupsError) {
10
+ return <div>Error: {locatorGroupsError}</div>
11
+ }
12
+
13
+ return (
14
+ <>
15
+ <DataTable
16
+ columns={locatorGroupTableCols}
17
+ data={locatorGroups as (LocatorGroup & { module: Module })[]}
18
+ filterColumn="name"
19
+ filterPlaceholder="Filter by name..."
20
+ createLink="/locator-groups/create"
21
+ modifyLink="/locator-groups/modify"
22
+ deleteAction={deleteLocatorGroupAction}
23
+ />
24
+ </>
25
+ )
26
+ }
27
+
28
+ export default LocatorGroupTable
@@ -0,0 +1,46 @@
1
+ import { getLocatorGroupByIdAction } from '@/actions/locator-groups/locator-group-actions'
2
+ import { LocatorGroup, Module } from '@prisma/client'
3
+ import React from 'react'
4
+ import LocatorGroupForm from '../../locator-group-form'
5
+ import { updateLocatorGroupAction } from '@/actions/locator-groups/locator-group-actions'
6
+ import { getAllModulesAction } from '@/actions/modules/module-actions'
7
+ import { Metadata } from 'next'
8
+
9
+ export const metadata: Metadata = {
10
+ title: 'Appraise | Modify Locator Group',
11
+ description: 'Update locator group configuration',
12
+ }
13
+
14
+ const ModifyLocator = async ({ params }: { params: Promise<{ id: string }> }) => {
15
+ const { id } = await params
16
+ const { data, error } = await getLocatorGroupByIdAction(id)
17
+
18
+ if (error) {
19
+ return <div>Error: {error}</div>
20
+ }
21
+
22
+ const locatorGroup = data as LocatorGroup
23
+
24
+ const { data: moduleList, error: moduleListError } = await getAllModulesAction()
25
+
26
+ if (moduleListError) {
27
+ return <div>Error: {moduleListError}</div>
28
+ }
29
+
30
+ return (
31
+ <LocatorGroupForm
32
+ defaultValues={{
33
+ name: locatorGroup.name ?? '',
34
+ moduleId: locatorGroup.moduleId ?? '',
35
+ route: locatorGroup.route ?? '',
36
+ }}
37
+ successTitle="Locator Group updated"
38
+ successMessage="Locator Group updated successfully"
39
+ onSubmitAction={updateLocatorGroupAction}
40
+ id={id}
41
+ moduleList={moduleList as Module[]}
42
+ />
43
+ )
44
+ }
45
+
46
+ export default ModifyLocator
@@ -0,0 +1,61 @@
1
+ import PageHeader from '@/components/typography/page-header'
2
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
3
+ import React from 'react'
4
+ import { Group } from 'lucide-react'
5
+ import LocatorGroupTable from './locator-group-table'
6
+ import { Suspense } from 'react'
7
+ import DataTableSkeleton from '@/components/loading-skeleton/data-table/data-table-skeleton'
8
+ import { getAllLocatorGroupsAction } from '@/actions/locator-groups/locator-group-actions'
9
+ import EmptyState from '@/components/data-state/empty-state'
10
+ import { LocatorGroup } from '@prisma/client'
11
+ import { Metadata } from 'next'
12
+
13
+ export const metadata: Metadata = {
14
+ title: 'Appraise | Locator Groups',
15
+ description: 'Manage locator groups for organizing locators',
16
+ }
17
+
18
+ const LocatorGroups = async () => {
19
+ const { data: locatorGroups, error: locatorGroupsError } = await getAllLocatorGroupsAction()
20
+
21
+ if (locatorGroupsError) {
22
+ return <div>Error: {locatorGroupsError}</div>
23
+ }
24
+
25
+ const locatorGroupsData = locatorGroups as LocatorGroup[]
26
+
27
+ if (!locatorGroupsData || locatorGroupsData.length === 0) {
28
+ return (
29
+ <div className="flex min-h-[calc(100vh-20rem)] items-center justify-center">
30
+ <EmptyState
31
+ icon={<Group className="h-8 w-8" />}
32
+ title="No locator groups found"
33
+ description="Get started by creating a locator group to organize your locators"
34
+ createRoute="/locator-groups/create"
35
+ createText="Create Locator Group"
36
+ />
37
+ </div>
38
+ )
39
+ }
40
+
41
+ return (
42
+ <>
43
+ <div className="mb-8">
44
+ <PageHeader>
45
+ <span className="flex items-center">
46
+ <Group className="mr-2 h-8 w-8" />
47
+ Locator Groups
48
+ </span>
49
+ </PageHeader>
50
+ <HeaderSubtitle>
51
+ Locator groups are used to group locators together. They are used to identify the elements on the page.
52
+ </HeaderSubtitle>
53
+ </div>
54
+ <Suspense fallback={<DataTableSkeleton />}>
55
+ <LocatorGroupTable />
56
+ </Suspense>
57
+ </>
58
+ )
59
+ }
60
+
61
+ export default LocatorGroups
@@ -0,0 +1,38 @@
1
+ import PageHeader from '@/components/typography/page-header'
2
+ import HeaderSubtitle from '@/components/typography/page-header-subtitle'
3
+ import React from 'react'
4
+ import LocatorForm from '../locator-form'
5
+ import { createLocatorAction } from '@/actions/locator/locator-actions'
6
+ import { getAllLocatorGroupsAction } from '@/actions/locator-groups/locator-group-actions'
7
+ import { LocatorGroup } from '@prisma/client'
8
+ import { Metadata } from 'next'
9
+
10
+ export const metadata: Metadata = {
11
+ title: 'Appraise | Create Locator',
12
+ description: 'Create a new locator to be used in your test cases',
13
+ }
14
+
15
+ const CreateLocator = async () => {
16
+ const { data: locatorGroupList, error: locatorGroupListError } = await getAllLocatorGroupsAction()
17
+
18
+ if (locatorGroupListError) {
19
+ return <div>Error: {locatorGroupListError}</div>
20
+ }
21
+
22
+ return (
23
+ <>
24
+ <div className="mb-8">
25
+ <PageHeader>Create Locator</PageHeader>
26
+ <HeaderSubtitle>Create a new locator to be used in your test cases.</HeaderSubtitle>
27
+ </div>
28
+ <LocatorForm
29
+ successTitle="Locator created"
30
+ successMessage="Locator created successfully"
31
+ onSubmitAction={createLocatorAction}
32
+ locatorGroupList={locatorGroupList as LocatorGroup[]}
33
+ />
34
+ </>
35
+ )
36
+ }
37
+
38
+ export default CreateLocator