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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/README.md +52 -52
  2. package/dist/cli.e2e.test.d.ts +2 -0
  3. package/dist/cli.e2e.test.d.ts.map +1 -0
  4. package/dist/cli.e2e.test.js +73 -0
  5. package/dist/cli.e2e.test.js.map +1 -0
  6. package/dist/config.test.d.ts +2 -0
  7. package/dist/config.test.d.ts.map +1 -0
  8. package/dist/config.test.js +65 -0
  9. package/dist/config.test.js.map +1 -0
  10. package/dist/copy-template.test.d.ts +2 -0
  11. package/dist/copy-template.test.d.ts.map +1 -0
  12. package/dist/copy-template.test.js +71 -0
  13. package/dist/copy-template.test.js.map +1 -0
  14. package/dist/download-repo.test.d.ts +2 -0
  15. package/dist/download-repo.test.d.ts.map +1 -0
  16. package/dist/download-repo.test.js +14 -0
  17. package/dist/download-repo.test.js.map +1 -0
  18. package/dist/install.test.d.ts +2 -0
  19. package/dist/install.test.d.ts.map +1 -0
  20. package/dist/install.test.js +119 -0
  21. package/dist/install.test.js.map +1 -0
  22. package/dist/prepare-template-utils.d.ts.map +1 -1
  23. package/dist/prepare-template-utils.js +5 -0
  24. package/dist/prepare-template-utils.js.map +1 -1
  25. package/dist/prompts.test.d.ts +2 -0
  26. package/dist/prompts.test.d.ts.map +1 -0
  27. package/dist/prompts.test.js +58 -0
  28. package/dist/prompts.test.js.map +1 -0
  29. package/dist/scaffold-gitignore.d.ts +1 -0
  30. package/dist/scaffold-gitignore.d.ts.map +1 -1
  31. package/dist/scaffold-gitignore.js +3 -0
  32. package/dist/scaffold-gitignore.js.map +1 -1
  33. package/package.json +3 -2
  34. package/templates/default/.appraise-template-meta.json +2 -2
  35. package/templates/default/.env.example +2 -2
  36. package/templates/default/.vscode/settings.json +2 -1
  37. package/templates/default/README.md +53 -53
  38. package/templates/default/automation/mapping/locator-map.json +1 -14
  39. package/templates/default/automation/steps/actions/click.step.ts +58 -58
  40. package/templates/default/automation/steps/actions/hover.step.ts +27 -27
  41. package/templates/default/automation/steps/actions/input.step.ts +84 -84
  42. package/templates/default/automation/steps/actions/navigation.step.ts +70 -70
  43. package/templates/default/automation/steps/actions/random_data.step.ts +142 -142
  44. package/templates/default/automation/steps/actions/store.step.ts +86 -86
  45. package/templates/default/automation/steps/actions/wait.step.ts +90 -90
  46. package/templates/default/automation/steps/validations/active_state_assertion.step.ts +30 -30
  47. package/templates/default/automation/steps/validations/navigation_assertion.step.ts +22 -22
  48. package/templates/default/automation/steps/validations/text_assertion.step.ts +107 -107
  49. package/templates/default/automation/steps/validations/visibility_assertion.step.ts +26 -26
  50. package/templates/default/components.json +24 -24
  51. package/templates/default/cucumber.mjs +16 -16
  52. package/templates/default/eslint.config.mjs +16 -16
  53. package/templates/default/gitignore +3 -0
  54. package/templates/default/next-env.d.ts +6 -6
  55. package/templates/default/next.config.ts +11 -11
  56. package/templates/default/package-lock.json +146 -75
  57. package/templates/default/package.json +2 -1
  58. package/templates/default/packages/cucumber-runtime/package.json +13 -13
  59. package/templates/default/packages/cucumber-runtime/src/cache.util.ts +93 -93
  60. package/templates/default/packages/cucumber-runtime/src/cli.ts +68 -68
  61. package/templates/default/packages/cucumber-runtime/src/environment.util.ts +21 -21
  62. package/templates/default/packages/cucumber-runtime/src/executor.ts +32 -32
  63. package/templates/default/packages/cucumber-runtime/src/hooks.ts +25 -3
  64. package/templates/default/packages/cucumber-runtime/src/index.ts +17 -17
  65. package/templates/default/packages/cucumber-runtime/src/locator.util.ts +234 -234
  66. package/templates/default/packages/cucumber-runtime/src/parameter-types.ts +7 -7
  67. package/templates/default/packages/cucumber-runtime/src/paths.ts +66 -1
  68. package/templates/default/packages/cucumber-runtime/src/random-data.util.ts +35 -35
  69. package/templates/default/packages/cucumber-runtime/src/types.ts +13 -13
  70. package/templates/default/packages/cucumber-runtime/src/world.ts +44 -44
  71. package/templates/default/packages/cucumber-runtime/tsconfig.json +11 -11
  72. package/templates/default/packages/locator-picker-companion/dist/cli.d.ts +1 -0
  73. package/templates/default/packages/locator-picker-companion/dist/cli.js +302 -0
  74. package/templates/default/packages/locator-picker-companion/dist/index.d.ts +3 -0
  75. package/templates/default/packages/locator-picker-companion/dist/index.js +3 -0
  76. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.d.ts +1 -0
  77. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.js +615 -0
  78. package/templates/default/packages/locator-picker-companion/dist/launcher.d.ts +11 -0
  79. package/templates/default/packages/locator-picker-companion/dist/launcher.js +59 -0
  80. package/templates/default/packages/locator-picker-companion/dist/selector-generator.d.ts +3 -0
  81. package/templates/default/packages/locator-picker-companion/dist/selector-generator.js +257 -0
  82. package/templates/default/packages/locator-picker-companion/dist/session-file.d.ts +22 -0
  83. package/templates/default/packages/locator-picker-companion/dist/session-file.js +150 -0
  84. package/templates/default/packages/locator-picker-companion/dist/types.d.ts +31 -0
  85. package/templates/default/packages/locator-picker-companion/dist/types.js +1 -0
  86. package/templates/default/packages/locator-picker-companion/package.json +17 -0
  87. package/templates/default/packages/locator-picker-companion/src/cli.ts +428 -0
  88. package/templates/default/packages/locator-picker-companion/src/index.ts +3 -0
  89. package/templates/default/packages/locator-picker-companion/src/injected-picker-script.ts +771 -0
  90. package/templates/default/packages/locator-picker-companion/src/launcher.ts +77 -0
  91. package/templates/default/packages/locator-picker-companion/src/selector-generator.ts +339 -0
  92. package/templates/default/packages/locator-picker-companion/src/session-file.ts +226 -0
  93. package/templates/default/packages/locator-picker-companion/src/types.ts +42 -0
  94. package/templates/default/packages/locator-picker-companion/tsconfig.json +14 -0
  95. package/templates/default/postcss.config.mjs +8 -8
  96. package/templates/default/prisma/dev.db +0 -0
  97. package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
  98. package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
  99. package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
  100. package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
  101. package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
  102. package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
  103. package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
  104. package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
  105. package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
  106. package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
  107. package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
  108. package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
  109. package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
  110. package/templates/default/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -0
  111. package/templates/default/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +20 -0
  112. package/templates/default/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +2 -0
  113. package/templates/default/prisma/schema.prisma +4 -0
  114. package/templates/default/scripts/install-playwright.ts +20 -0
  115. package/templates/default/scripts/protect-seeded-files.ts +38 -38
  116. package/templates/default/scripts/regenerate-features.ts +94 -94
  117. package/templates/default/scripts/setup-env.ts +19 -19
  118. package/templates/default/scripts/sync-all.ts +22 -66
  119. package/templates/default/scripts/sync-appraise-base-template.ts +57 -19
  120. package/templates/default/scripts/sync-environments.ts +40 -21
  121. package/templates/default/scripts/sync-locator-groups.ts +410 -410
  122. package/templates/default/scripts/sync-locators.ts +398 -398
  123. package/templates/default/scripts/sync-modules.ts +341 -341
  124. package/templates/default/scripts/sync-tags.ts +2 -3
  125. package/templates/default/scripts/sync-template-step-groups.ts +0 -3
  126. package/templates/default/scripts/sync-template-steps.ts +37 -11
  127. package/templates/default/scripts/sync-test-cases.ts +68 -16
  128. package/templates/default/scripts/sync-test-suites.ts +7 -5
  129. package/templates/default/src/actions/conflict/conflict.action.ts +33 -33
  130. package/templates/default/src/actions/dashboard/dashboard-actions.ts +240 -240
  131. package/templates/default/src/actions/environments/environment-actions.ts +188 -188
  132. package/templates/default/src/actions/locator/locator-actions.ts +490 -490
  133. package/templates/default/src/actions/locator-groups/locator-group-actions.ts +6 -3
  134. package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +243 -0
  135. package/templates/default/src/actions/modules/module-actions.ts +135 -135
  136. package/templates/default/src/actions/reports/report-actions.ts +51 -49
  137. package/templates/default/src/actions/review/review-actions.ts +147 -147
  138. package/templates/default/src/actions/settings/sync-actions.ts +46 -0
  139. package/templates/default/src/actions/tags/tag-actions.ts +107 -107
  140. package/templates/default/src/actions/template-step/template-step-actions.ts +38 -4
  141. package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +10 -3
  142. package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -238
  143. package/templates/default/src/actions/test-case/test-case-actions.ts +356 -356
  144. package/templates/default/src/actions/test-run/test-run-actions.ts +222 -129
  145. package/templates/default/src/actions/test-suite/test-suite-actions.ts +95 -17
  146. package/templates/default/src/actions/user/user-actions.ts +13 -13
  147. package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
  148. package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -219
  149. package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
  150. package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -24
  151. package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -46
  152. package/templates/default/src/app/(base)/environments/page.tsx +59 -59
  153. package/templates/default/src/app/(base)/layout.tsx +10 -10
  154. package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
  155. package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
  156. package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
  157. package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
  158. package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
  159. package/templates/default/src/app/(base)/locator-groups/page.tsx +20 -8
  160. package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +542 -0
  161. package/templates/default/src/app/(base)/locators/create/page.tsx +32 -19
  162. package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
  163. package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -73
  164. package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
  165. package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +56 -27
  166. package/templates/default/src/app/(base)/locators/page.tsx +13 -13
  167. package/templates/default/src/app/(base)/locators/picker/page.tsx +7 -0
  168. package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -66
  169. package/templates/default/src/app/(base)/modules/create/page.tsx +34 -34
  170. package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -46
  171. package/templates/default/src/app/(base)/modules/module-form.tsx +126 -126
  172. package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -85
  173. package/templates/default/src/app/(base)/modules/module-table.tsx +24 -24
  174. package/templates/default/src/app/(base)/modules/page.tsx +59 -59
  175. package/templates/default/src/app/(base)/reports/[id]/page.tsx +40 -33
  176. package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
  177. package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -78
  178. package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -46
  179. package/templates/default/src/app/(base)/reports/page.tsx +98 -98
  180. package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -16
  181. package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
  182. package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
  183. package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +12 -1
  184. package/templates/default/src/app/(base)/reports/report-view-table.tsx +1 -0
  185. package/templates/default/src/app/(base)/reports/test-cases/page.tsx +40 -42
  186. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
  187. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
  188. package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
  189. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
  190. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
  191. package/templates/default/src/app/(base)/reports/view-logs-button.tsx +58 -60
  192. package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -26
  193. package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -15
  194. package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -26
  195. package/templates/default/src/app/(base)/reviews/page.tsx +26 -26
  196. package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -26
  197. package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -11
  198. package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -9
  199. package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -9
  200. package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -15
  201. package/templates/default/src/app/(base)/settings/page.tsx +30 -0
  202. package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +261 -0
  203. package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
  204. package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
  205. package/templates/default/src/app/(base)/tags/page.tsx +58 -58
  206. package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -147
  207. package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
  208. package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
  209. package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
  210. package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -45
  211. package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
  212. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -167
  213. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
  214. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -32
  215. package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -37
  216. package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -49
  217. package/templates/default/src/app/(base)/template-steps/page.tsx +58 -58
  218. package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -213
  219. package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -384
  220. package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -158
  221. package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -24
  222. package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
  223. package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
  224. package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
  225. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -84
  226. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -262
  227. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
  228. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
  229. package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -76
  230. package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -96
  231. package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -38
  232. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -73
  233. package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
  234. package/templates/default/src/app/(base)/test-cases/page.tsx +2 -2
  235. package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -82
  236. package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -395
  237. package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +6 -71
  238. package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +2 -2
  239. package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +4 -1
  240. package/templates/default/src/app/(base)/test-runs/create/page.tsx +11 -9
  241. package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
  242. package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +37 -44
  243. package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
  244. package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
  245. package/templates/default/src/app/(base)/test-suites/create/page.tsx +3 -2
  246. package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +2 -1
  247. package/templates/default/src/app/(base)/test-suites/page.tsx +57 -21
  248. package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +16 -17
  249. package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +2 -1
  250. package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -29
  251. package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
  252. package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
  253. package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
  254. package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
  255. package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
  256. package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
  257. package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -0
  258. package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +97 -34
  259. package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +4 -1
  260. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -147
  261. package/templates/default/src/app/globals.css +147 -147
  262. package/templates/default/src/app/layout.tsx +4 -0
  263. package/templates/default/src/app/page.tsx +2 -0
  264. package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
  265. package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
  266. package/templates/default/src/components/base-node.tsx +21 -21
  267. package/templates/default/src/components/chart/pie-chart.tsx +73 -73
  268. package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -460
  269. package/templates/default/src/components/data-state/empty-state.tsx +40 -40
  270. package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
  271. package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
  272. package/templates/default/src/components/diagram/button-edge.tsx +54 -54
  273. package/templates/default/src/components/diagram/dynamic-parameters.tsx +474 -474
  274. package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
  275. package/templates/default/src/components/diagram/flow-diagram.tsx +470 -470
  276. package/templates/default/src/components/diagram/node-form.tsx +262 -262
  277. package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
  278. package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
  279. package/templates/default/src/components/form/error-message.tsx +7 -7
  280. package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
  281. package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
  282. package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
  283. package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
  284. package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
  285. package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
  286. package/templates/default/src/components/logo.tsx +15 -15
  287. package/templates/default/src/components/navigation/command-badge.tsx +34 -34
  288. package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
  289. package/templates/default/src/components/navigation/entity-search-command.tsx +116 -116
  290. package/templates/default/src/components/navigation/nav-card.tsx +31 -31
  291. package/templates/default/src/components/navigation/nav-command.tsx +13 -0
  292. package/templates/default/src/components/navigation/nav-link.tsx +60 -60
  293. package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
  294. package/templates/default/src/components/node-header.tsx +159 -159
  295. package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -253
  296. package/templates/default/src/components/table/table-actions.tsx +172 -172
  297. package/templates/default/src/components/test-case/test-case-columns.tsx +76 -0
  298. package/templates/default/src/components/test-case/test-case-picker.tsx +244 -0
  299. package/templates/default/src/components/test-run/download-logs-button.tsx +92 -99
  300. package/templates/default/src/components/test-run/log-viewer.tsx +1 -14
  301. package/templates/default/src/components/test-run/test-run-details.tsx +15 -2
  302. package/templates/default/src/components/test-run/test-run-header.tsx +149 -149
  303. package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
  304. package/templates/default/src/components/test-suite/test-suite-picker.tsx +444 -0
  305. package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
  306. package/templates/default/src/components/theme/theme-provider.tsx +8 -8
  307. package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
  308. package/templates/default/src/components/typography/page-header.tsx +7 -7
  309. package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
  310. package/templates/default/src/components/ui/alert.tsx +43 -43
  311. package/templates/default/src/components/ui/avatar.tsx +40 -40
  312. package/templates/default/src/components/ui/badge.tsx +29 -29
  313. package/templates/default/src/components/ui/button.tsx +47 -47
  314. package/templates/default/src/components/ui/calendar.tsx +158 -158
  315. package/templates/default/src/components/ui/card.tsx +43 -43
  316. package/templates/default/src/components/ui/checkbox.tsx +28 -28
  317. package/templates/default/src/components/ui/command.tsx +135 -135
  318. package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
  319. package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
  320. package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
  321. package/templates/default/src/components/ui/data-table.tsx +261 -261
  322. package/templates/default/src/components/ui/dialog.tsx +97 -97
  323. package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
  324. package/templates/default/src/components/ui/input.tsx +22 -22
  325. package/templates/default/src/components/ui/kbd.tsx +28 -28
  326. package/templates/default/src/components/ui/label.tsx +19 -19
  327. package/templates/default/src/components/ui/loading.tsx +12 -12
  328. package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
  329. package/templates/default/src/components/ui/multi-select.tsx +142 -142
  330. package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
  331. package/templates/default/src/components/ui/popover.tsx +33 -33
  332. package/templates/default/src/components/ui/progress.tsx +25 -25
  333. package/templates/default/src/components/ui/radio-group.tsx +44 -44
  334. package/templates/default/src/components/ui/scroll-area.tsx +40 -40
  335. package/templates/default/src/components/ui/select.tsx +151 -151
  336. package/templates/default/src/components/ui/separator.tsx +22 -22
  337. package/templates/default/src/components/ui/skeleton.tsx +7 -7
  338. package/templates/default/src/components/ui/table.tsx +76 -76
  339. package/templates/default/src/components/ui/tabs.tsx +55 -55
  340. package/templates/default/src/components/ui/textarea.tsx +21 -21
  341. package/templates/default/src/components/ui/toast.tsx +113 -113
  342. package/templates/default/src/components/ui/toaster.tsx +26 -26
  343. package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -87
  344. package/templates/default/src/config/db-config.ts +10 -10
  345. package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
  346. package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
  347. package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -20
  348. package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
  349. package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
  350. package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -23
  351. package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
  352. package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
  353. package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
  354. package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
  355. package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
  356. package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
  357. package/templates/default/src/constants/form-opts/test-run-form-opts.ts +5 -3
  358. package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
  359. package/templates/default/src/hooks/use-toast.ts +187 -187
  360. package/templates/default/src/lib/automation/paths.ts +42 -12
  361. package/templates/default/src/lib/automation/projection-service.ts +2 -1
  362. package/templates/default/src/lib/bidirectional-sync.ts +432 -432
  363. package/templates/default/src/lib/database-sync.ts +2 -7
  364. package/templates/default/src/lib/environment-file-utils.ts +184 -184
  365. package/templates/default/src/lib/executor/local-executor-adapter.ts +24 -25
  366. package/templates/default/src/lib/executor/types.ts +2 -2
  367. package/templates/default/src/lib/feature-file-generator.ts +5 -66
  368. package/templates/default/src/lib/gherkin-parser.ts +259 -259
  369. package/templates/default/src/lib/locator-group-file-utils.ts +307 -307
  370. package/templates/default/src/lib/locator-picker/session-manager.ts +452 -0
  371. package/templates/default/src/lib/locator-picker/suggestions.ts +124 -0
  372. package/templates/default/src/lib/metrics/metric-calculator.ts +5 -0
  373. package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
  374. package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
  375. package/templates/default/src/lib/process/task-spawner.ts +39 -2
  376. package/templates/default/src/lib/sync/projected-feature-utils.ts +113 -0
  377. package/templates/default/src/lib/sync/sync-executor.ts +130 -0
  378. package/templates/default/src/lib/sync/sync-pending-counts.test.ts +239 -0
  379. package/templates/default/src/lib/sync/sync-pending-counts.ts +1358 -0
  380. package/templates/default/src/lib/sync/sync-registry.ts +149 -0
  381. package/templates/default/src/lib/tag-utils.ts +28 -0
  382. package/templates/default/src/lib/template-sync-utils.d.ts +6 -6
  383. package/templates/default/src/lib/template-sync-utils.js +46 -46
  384. package/templates/default/src/lib/template-sync-utils.ts +63 -63
  385. package/templates/default/src/lib/test-case-utils.ts +6 -6
  386. package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
  387. package/templates/default/src/lib/test-run/matching.ts +117 -0
  388. package/templates/default/src/lib/test-run/process-manager.ts +2 -0
  389. package/templates/default/src/lib/test-run/report-parser.ts +352 -316
  390. package/templates/default/src/lib/test-run/test-run-executor.ts +13 -15
  391. package/templates/default/src/lib/test-run/winston-logger.ts +64 -66
  392. package/templates/default/src/lib/test-suite-identifier-service.ts +76 -0
  393. package/templates/default/src/lib/test-suite-utils.ts +6 -0
  394. package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
  395. package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
  396. package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
  397. package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
  398. package/templates/default/src/lib/utils/template-step-file-generator.ts +104 -104
  399. package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +0 -8
  400. package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
  401. package/templates/default/src/lib/utils.ts +31 -31
  402. package/templates/default/src/types/diagram/diagram.ts +34 -34
  403. package/templates/default/src/types/diagram/template-step.ts +11 -11
  404. package/templates/default/src/types/executor/browser.type.ts +1 -1
  405. package/templates/default/src/types/form/actionHandler.ts +6 -6
  406. package/templates/default/src/types/locator/locator.type.ts +11 -11
  407. package/templates/default/src/types/locator-picker.ts +65 -0
  408. package/templates/default/src/types/step/step.type.ts +1 -1
  409. package/templates/default/src/types/table/data-table.ts +6 -6
  410. package/templates/default/src/types/test-case-picker.ts +6 -0
  411. package/templates/default/src/types/test-suite-picker.ts +18 -0
  412. package/templates/default/tailwind.config.ts +62 -62
  413. package/templates/default/tsconfig.json +4 -1
  414. package/templates/default/appraisejs.config.json +0 -1
