@thinkwise/testwise 0.2.62 → 0.2.99

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 (458) hide show
  1. package/Testwise.ts +35 -0
  2. package/artifact-builder/ArtifactManager.ts +25 -2
  3. package/artifact-builder/ComponentClassModelBuilder.ts +148 -0
  4. package/artifact-builder/InterfaceGenerator.ts +31 -33
  5. package/artifact-builder/ModelDataBuilder.ts +18 -20
  6. package/artifact-builder/ModelDataRefiner.ts +23 -3
  7. package/artifact-builder/SchemaGenerator.ts +45 -35
  8. package/artifact-builder/ScreenInterfaceRefiner.ts +25 -10
  9. package/artifact-builder/SelectorBuilder.ts +30 -24
  10. package/artifact-builder/SubjectClassModelBuilder.ts +209 -0
  11. package/artifact-builder/SubjectComponentGenerator.ts +67 -246
  12. package/artifact-builder/SubjectGenerator.ts +117 -230
  13. package/artifact-builder/SubjectRegistration.ts +41 -32
  14. package/artifact-builder/TsFileModel.ts +94 -0
  15. package/artifact-builder/TsFileSerializer.ts +247 -0
  16. package/artifact-builder/helpers/DataRetriever.ts +64 -27
  17. package/artifact-builder/helpers/NamingHandler.ts +23 -78
  18. package/artifact-builder/helpers/PipelinePaths.ts +123 -0
  19. package/artifact-builder/helpers/Stopwatch.ts +10 -0
  20. package/artifact-builder/helpers/index.ts +1 -0
  21. package/artifact-builder/index.ts +4 -0
  22. package/components/BaseComponentObjects.ts +17 -0
  23. package/components/action-bar/ActionBar.ts +35 -47
  24. package/components/action-bar/ActionBarObjects.ts +2 -0
  25. package/components/action-bar/CustomActionBar.ts +6 -0
  26. package/components/cardlist/Cardlist.ts +6 -0
  27. package/components/chart/Chart.ts +6 -0
  28. package/components/combined-filter/CombinedFilter.ts +9 -0
  29. package/components/cube-view-bar/CubeViewBar.ts +6 -0
  30. package/components/export/ExportComponent.ts +12 -0
  31. package/components/filter/ExcelStyleFilterPopup.ts +83 -10
  32. package/components/filter/ExcelStyleFilterPopupObjects.ts +29 -3
  33. package/components/filter/FilterForm.ts +10 -0
  34. package/components/filter/FilterPopup.ts +30 -9
  35. package/components/filter/FilterPopupObjects.ts +10 -3
  36. package/components/filter/FindForm.ts +7 -0
  37. package/components/filter/ManagePrefilterPopup.ts +11 -0
  38. package/components/form/Form.ts +16 -0
  39. package/components/grid/Grid.ts +50 -14
  40. package/components/grid/GridObjects.ts +0 -15
  41. package/components/maps/Maps.ts +6 -0
  42. package/components/menu/ListBarMenuComponent.ts +10 -0
  43. package/components/pivot-grid/PivotGrid.ts +6 -0
  44. package/components/pivot-grid/PivotGridFieldList.ts +7 -0
  45. package/components/pop-up/AllRowsPopUp.ts +12 -0
  46. package/components/pop-up/PopUpComponent.ts +11 -0
  47. package/components/prefilter-list/PrefilterList.ts +9 -0
  48. package/components/preview/Preview.ts +6 -0
  49. package/components/report-bar/ReportBar.ts +6 -0
  50. package/components/report-tiles/ReportTiles.ts +6 -0
  51. package/components/scheduler/Scheduler.ts +6 -0
  52. package/components/snackbar/SnackBar.ts +12 -0
  53. package/components/splitter/Splitter.ts +6 -0
  54. package/components/tab/BaseTab.ts +5 -0
  55. package/components/tab/DetailTabPage.ts +11 -0
  56. package/components/tab/Tab.ts +10 -0
  57. package/components/task/TaskBar.ts +13 -3
  58. package/components/task/TaskTiles.ts +12 -3
  59. package/components/topbar/TopBar.ts +10 -0
  60. package/components/tree-view/TreeView.ts +9 -0
  61. package/controls/DateControl.ts +47 -9
  62. package/controls/DateControlObjects.ts +15 -0
  63. package/controls/FormComboBox.ts +43 -26
  64. package/controls/FormComboBoxObjects.ts +27 -0
  65. package/controls/GridColumnControl.ts +35 -4
  66. package/controls/GridColumnControlObjects.ts +1 -1
  67. package/controls/InputFieldControl.ts +61 -15
  68. package/controls/InputFieldControlObjects.ts +19 -0
  69. package/controls/LookupDropdown.ts +59 -31
  70. package/controls/LookupDropdownObjects.ts +19 -0
  71. package/dist/Testwise.js +35 -0
  72. package/dist/Testwise.js.map +1 -1
  73. package/dist/artifact-builder/ArtifactManager.d.ts +18 -1
  74. package/dist/artifact-builder/ArtifactManager.js +24 -2
  75. package/dist/artifact-builder/ArtifactManager.js.map +1 -1
  76. package/dist/artifact-builder/ComponentClassModelBuilder.d.ts +22 -0
  77. package/dist/artifact-builder/ComponentClassModelBuilder.js +115 -0
  78. package/dist/artifact-builder/ComponentClassModelBuilder.js.map +1 -0
  79. package/dist/artifact-builder/InterfaceGenerator.d.ts +15 -6
  80. package/dist/artifact-builder/InterfaceGenerator.js +27 -26
  81. package/dist/artifact-builder/InterfaceGenerator.js.map +1 -1
  82. package/dist/artifact-builder/ModelDataBuilder.d.ts +7 -0
  83. package/dist/artifact-builder/ModelDataBuilder.js +13 -5
  84. package/dist/artifact-builder/ModelDataBuilder.js.map +1 -1
  85. package/dist/artifact-builder/ModelDataRefiner.d.ts +18 -1
  86. package/dist/artifact-builder/ModelDataRefiner.js +18 -3
  87. package/dist/artifact-builder/ModelDataRefiner.js.map +1 -1
  88. package/dist/artifact-builder/SchemaGenerator.d.ts +21 -5
  89. package/dist/artifact-builder/SchemaGenerator.js +38 -26
  90. package/dist/artifact-builder/SchemaGenerator.js.map +1 -1
  91. package/dist/artifact-builder/ScreenInterfaceRefiner.d.ts +18 -1
  92. package/dist/artifact-builder/ScreenInterfaceRefiner.js +23 -9
  93. package/dist/artifact-builder/ScreenInterfaceRefiner.js.map +1 -1
  94. package/dist/artifact-builder/SelectorBuilder.d.ts +18 -5
  95. package/dist/artifact-builder/SelectorBuilder.js +29 -14
  96. package/dist/artifact-builder/SelectorBuilder.js.map +1 -1
  97. package/dist/artifact-builder/SubjectClassModelBuilder.d.ts +38 -0
  98. package/dist/artifact-builder/SubjectClassModelBuilder.js +158 -0
  99. package/dist/artifact-builder/SubjectClassModelBuilder.js.map +1 -0
  100. package/dist/artifact-builder/SubjectComponentGenerator.d.ts +25 -14
  101. package/dist/artifact-builder/SubjectComponentGenerator.js +65 -189
  102. package/dist/artifact-builder/SubjectComponentGenerator.js.map +1 -1
  103. package/dist/artifact-builder/SubjectGenerator.d.ts +32 -13
  104. package/dist/artifact-builder/SubjectGenerator.js +81 -165
  105. package/dist/artifact-builder/SubjectGenerator.js.map +1 -1
  106. package/dist/artifact-builder/SubjectRegistration.d.ts +22 -8
  107. package/dist/artifact-builder/SubjectRegistration.js +29 -14
  108. package/dist/artifact-builder/SubjectRegistration.js.map +1 -1
  109. package/dist/artifact-builder/TsFileModel.d.ts +86 -0
  110. package/dist/artifact-builder/TsFileModel.js +2 -0
  111. package/dist/artifact-builder/TsFileModel.js.map +1 -0
  112. package/dist/artifact-builder/TsFileSerializer.d.ts +19 -0
  113. package/dist/artifact-builder/TsFileSerializer.js +225 -0
  114. package/dist/artifact-builder/TsFileSerializer.js.map +1 -0
  115. package/dist/artifact-builder/helpers/DataRetriever.d.ts +22 -3
  116. package/dist/artifact-builder/helpers/DataRetriever.js +56 -26
  117. package/dist/artifact-builder/helpers/DataRetriever.js.map +1 -1
  118. package/dist/artifact-builder/helpers/NamingHandler.d.ts +18 -6
  119. package/dist/artifact-builder/helpers/NamingHandler.js +20 -61
  120. package/dist/artifact-builder/helpers/NamingHandler.js.map +1 -1
  121. package/dist/artifact-builder/helpers/PipelinePaths.d.ts +52 -0
  122. package/dist/artifact-builder/helpers/PipelinePaths.js +99 -0
  123. package/dist/artifact-builder/helpers/PipelinePaths.js.map +1 -0
  124. package/dist/artifact-builder/helpers/Stopwatch.d.ts +10 -0
  125. package/dist/artifact-builder/helpers/Stopwatch.js +10 -0
  126. package/dist/artifact-builder/helpers/Stopwatch.js.map +1 -1
  127. package/dist/artifact-builder/helpers/index.d.ts +1 -0
  128. package/dist/artifact-builder/helpers/index.js +1 -0
  129. package/dist/artifact-builder/helpers/index.js.map +1 -1
  130. package/dist/artifact-builder/index.d.ts +4 -0
  131. package/dist/artifact-builder/index.js +4 -0
  132. package/dist/artifact-builder/index.js.map +1 -1
  133. package/dist/components/BaseComponentObjects.d.ts +17 -0
  134. package/dist/components/BaseComponentObjects.js +17 -0
  135. package/dist/components/BaseComponentObjects.js.map +1 -1
  136. package/dist/components/action-bar/ActionBar.d.ts +21 -24
  137. package/dist/components/action-bar/ActionBar.js +31 -24
  138. package/dist/components/action-bar/ActionBar.js.map +1 -1
  139. package/dist/components/action-bar/ActionBarObjects.d.ts +1 -0
  140. package/dist/components/action-bar/ActionBarObjects.js +1 -0
  141. package/dist/components/action-bar/ActionBarObjects.js.map +1 -1
  142. package/dist/components/action-bar/CustomActionBar.d.ts +6 -0
  143. package/dist/components/action-bar/CustomActionBar.js +6 -0
  144. package/dist/components/action-bar/CustomActionBar.js.map +1 -1
  145. package/dist/components/cardlist/Cardlist.d.ts +6 -0
  146. package/dist/components/cardlist/Cardlist.js +6 -0
  147. package/dist/components/cardlist/Cardlist.js.map +1 -1
  148. package/dist/components/chart/Chart.d.ts +6 -0
  149. package/dist/components/chart/Chart.js +6 -0
  150. package/dist/components/chart/Chart.js.map +1 -1
  151. package/dist/components/combined-filter/CombinedFilter.d.ts +9 -0
  152. package/dist/components/combined-filter/CombinedFilter.js +9 -0
  153. package/dist/components/combined-filter/CombinedFilter.js.map +1 -1
  154. package/dist/components/cube-view-bar/CubeViewBar.d.ts +6 -0
  155. package/dist/components/cube-view-bar/CubeViewBar.js +6 -0
  156. package/dist/components/cube-view-bar/CubeViewBar.js.map +1 -1
  157. package/dist/components/export/ExportComponent.d.ts +12 -0
  158. package/dist/components/export/ExportComponent.js +12 -0
  159. package/dist/components/export/ExportComponent.js.map +1 -1
  160. package/dist/components/filter/ExcelStyleFilterPopup.d.ts +25 -2
  161. package/dist/components/filter/ExcelStyleFilterPopup.js +60 -6
  162. package/dist/components/filter/ExcelStyleFilterPopup.js.map +1 -1
  163. package/dist/components/filter/ExcelStyleFilterPopupObjects.d.ts +8 -1
  164. package/dist/components/filter/ExcelStyleFilterPopupObjects.js +15 -2
  165. package/dist/components/filter/ExcelStyleFilterPopupObjects.js.map +1 -1
  166. package/dist/components/filter/FilterForm.d.ts +10 -0
  167. package/dist/components/filter/FilterForm.js +10 -0
  168. package/dist/components/filter/FilterForm.js.map +1 -1
  169. package/dist/components/filter/FilterPopup.d.ts +22 -4
  170. package/dist/components/filter/FilterPopup.js +17 -9
  171. package/dist/components/filter/FilterPopup.js.map +1 -1
  172. package/dist/components/filter/FilterPopupObjects.d.ts +5 -2
  173. package/dist/components/filter/FilterPopupObjects.js +5 -2
  174. package/dist/components/filter/FilterPopupObjects.js.map +1 -1
  175. package/dist/components/filter/FindForm.d.ts +7 -0
  176. package/dist/components/filter/FindForm.js +7 -0
  177. package/dist/components/filter/FindForm.js.map +1 -1
  178. package/dist/components/filter/ManagePrefilterPopup.d.ts +11 -0
  179. package/dist/components/filter/ManagePrefilterPopup.js +11 -0
  180. package/dist/components/filter/ManagePrefilterPopup.js.map +1 -1
  181. package/dist/components/form/Form.d.ts +16 -0
  182. package/dist/components/form/Form.js +16 -0
  183. package/dist/components/form/Form.js.map +1 -1
  184. package/dist/components/grid/Grid.d.ts +20 -1
  185. package/dist/components/grid/Grid.js +35 -25
  186. package/dist/components/grid/Grid.js.map +1 -1
  187. package/dist/components/grid/GridObjects.d.ts +0 -4
  188. package/dist/components/grid/GridObjects.js +0 -6
  189. package/dist/components/grid/GridObjects.js.map +1 -1
  190. package/dist/components/maps/Maps.d.ts +6 -0
  191. package/dist/components/maps/Maps.js +6 -0
  192. package/dist/components/maps/Maps.js.map +1 -1
  193. package/dist/components/menu/ListBarMenuComponent.d.ts +10 -0
  194. package/dist/components/menu/ListBarMenuComponent.js +10 -0
  195. package/dist/components/menu/ListBarMenuComponent.js.map +1 -1
  196. package/dist/components/pivot-grid/PivotGrid.d.ts +6 -0
  197. package/dist/components/pivot-grid/PivotGrid.js +6 -0
  198. package/dist/components/pivot-grid/PivotGrid.js.map +1 -1
  199. package/dist/components/pivot-grid/PivotGridFieldList.d.ts +7 -0
  200. package/dist/components/pivot-grid/PivotGridFieldList.js +7 -0
  201. package/dist/components/pivot-grid/PivotGridFieldList.js.map +1 -1
  202. package/dist/components/pop-up/AllRowsPopUp.d.ts +12 -0
  203. package/dist/components/pop-up/AllRowsPopUp.js +12 -0
  204. package/dist/components/pop-up/AllRowsPopUp.js.map +1 -1
  205. package/dist/components/pop-up/PopUpComponent.d.ts +11 -0
  206. package/dist/components/pop-up/PopUpComponent.js +11 -0
  207. package/dist/components/pop-up/PopUpComponent.js.map +1 -1
  208. package/dist/components/prefilter-list/PrefilterList.d.ts +9 -0
  209. package/dist/components/prefilter-list/PrefilterList.js +9 -0
  210. package/dist/components/prefilter-list/PrefilterList.js.map +1 -1
  211. package/dist/components/preview/Preview.d.ts +6 -0
  212. package/dist/components/preview/Preview.js +6 -0
  213. package/dist/components/preview/Preview.js.map +1 -1
  214. package/dist/components/report-bar/ReportBar.d.ts +6 -0
  215. package/dist/components/report-bar/ReportBar.js +6 -0
  216. package/dist/components/report-bar/ReportBar.js.map +1 -1
  217. package/dist/components/report-tiles/ReportTiles.d.ts +6 -0
  218. package/dist/components/report-tiles/ReportTiles.js +6 -0
  219. package/dist/components/report-tiles/ReportTiles.js.map +1 -1
  220. package/dist/components/scheduler/Scheduler.d.ts +6 -0
  221. package/dist/components/scheduler/Scheduler.js +6 -0
  222. package/dist/components/scheduler/Scheduler.js.map +1 -1
  223. package/dist/components/snackbar/SnackBar.d.ts +12 -0
  224. package/dist/components/snackbar/SnackBar.js +12 -0
  225. package/dist/components/snackbar/SnackBar.js.map +1 -1
  226. package/dist/components/splitter/Splitter.d.ts +6 -0
  227. package/dist/components/splitter/Splitter.js +6 -0
  228. package/dist/components/splitter/Splitter.js.map +1 -1
  229. package/dist/components/tab/BaseTab.d.ts +5 -0
  230. package/dist/components/tab/BaseTab.js +5 -0
  231. package/dist/components/tab/BaseTab.js.map +1 -1
  232. package/dist/components/tab/DetailTabPage.d.ts +11 -0
  233. package/dist/components/tab/DetailTabPage.js +11 -0
  234. package/dist/components/tab/DetailTabPage.js.map +1 -1
  235. package/dist/components/tab/Tab.d.ts +10 -0
  236. package/dist/components/tab/Tab.js +10 -0
  237. package/dist/components/tab/Tab.js.map +1 -1
  238. package/dist/components/task/TaskBar.d.ts +12 -2
  239. package/dist/components/task/TaskBar.js +13 -3
  240. package/dist/components/task/TaskBar.js.map +1 -1
  241. package/dist/components/task/TaskTiles.d.ts +11 -2
  242. package/dist/components/task/TaskTiles.js +12 -3
  243. package/dist/components/task/TaskTiles.js.map +1 -1
  244. package/dist/components/topbar/TopBar.d.ts +10 -0
  245. package/dist/components/topbar/TopBar.js +10 -0
  246. package/dist/components/topbar/TopBar.js.map +1 -1
  247. package/dist/components/tree-view/TreeView.d.ts +9 -0
  248. package/dist/components/tree-view/TreeView.js +9 -0
  249. package/dist/components/tree-view/TreeView.js.map +1 -1
  250. package/dist/controls/DateControl.d.ts +40 -2
  251. package/dist/controls/DateControl.js +24 -7
  252. package/dist/controls/DateControl.js.map +1 -1
  253. package/dist/controls/DateControlObjects.d.ts +8 -1
  254. package/dist/controls/DateControlObjects.js +8 -1
  255. package/dist/controls/DateControlObjects.js.map +1 -1
  256. package/dist/controls/FormComboBox.d.ts +30 -0
  257. package/dist/controls/FormComboBox.js +19 -16
  258. package/dist/controls/FormComboBox.js.map +1 -1
  259. package/dist/controls/FormComboBoxObjects.d.ts +12 -1
  260. package/dist/controls/FormComboBoxObjects.js +15 -1
  261. package/dist/controls/FormComboBoxObjects.js.map +1 -1
  262. package/dist/controls/GridColumnControl.d.ts +30 -0
  263. package/dist/controls/GridColumnControl.js +13 -4
  264. package/dist/controls/GridColumnControl.js.map +1 -1
  265. package/dist/controls/GridColumnControlObjects.js +1 -1
  266. package/dist/controls/GridColumnControlObjects.js.map +1 -1
  267. package/dist/controls/InputFieldControl.d.ts +50 -3
  268. package/dist/controls/InputFieldControl.js +40 -11
  269. package/dist/controls/InputFieldControl.js.map +1 -1
  270. package/dist/controls/InputFieldControlObjects.d.ts +10 -1
  271. package/dist/controls/InputFieldControlObjects.js +10 -1
  272. package/dist/controls/InputFieldControlObjects.js.map +1 -1
  273. package/dist/controls/LookupDropdown.d.ts +29 -0
  274. package/dist/controls/LookupDropdown.js +36 -25
  275. package/dist/controls/LookupDropdown.js.map +1 -1
  276. package/dist/controls/LookupDropdownObjects.d.ts +10 -0
  277. package/dist/controls/LookupDropdownObjects.js +11 -0
  278. package/dist/controls/LookupDropdownObjects.js.map +1 -0
  279. package/dist/enums/ElementTypes.d.ts +18 -0
  280. package/dist/enums/ElementTypes.js +18 -0
  281. package/dist/enums/ElementTypes.js.map +1 -1
  282. package/dist/enums/ExportFormat.d.ts +8 -0
  283. package/dist/enums/ExportFormat.js +8 -0
  284. package/dist/enums/ExportFormat.js.map +1 -1
  285. package/dist/enums/LogLevel.d.ts +17 -0
  286. package/dist/enums/LogLevel.js +17 -1
  287. package/dist/enums/LogLevel.js.map +1 -1
  288. package/dist/enums/index.d.ts +1 -0
  289. package/dist/enums/index.js +1 -0
  290. package/dist/enums/index.js.map +1 -1
  291. package/dist/helpers/ConfigChecker.d.ts +13 -0
  292. package/dist/helpers/ConfigChecker.js +13 -0
  293. package/dist/helpers/ConfigChecker.js.map +1 -1
  294. package/dist/helpers/Ensure.d.ts +13 -0
  295. package/dist/helpers/Ensure.js +13 -0
  296. package/dist/helpers/Ensure.js.map +1 -1
  297. package/dist/helpers/FlightTracker.d.ts +13 -3
  298. package/dist/helpers/FlightTracker.js +103 -17
  299. package/dist/helpers/FlightTracker.js.map +1 -1
  300. package/dist/helpers/GlobalWaitEventHandler.d.ts +13 -0
  301. package/dist/helpers/GlobalWaitEventHandler.js +13 -0
  302. package/dist/helpers/GlobalWaitEventHandler.js.map +1 -1
  303. package/dist/helpers/LoginHelper.d.ts +35 -1
  304. package/dist/helpers/LoginHelper.js +46 -11
  305. package/dist/helpers/LoginHelper.js.map +1 -1
  306. package/dist/helpers/PathResolver.d.ts +22 -0
  307. package/dist/helpers/PathResolver.js +22 -0
  308. package/dist/helpers/PathResolver.js.map +1 -1
  309. package/dist/helpers/Poll.d.ts +13 -1
  310. package/dist/helpers/Poll.js +12 -0
  311. package/dist/helpers/Poll.js.map +1 -1
  312. package/dist/helpers/RegexHelper.d.ts +15 -0
  313. package/dist/helpers/RegexHelper.js +15 -3
  314. package/dist/helpers/RegexHelper.js.map +1 -1
  315. package/dist/helpers/SubjectNavigator.d.ts +26 -0
  316. package/dist/helpers/SubjectNavigator.js +51 -0
  317. package/dist/helpers/SubjectNavigator.js.map +1 -0
  318. package/dist/helpers/UserSimulationHelper.d.ts +14 -0
  319. package/dist/helpers/UserSimulationHelper.js +14 -0
  320. package/dist/helpers/UserSimulationHelper.js.map +1 -1
  321. package/dist/helpers/index.d.ts +1 -0
  322. package/dist/helpers/index.js +1 -0
  323. package/dist/helpers/index.js.map +1 -1
  324. package/dist/index.d.ts +6 -20
  325. package/dist/index.js +1 -0
  326. package/dist/index.js.map +1 -1
  327. package/dist/interfaces/IComponentObjects.d.ts +12 -0
  328. package/dist/interfaces/IComponentSchemaMeta.d.ts +15 -0
  329. package/dist/interfaces/IComponentSchemaMeta.js +2 -0
  330. package/dist/interfaces/IComponentSchemaMeta.js.map +1 -0
  331. package/dist/interfaces/IProperty.d.ts +13 -0
  332. package/dist/interfaces/IRegisteredSubjects.d.ts +12 -0
  333. package/dist/interfaces/ISeedSubjectDraft.d.ts +16 -0
  334. package/dist/interfaces/ISeedSubjectDraft.js +2 -0
  335. package/dist/interfaces/ISeedSubjectDraft.js.map +1 -0
  336. package/dist/interfaces/ISubject.d.ts +13 -0
  337. package/dist/interfaces/ISubjectDetail.d.ts +11 -0
  338. package/dist/interfaces/ISubjectDetail.js +2 -0
  339. package/dist/interfaces/ISubjectDetail.js.map +1 -0
  340. package/dist/mcp/ArtifactResolver.d.ts +152 -0
  341. package/dist/mcp/ArtifactResolver.js +232 -0
  342. package/dist/mcp/ArtifactResolver.js.map +1 -0
  343. package/dist/mcp/index.d.ts +2 -0
  344. package/dist/mcp/index.js +2 -0
  345. package/dist/mcp/index.js.map +1 -0
  346. package/dist/page-extensions/GlobalComponents.d.ts +30 -0
  347. package/dist/page-extensions/GlobalComponents.js +30 -0
  348. package/dist/page-extensions/GlobalComponents.js.map +1 -1
  349. package/dist/page-extensions/GoToDeepLink.d.ts +9 -0
  350. package/dist/page-extensions/GoToDeepLink.js +9 -0
  351. package/dist/page-extensions/GoToDeepLink.js.map +1 -1
  352. package/dist/page-extensions/LoginFeatures.d.ts +8 -0
  353. package/dist/page-extensions/LoginFeatures.js +8 -0
  354. package/dist/page-extensions/LoginFeatures.js.map +1 -1
  355. package/dist/page-extensions/SubjectRegistry.d.ts +31 -0
  356. package/dist/page-extensions/SubjectRegistry.js +31 -0
  357. package/dist/page-extensions/SubjectRegistry.js.map +1 -1
  358. package/dist/page-extensions/UserSimulation.d.ts +21 -0
  359. package/dist/page-extensions/UserSimulation.js +21 -0
  360. package/dist/page-extensions/UserSimulation.js.map +1 -1
  361. package/dist/page-extensions/WaitEventHandler.d.ts +20 -0
  362. package/dist/page-extensions/WaitEventHandler.js +20 -0
  363. package/dist/page-extensions/WaitEventHandler.js.map +1 -1
  364. package/dist/page-overrides/ClickOverride.d.ts +23 -2
  365. package/dist/page-overrides/ClickOverride.js +34 -50
  366. package/dist/page-overrides/ClickOverride.js.map +1 -1
  367. package/dist/page-overrides/FillOverride.d.ts +23 -0
  368. package/dist/page-overrides/FillOverride.js +46 -66
  369. package/dist/page-overrides/FillOverride.js.map +1 -1
  370. package/dist/services/ConfigBuilder.d.ts +24 -0
  371. package/dist/services/ConfigBuilder.js +24 -0
  372. package/dist/services/ConfigBuilder.js.map +1 -1
  373. package/dist/services/IndiciumApi.service.d.ts +26 -0
  374. package/dist/services/IndiciumApi.service.js +40 -5
  375. package/dist/services/IndiciumApi.service.js.map +1 -1
  376. package/dist/services/Logger.d.ts +13 -0
  377. package/dist/services/Logger.js +39 -0
  378. package/dist/services/Logger.js.map +1 -1
  379. package/dist/types/Components.d.ts +18 -1
  380. package/dist/types/Components.js +0 -1
  381. package/dist/types/Components.js.map +1 -1
  382. package/dist/types/LocatorType.d.ts +5 -0
  383. package/dist/types/LocatorType.js +2 -0
  384. package/dist/types/LocatorType.js.map +1 -0
  385. package/dist/types/PollTypes.d.ts +8 -0
  386. package/dist/types/Test.d.ts +18 -0
  387. package/dist/types/Universal.d.ts +12 -0
  388. package/dist/types/index.d.ts +2 -0
  389. package/dist/types/index.js +2 -0
  390. package/dist/types/index.js.map +1 -1
  391. package/enums/ElementTypes.ts +18 -0
  392. package/enums/ExportFormat.ts +8 -0
  393. package/enums/LogLevel.ts +17 -1
  394. package/enums/index.ts +1 -0
  395. package/helpers/ConfigChecker.ts +13 -0
  396. package/helpers/Ensure.ts +13 -0
  397. package/helpers/FlightTracker.ts +109 -20
  398. package/helpers/GlobalWaitEventHandler.ts +13 -0
  399. package/helpers/LoginHelper.ts +49 -12
  400. package/helpers/PathResolver.ts +22 -0
  401. package/helpers/Poll.ts +13 -1
  402. package/helpers/RegexHelper.ts +15 -3
  403. package/helpers/SubjectNavigator.ts +57 -0
  404. package/helpers/UserSimulationHelper.ts +14 -0
  405. package/helpers/index.ts +1 -0
  406. package/index.ts +1 -0
  407. package/interfaces/IComponentObjects.ts +12 -0
  408. package/interfaces/IComponentSchemaMeta.ts +17 -0
  409. package/interfaces/IProperty.ts +13 -0
  410. package/interfaces/IRegisteredSubjects.ts +12 -0
  411. package/interfaces/ISeedSubjectDraft.ts +17 -0
  412. package/interfaces/ISubject.ts +13 -0
  413. package/interfaces/ISubjectDetail.ts +12 -0
  414. package/mcp/ArtifactResolver.ts +296 -0
  415. package/mcp/index.ts +2 -0
  416. package/package.json +20 -8
  417. package/page-extensions/GlobalComponents.ts +30 -0
  418. package/page-extensions/GoToDeepLink.ts +9 -0
  419. package/page-extensions/LoginFeatures.ts +8 -0
  420. package/page-extensions/SubjectRegistry.ts +32 -0
  421. package/page-extensions/UserSimulation.ts +21 -0
  422. package/page-extensions/WaitEventHandler.ts +20 -0
  423. package/page-overrides/ClickOverride.ts +36 -55
  424. package/page-overrides/FillOverride.ts +59 -73
  425. package/promptCredentials.js +1 -1
  426. package/scripts/Testwise.template.json +1 -1
  427. package/scripts/diagram.js +2267 -0
  428. package/scripts/main.js +84 -63
  429. package/scripts/postinstall.js +55 -42
  430. package/scripts/setup.js +91 -37
  431. package/scripts/sync.js +767 -748
  432. package/services/ConfigBuilder.ts +24 -0
  433. package/services/IndiciumApi.service.ts +44 -6
  434. package/services/Logger.ts +40 -0
  435. package/templates/copilot-instructions.md +130 -0
  436. package/templates/mcp.json +9 -0
  437. package/templates/testwise-test-expert.agent.md +453 -0
  438. package/tests/tsconfig.json +12 -0
  439. package/tsconfig.json +6 -2
  440. package/types/Components.ts +17 -2
  441. package/types/LocatorType.ts +5 -0
  442. package/types/PollTypes.ts +8 -0
  443. package/types/Test.ts +18 -0
  444. package/types/Universal.ts +12 -0
  445. package/types/index.ts +2 -0
  446. package/dist/interfaces/IStoredTestResults.d.ts +0 -5
  447. package/dist/interfaces/IStoredTestResults.js +0 -2
  448. package/dist/interfaces/IStoredTestResults.js.map +0 -1
  449. package/dist/templates/test-artifacts/SubjectPageBase.d.ts +0 -5
  450. package/dist/templates/test-artifacts/SubjectPageBase.js +0 -6
  451. package/dist/templates/test-artifacts/SubjectPageBase.js.map +0 -1
  452. package/dist/templates/test-artifacts/screens/index.d.ts +0 -1
  453. package/dist/templates/test-artifacts/screens/index.js +0 -2
  454. package/dist/templates/test-artifacts/screens/index.js.map +0 -1
  455. package/dist/templates/test-artifacts/subjects/index.d.ts +0 -1
  456. package/dist/templates/test-artifacts/subjects/index.js +0 -2
  457. package/dist/templates/test-artifacts/subjects/index.js.map +0 -1
  458. package/interfaces/IStoredTestResults.ts +0 -6
