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,257 @@
1
+ function normalizeText(value) {
2
+ return (value !== null && value !== void 0 ? value : '').replace(/\s+/g, ' ').trim();
3
+ }
4
+ function normalizeRoute(value) {
5
+ if (!value) {
6
+ return '/';
7
+ }
8
+ try {
9
+ return new URL(value).pathname || '/';
10
+ }
11
+ catch (_a) {
12
+ return value.startsWith('/') ? value : `/${value}`;
13
+ }
14
+ }
15
+ function escapeForCss(value) {
16
+ return value.replace(/[^a-zA-Z0-9_-]/g, match => `\\${match}`);
17
+ }
18
+ function escapeForSelectorText(value) {
19
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
20
+ }
21
+ function isLikelyStableIdentifier(value) {
22
+ if (!value) {
23
+ return false;
24
+ }
25
+ const normalized = value.trim();
26
+ if (!normalized || normalized.length > 120) {
27
+ return false;
28
+ }
29
+ return !/\d{4,}/.test(normalized) && !/[A-Fa-f0-9]{8,}/.test(normalized);
30
+ }
31
+ function buildCssSelector(snapshot) {
32
+ const parts = [snapshot.tagName];
33
+ if (isLikelyStableIdentifier(snapshot.nameAttribute)) {
34
+ parts.push(`[name="${escapeForSelectorText(snapshot.nameAttribute)}"]`);
35
+ }
36
+ if (isLikelyStableIdentifier(snapshot.typeAttribute)) {
37
+ parts.push(`[type="${escapeForSelectorText(snapshot.typeAttribute)}"]`);
38
+ }
39
+ if (isLikelyStableIdentifier(snapshot.ariaLabel)) {
40
+ parts.push(`[aria-label="${escapeForSelectorText(snapshot.ariaLabel)}"]`);
41
+ }
42
+ if (parts.length === 1 && snapshot.stableClasses.length > 0) {
43
+ parts.push(...snapshot.stableClasses.slice(0, 2).map(className => `.${escapeForCss(className)}`));
44
+ }
45
+ return parts.length > 1 ? `css=${parts.join('')}` : '';
46
+ }
47
+ function buildXPathSelector(snapshot) {
48
+ if (snapshot.id) {
49
+ return `xpath=//*[@id="${snapshot.id.replace(/"/g, '\\"')}"]`;
50
+ }
51
+ if (snapshot.text) {
52
+ return `xpath=//${snapshot.tagName}[normalize-space()="${snapshot.text.replace(/"/g, '\\"')}"]`;
53
+ }
54
+ return `xpath=//${snapshot.tagName}`;
55
+ }
56
+ function buildPrimarySelector(snapshot) {
57
+ if (isLikelyStableIdentifier(snapshot.testAttributeValue)) {
58
+ return {
59
+ selector: `css=[${snapshot.testAttributeName}="${escapeForSelectorText(snapshot.testAttributeValue)}"]`,
60
+ strategy: 'test-id',
61
+ };
62
+ }
63
+ if (snapshot.role && snapshot.accessibleName && snapshot.roleNameMatchCount === 1) {
64
+ return {
65
+ selector: `role=${snapshot.role}[name="${escapeForSelectorText(snapshot.accessibleName)}"]`,
66
+ strategy: 'role',
67
+ };
68
+ }
69
+ if (snapshot.labelText) {
70
+ return {
71
+ selector: `label="${escapeForSelectorText(snapshot.labelText)}"`,
72
+ strategy: 'label',
73
+ };
74
+ }
75
+ if (snapshot.placeholder) {
76
+ return {
77
+ selector: `placeholder="${escapeForSelectorText(snapshot.placeholder)}"`,
78
+ strategy: 'placeholder',
79
+ };
80
+ }
81
+ if (isLikelyStableIdentifier(snapshot.id)) {
82
+ return {
83
+ selector: `css=#${escapeForCss(snapshot.id)}`,
84
+ strategy: 'id',
85
+ };
86
+ }
87
+ const cssSelector = buildCssSelector(snapshot);
88
+ if (cssSelector) {
89
+ return {
90
+ selector: cssSelector,
91
+ strategy: 'css',
92
+ };
93
+ }
94
+ return {
95
+ selector: buildXPathSelector(snapshot),
96
+ strategy: 'xpath',
97
+ };
98
+ }
99
+ async function getElementSnapshot(elementHandle) {
100
+ return elementHandle.evaluate(node => {
101
+ const element = node;
102
+ const normalizeText = (value) => (value !== null && value !== void 0 ? value : '').replace(/\s+/g, ' ').trim();
103
+ const isLikelyStableIdentifier = (value) => {
104
+ if (!value) {
105
+ return false;
106
+ }
107
+ const normalized = value.trim();
108
+ if (!normalized || normalized.length > 120) {
109
+ return false;
110
+ }
111
+ return !/\d{4,}/.test(normalized) && !/[A-Fa-f0-9]{8,}/.test(normalized);
112
+ };
113
+ const getLabelText = (candidate) => {
114
+ if (!['input', 'textarea', 'select'].includes(candidate.tagName.toLowerCase())) {
115
+ return '';
116
+ }
117
+ const input = candidate;
118
+ if (input.labels && input.labels.length > 0) {
119
+ return normalizeText(Array.from(input.labels)
120
+ .map(label => label.textContent || '')
121
+ .join(' '));
122
+ }
123
+ return '';
124
+ };
125
+ const getAccessibleName = (candidate) => {
126
+ const ariaLabel = normalizeText(candidate.getAttribute('aria-label'));
127
+ if (ariaLabel) {
128
+ return ariaLabel;
129
+ }
130
+ const labelledBy = normalizeText(candidate.getAttribute('aria-labelledby'));
131
+ if (labelledBy) {
132
+ const text = labelledBy
133
+ .split(/\s+/)
134
+ .map(id => { var _a; return ((_a = document.getElementById(id)) === null || _a === void 0 ? void 0 : _a.textContent) || ''; })
135
+ .join(' ');
136
+ const normalized = normalizeText(text);
137
+ if (normalized) {
138
+ return normalized;
139
+ }
140
+ }
141
+ const labelText = getLabelText(candidate);
142
+ if (labelText) {
143
+ return labelText;
144
+ }
145
+ const alt = normalizeText(candidate.getAttribute('alt'));
146
+ if (alt) {
147
+ return alt;
148
+ }
149
+ const title = normalizeText(candidate.getAttribute('title'));
150
+ if (title) {
151
+ return title;
152
+ }
153
+ const placeholder = normalizeText(candidate.getAttribute('placeholder'));
154
+ if (placeholder) {
155
+ return placeholder;
156
+ }
157
+ return normalizeText(candidate.textContent).slice(0, 240);
158
+ };
159
+ const getRole = (candidate) => {
160
+ const explicitRole = normalizeText(candidate.getAttribute('role'));
161
+ if (explicitRole) {
162
+ return explicitRole;
163
+ }
164
+ const tagName = candidate.tagName.toLowerCase();
165
+ if (tagName === 'button') {
166
+ return 'button';
167
+ }
168
+ if (tagName === 'a' && candidate.hasAttribute('href')) {
169
+ return 'link';
170
+ }
171
+ if (tagName === 'textarea') {
172
+ return 'textbox';
173
+ }
174
+ if (tagName === 'select') {
175
+ return 'combobox';
176
+ }
177
+ if (tagName === 'img') {
178
+ return 'img';
179
+ }
180
+ if (tagName === 'input') {
181
+ const type = (candidate.getAttribute('type') || 'text').toLowerCase();
182
+ if (['button', 'submit', 'reset'].includes(type)) {
183
+ return 'button';
184
+ }
185
+ if (type === 'checkbox') {
186
+ return 'checkbox';
187
+ }
188
+ if (type === 'radio') {
189
+ return 'radio';
190
+ }
191
+ return 'textbox';
192
+ }
193
+ return '';
194
+ };
195
+ const role = getRole(element);
196
+ const accessibleName = getAccessibleName(element);
197
+ let roleNameMatchCount = 0;
198
+ if (role && accessibleName) {
199
+ for (const candidate of Array.from(document.querySelectorAll('*'))) {
200
+ if (getRole(candidate) !== role) {
201
+ continue;
202
+ }
203
+ if (getAccessibleName(candidate) !== accessibleName) {
204
+ continue;
205
+ }
206
+ roleNameMatchCount += 1;
207
+ if (roleNameMatchCount > 1) {
208
+ break;
209
+ }
210
+ }
211
+ }
212
+ let testAttributeName = '';
213
+ let testAttributeValue = '';
214
+ for (const attributeName of ['data-testid', 'data-test', 'data-qa']) {
215
+ const value = element.getAttribute(attributeName);
216
+ if (isLikelyStableIdentifier(value)) {
217
+ testAttributeName = attributeName;
218
+ testAttributeValue = value;
219
+ break;
220
+ }
221
+ }
222
+ return {
223
+ tagName: element.tagName.toLowerCase(),
224
+ text: normalizeText(element.textContent).slice(0, 240),
225
+ accessibleName,
226
+ labelText: getLabelText(element),
227
+ placeholder: normalizeText(element.getAttribute('placeholder')),
228
+ id: normalizeText(element.getAttribute('id')),
229
+ role,
230
+ roleNameMatchCount,
231
+ stableClasses: Array.from(element.classList || [])
232
+ .filter((className) => isLikelyStableIdentifier(className))
233
+ .slice(0, 2),
234
+ nameAttribute: normalizeText(element.getAttribute('name')),
235
+ typeAttribute: normalizeText(element.getAttribute('type')),
236
+ ariaLabel: normalizeText(element.getAttribute('aria-label')),
237
+ testAttributeName,
238
+ testAttributeValue,
239
+ };
240
+ });
241
+ }
242
+ export async function generatePickedLocatorPayload(page, elementHandle) {
243
+ const snapshot = await getElementSnapshot(elementHandle);
244
+ const selection = buildPrimarySelector(snapshot);
245
+ const currentUrl = page.url();
246
+ const pageTitle = normalizeText(await page.title().catch(() => ''));
247
+ return {
248
+ selector: selection.selector,
249
+ strategy: selection.strategy,
250
+ currentUrl,
251
+ pathname: normalizeRoute(currentUrl),
252
+ pageTitle,
253
+ tagName: snapshot.tagName,
254
+ text: snapshot.text || undefined,
255
+ accessibleName: snapshot.accessibleName || undefined,
256
+ };
257
+ }
@@ -0,0 +1,22 @@
1
+ import type { CompanionSessionFile } from './types.js';
2
+ export declare function getLocatorPickerRootDir(repoRoot?: string): string;
3
+ export declare function getLocatorPickerSessionsDir(repoRoot?: string): string;
4
+ export declare function getLocatorPickerProfilesDir(repoRoot?: string): string;
5
+ export declare function getLocatorPickerLogsDir(repoRoot?: string): string;
6
+ export declare function getLocatorPickerProfileDir(sessionId: string, repoRoot?: string): string;
7
+ export declare function getLocatorPickerRuntimeDir(repoRoot?: string): string;
8
+ export declare function getLocatorPickerRuntimeHomeDir(repoRoot?: string): string;
9
+ export declare function getLocatorPickerRuntimeEnv(repoRoot?: string, baseEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
10
+ export declare function getLocatorPickerSessionFilePath(sessionId: string, repoRoot?: string): string;
11
+ export declare function getLocatorPickerCrashLogPath(sessionId: string, repoRoot?: string): string;
12
+ export declare function removeLocatorPickerProfileDir(sessionId: string, repoRoot?: string): Promise<void>;
13
+ export declare function removeLocatorPickerSessionFile(sessionId: string, repoRoot?: string): Promise<void>;
14
+ export declare function clearLocatorPickerCrashLogs(repoRoot?: string): Promise<void>;
15
+ export declare function createLocatorPickerCrashLog(logFilePath: string): Promise<void>;
16
+ export declare function appendLocatorPickerCrashLog(logFilePath: string, message: string): Promise<void>;
17
+ export declare function ensureLocatorPickerDirectories(repoRoot?: string): Promise<void>;
18
+ export declare function readLocatorPickerSessionFile(sessionFilePath: string): Promise<CompanionSessionFile | null>;
19
+ export declare function writeLocatorPickerSessionFile(sessionFilePath: string, session: Omit<CompanionSessionFile, 'updatedAt'> & {
20
+ updatedAt?: string;
21
+ }): Promise<CompanionSessionFile>;
22
+ export declare function patchLocatorPickerSessionFile(sessionFilePath: string, patch: Partial<CompanionSessionFile> | ((current: CompanionSessionFile) => Partial<CompanionSessionFile> | CompanionSessionFile)): Promise<CompanionSessionFile | null>;
@@ -0,0 +1,150 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { access, appendFile, mkdir, readFile, rename, rm, unlink, writeFile } from 'fs/promises';
3
+ import path from 'path';
4
+ const sessionFileOperationQueue = new Map();
5
+ function withTimestamp(session) {
6
+ var _a;
7
+ return Object.assign(Object.assign({}, session), { updatedAt: (_a = session.updatedAt) !== null && _a !== void 0 ? _a : new Date().toISOString() });
8
+ }
9
+ export function getLocatorPickerRootDir(repoRoot = process.cwd()) {
10
+ return path.join(repoRoot, '.tmp', 'locator-picker');
11
+ }
12
+ export function getLocatorPickerSessionsDir(repoRoot = process.cwd()) {
13
+ return path.join(getLocatorPickerRootDir(repoRoot), 'sessions');
14
+ }
15
+ export function getLocatorPickerProfilesDir(repoRoot = process.cwd()) {
16
+ return path.join(getLocatorPickerRootDir(repoRoot), 'profiles');
17
+ }
18
+ export function getLocatorPickerLogsDir(repoRoot = process.cwd()) {
19
+ return path.join(getLocatorPickerRootDir(repoRoot), 'logs');
20
+ }
21
+ export function getLocatorPickerProfileDir(sessionId, repoRoot = process.cwd()) {
22
+ return path.join(getLocatorPickerProfilesDir(repoRoot), sessionId);
23
+ }
24
+ export function getLocatorPickerRuntimeDir(repoRoot = process.cwd()) {
25
+ return path.join(getLocatorPickerRootDir(repoRoot), 'runtime');
26
+ }
27
+ export function getLocatorPickerRuntimeHomeDir(repoRoot = process.cwd()) {
28
+ return path.join(getLocatorPickerRuntimeDir(repoRoot), 'home');
29
+ }
30
+ export function getLocatorPickerRuntimeEnv(repoRoot = process.cwd(), baseEnv = process.env) {
31
+ const runtimeDir = getLocatorPickerRuntimeDir(repoRoot);
32
+ const runtimeHomeDir = getLocatorPickerRuntimeHomeDir(repoRoot);
33
+ const tempDir = path.join(runtimeDir, 'tmp');
34
+ const configDir = path.join(runtimeDir, 'config');
35
+ const cacheDir = path.join(runtimeDir, 'cache');
36
+ const appDataDir = path.join(runtimeDir, 'appdata');
37
+ const localAppDataDir = path.join(runtimeDir, 'localappdata');
38
+ return Object.assign(Object.assign({}, baseEnv), { HOME: runtimeHomeDir, USERPROFILE: runtimeHomeDir, APPDATA: appDataDir, LOCALAPPDATA: localAppDataDir, XDG_CONFIG_HOME: configDir, XDG_CACHE_HOME: cacheDir, TMPDIR: tempDir, TMP: tempDir, TEMP: tempDir });
39
+ }
40
+ export function getLocatorPickerSessionFilePath(sessionId, repoRoot = process.cwd()) {
41
+ return path.join(getLocatorPickerSessionsDir(repoRoot), `${sessionId}.json`);
42
+ }
43
+ export function getLocatorPickerCrashLogPath(sessionId, repoRoot = process.cwd()) {
44
+ return path.join(getLocatorPickerLogsDir(repoRoot), `${sessionId}.log`);
45
+ }
46
+ export async function removeLocatorPickerProfileDir(sessionId, repoRoot = process.cwd()) {
47
+ await rm(getLocatorPickerProfileDir(sessionId, repoRoot), {
48
+ force: true,
49
+ recursive: true,
50
+ }).catch(() => undefined);
51
+ }
52
+ export async function removeLocatorPickerSessionFile(sessionId, repoRoot = process.cwd()) {
53
+ await unlink(getLocatorPickerSessionFilePath(sessionId, repoRoot)).catch(() => undefined);
54
+ }
55
+ export async function clearLocatorPickerCrashLogs(repoRoot = process.cwd()) {
56
+ await rm(getLocatorPickerLogsDir(repoRoot), {
57
+ force: true,
58
+ recursive: true,
59
+ }).catch(() => console.error('Failed to clear locator picker crash logs.'));
60
+ await mkdir(getLocatorPickerLogsDir(repoRoot), { recursive: true });
61
+ }
62
+ export async function createLocatorPickerCrashLog(logFilePath) {
63
+ await mkdir(path.dirname(logFilePath), { recursive: true });
64
+ await writeFile(logFilePath, '', 'utf8');
65
+ }
66
+ export async function appendLocatorPickerCrashLog(logFilePath, message) {
67
+ try {
68
+ await access(logFilePath);
69
+ }
70
+ catch (_a) {
71
+ return;
72
+ }
73
+ await appendFile(logFilePath, `[${new Date().toISOString()}] ${message}\n`, 'utf8');
74
+ }
75
+ export async function ensureLocatorPickerDirectories(repoRoot = process.cwd()) {
76
+ const runtimeDir = getLocatorPickerRuntimeDir(repoRoot);
77
+ const runtimeHomeDir = getLocatorPickerRuntimeHomeDir(repoRoot);
78
+ const tempDir = path.join(runtimeDir, 'tmp');
79
+ const configDir = path.join(runtimeDir, 'config');
80
+ const cacheDir = path.join(runtimeDir, 'cache');
81
+ const appDataDir = path.join(runtimeDir, 'appdata');
82
+ const localAppDataDir = path.join(runtimeDir, 'localappdata');
83
+ await mkdir(getLocatorPickerSessionsDir(repoRoot), { recursive: true });
84
+ await mkdir(getLocatorPickerProfilesDir(repoRoot), { recursive: true });
85
+ await mkdir(getLocatorPickerLogsDir(repoRoot), { recursive: true });
86
+ await mkdir(runtimeHomeDir, { recursive: true });
87
+ await mkdir(tempDir, { recursive: true });
88
+ await mkdir(configDir, { recursive: true });
89
+ await mkdir(cacheDir, { recursive: true });
90
+ await mkdir(appDataDir, { recursive: true });
91
+ await mkdir(localAppDataDir, { recursive: true });
92
+ }
93
+ export async function readLocatorPickerSessionFile(sessionFilePath) {
94
+ try {
95
+ const raw = await readFile(sessionFilePath, 'utf8');
96
+ return JSON.parse(raw);
97
+ }
98
+ catch (_a) {
99
+ return null;
100
+ }
101
+ }
102
+ async function enqueueSessionFileOperation(sessionFilePath, operation) {
103
+ var _a;
104
+ const previousOperation = (_a = sessionFileOperationQueue.get(sessionFilePath)) !== null && _a !== void 0 ? _a : Promise.resolve();
105
+ const nextOperation = previousOperation.catch(() => undefined).then(operation);
106
+ sessionFileOperationQueue.set(sessionFilePath, nextOperation);
107
+ try {
108
+ return await nextOperation;
109
+ }
110
+ finally {
111
+ if (sessionFileOperationQueue.get(sessionFilePath) === nextOperation) {
112
+ sessionFileOperationQueue.delete(sessionFilePath);
113
+ }
114
+ }
115
+ }
116
+ async function writeLocatorPickerSessionFileImmediate(sessionFilePath, session) {
117
+ await mkdir(path.dirname(sessionFilePath), { recursive: true });
118
+ const normalized = withTimestamp(session);
119
+ const serialized = `${JSON.stringify(normalized, null, 2)}\n`;
120
+ const tempFilePath = `${sessionFilePath}.${process.pid}.${randomUUID()}.tmp`;
121
+ try {
122
+ await writeFile(tempFilePath, serialized, 'utf8');
123
+ await rename(tempFilePath, sessionFilePath);
124
+ }
125
+ catch (error) {
126
+ await unlink(tempFilePath).catch(() => undefined);
127
+ const code = error instanceof Error && 'code' in error ? String(error.code) : '';
128
+ if (process.platform === 'win32' || code === 'EPERM' || code === 'EACCES' || code === 'ENOENT') {
129
+ await writeFile(sessionFilePath, serialized, 'utf8');
130
+ }
131
+ else {
132
+ throw error;
133
+ }
134
+ }
135
+ return normalized;
136
+ }
137
+ export async function writeLocatorPickerSessionFile(sessionFilePath, session) {
138
+ return enqueueSessionFileOperation(sessionFilePath, () => writeLocatorPickerSessionFileImmediate(sessionFilePath, session));
139
+ }
140
+ export async function patchLocatorPickerSessionFile(sessionFilePath, patch) {
141
+ return enqueueSessionFileOperation(sessionFilePath, async () => {
142
+ const current = await readLocatorPickerSessionFile(sessionFilePath);
143
+ if (!current) {
144
+ return null;
145
+ }
146
+ const nextPatch = typeof patch === 'function' ? patch(current) : patch;
147
+ const nextSession = Object.assign(Object.assign(Object.assign({}, current), nextPatch), { updatedAt: new Date().toISOString() });
148
+ return writeLocatorPickerSessionFileImmediate(sessionFilePath, nextSession);
149
+ });
150
+ }
@@ -0,0 +1,31 @@
1
+ export type CompanionSessionStatus = 'starting' | 'ready' | 'picked' | 'saving' | 'closed' | 'error';
2
+ export type CompanionPickedLocatorStrategy = 'test-id' | 'role' | 'label' | 'placeholder' | 'id' | 'css' | 'xpath';
3
+ export interface CompanionLaunchSource {
4
+ environmentId?: string;
5
+ environmentName?: string;
6
+ url: string;
7
+ }
8
+ export interface CompanionPickedLocatorPayload {
9
+ selector: string;
10
+ currentUrl: string;
11
+ pathname: string;
12
+ pageTitle: string;
13
+ tagName: string;
14
+ text?: string;
15
+ accessibleName?: string;
16
+ strategy?: CompanionPickedLocatorStrategy;
17
+ }
18
+ export interface CompanionSessionFile {
19
+ sessionId: string;
20
+ status: CompanionSessionStatus;
21
+ launchSource: CompanionLaunchSource;
22
+ currentUrl: string;
23
+ currentPathname: string;
24
+ pageTitle: string;
25
+ companionPid: number | null;
26
+ crashLogPath?: string;
27
+ pickedLocator?: CompanionPickedLocatorPayload;
28
+ error?: string;
29
+ startedAt: string;
30
+ updatedAt: string;
31
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@appraise/locator-picker-companion",
3
+ "private": true,
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": "./dist/index.js",
9
+ "./launcher": "./dist/launcher.js",
10
+ "./session-file": "./dist/session-file.js",
11
+ "./types": "./dist/types.js"
12
+ },
13
+ "scripts": {
14
+ "build": "tsc -p tsconfig.json",
15
+ "dev": "node --import tsx ./src/cli.ts"
16
+ }
17
+ }