@@ -0,0 +1,615 @@
1
+ export function installLocatorPickerOverlay() {
2
+ var _a;
3
+ const globalState = window;
4
+ const ROOT_ID = 'appraise-locator-picker-root';
5
+ const STYLE_ID = 'appraise-locator-picker-style';
6
+ const HOVER_CLASS = 'appraise-locator-picker-hover';
7
+ const ACTIVE_CLASS = 'appraise-locator-picker-active';
8
+ const state = (_a = globalState.__appraiseLocatorPickerState) !== null && _a !== void 0 ? _a : (globalState.__appraiseLocatorPickerState = {
9
+ picking: false,
10
+ submitting: false,
11
+ hoveredElement: null,
12
+ preview: null,
13
+ error: '',
14
+ elements: {},
15
+ });
16
+ function stopOverlayEvent(event) {
17
+ event.preventDefault();
18
+ event.stopPropagation();
19
+ }
20
+ function normalizeText(value) {
21
+ return (value !== null && value !== void 0 ? value : '').replace(/\s+/g, ' ').trim();
22
+ }
23
+ function escapeForCss(value) {
24
+ return value.replace(/[^a-zA-Z0-9_-]/g, match => `\\${match}`);
25
+ }
26
+ function escapeForSelectorText(value) {
27
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
28
+ }
29
+ function normalizeRoute(value) {
30
+ if (!value) {
31
+ return '/';
32
+ }
33
+ try {
34
+ return new URL(value).pathname || '/';
35
+ }
36
+ catch (_a) {
37
+ return value.startsWith('/') ? value : `/${value}`;
38
+ }
39
+ }
40
+ function isLikelyStableIdentifier(value) {
41
+ if (!value) {
42
+ return false;
43
+ }
44
+ const normalized = value.trim();
45
+ if (!normalized || normalized.length > 120) {
46
+ return false;
47
+ }
48
+ return !/\d{4,}/.test(normalized) && !/[A-Fa-f0-9]{8,}/.test(normalized);
49
+ }
50
+ function isFormControl(element) {
51
+ return ['input', 'textarea', 'select'].includes(element.tagName.toLowerCase());
52
+ }
53
+ function getLabelText(element) {
54
+ if (!isFormControl(element)) {
55
+ return '';
56
+ }
57
+ const input = element;
58
+ if (input.labels && input.labels.length > 0) {
59
+ return normalizeText(Array.from(input.labels)
60
+ .map(label => label.textContent || '')
61
+ .join(' '));
62
+ }
63
+ return '';
64
+ }
65
+ function getAccessibleName(element) {
66
+ const ariaLabel = normalizeText(element.getAttribute('aria-label'));
67
+ if (ariaLabel) {
68
+ return ariaLabel;
69
+ }
70
+ const labelledBy = normalizeText(element.getAttribute('aria-labelledby'));
71
+ if (labelledBy) {
72
+ const text = labelledBy
73
+ .split(/\s+/)
74
+ .map(id => { var _a; return ((_a = document.getElementById(id)) === null || _a === void 0 ? void 0 : _a.textContent) || ''; })
75
+ .join(' ');
76
+ const normalized = normalizeText(text);
77
+ if (normalized) {
78
+ return normalized;
79
+ }
80
+ }
81
+ const labelText = getLabelText(element);
82
+ if (labelText) {
83
+ return labelText;
84
+ }
85
+ const alt = normalizeText(element.getAttribute('alt'));
86
+ if (alt) {
87
+ return alt;
88
+ }
89
+ const title = normalizeText(element.getAttribute('title'));
90
+ if (title) {
91
+ return title;
92
+ }
93
+ const placeholder = normalizeText(element.getAttribute('placeholder'));
94
+ if (placeholder) {
95
+ return placeholder;
96
+ }
97
+ return normalizeText(element.textContent).slice(0, 240);
98
+ }
99
+ function getRole(element) {
100
+ const explicitRole = normalizeText(element.getAttribute('role'));
101
+ if (explicitRole) {
102
+ return explicitRole;
103
+ }
104
+ const tagName = element.tagName.toLowerCase();
105
+ if (tagName === 'button') {
106
+ return 'button';
107
+ }
108
+ if (tagName === 'a' && element.hasAttribute('href')) {
109
+ return 'link';
110
+ }
111
+ if (tagName === 'textarea') {
112
+ return 'textbox';
113
+ }
114
+ if (tagName === 'select') {
115
+ return 'combobox';
116
+ }
117
+ if (tagName === 'img') {
118
+ return 'img';
119
+ }
120
+ if (tagName === 'input') {
121
+ const type = (element.getAttribute('type') || 'text').toLowerCase();
122
+ if (['button', 'submit', 'reset'].includes(type)) {
123
+ return 'button';
124
+ }
125
+ if (type === 'checkbox') {
126
+ return 'checkbox';
127
+ }
128
+ if (type === 'radio') {
129
+ return 'radio';
130
+ }
131
+ return 'textbox';
132
+ }
133
+ return '';
134
+ }
135
+ function countRoleNameMatches(role, accessibleName) {
136
+ let count = 0;
137
+ for (const candidate of Array.from(document.querySelectorAll('*'))) {
138
+ if (getRole(candidate) !== role) {
139
+ continue;
140
+ }
141
+ if (getAccessibleName(candidate) !== accessibleName) {
142
+ continue;
143
+ }
144
+ count += 1;
145
+ if (count > 1) {
146
+ break;
147
+ }
148
+ }
149
+ return count;
150
+ }
151
+ function buildCssSelector(element) {
152
+ const tagName = element.tagName.toLowerCase();
153
+ const name = element.getAttribute('name');
154
+ const type = element.getAttribute('type');
155
+ const ariaLabel = element.getAttribute('aria-label');
156
+ const parts = [tagName];
157
+ if (isLikelyStableIdentifier(name)) {
158
+ parts.push(`[name="${escapeForSelectorText(name)}"]`);
159
+ }
160
+ if (isLikelyStableIdentifier(type)) {
161
+ parts.push(`[type="${escapeForSelectorText(type)}"]`);
162
+ }
163
+ if (isLikelyStableIdentifier(ariaLabel)) {
164
+ parts.push(`[aria-label="${escapeForSelectorText(ariaLabel)}"]`);
165
+ }
166
+ if (parts.length === 1) {
167
+ const stableClasses = Array.from(element.classList || []).filter(isLikelyStableIdentifier).slice(0, 2);
168
+ if (stableClasses.length > 0) {
169
+ parts.push(...stableClasses.map(className => `.${escapeForCss(className)}`));
170
+ }
171
+ }
172
+ return parts.length > 1 ? `css=${parts.join('')}` : '';
173
+ }
174
+ function buildXPathSelector(element, text) {
175
+ const tagName = element.tagName.toLowerCase();
176
+ const id = element.getAttribute('id');
177
+ if (id) {
178
+ return `xpath=//*[@id="${id.replace(/"/g, '\\"')}"]`;
179
+ }
180
+ if (text) {
181
+ return `xpath=//${tagName}[normalize-space()="${text.replace(/"/g, '\\"')}"]`;
182
+ }
183
+ return `xpath=//${tagName}`;
184
+ }
185
+ function buildPrimarySelector(element) {
186
+ for (const attributeName of ['data-testid', 'data-test', 'data-qa']) {
187
+ const value = element.getAttribute(attributeName);
188
+ if (isLikelyStableIdentifier(value)) {
189
+ return {
190
+ selector: `css=[${attributeName}="${escapeForSelectorText(value)}"]`,
191
+ strategy: 'test-id',
192
+ };
193
+ }
194
+ }
195
+ const accessibleName = getAccessibleName(element);
196
+ const role = getRole(element);
197
+ if (role && accessibleName && countRoleNameMatches(role, accessibleName) === 1) {
198
+ return {
199
+ selector: `role=${role}[name="${escapeForSelectorText(accessibleName)}"]`,
200
+ strategy: 'role',
201
+ };
202
+ }
203
+ const labelText = getLabelText(element);
204
+ if (labelText) {
205
+ return {
206
+ selector: `label="${escapeForSelectorText(labelText)}"`,
207
+ strategy: 'label',
208
+ };
209
+ }
210
+ const placeholder = normalizeText(element.getAttribute('placeholder'));
211
+ if (placeholder) {
212
+ return {
213
+ selector: `placeholder="${escapeForSelectorText(placeholder)}"`,
214
+ strategy: 'placeholder',
215
+ };
216
+ }
217
+ const id = element.getAttribute('id');
218
+ if (isLikelyStableIdentifier(id)) {
219
+ return {
220
+ selector: `css=#${escapeForCss(id)}`,
221
+ strategy: 'id',
222
+ };
223
+ }
224
+ const cssSelector = buildCssSelector(element);
225
+ if (cssSelector) {
226
+ return {
227
+ selector: cssSelector,
228
+ strategy: 'css',
229
+ };
230
+ }
231
+ return {
232
+ selector: buildXPathSelector(element, normalizeText(element.textContent).slice(0, 120)),
233
+ strategy: 'xpath',
234
+ };
235
+ }
236
+ function buildPreviewPayload(element) {
237
+ const selection = buildPrimarySelector(element);
238
+ return {
239
+ selector: selection.selector,
240
+ strategy: selection.strategy,
241
+ currentUrl: window.location.href,
242
+ pathname: normalizeRoute(window.location.href),
243
+ pageTitle: document.title || '',
244
+ tagName: element.tagName.toLowerCase(),
245
+ text: normalizeText(element.textContent).slice(0, 240) || undefined,
246
+ accessibleName: getAccessibleName(element) || undefined,
247
+ };
248
+ }
249
+ function clearHover() {
250
+ if (state.hoveredElement instanceof Element) {
251
+ state.hoveredElement.classList.remove(HOVER_CLASS);
252
+ }
253
+ state.hoveredElement = null;
254
+ }
255
+ function setPicking(enabled) {
256
+ state.picking = enabled;
257
+ document.documentElement.classList.toggle(ACTIVE_CLASS, enabled);
258
+ if (!enabled) {
259
+ clearHover();
260
+ }
261
+ render();
262
+ }
263
+ function resolveElement(target) {
264
+ if (target instanceof Element) {
265
+ return target;
266
+ }
267
+ if (target instanceof Node) {
268
+ return target.parentElement;
269
+ }
270
+ return null;
271
+ }
272
+ function getMountTarget() {
273
+ var _a, _b;
274
+ return (_b = (_a = document.body) !== null && _a !== void 0 ? _a : document.documentElement) !== null && _b !== void 0 ? _b : null;
275
+ }
276
+ function ensureStyle() {
277
+ if (!document.documentElement) {
278
+ return;
279
+ }
280
+ if (document.getElementById(STYLE_ID)) {
281
+ return;
282
+ }
283
+ const style = document.createElement('style');
284
+ style.id = STYLE_ID;
285
+ style.textContent = `
286
+ .${HOVER_CLASS} {
287
+ outline: 2px solid #0f766e !important;
288
+ outline-offset: 2px !important;
289
+ background-color: rgba(15, 118, 110, 0.12) !important;
290
+ cursor: crosshair !important;
291
+ }
292
+
293
+ html.${ACTIVE_CLASS},
294
+ html.${ACTIVE_CLASS} * {
295
+ cursor: crosshair !important;
296
+ }
297
+
298
+ #${ROOT_ID} {
299
+ position: fixed;
300
+ right: 20px;
301
+ bottom: 20px;
302
+ z-index: 2147483647;
303
+ width: min(360px, calc(100vw - 32px));
304
+ padding: 16px;
305
+ border-radius: 18px;
306
+ border: 1px solid rgba(15, 23, 42, 0.14);
307
+ background: rgba(255, 255, 255, 0.96);
308
+ box-shadow: 0 18px 40px rgba(15, 23, 42, 0.18);
309
+ backdrop-filter: blur(12px);
310
+ color: #0f172a;
311
+ font-family: "Segoe UI", "Helvetica Neue", sans-serif;
312
+ }
313
+
314
+ #${ROOT_ID} * {
315
+ box-sizing: border-box;
316
+ font-family: inherit;
317
+ }
318
+
319
+ #${ROOT_ID} .appraise-picker-heading {
320
+ margin: 0 0 6px;
321
+ font-size: 15px;
322
+ font-weight: 700;
323
+ }
324
+
325
+ #${ROOT_ID} .appraise-picker-copy {
326
+ margin: 0;
327
+ color: #475569;
328
+ font-size: 12px;
329
+ line-height: 1.45;
330
+ }
331
+
332
+ #${ROOT_ID} .appraise-picker-status {
333
+ margin: 10px 0 0;
334
+ color: #0f766e;
335
+ font-size: 12px;
336
+ font-weight: 600;
337
+ }
338
+
339
+ #${ROOT_ID} .appraise-picker-card {
340
+ margin-top: 14px;
341
+ padding: 12px;
342
+ border-radius: 14px;
343
+ background: #f8fafc;
344
+ border: 1px solid rgba(148, 163, 184, 0.25);
345
+ }
346
+
347
+ #${ROOT_ID} .appraise-picker-label {
348
+ display: block;
349
+ margin-bottom: 6px;
350
+ color: #334155;
351
+ font-size: 11px;
352
+ font-weight: 700;
353
+ letter-spacing: 0.04em;
354
+ text-transform: uppercase;
355
+ }
356
+
357
+ #${ROOT_ID} .appraise-picker-value {
358
+ margin: 0;
359
+ color: #0f172a;
360
+ font-size: 12px;
361
+ line-height: 1.5;
362
+ white-space: pre-wrap;
363
+ word-break: break-word;
364
+ }
365
+
366
+ #${ROOT_ID} .appraise-picker-actions {
367
+ display: flex;
368
+ flex-wrap: wrap;
369
+ gap: 8px;
370
+ margin-top: 14px;
371
+ }
372
+
373
+ #${ROOT_ID} button {
374
+ border: none;
375
+ border-radius: 999px;
376
+ padding: 10px 14px;
377
+ font-size: 12px;
378
+ font-weight: 700;
379
+ cursor: pointer;
380
+ }
381
+
382
+ #${ROOT_ID} button:disabled {
383
+ cursor: not-allowed;
384
+ opacity: 0.6;
385
+ }
386
+
387
+ #${ROOT_ID} .appraise-picker-primary {
388
+ background: #0f766e;
389
+ color: #ffffff;
390
+ }
391
+
392
+ #${ROOT_ID} .appraise-picker-secondary {
393
+ background: #e2e8f0;
394
+ color: #0f172a;
395
+ }
396
+
397
+ #${ROOT_ID} .appraise-picker-error {
398
+ margin: 10px 0 0;
399
+ color: #b91c1c;
400
+ font-size: 12px;
401
+ line-height: 1.4;
402
+ }
403
+ `;
404
+ document.documentElement.appendChild(style);
405
+ }
406
+ function ensureRoot() {
407
+ var _a;
408
+ const mountTarget = getMountTarget();
409
+ if (!mountTarget) {
410
+ return;
411
+ }
412
+ if ((_a = state.elements.root) === null || _a === void 0 ? void 0 : _a.isConnected) {
413
+ return;
414
+ }
415
+ const root = document.createElement('div');
416
+ root.id = ROOT_ID;
417
+ root.setAttribute('role', 'dialog');
418
+ root.setAttribute('aria-label', 'Appraise locator picker');
419
+ const heading = document.createElement('p');
420
+ heading.className = 'appraise-picker-heading';
421
+ heading.textContent = 'Appraise Locator Picker';
422
+ const helperText = document.createElement('p');
423
+ helperText.className = 'appraise-picker-copy';
424
+ const statusText = document.createElement('p');
425
+ statusText.className = 'appraise-picker-status';
426
+ const previewCard = document.createElement('div');
427
+ previewCard.className = 'appraise-picker-card';
428
+ const selectorLabel = document.createElement('span');
429
+ selectorLabel.className = 'appraise-picker-label';
430
+ selectorLabel.textContent = 'Selector';
431
+ const selectorValue = document.createElement('pre');
432
+ selectorValue.className = 'appraise-picker-value';
433
+ const metadataLabel = document.createElement('span');
434
+ metadataLabel.className = 'appraise-picker-label';
435
+ metadataLabel.textContent = 'Page';
436
+ const metadataValue = document.createElement('p');
437
+ metadataValue.className = 'appraise-picker-value';
438
+ previewCard.appendChild(selectorLabel);
439
+ previewCard.appendChild(selectorValue);
440
+ previewCard.appendChild(metadataLabel);
441
+ previewCard.appendChild(metadataValue);
442
+ const errorValue = document.createElement('p');
443
+ errorValue.className = 'appraise-picker-error';
444
+ const actions = document.createElement('div');
445
+ actions.className = 'appraise-picker-actions';
446
+ const startButton = document.createElement('button');
447
+ startButton.className = 'appraise-picker-primary';
448
+ startButton.type = 'button';
449
+ startButton.textContent = 'Start picking';
450
+ startButton.addEventListener('click', event => {
451
+ stopOverlayEvent(event);
452
+ state.submitting = false;
453
+ state.preview = null;
454
+ state.error = '';
455
+ setPicking(true);
456
+ });
457
+ const useButton = document.createElement('button');
458
+ useButton.className = 'appraise-picker-primary';
459
+ useButton.type = 'button';
460
+ useButton.textContent = 'Use selector';
461
+ useButton.addEventListener('click', event => {
462
+ stopOverlayEvent(event);
463
+ if (!state.preview || state.submitting || !globalState.__appraiseLocatorPickerConfirm) {
464
+ return;
465
+ }
466
+ state.submitting = true;
467
+ state.error = '';
468
+ render();
469
+ void globalState
470
+ .__appraiseLocatorPickerConfirm(state.preview)
471
+ .catch(error => {
472
+ state.error = error instanceof Error ? error.message : 'Unable to use selector.';
473
+ })
474
+ .finally(() => {
475
+ state.submitting = false;
476
+ render();
477
+ });
478
+ });
479
+ const pickAgainButton = document.createElement('button');
480
+ pickAgainButton.className = 'appraise-picker-secondary';
481
+ pickAgainButton.type = 'button';
482
+ pickAgainButton.textContent = 'Pick again';
483
+ pickAgainButton.addEventListener('click', event => {
484
+ stopOverlayEvent(event);
485
+ state.submitting = false;
486
+ state.preview = null;
487
+ state.error = '';
488
+ setPicking(true);
489
+ });
490
+ const cancelButton = document.createElement('button');
491
+ cancelButton.className = 'appraise-picker-secondary';
492
+ cancelButton.type = 'button';
493
+ cancelButton.textContent = 'Cancel';
494
+ cancelButton.addEventListener('click', event => {
495
+ stopOverlayEvent(event);
496
+ if (state.submitting || !globalState.__appraiseLocatorPickerCancel) {
497
+ return;
498
+ }
499
+ state.submitting = true;
500
+ render();
501
+ void globalState.__appraiseLocatorPickerCancel().catch(() => undefined);
502
+ });
503
+ actions.append(startButton, useButton, pickAgainButton, cancelButton);
504
+ root.append(heading, helperText, statusText, previewCard, errorValue, actions);
505
+ root.addEventListener('pointerdown', event => event.stopPropagation());
506
+ root.addEventListener('click', event => event.stopPropagation());
507
+ mountTarget.appendChild(root);
508
+ state.elements = {
509
+ root,
510
+ startButton,
511
+ useButton,
512
+ pickAgainButton,
513
+ cancelButton,
514
+ helperText,
515
+ statusText,
516
+ selectorValue,
517
+ metadataValue,
518
+ errorValue,
519
+ };
520
+ }
521
+ function render() {
522
+ var _a, _b;
523
+ ensureStyle();
524
+ ensureRoot();
525
+ document.documentElement.classList.toggle(ACTIVE_CLASS, state.picking);
526
+ if (state.hoveredElement && !state.hoveredElement.isConnected) {
527
+ state.hoveredElement = null;
528
+ }
529
+ const { helperText, statusText, selectorValue, metadataValue, errorValue, startButton, useButton, pickAgainButton, cancelButton } = state.elements;
530
+ if (!helperText || !statusText || !selectorValue || !metadataValue || !errorValue || !startButton || !useButton || !pickAgainButton || !cancelButton) {
531
+ return;
532
+ }
533
+ helperText.textContent = state.preview
534
+ ? 'Review the generated selector, then confirm it or pick a different element.'
535
+ : 'Start picking, hover to highlight, then click one element to preview a single generated selector.';
536
+ if (state.picking) {
537
+ statusText.textContent = 'Picking mode is on';
538
+ }
539
+ else if (state.preview) {
540
+ statusText.textContent = 'Selection ready';
541
+ }
542
+ else {
543
+ statusText.textContent = 'Waiting to start';
544
+ }
545
+ selectorValue.textContent = (_b = (_a = state.preview) === null || _a === void 0 ? void 0 : _a.selector) !== null && _b !== void 0 ? _b : 'No selector picked yet.';
546
+ metadataValue.textContent = state.preview
547
+ ? [state.preview.pageTitle || '(untitled page)', state.preview.currentUrl].filter(Boolean).join('\n')
548
+ : 'The selected page metadata will appear here.';
549
+ errorValue.textContent = state.error;
550
+ startButton.style.display = state.preview ? 'none' : 'inline-flex';
551
+ useButton.style.display = state.preview ? 'inline-flex' : 'none';
552
+ pickAgainButton.style.display = state.preview ? 'inline-flex' : 'none';
553
+ useButton.disabled = !state.preview || state.submitting;
554
+ pickAgainButton.disabled = state.submitting;
555
+ cancelButton.disabled = state.submitting;
556
+ }
557
+ function installOrRender() {
558
+ render();
559
+ }
560
+ if (!globalState.__appraiseLocatorPickerDomListenersBound) {
561
+ globalState.__appraiseLocatorPickerDomListenersBound = true;
562
+ document.addEventListener('DOMContentLoaded', installOrRender);
563
+ window.addEventListener('load', installOrRender);
564
+ }
565
+ if (globalState.__appraiseLocatorPickerInstalled) {
566
+ installOrRender();
567
+ return;
568
+ }
569
+ globalState.__appraiseLocatorPickerInstalled = true;
570
+ document.addEventListener('mouseover', event => {
571
+ if (!state.picking) {
572
+ return;
573
+ }
574
+ const target = resolveElement(event.target);
575
+ if (!target || target.closest(`#${ROOT_ID}`)) {
576
+ return;
577
+ }
578
+ clearHover();
579
+ target.classList.add(HOVER_CLASS);
580
+ state.hoveredElement = target;
581
+ }, true);
582
+ document.addEventListener('mouseout', event => {
583
+ if (!state.picking) {
584
+ return;
585
+ }
586
+ const target = resolveElement(event.target);
587
+ if (target instanceof Element) {
588
+ target.classList.remove(HOVER_CLASS);
589
+ }
590
+ }, true);
591
+ document.addEventListener('click', event => {
592
+ if (!state.picking) {
593
+ return;
594
+ }
595
+ const target = resolveElement(event.target);
596
+ if (!target || target.closest(`#${ROOT_ID}`)) {
597
+ return;
598
+ }
599
+ event.preventDefault();
600
+ event.stopPropagation();
601
+ event.stopImmediatePropagation();
602
+ void Promise.resolve()
603
+ .then(() => {
604
+ const preview = buildPreviewPayload(target);
605
+ state.preview = preview;
606
+ state.error = '';
607
+ setPicking(false);
608
+ })
609
+ .catch(error => {
610
+ state.error = error instanceof Error ? error.message : 'Unable to inspect that element.';
611
+ setPicking(false);
612
+ });
613
+ }, true);
614
+ installOrRender();
615
+ }
@@ -0,0 +1,11 @@
1
+ export declare function getLocatorPickerCompanionPaths(repoRoot?: string): {
2
+ packageRoot: string;
3
+ sourceRoot: string;
4
+ distCliPath: string;
5
+ tsconfigPath: string;
6
+ tscCliPath: string;
7
+ };
8
+ export declare function resolveLocatorPickerCompanionInvocation(cliArgs: string[], repoRoot?: string): Promise<{
9
+ command: string;
10
+ args: string[];
11
+ }>;
@@ -0,0 +1,59 @@
1
+ import { access, readdir, stat } from 'fs/promises';
2
+ import { execa } from 'execa';
3
+ import path from 'path';
4
+ async function pathExists(targetPath) {
5
+ try {
6
+ await access(targetPath);
7
+ return true;
8
+ }
9
+ catch (_a) {
10
+ return false;
11
+ }
12
+ }
13
+ async function getLatestModifiedTime(targetPath) {
14
+ const stats = await stat(targetPath);
15
+ if (!stats.isDirectory()) {
16
+ return stats.mtimeMs;
17
+ }
18
+ const entries = await readdir(targetPath, { withFileTypes: true });
19
+ const times = await Promise.all(entries.map(entry => getLatestModifiedTime(path.join(targetPath, entry.name))));
20
+ return Math.max(stats.mtimeMs, ...times);
21
+ }
22
+ export function getLocatorPickerCompanionPaths(repoRoot = process.cwd()) {
23
+ const packageRoot = path.join(repoRoot, 'packages', 'locator-picker-companion');
24
+ return {
25
+ packageRoot,
26
+ sourceRoot: path.join(packageRoot, 'src'),
27
+ distCliPath: path.join(packageRoot, 'dist', 'cli.js'),
28
+ tsconfigPath: path.join(packageRoot, 'tsconfig.json'),
29
+ tscCliPath: path.join(repoRoot, 'node_modules', 'typescript', 'bin', 'tsc'),
30
+ };
31
+ }
32
+ async function ensureLocatorPickerCompanionBuilt(repoRoot = process.cwd()) {
33
+ const { distCliPath, sourceRoot, tsconfigPath, tscCliPath } = getLocatorPickerCompanionPaths(repoRoot);
34
+ if (await pathExists(distCliPath)) {
35
+ const [distMtime, srcMtime] = await Promise.all([
36
+ getLatestModifiedTime(distCliPath),
37
+ getLatestModifiedTime(sourceRoot),
38
+ ]);
39
+ if (distMtime >= srcMtime) {
40
+ return distCliPath;
41
+ }
42
+ }
43
+ await execa(process.execPath, [tscCliPath, '-p', tsconfigPath], {
44
+ cwd: repoRoot,
45
+ env: process.env,
46
+ stdio: 'pipe',
47
+ });
48
+ if (!(await pathExists(distCliPath))) {
49
+ throw new Error('Locator picker companion build completed without producing dist/cli.js.');
50
+ }
51
+ return distCliPath;
52
+ }
53
+ export async function resolveLocatorPickerCompanionInvocation(cliArgs, repoRoot = process.cwd()) {
54
+ const distCliPath = await ensureLocatorPickerCompanionBuilt(repoRoot);
55
+ return {
56
+ command: process.execPath,
57
+ args: [distCliPath, ...cliArgs],
58
+ };
59
+ }
@@ -0,0 +1,3 @@
1
+ import type { ElementHandle, Page } from 'playwright';
2
+ import type { CompanionPickedLocatorPayload } from './types.js';
3
+ export declare function generatePickedLocatorPayload(page: Page, elementHandle: ElementHandle): Promise<CompanionPickedLocatorPayload>;