@@ -0,0 +1,247 @@
1
+ import { IndentationText, Project, QuoteKind, Scope, type SourceFile, StructureKind } from 'ts-morph';
2
+ import type { SubjectComponents } from '../types/Components.js';
3
+ import type { ComponentClassModel, TsFileModel } from './TsFileModel.js';
4
+
5
+ /**
6
+ * Converts in-memory TypeScript file models (`TsFileModel`, `ComponentClassModel`)
7
+ * into formatted TypeScript source strings using `ts-morph` AST manipulation.
8
+ *
9
+ * **Why ts-morph instead of string templates:** String-template code generation
10
+ * is fragile — it breaks on quoting, indentation, and special characters.
11
+ * `ts-morph` builds a real AST and prints it, so the output is always
12
+ * syntactically valid and consistently formatted.
13
+ *
14
+ * **Exported functions:**
15
+ * - `serializeTsFile(model)` — writes a complete subject class file from a
16
+ * `TsFileModel` (used by `SubjectGenerator`).
17
+ * - `appendComponentClass(existingContent, model)` — appends a typed component
18
+ * class body to an existing interface file (used by `SubjectComponentGenerator`).
19
+ * - `refineComponentInterface(rawContent, componentType)` — post-processes a
20
+ * raw quicktype interface file (adds Testwise imports, removes `Locator` base).
21
+ */
22
+
23
+ function createProject(existingContent?: string): { project: Project; file: SourceFile } {
24
+ const project = new Project({
25
+ useInMemoryFileSystem: true,
26
+ skipAddingFilesFromTsConfig: true,
27
+ manipulationSettings: {
28
+ indentationText: IndentationText.TwoSpaces,
29
+ quoteKind: QuoteKind.Single
30
+ }
31
+ });
32
+ const file = project.createSourceFile('output.ts', existingContent ?? '');
33
+ return { project, file };
34
+ }
35
+
36
+ /** Builds a subject class file from a typed model. No string templates. */
37
+ export function serializeTsFile(model: TsFileModel): string {
38
+ const { file } = createProject();
39
+
40
+ for (const imp of model.imports) {
41
+ file.addImportDeclaration({
42
+ isTypeOnly: imp.isTypeOnly,
43
+ namedImports: imp.namedImports.map((n) => ({ name: n.name, isTypeOnly: n.isTypeOnly ?? false })),
44
+ moduleSpecifier: imp.from
45
+ });
46
+ }
47
+
48
+ const cls = model.classModel;
49
+
50
+ file.addClass({
51
+ name: cls.name,
52
+ extends: cls.extendsClass,
53
+ implements: [cls.implementsInterface],
54
+ isExported: true,
55
+ properties: cls.properties.map((p) => ({
56
+ kind: StructureKind.Property as const,
57
+ scope: p.access === 'private' ? Scope.Private : undefined,
58
+ name: p.name,
59
+ type: p.type
60
+ })),
61
+ ctors: [
62
+ {
63
+ parameters: cls.constructor.params.map((p) => ({ name: p.name, type: p.type })),
64
+ statements: [
65
+ `super(${cls.constructor.superCall});`,
66
+ ...cls.constructor.assignments.map((a) => `this.${a.property} = ${a.value};`),
67
+ ...cls.constructor.extraLines
68
+ ]
69
+ }
70
+ ],
71
+ methods: (cls.methods ?? []).map((m) => ({
72
+ scope: Scope.Public,
73
+ isAsync: m.isAsync,
74
+ name: m.name,
75
+ statements: m.bodyLines
76
+ }))
77
+ });
78
+
79
+ return file.print();
80
+ }
81
+
82
+ /**
83
+ * Parses an existing component interface file, appends the component class and
84
+ * any required control imports, and returns the complete printed file.
85
+ * Replaces string-template-based class body generation — no string templates.
86
+ */
87
+ export function appendComponentClass(existingContent: string, model: ComponentClassModel): string {
88
+ const { file } = createProject(existingContent);
89
+
90
+ addControlImports(file, model);
91
+
92
+ const contextProp = {
93
+ kind: StructureKind.Property as const,
94
+ scope: Scope.Private,
95
+ name: '_context',
96
+ type: 'Locator'
97
+ };
98
+
99
+ if (model.componentType === 'Grid') {
100
+ file.addClass({
101
+ name: `${model.interfaceName}Component`,
102
+ extends: model.componentType,
103
+ implements: [model.interfaceName],
104
+ isExported: true,
105
+ properties: [contextProp],
106
+ ctors: [
107
+ {
108
+ parameters: [{ name: 'context', type: 'Locator' }],
109
+ statements: ['super(context);', 'this._context = context;']
110
+ }
111
+ ],
112
+ getAccessors: model.getters.map((g) => ({
113
+ scope: Scope.Public,
114
+ name: g.name,
115
+ returnType: g.returnType,
116
+ statements: [g.bodyLine]
117
+ }))
118
+ });
119
+ } else {
120
+ file.addClass({
121
+ name: `${model.interfaceName}Component`,
122
+ extends: model.componentType,
123
+ implements: [model.interfaceName],
124
+ isExported: true,
125
+ properties: [contextProp, ...model.properties.map((p) => ({ name: p.name, type: p.type }))],
126
+ ctors: [
127
+ {
128
+ parameters: [{ name: 'context', type: 'Locator' }],
129
+ statements: [
130
+ 'super(context);',
131
+ 'this._context = context;',
132
+ ...model.assignments.map((a) => `this.${a.property} = ${a.value};`)
133
+ ]
134
+ }
135
+ ]
136
+ });
137
+ }
138
+
139
+ return file.print();
140
+ }
141
+
142
+ // ── Control import resolution ──────────────────────────────────────────────
143
+
144
+ const controlImportMap: Record<string, { createFn: string; moduleSpecifier: string }> = {
145
+ ILookupDropdown: {
146
+ createFn: 'createLookupDropdown',
147
+ moduleSpecifier: '../../../../controls/LookupDropdown.js'
148
+ },
149
+ IFormComboBox: {
150
+ createFn: 'createFormComboBox',
151
+ moduleSpecifier: '../../../../controls/FormComboBox.js'
152
+ },
153
+ IInputFieldControl: {
154
+ createFn: 'createInputFieldControl',
155
+ moduleSpecifier: '../../../../controls/InputFieldControl.js'
156
+ },
157
+ IDateControl: {
158
+ createFn: 'createDateControl',
159
+ moduleSpecifier: '../../../../controls/DateControl.js'
160
+ }
161
+ };
162
+
163
+ function addControlImports(file: SourceFile, model: ComponentClassModel): void {
164
+ const usedTypes = new Set(model.properties.map((p) => p.type));
165
+
166
+ for (const [typeName, { createFn, moduleSpecifier }] of Object.entries(controlImportMap)) {
167
+ if (!usedTypes.has(typeName)) continue;
168
+
169
+ const alreadyImported = file.getImportDeclarations().some((d) => d.getModuleSpecifierValue() === moduleSpecifier);
170
+ if (alreadyImported) continue;
171
+
172
+ file.addImportDeclaration({
173
+ namedImports: [{ name: createFn }, { name: typeName, isTypeOnly: true }],
174
+ moduleSpecifier
175
+ });
176
+ }
177
+ }
178
+
179
+ // ── Form property-type suffix mapping ─────────────────────────────────────
180
+
181
+ const formTypeSuffixMap: Record<string, string> = {
182
+ Lookup: 'ILookupDropdown',
183
+ ComboBox: 'IFormComboBox',
184
+ Field: 'IInputFieldControl',
185
+ DatePicker: 'IDateControl'
186
+ };
187
+
188
+ /**
189
+ * Transforms a raw quicktype-generated interface file into a refined component
190
+ * interface file using ts-morph AST manipulation — no string templates.
191
+ *
192
+ * Replaces the five string-manipulation methods previously in SubjectComponentGenerator:
193
+ * removeLocatorInterface, addComponentImports, setSubjectExtendsComponent,
194
+ * transformGridInterface, transformInterfaceTypes.
195
+ */
196
+ export function refineComponentInterface(rawContent: string, componentType: SubjectComponents): string {
197
+ const { file } = createProject(rawContent);
198
+
199
+ // Remove the stray Locator interface that quicktype emits alongside the real schema
200
+ file.getInterface('Locator')?.remove();
201
+
202
+ // Prepend the imports this component type needs
203
+ file.insertImportDeclarations(0, [
204
+ {
205
+ namedImports: [{ name: componentType }],
206
+ moduleSpecifier: '../../../../components/index.js'
207
+ },
208
+ ...(componentType === 'Grid'
209
+ ? [
210
+ {
211
+ namedImports: [{ name: 'createGridColumnControl' }, { name: 'IGridColumnControl', isTypeOnly: true }],
212
+ moduleSpecifier: '../../../../controls/GridColumnControl.js'
213
+ }
214
+ ]
215
+ : []),
216
+ {
217
+ isTypeOnly: true,
218
+ namedImports: [{ name: 'Locator' }],
219
+ moduleSpecifier: '@playwright/test'
220
+ }
221
+ ]);
222
+
223
+ // Find the main interface (no extends clause yet) and make it extend the component
224
+ const mainInterface = file.getInterfaces().find((i) => i.getExtends().length === 0);
225
+ if (mainInterface) {
226
+ mainInterface.addExtends(componentType);
227
+
228
+ if (componentType === 'Grid') {
229
+ // Swap every Locator-typed property for a readonly IGridColumnControl
230
+ for (const prop of mainInterface.getProperties()) {
231
+ const typeText = prop.getTypeNode()?.getText() ?? '';
232
+ if (typeText === 'Locator' || typeText === 'Locator[]') {
233
+ prop.setIsReadonly(true);
234
+ prop.setType('IGridColumnControl');
235
+ }
236
+ }
237
+ } else {
238
+ // Map Form property name suffixes to their control types
239
+ for (const prop of mainInterface.getProperties()) {
240
+ const suffix = Object.keys(formTypeSuffixMap).find((s) => prop.getName().endsWith(s));
241
+ if (suffix) prop.setType(formTypeSuffixMap[suffix]);
242
+ }
243
+ }
244
+ }
245
+
246
+ return file.print();
247
+ }
@@ -1,67 +1,104 @@
1
1
  import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
- import { PathResolver } from '../../helpers/PathResolver.js';
4
2
  import type { IRegisteredSubjects } from '../../interfaces/IRegisteredSubjects.js';
5
3
  import type { ISubject } from '../../interfaces/ISubject.js';
4
+ import { PipelinePaths } from './PipelinePaths.js';
6
5
 
6
+ /**
7
+ * Thin file-system accessor that reads all JSON seed-data files used by the
8
+ * artifact-builder pipeline and returns them as typed objects.
9
+ *
10
+ * **What it does:** Abstracts away all `fs.readFileSync` / JSON.parse calls so
11
+ * that pipeline steps only deal with typed data, never raw file I/O. All path
12
+ * resolution is delegated to `PipelinePaths` — there are no hardcoded paths here.
13
+ *
14
+ * **Why it exists as a separate class:** Injecting `DataRetriever` into each
15
+ * pipeline step makes the steps unit-testable without touching the real
16
+ * filesystem. Tests pass a `DataRetriever` constructed with a fake
17
+ * `PipelinePaths` that points to a temp directory.
18
+ *
19
+ * **For contributors:** If the pipeline gains a new seed-data file, add a
20
+ * typed accessor method here (and a corresponding path getter to
21
+ * `PipelinePaths`).
22
+ */
7
23
  export class DataRetriever {
8
- private _consumerRootDirectory: string = new PathResolver().getConsumerRootDirectory();
24
+ private readonly _paths: PipelinePaths;
25
+
26
+ constructor(paths?: PipelinePaths) {
27
+ /* v8 ignore next -- default only used at runtime, not in unit tests */
28
+ this._paths = paths ?? new PipelinePaths();
29
+ }
9
30
 
10
31
  public getSubjectsSeedData(): ISubject[] {
11
- const seedPath = path.join(this._consumerRootDirectory, 'seed-data/subjects.json');
32
+ const seedPath = this._paths.subjectsJson;
33
+
12
34
  if (!fs.existsSync(seedPath)) {
13
- console.error(`Seed data file not found at: ${seedPath}`);
35
+ throw new Error(`subjects.json not found at: ${seedPath}. Run the model data build step first.`);
14
36
  }
15
37
 
16
- const json = fs.readFileSync(seedPath, 'utf-8');
17
- return this.toISubject(json) as unknown as ISubject[];
38
+ return this.parseJsonFile<ISubject[]>(seedPath);
18
39
  }
19
40
 
20
41
  public getRegisteredSubjects(): IRegisteredSubjects[] | null {
21
- const registeredSubjectsPath = path.join(this._consumerRootDirectory, 'seed-data/registeredSubjects.json');
42
+ const registeredSubjectsPath = this._paths.registeredSubjectsJson;
22
43
 
23
44
  if (!fs.existsSync(registeredSubjectsPath)) {
24
- console.info(`Seed data file not found at: ${registeredSubjectsPath}`);
25
-
45
+ console.info(`registeredSubjects.json not found at: ${registeredSubjectsPath}. No subjects are registered.`);
26
46
  return null;
27
47
  }
28
48
 
29
- const json = fs.readFileSync(registeredSubjectsPath, 'utf-8');
30
- return this.toIRegisteredSubjects(json) as unknown as IRegisteredSubjects[];
49
+ return this.parseJsonFile<IRegisteredSubjects[]>(registeredSubjectsPath);
31
50
  }
32
51
 
33
52
  public getSubjectsToBuild(): ISubject[] {
34
- const subjectsToBuildPath = path.join(this._consumerRootDirectory, 'seed-data/subjectsToBuild.json');
35
- if (!fs.existsSync(subjectsToBuildPath)) {
36
- console.info(`subjectsToBuild.json not found at: ${subjectsToBuildPath}. Using all subjects as fallback.`);
53
+ const subjectsToBuildPath = this._paths.subjectsToBuildJson;
37
54
 
55
+ if (!fs.existsSync(subjectsToBuildPath)) {
56
+ console.info(`subjectsToBuild.json not found – falling back to full subjects seed data.`);
38
57
  return this.getSubjectsSeedData();
39
58
  }
40
59
 
41
- const json = fs.readFileSync(subjectsToBuildPath, 'utf-8');
42
- return this.toISubject(json) as unknown as ISubject[];
60
+ return this.parseJsonFile<ISubject[]>(subjectsToBuildPath);
43
61
  }
44
62
 
45
63
  public getScreensToBuild(): string[] {
46
- const screensToBuildPath = path.join(this._consumerRootDirectory, 'seed-data/screensToBuild.json');
64
+ const screensToBuildPath = this._paths.screensToBuildJson;
65
+
47
66
  if (!fs.existsSync(screensToBuildPath)) {
48
- console.info(`screensToBuild.json not found.`);
67
+ console.info(`screensToBuild.json not found – all screens will be processed.`);
49
68
  return [];
50
69
  }
51
70
 
52
- const json = fs.readFileSync(screensToBuildPath, 'utf-8');
53
- return JSON.parse(json) as string[];
71
+ return this.parseJsonFile<string[]>(screensToBuildPath);
54
72
  }
55
73
 
56
- public getSeedDataDirectory(): string {
57
- return path.join(this._consumerRootDirectory, 'seed-data');
74
+ public getScreenComponentMeta(screenTypeId: string): Record<string, string> {
75
+ const schemaPath = `${this._paths.screenSchemas}/${screenTypeId}.json`;
76
+
77
+ if (!fs.existsSync(schemaPath)) return {};
78
+
79
+ const schema = this.parseJsonFile<{ properties?: Record<string, unknown> }>(schemaPath);
80
+ const result: Record<string, string> = {};
81
+
82
+ for (const originalId of Object.keys(schema.properties ?? {})) {
83
+ // Normalize to lowercase-alphanumeric so the lookup is insensitive to
84
+ // camelCase variations between change-case and quicktype's nice-property-names.
85
+ const normalizedKey = originalId.toLowerCase().replace(/[^a-z0-9]/g, '');
86
+ result[normalizedKey] = originalId;
87
+ }
88
+
89
+ return result;
58
90
  }
59
91
 
60
- private toISubject(json: string): ISubject {
61
- return JSON.parse(json);
92
+ public getSeedDataDirectory(): string {
93
+ return this._paths.seedData;
62
94
  }
63
95
 
64
- private toIRegisteredSubjects(json: string): IRegisteredSubjects {
65
- return JSON.parse(json);
96
+ private parseJsonFile<T>(filePath: string): T {
97
+ const raw = fs.readFileSync(filePath, 'utf-8');
98
+ try {
99
+ return JSON.parse(raw) as T;
100
+ } catch (cause) {
101
+ throw new Error(`Failed to parse JSON at ${filePath}: ${(cause as Error).message}`);
102
+ }
66
103
  }
67
104
  }
@@ -1,8 +1,24 @@
1
1
  import * as path from 'node:path';
2
2
  import { pascalCase, snakeCase } from 'change-case';
3
3
  import { KnownElementTypes } from '../../enums/ElementTypes.js';
4
- import type { ScreenComponents, SubjectComponents } from '../../types/Components.js';
5
-
4
+ import type { SubjectComponents } from '../../types/Components.js';
5
+
6
+ /**
7
+ * Centralises all naming and string-transformation logic used by the
8
+ * artifact-builder pipeline.
9
+ *
10
+ * **What it does:**
11
+ * - Converts subject/variant/screentype tuples into the correct PascalCase
12
+ * class names that are written to the generated subject files.
13
+ * - Maps `control_type` strings from the Indicium API to the Testwise control
14
+ * class suffix that appears in generated component interfaces
15
+ * (e.g. `"lookup"` → `"Lookup"` → property name ends in `Lookup`).
16
+ * - Handles edge cases like `Form` vs `Grid` defaults and multi-variant naming.
17
+ *
18
+ * **For contributors:** If the Thinkwise model introduces a new control type
19
+ * that should map to a different Testwise control, add it to the mapping
20
+ * matrix inside `getElementSuffixFromControlTypeAndComponentType`.
21
+ */
6
22
  export class NamingHandler {
7
23
  public getDefaultElementSuffixFromComponentType(componentType: SubjectComponents): KnownElementTypes {
8
24
  const controlTypeMapping: Record<SubjectComponents, KnownElementTypes> = {
@@ -47,49 +63,6 @@ export class NamingHandler {
47
63
  ).toLowerCase();
48
64
  }
49
65
 
50
- public getIdFromElementName(elementName: string, componentType: SubjectComponents, controlType: string): string {
51
- const elementSuffixToRemove = this.getElementSuffixFromControlTypeAndComponentType(controlType, componentType);
52
- const elementSuffixToRemoveFormatted = elementSuffixToRemove.replace(/_/g, '-').toLowerCase();
53
-
54
- let id = this.toSnakeCase(elementName)
55
- .replace(/([a-z])([A-Z])/g, '$1-$2')
56
- .toLowerCase()
57
- .replace(/_/g, '-');
58
-
59
- if (elementSuffixToRemove) {
60
- const suffixRegex = new RegExp(`-?${elementSuffixToRemoveFormatted}$`, 'i');
61
- id = id.replace(suffixRegex, '');
62
- }
63
-
64
- return id.replace(/-+/g, '-').replace(/-+$/g, '');
65
- }
66
-
67
- public getComponentTypeFromFileName(fileName: string): SubjectComponents {
68
- // ToDo: use this
69
- const match = fileName.match(/([A-Z][a-z]+)(?=\.ts$)/);
70
- if (match) {
71
- const componentName = match[1];
72
- if (componentName === 'Form') return 'Form';
73
- if (componentName === 'Grid') return 'Grid';
74
- }
75
- throw new Error(`Unknown component type in file name: ${fileName}`);
76
- }
77
-
78
- public getElementTypeFromElementName(elementName: string): string {
79
- const snakeCaseElementName = this.toSnakeCase(elementName);
80
- const parts = snakeCaseElementName.split('_');
81
-
82
- for (let i = parts.length - 1; i > 0; i--) {
83
- const candidate = parts.slice(i).join('_');
84
-
85
- if (Object.values(KnownElementTypes).includes(candidate as KnownElementTypes)) {
86
- return candidate;
87
- }
88
- }
89
-
90
- throw new Error(`No KnownElementType match found for a partial suffix of "${elementName}"`);
91
- }
92
-
93
66
  public getSubjectFromFileName(fileName: string): string {
94
67
  return fileName.replace(/([A-Z][a-z0-9]*)$/, '');
95
68
  }
@@ -102,6 +75,10 @@ export class NamingHandler {
102
75
  return pascalCase(name);
103
76
  }
104
77
 
78
+ public toSubjectPascalCase(name: string): string {
79
+ return this.toPascalCase(name.replace(/_(\d)/g, '$1'));
80
+ }
81
+
105
82
  public formatPropertyName(name: string): string {
106
83
  return name.charAt(0).toLowerCase() + name.slice(1);
107
84
  }
@@ -114,45 +91,13 @@ export class NamingHandler {
114
91
  return snakeCase(value);
115
92
  }
116
93
 
117
- public getComponentIdFromName(componentName: string, componentType: ScreenComponents): string {
118
- if (componentType === 'ActionBar' || componentType === 'CustomActionBar') {
119
- const capitalizedComponentName = this.capitalizeFirstLetter(componentName);
120
- return capitalizedComponentName.replace(/Toolbar/, 'Toolbar_');
121
- }
122
-
123
- if (componentType === 'Splitter') {
124
- const componentId = componentName.toLowerCase();
125
-
126
- if (/^splitter\d+$/.test(componentId)) {
127
- return componentId;
128
- }
129
-
130
- return componentId.replace(/splitter/, 'splitter-');
131
- }
132
-
133
- if (componentType === 'Tab') {
134
- return this.capitalizeFirstLetter(componentName);
135
- }
136
-
137
- return componentName;
138
- }
139
-
140
94
  public capitalizeFirstLetter(value: string): string {
141
95
  return value.charAt(0).toUpperCase() + value.slice(1);
142
96
  }
143
97
 
144
- public getTabParentFromComponentName(componentName: string): string {
145
- const match = componentName.match(/^[a-z0-9]+(?=[A-Z])/);
146
- if (match) {
147
- return match[0];
148
- }
149
-
150
- throw new Error(`Could not extract tab parent from component name: ${componentName}`);
151
- }
152
-
153
98
  public generateSubjectClassName(subject: { subject: string; screentype_context: string; variant: string }): string {
154
99
  const uniqueSubjectIdentifier = subject.variant !== '' ? `${subject.subject}_${subject.variant}` : subject.subject;
155
100
  const className = `${uniqueSubjectIdentifier}_${subject.screentype_context}`;
156
- return this.toPascalCase(className);
101
+ return this.toSubjectPascalCase(className);
157
102
  }
158
103
  }
@@ -0,0 +1,123 @@
1
+ import * as path from 'node:path';
2
+ import { dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { PathResolver } from '../../helpers/PathResolver.js';
5
+
6
+ // Resolved once at module load so every PipelinePaths instance shares
7
+ // the same package root without re-computing it on construction.
8
+ const _moduleFilename = fileURLToPath(import.meta.url);
9
+ const _moduleDirname = dirname(_moduleFilename);
10
+
11
+ // dist/artifact-builder/helpers → dist/artifact-builder → dist → package-root
12
+ const packageRoot = path.resolve(_moduleDirname, '../../..');
13
+
14
+ /**
15
+ * Single source of truth for all filesystem paths used by the artifact-builder
16
+ * pipeline.
17
+ *
18
+ * - Generated seed data (subjects.json, screen-schemas) lives under the
19
+ * **package root** (`node_modules/@thinkwise/testwise/seed-data/`) because
20
+ * it is rebuilt on every sync and can safely be regenerated.
21
+ * - `registeredSubjects.json` lives in the **consumer project root** because
22
+ * it represents the user's curated subject list and must never be lost when
23
+ * `node_modules` is wiped and reinstalled.
24
+ */
25
+ export class PipelinePaths {
26
+ private readonly _packageRoot: string;
27
+ private readonly _consumerRoot: string;
28
+
29
+ constructor() {
30
+ this._packageRoot = packageRoot;
31
+ /* v8 ignore next -- PathResolver walks the real filesystem; exercised via integration */
32
+ this._consumerRoot = new PathResolver().getConsumerRootDirectory();
33
+ }
34
+
35
+ // ── Package root – seed data ─────────────────────────────────────────────
36
+
37
+ /** `<package>/seed-data/` */
38
+ get seedData(): string {
39
+ return path.join(this._packageRoot, 'seed-data');
40
+ }
41
+
42
+ /** `<consumer>/seed-data/screen-schemas/` */
43
+ get screenSchemas(): string {
44
+ return path.join(this.seedData, 'screen-schemas');
45
+ }
46
+
47
+ /** `<consumer>/seed-data/subjects.json` */
48
+ get subjectsJson(): string {
49
+ return path.join(this.seedData, 'subjects.json');
50
+ }
51
+
52
+ /** `<consumer>/seed-data/subjectsToBuild.json` */
53
+ get subjectsToBuildJson(): string {
54
+ return path.join(this.seedData, 'subjectsToBuild.json');
55
+ }
56
+
57
+ /** `<consumer>/seed-data/screensToBuild.json` */
58
+ get screensToBuildJson(): string {
59
+ return path.join(this.seedData, 'screensToBuild.json');
60
+ }
61
+
62
+ /** `<consumer>/seed-data/registeredSubjects.json` – lives in the consumer project so it survives `npm install` */
63
+ get registeredSubjectsJson(): string {
64
+ return path.join(this._consumerRoot, 'seed-data', 'registeredSubjects.json');
65
+ }
66
+
67
+ // ── Package root – generated artifacts ─────────────────────────────────
68
+
69
+ /** `<package>/test-artifacts/` */
70
+ get testArtifacts(): string {
71
+ return path.join(this._packageRoot, 'test-artifacts');
72
+ }
73
+
74
+ /** `<package>/test-artifacts/screens/` */
75
+ get screens(): string {
76
+ return path.join(this.testArtifacts, 'screens');
77
+ }
78
+
79
+ /** `<package>/test-artifacts/screens/index.ts` */
80
+ get screensIndex(): string {
81
+ return path.join(this.screens, 'index.ts');
82
+ }
83
+
84
+ /** `<package>/test-artifacts/subjects/` */
85
+ get subjects(): string {
86
+ return path.join(this.testArtifacts, 'subjects');
87
+ }
88
+
89
+ /**
90
+ * `<package>/dist/test-artifacts/schemas/`
91
+ *
92
+ * Intermediate JSON schemas are kept inside `dist/` so that the TypeScript
93
+ * compiler does not include them in compilation but they are accessible at
94
+ * runtime after the initial `tsc` pass.
95
+ */
96
+ get schemas(): string {
97
+ return path.join(this._packageRoot, 'dist', 'test-artifacts', 'schemas');
98
+ }
99
+
100
+ // ── Package root – source files ─────────────────────────────────────────
101
+
102
+ /** `<package>/page-extensions/SubjectRegistry.ts` */
103
+ get subjectRegistry(): string {
104
+ return path.join(this._packageRoot, 'page-extensions', 'SubjectRegistry.ts');
105
+ }
106
+
107
+ /** `<package>/templates/SubjectRegistry.template.ts` */
108
+ get subjectRegistryTemplate(): string {
109
+ return path.join(this._packageRoot, 'templates', 'SubjectRegistry.template.ts');
110
+ }
111
+
112
+ // ── Derived helpers ─────────────────────────────────────────────────────
113
+
114
+ /** `<package>/test-artifacts/subjects/<subjectName>/` */
115
+ subjectFolder(subjectName: string): string {
116
+ return path.join(this.subjects, subjectName);
117
+ }
118
+
119
+ /** `<package>/test-artifacts/subjects/<subjectName>/Components/` */
120
+ subjectComponentsFolder(subjectName: string): string {
121
+ return path.join(this.subjectFolder(subjectName), 'Components');
122
+ }
123
+ }
@@ -1,5 +1,15 @@
1
1
  import { performance } from 'node:perf_hooks';
2
2
 
3
+ /**
4
+ * Minimal lap timer used to log how long each pipeline step takes.
5
+ *
6
+ * ```ts
7
+ * const sw = new Stopwatch();
8
+ * const lap = sw.start('SchemaGenerator');
9
+ * // ... do work ...
10
+ * lap.stop(); // logs: "[0.412s]: SchemaGenerator"
11
+ * ```
12
+ */
3
13
  export class Stopwatch {
4
14
  start(message: string) {
5
15
  const startTime = performance.now();
@@ -1,3 +1,4 @@
1
1
  export * from './DataRetriever.js';
2
2
  export * from './NamingHandler.js';
3
+ export * from './PipelinePaths.js';
3
4
  export * from './Stopwatch.js';
@@ -1,9 +1,13 @@
1
1
  export * from './ArtifactManager.js';
2
+ export * from './ComponentClassModelBuilder.js';
2
3
  export * from './helpers/index.js';
3
4
  export * from './InterfaceGenerator.js';
4
5
  export * from './ModelDataRefiner.js';
5
6
  export * from './SchemaGenerator.js';
6
7
  export * from './ScreenInterfaceRefiner.js';
8
+ export * from './SubjectClassModelBuilder.js';
7
9
  export * from './SubjectComponentGenerator.js';
8
10
  export * from './SubjectGenerator.js';
9
11
  export * from './SubjectRegistration.js';
12
+ export * from './TsFileModel.js';
13
+ export * from './TsFileSerializer.js';