@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
package/Testwise.ts CHANGED
@@ -9,6 +9,41 @@ import type { Test } from './types/Test.js';
9
9
 
10
10
  export * from '@playwright/test';
11
11
 
12
+ /**
13
+ * The main entry point for the Testwise library.
14
+ *
15
+ * **What to import:** Consumer projects import `test` (and optionally
16
+ * `bddTest`) from `@thinkwise/testwise` instead of from `@playwright/test`.
17
+ * This gives you a fully-extended fixture with all Testwise capabilities
18
+ * already wired up:
19
+ *
20
+ * ```ts
21
+ * import { test, expect } from '@thinkwise/testwise';
22
+ *
23
+ * test('create employee', async ({ page }) => {
24
+ * await page.logIn();
25
+ * const emp = await page.subject.EmployeeEditable1Main.goTo();
26
+ * await emp.form.firstNameField.fill('Jane');
27
+ * await emp.actionBar.save();
28
+ * await expect(page.components.snackBar.message).toBeVisible();
29
+ * });
30
+ * ```
31
+ *
32
+ * **What `test` adds on top of Playwright base:**
33
+ *
34
+ * | Layer | What it adds |
35
+ * |---|---|
36
+ * | `ClickOverride` / `FillOverride` | Patches `page.click` and `page.fill` to wait for XHR idle after each action |
37
+ * | `Components` | `page.components` — global Thinkwise UI component instances |
38
+ * | `GoToDeepLink` | `page.goToDeepLink(path)` — deep-link navigation |
39
+ * | `LoginFeatures` | `page.logIn()` / `page.logOut()` etc. |
40
+ * | `UserSimulation` | `page.simulate.*` — keyboard/mouse helpers |
41
+ * | `WaitEventHandler` | `page.waitEvent(url)` — waits for specific response URLs |
42
+ * | `SubjectRegistry` | `page.subject.*` — access to all generated subject classes |
43
+ *
44
+ * Use `bddTest` instead of `test` when combining Testwise with `playwright-bdd`
45
+ * step definitions.
46
+ */
12
47
  function combineExtensions(baseTest: Test, ...extensions: { new (test: Test): { test: Test } }[]) {
13
48
  return extensions.reduce((test, Extension) => new Extension(test).test, baseTest);
14
49
  }
@@ -1,16 +1,39 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
+ import { PipelinePaths } from './helpers/PipelinePaths.js';
4
5
 
6
+ /**
7
+ * Manages backup and restore of the `test-artifacts/` directory to protect
8
+ * against failed or partial pipeline runs.
9
+ *
10
+ * **What it does:**
11
+ * - Before the pipeline writes any new files it calls `performBackup()` to
12
+ * copy the existing `test-artifacts/` folder into a sibling
13
+ * `@thinkwise/backups/test-artifacts/` package that survives `node_modules`
14
+ * reinstalls.
15
+ * - If the pipeline fails, the caller invokes `restoreBackup()` to reinstate
16
+ * the last known-good artifacts so the consumer project's tests remain
17
+ * runnable while the issue is investigated.
18
+ *
19
+ * **When it is called:** Automatically by `sync.js` at the start and on
20
+ * failure of every `testwise sync` run. You do not need to call it manually.
21
+ */
5
22
  export class ArtifactManager {
6
23
  private _backupPath: string;
7
24
  private _artifactPath: string;
8
25
 
9
- constructor() {
26
+ constructor(paths?: PipelinePaths) {
27
+ const p = paths ?? new PipelinePaths();
28
+ this._artifactPath = p.testArtifacts;
29
+
30
+ // The backup is stored in the sibling @thinkwise/backups package so it
31
+ // survives reinstalls of this package. Three levels up from
32
+ // dist/artifact-builder/ lands at node_modules/@thinkwise/ (the org scope
33
+ // folder), and from there we descend into the backups package.
10
34
  const _filename = fileURLToPath(import.meta.url);
11
35
  const _dirname = path.dirname(_filename);
12
36
  this._backupPath = path.resolve(_dirname, '..', '..', '..', 'backups', 'test-artifacts');
13
- this._artifactPath = path.resolve(_dirname, '..', '..', 'test-artifacts');
14
37
  }
15
38
 
16
39
  performBackup() {
@@ -0,0 +1,148 @@
1
+ import { KnownElementTypes } from '../enums/ElementTypes.js';
2
+ import type { IComponentSchemaMeta } from '../interfaces/IComponentSchemaMeta.js';
3
+ import type { SubjectComponents } from '../types/Components.js';
4
+ import type { NamingHandler } from './helpers/NamingHandler.js';
5
+ import type { SelectorBuilder } from './SelectorBuilder.js';
6
+ import type {
7
+ ComponentAssignmentModel,
8
+ ComponentClassModel,
9
+ ComponentGetterModel,
10
+ ComponentPropertyModel
11
+ } from './TsFileModel.js';
12
+
13
+ /**
14
+ * **Pipeline sub-step** — Builds a pure in-memory model (`ComponentClassModel`)
15
+ * for the typed component class appended to a generated screen interface file
16
+ * (e.g. `EmployeeForm`, `EmployeeGrid`). Contains no file I/O — fully unit-testable.
17
+ */
18
+ export class ComponentClassModelBuilder {
19
+ private readonly _namingHandler: NamingHandler;
20
+ private readonly _selectorBuilder: SelectorBuilder;
21
+
22
+ constructor(namingHandler: NamingHandler, selectorBuilder: SelectorBuilder) {
23
+ this._namingHandler = namingHandler;
24
+ this._selectorBuilder = selectorBuilder;
25
+ }
26
+
27
+ public build(
28
+ interfaceName: string,
29
+ componentType: SubjectComponents,
30
+ propertyLines: string[],
31
+ meta: IComponentSchemaMeta
32
+ ): ComponentClassModel {
33
+ if (componentType === 'Grid') {
34
+ return {
35
+ interfaceName,
36
+ componentType,
37
+ properties: [],
38
+ assignments: [],
39
+ getters: this.buildGetters(propertyLines, meta)
40
+ };
41
+ }
42
+
43
+ return {
44
+ interfaceName,
45
+ componentType,
46
+ properties: this.buildProperties(propertyLines, meta),
47
+ assignments: this.buildAssignments(propertyLines, meta),
48
+ getters: []
49
+ };
50
+ }
51
+
52
+ public buildGetters(propertyLines: string[], meta: IComponentSchemaMeta): ComponentGetterModel[] {
53
+ return propertyLines.map((line) => {
54
+ const property = line.replace('readonly', '').split(':')[0].trim();
55
+ const colId =
56
+ meta.properties[this._namingHandler.toSnakeCase(property)]?.colId ??
57
+ this.getColIdFromPropertyName(property, 'Grid');
58
+ const columnId = this._selectorBuilder.getElementId(colId, 'Grid');
59
+
60
+ return {
61
+ name: property,
62
+ returnType: 'IGridColumnControl',
63
+ bodyLine: `return createGridColumnControl(this._context, '${columnId}');`
64
+ };
65
+ });
66
+ }
67
+
68
+ public buildProperties(propertyLines: string[], meta: IComponentSchemaMeta): ComponentPropertyModel[] {
69
+ return propertyLines.map((line) => {
70
+ const property = line.replace(/^\s+/, '').split(':')[0].replace(/\?$/, '').trim();
71
+ return { name: property, type: this.resolvePropertyType(property, meta) };
72
+ });
73
+ }
74
+
75
+ public buildAssignments(propertyLines: string[], meta: IComponentSchemaMeta): ComponentAssignmentModel[] {
76
+ return propertyLines.map((line) => {
77
+ const property = line.split(':')[0].replace(/\?$/, '').trim();
78
+ const snakeKey = this._namingHandler.toSnakeCase(property);
79
+ const propMeta = meta.properties[snakeKey];
80
+ const colId = propMeta?.colId ?? this.getColIdFromPropertyName(property, meta.componentType);
81
+ const elementType = propMeta?.elementType ?? this.getElementTypeFromPropertyName(property);
82
+
83
+ if (meta.componentType === 'Form') {
84
+ const elementId = this._selectorBuilder.getElementId(colId, 'Form');
85
+
86
+ switch (elementType) {
87
+ case KnownElementTypes.Lookup:
88
+ return { property, value: `createLookupDropdown(this._context, '${elementId}')` };
89
+ case KnownElementTypes.DatePicker:
90
+ return { property, value: `createDateControl(this._context, '${elementId}')` };
91
+ case KnownElementTypes.ComboBox:
92
+ return { property, value: `createFormComboBox(this._context, '${elementId}')` };
93
+ case KnownElementTypes.Field:
94
+ return { property, value: `createInputFieldControl(this._context, '${elementId}')` };
95
+ }
96
+ }
97
+
98
+ const pageLocatorString = this._selectorBuilder.getLocatorString(colId, elementType ?? '', meta.componentType);
99
+ return { property, value: pageLocatorString };
100
+ });
101
+ }
102
+
103
+ private resolvePropertyType(property: string, meta: IComponentSchemaMeta): string {
104
+ if (meta.componentType === 'Form') {
105
+ const elementType =
106
+ meta.properties[this._namingHandler.toSnakeCase(property)]?.elementType ??
107
+ this.getElementTypeFromPropertyName(property);
108
+
109
+ switch (elementType) {
110
+ case KnownElementTypes.Lookup:
111
+ return 'ILookupDropdown';
112
+ case KnownElementTypes.ComboBox:
113
+ return 'IFormComboBox';
114
+ case KnownElementTypes.Field:
115
+ return 'IInputFieldControl';
116
+ case KnownElementTypes.DatePicker:
117
+ return 'IDateControl';
118
+ }
119
+ }
120
+
121
+ return 'Locator';
122
+ }
123
+
124
+ private getElementTypeFromPropertyName(property: string): string | undefined {
125
+ if (property.endsWith('Lookup')) return KnownElementTypes.Lookup;
126
+ if (property.endsWith('DatePicker')) return KnownElementTypes.DatePicker;
127
+ if (property.endsWith('ComboBox')) return KnownElementTypes.ComboBox;
128
+ if (property.endsWith('Field')) return KnownElementTypes.Field;
129
+ return undefined;
130
+ }
131
+
132
+ private getColIdFromPropertyName(property: string, componentType: SubjectComponents): string {
133
+ const snakeName = this._namingHandler.toSnakeCase(property);
134
+
135
+ if (componentType === 'Grid') {
136
+ return snakeName.replace(/_column$/, '');
137
+ }
138
+
139
+ const formSuffixes = ['_lookup', '_date_picker', '_combo_box', '_dropdown', '_field', '_checkbox', '_textarea'];
140
+ for (const suffix of formSuffixes) {
141
+ if (snakeName.endsWith(suffix)) {
142
+ return snakeName.slice(0, -suffix.length);
143
+ }
144
+ }
145
+
146
+ return snakeName;
147
+ }
148
+ }
@@ -1,29 +1,40 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
3
  import * as prettier from 'prettier';
5
4
  import { FetchingJSONSchemaStore, InputData, JSONSchemaInput, quicktype } from 'quicktype-core';
6
- import { PathResolver } from '../helpers/PathResolver.js';
7
- import { DataRetriever, NamingHandler } from '../index.js';
5
+ import { DataRetriever, NamingHandler, PipelinePaths } from './helpers/index.js';
6
+
7
+ /**
8
+ * **Pipeline Step 4** — Runs quicktype to convert the JSON Schema files
9
+ * produced by `SchemaGenerator` into TypeScript interface files.
10
+ *
11
+ * **What it does:** For each schema in `dist/test-artifacts/schemas/`, it
12
+ * invokes the `quicktype-core` library to generate a `.ts` file containing
13
+ * a TypeScript interface that matches the JSON shape. The result lands in
14
+ * `test-artifacts/screens/` and is then refined by `ScreenInterfaceRefiner`.
15
+ *
16
+ * **When it runs:** Step 4 of `testwise sync`, after `SchemaGenerator`.
17
+ */
8
18
 
9
19
  export class InterfaceGenerator {
10
20
  private readonly _namingHandler: NamingHandler;
11
- private _filename: string;
12
- private _dirname: string;
13
- private _screensToBuild: string[];
21
+ private readonly _screensToBuild: string[];
22
+ private readonly _paths: PipelinePaths;
14
23
 
15
- constructor() {
24
+ constructor(paths?: PipelinePaths) {
25
+ this._paths = paths ?? new PipelinePaths();
16
26
  this._namingHandler = new NamingHandler();
17
- this._filename = fileURLToPath(import.meta.url);
18
- this._dirname = path.dirname(this._filename);
19
- this._screensToBuild = new DataRetriever().getScreensToBuild();
27
+ this._screensToBuild = new DataRetriever(this._paths).getScreensToBuild();
20
28
  }
21
29
 
22
30
  public async generateScreenInterfacesFromSchemas() {
23
- const screenOutputDirectory = path.resolve(this._dirname, '..', '..', 'test-artifacts/screens/');
31
+ const screenOutputDirectory = this._paths.screens;
24
32
  this.verifyOutputDirectory(screenOutputDirectory);
25
33
 
26
- const schemasDirectory = this.getScreenSchemaFilesPath();
34
+ const schemasDirectory = this._paths.screenSchemas;
35
+ if (!fs.existsSync(schemasDirectory)) {
36
+ throw new Error(`Screen schemas directory not found at: ${schemasDirectory}`);
37
+ }
27
38
 
28
39
  await this.generateInterfacesFromSchemaFiles(schemasDirectory, SchemaType.Screen, screenOutputDirectory);
29
40
 
@@ -31,10 +42,14 @@ export class InterfaceGenerator {
31
42
  }
32
43
 
33
44
  public async generateSubjectInterfacesFromSchemas() {
34
- const schemasDirectory = path.resolve(this._dirname, '../test-artifacts/schemas');
35
- const subjectOutputDirectory = path.resolve(this._dirname, '..', '..', 'test-artifacts/subjects');
45
+ const schemasDirectory = this._paths.schemas;
46
+ const subjectOutputDirectory = this._paths.subjects;
47
+
48
+ if (!fs.existsSync(schemasDirectory)) {
49
+ // No schemas generated yet – nothing to do.
50
+ return;
51
+ }
36
52
 
37
- this.verifyGeneratedSubjectSchemasDirectory(schemasDirectory);
38
53
  this.verifyOutputDirectory(subjectOutputDirectory);
39
54
 
40
55
  await this.generateInterfacesFromSchemaFiles(schemasDirectory, SchemaType.Subject, subjectOutputDirectory);
@@ -42,12 +57,6 @@ export class InterfaceGenerator {
42
57
  console.info('All subject schemas processed.');
43
58
  }
44
59
 
45
- private verifyGeneratedSubjectSchemasDirectory(directory: string) {
46
- if (!fs.existsSync(directory)) {
47
- return;
48
- }
49
- }
50
-
51
60
  private verifyOutputDirectory(directory: string) {
52
61
  if (!fs.existsSync(directory)) {
53
62
  fs.mkdirSync(directory, { recursive: true });
@@ -55,7 +64,7 @@ export class InterfaceGenerator {
55
64
  }
56
65
 
57
66
  private getGeneratedSubjectSchemas(schemasDirectory: string): string[] {
58
- return fs.readdirSync(schemasDirectory).filter((f) => f.endsWith('.json'));
67
+ return fs.readdirSync(schemasDirectory).filter((f) => f.endsWith('.json') && !f.endsWith('.meta.json'));
59
68
  }
60
69
 
61
70
  private verifySubjectComponentsDirectory(directory: string, subject: string) {
@@ -154,17 +163,6 @@ export class InterfaceGenerator {
154
163
 
155
164
  await Promise.all(tasks);
156
165
  }
157
-
158
- public getScreenSchemaFilesPath(): string {
159
- const directory = new PathResolver().getConsumerRootDirectory();
160
-
161
- const screenSchemasPath = path.join(directory, 'seed-data/screen-schemas/');
162
- if (!fs.existsSync(screenSchemasPath)) {
163
- throw new Error(`Screen schemas directory not found at: ${screenSchemasPath}`);
164
- }
165
-
166
- return screenSchemasPath;
167
- }
168
166
  }
169
167
 
170
168
  enum SchemaType {
@@ -1,21 +1,24 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- /** biome-ignore-all lint/style/noNonNullAssertion: Because I can */
3
2
  /** biome-ignore-all lint/suspicious/noExplicitAny: Because I can */
4
3
  import * as fs from 'node:fs/promises';
5
4
  import * as path from 'node:path';
6
5
  import type { IProperty } from '../interfaces/IProperty.js';
6
+ import type { ISeedSubjectDraft } from '../interfaces/ISeedSubjectDraft.js';
7
7
  import { indiciumApi } from '../services/IndiciumApi.service.js';
8
8
  import { DataRetriever } from './helpers/DataRetriever.js';
9
9
 
10
- // ToDo: move this to a types folder
11
- type Subjects = {
10
+ interface IPropertyWithSubjectIdentifiers extends IProperty {
12
11
  subject: string;
13
12
  variant: string;
14
- screentype_context: string;
15
- screentype_id: 'main' | 'detail' | 'zoom' | 'popup';
16
- properties?: IProperty[];
17
- };
13
+ }
18
14
 
15
+ /**
16
+ * **Pipeline Step 1** — Fetches the raw Thinkwise application model from the
17
+ * Indicium API and writes it into `seed-data/`.
18
+ * Calls the API to list all subjects + properties, writes `subjects.json`,
19
+ * and downloads each subject's screen schema JSON into `seed-data/screen-schemas/`.
20
+ * Run via `testwise sync` — requires valid credentials in `Testwise.json`.
21
+ */
19
22
  export async function buildSubjects() {
20
23
  if (!(await indiciumApi.canConnectToProject())) {
21
24
  console.log('Cannot connect to Indicium API. Aborting subject build.');
@@ -24,7 +27,7 @@ export async function buildSubjects() {
24
27
 
25
28
  const rawTables: any[] = await indiciumApi.getAllTables();
26
29
 
27
- const subjects: Subjects[] = rawTables
30
+ const subjects: ISeedSubjectDraft[] = rawTables
28
31
  .flatMap((tab: any) => {
29
32
  const base = {
30
33
  subject: tab.tab_id,
@@ -77,18 +80,19 @@ export async function buildSubjects() {
77
80
  console.log(`Seed data written to ${seedDataPath}`);
78
81
  }
79
82
 
80
- async function setLookupDropdowns(subjects: Subjects[]): Promise<Subjects[]> {
83
+ async function setLookupDropdowns(subjects: ISeedSubjectDraft[]): Promise<ISeedSubjectDraft[]> {
81
84
  const lookupMappings: any[] = await indiciumApi.getLookups();
82
85
 
83
86
  for (const mapping of lookupMappings) {
84
- const targetSubject = subjects.find(
87
+ const matchingSubjects = subjects.filter(
85
88
  (subj) => subj.subject === mapping.tab_id && subj.variant === mapping.tab_variant_id
86
89
  );
87
90
 
88
- const targetProperty = targetSubject?.properties?.find((prop) => prop.col === mapping.col_id);
89
-
90
- if (targetProperty) {
91
- targetProperty.control_type = 'LOOKUP_DROPDOWN';
91
+ for (const subject of matchingSubjects) {
92
+ const targetProperty = subject.properties?.find((prop) => prop.col === mapping.col_id);
93
+ if (targetProperty) {
94
+ targetProperty.control_type = 'LOOKUP_DROPDOWN';
95
+ }
92
96
  }
93
97
  }
94
98
 
@@ -157,9 +161,3 @@ export async function buildScreens() {
157
161
  }
158
162
  console.log('Screen schemas generated successfully.');
159
163
  }
160
-
161
- // ToDo: move this to a interfaces folder
162
- interface IPropertyWithSubjectIdentifiers extends IProperty {
163
- subject: string;
164
- variant: string;
165
- }
@@ -1,10 +1,30 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { DataRetriever } from '../index.js';
4
3
  import type { IRegisteredSubjects } from '../interfaces/IRegisteredSubjects.js';
5
-
4
+ import { DataRetriever } from './helpers/DataRetriever.js';
5
+ import type { PipelinePaths } from './helpers/PipelinePaths.js';
6
+
7
+ /**
8
+ * **Pipeline Step 2** — Filters the full subject seed-data down to only the
9
+ * subjects that the consumer project has registered.
10
+ *
11
+ * **What it does:**
12
+ * - Reads `registeredSubjects.json` from the consumer project root (the
13
+ * curated list the developer maintains via `testwise register`).
14
+ * - Intersects it with `seed-data/subjects.json` to produce two smaller files:
15
+ * - `seed-data/subjectsToBuild.json` — subjects whose classes need generating.
16
+ * - `seed-data/screensToBuild.json` — screen schema files to run through quicktype.
17
+ * - If no subjects are registered, it clears both files so later steps produce
18
+ * no output instead of failing.
19
+ *
20
+ * **When it runs:** Step 2 of `testwise sync`, immediately after `ModelDataBuilder`.
21
+ */
6
22
  export class ModelDataRefiner {
7
- private _dataRetriever = new DataRetriever();
23
+ private readonly _dataRetriever: DataRetriever;
24
+
25
+ constructor(paths?: PipelinePaths) {
26
+ this._dataRetriever = new DataRetriever(paths);
27
+ }
8
28
 
9
29
  public run() {
10
30
  const seedDataDir = this._dataRetriever.getSeedDataDirectory();
@@ -1,30 +1,45 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
- import { dirname } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
- import { DataRetriever } from '../index.js';
7
4
  import type { ISubject } from '../interfaces/ISubject.js';
8
5
  import type { SubjectComponents } from '../types/Components.js';
6
+ import { DataRetriever } from './helpers/DataRetriever.js';
9
7
  import { NamingHandler } from './helpers/NamingHandler.js';
10
-
11
- const currentFilename = fileURLToPath(import.meta.url);
12
- const currentDirname = dirname(currentFilename);
13
-
8
+ import { PipelinePaths } from './helpers/PipelinePaths.js';
9
+
10
+ /**
11
+ * **Pipeline Step 3** — Converts raw Thinkwise screen-schema JSON files into
12
+ * structured JSON Schema files that `quicktype` can consume.
13
+ *
14
+ * **What it does:**
15
+ * - Reads the screen-schema files listed in `seed-data/screensToBuild.json`.
16
+ * - For each subject, generates a JSON Schema describing the shape of the
17
+ * screen's fields and component structure.
18
+ * - Writes one `.json` schema and one `.meta.json` sidecar file per screen
19
+ * into `dist/test-artifacts/schemas/`. The `.meta.json` records which
20
+ * component type (Form or Grid) owns each property, which
21
+ * `SubjectComponentGenerator` reads back in step 6.
22
+ *
23
+ * **When it runs:** Step 3 of `testwise sync`, after `ModelDataRefiner`.
24
+ */
14
25
  export class SchemaGenerator {
15
- private _namingHandler: NamingHandler;
16
- private _dataRetriever: DataRetriever;
17
-
18
- constructor() {
26
+ private readonly _namingHandler: NamingHandler;
27
+ private readonly _dataRetriever: DataRetriever;
28
+ private readonly _schemasDir: string;
29
+ private readonly _screensDir: string;
30
+
31
+ constructor(paths?: PipelinePaths) {
32
+ /* v8 ignore next -- default only used at runtime, not in unit tests */
33
+ const p = paths ?? new PipelinePaths();
19
34
  this._namingHandler = new NamingHandler();
20
- this._dataRetriever = new DataRetriever();
35
+ this._dataRetriever = new DataRetriever(p);
36
+ this._schemasDir = p.schemas;
37
+ this._screensDir = p.screens;
21
38
  }
22
39
 
23
40
  public generateSchema() {
24
- const schemasDir = path.resolve(currentDirname, '../dist/test-artifacts/schemas');
25
-
26
- if (!fs.existsSync(schemasDir)) {
27
- fs.mkdirSync(schemasDir, { recursive: true });
41
+ if (!fs.existsSync(this._schemasDir)) {
42
+ fs.mkdirSync(this._schemasDir, { recursive: true });
28
43
  }
29
44
 
30
45
  const subjects = this._dataRetriever.getSubjectsToBuild();
@@ -34,11 +49,6 @@ export class SchemaGenerator {
34
49
  }
35
50
  }
36
51
 
37
- public iSubjectToJson(value: ISubject): string {
38
- return JSON.stringify(value);
39
- }
40
-
41
- // Changes start here
42
52
  private createSubjectSchema(subject: ISubject): void {
43
53
  const screen = { content: this.getScreenContent(subject.screentype_id) };
44
54
  const componentsToProcess = this.getComponentsToProcess(screen);
@@ -76,21 +86,13 @@ export class SchemaGenerator {
76
86
 
77
87
  private getScreenContent(screenTypeId: string): string {
78
88
  const screenFileName = this._namingHandler.toPascalCase(screenTypeId);
79
- const _filename = fileURLToPath(import.meta.url);
80
- const _dirname = path.dirname(_filename);
81
- const screenLocation = path.resolve(_dirname, '..', '..', 'test-artifacts/screens/');
82
-
83
- return fs.readFileSync(path.join(screenLocation, `I${screenFileName}.ts`), 'utf-8');
89
+ return fs.readFileSync(path.join(this._screensDir, `I${screenFileName}.ts`), 'utf-8');
84
90
  }
85
91
 
86
92
  private createComponentSchema(subject: ISubject, componentType: SubjectComponents): void {
87
93
  const interfaceName = `${subject.subject}_${componentType.toLowerCase()}`;
88
- const schemasDir = path.join(currentDirname, '..', '..', 'dist/test-artifacts/schemas');
89
- const fileName = `${this._namingHandler.toPascalCase(interfaceName)}.json`;
90
-
91
- if (fs.existsSync(path.join(schemasDir, fileName))) {
92
- return;
93
- }
94
+ const fileName = `${this._namingHandler.toSubjectPascalCase(interfaceName)}.json`;
95
+ const schemaFilePath = path.join(this._schemasDir, fileName);
94
96
 
95
97
  // biome-ignore lint/suspicious/noExplicitAny: reason 42
96
98
  const componentSchema: any = {
@@ -111,6 +113,9 @@ export class SchemaGenerator {
111
113
  }
112
114
  };
113
115
 
116
+ // Maps original schema field name → { colId, elementType }
117
+ const propertyMeta: Record<string, { colId: string; elementType: string }> = {};
118
+
114
119
  subject.properties.forEach((property) => {
115
120
  const componentTypeSuffix = this._namingHandler.getElementSuffixFromControlTypeAndComponentType(
116
121
  property.control_type,
@@ -120,12 +125,17 @@ export class SchemaGenerator {
120
125
 
121
126
  componentSchema.properties[fieldName] = { $ref: '#/definitions/Locator' };
122
127
  componentSchema.required.push(fieldName);
128
+ propertyMeta[fieldName] = { colId: property.col, elementType: componentTypeSuffix };
123
129
  });
124
130
 
125
- if (!fs.existsSync(schemasDir)) {
126
- fs.mkdirSync(schemasDir, { recursive: true });
131
+ /* v8 ignore next 3 — generateSchema() always creates this dir first */
132
+ if (!fs.existsSync(this._schemasDir)) {
133
+ fs.mkdirSync(this._schemasDir, { recursive: true });
127
134
  }
128
135
 
129
- fs.writeFileSync(path.join(schemasDir, fileName), JSON.stringify(componentSchema, null, 2));
136
+ const schemaMeta = { componentType, properties: propertyMeta };
137
+ const metaFileName = fileName.replace('.json', '.meta.json');
138
+ fs.writeFileSync(schemaFilePath, JSON.stringify(componentSchema, null, 2));
139
+ fs.writeFileSync(path.join(this._schemasDir, metaFileName), JSON.stringify(schemaMeta, null, 2));
130
140
  }
131
141
  }
@@ -1,15 +1,31 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
3
  import { disabledScreenComponents, type ScreenComponents, screenComponents } from '../types/Components.js';
5
-
4
+ import { PipelinePaths } from './helpers/PipelinePaths.js';
5
+
6
+ /**
7
+ * **Pipeline Step 5** — Post-processes the raw TypeScript interface files
8
+ * emitted by `InterfaceGenerator` (quicktype) to make them usable as
9
+ * Testwise screen contracts.
10
+ *
11
+ * **What it does:**
12
+ * - Removes the `Locator` base interface that quicktype adds (not needed here).
13
+ * - Strips placeholder interfaces for component types that Testwise does not
14
+ * yet support (see `disabledScreenComponents`).
15
+ * - Merges multiple `Tab` component interfaces into one to avoid duplicates.
16
+ * - Adds the generated screen interface as an export to `screens/index.ts`.
17
+ *
18
+ * **When it runs:** Step 5 of `testwise sync`, immediately after
19
+ * `InterfaceGenerator` has written the raw quicktype output.
20
+ */
6
21
  export class ScreenInterfaceRefiner {
7
22
  private readonly _screensDirectory: string;
23
+ private readonly _screensIndexPath: string;
8
24
 
9
- constructor() {
10
- const _filename = fileURLToPath(import.meta.url);
11
- const _dirname = path.dirname(_filename);
12
- this._screensDirectory = path.resolve(_dirname, '../../test-artifacts/screens');
25
+ constructor(paths?: PipelinePaths) {
26
+ const p = paths ?? new PipelinePaths();
27
+ this._screensDirectory = p.screens;
28
+ this._screensIndexPath = p.screensIndex;
13
29
  }
14
30
 
15
31
  public refine() {
@@ -43,8 +59,7 @@ export class ScreenInterfaceRefiner {
43
59
  }
44
60
 
45
61
  private indexScreenInterface(screenFile: string) {
46
- const indexPath = path.resolve(this._screensDirectory, 'index.ts');
47
- let indexContent = fs.readFileSync(indexPath, 'utf-8');
62
+ let indexContent = fs.existsSync(this._screensIndexPath) ? fs.readFileSync(this._screensIndexPath, 'utf-8') : '';
48
63
 
49
64
  const fileJS = screenFile.replace('.ts', '.js');
50
65
  const exportLine = `export * from './${fileJS}';\n`;
@@ -56,7 +71,7 @@ export class ScreenInterfaceRefiner {
56
71
  }
57
72
  lines.splice(insertPos, 0, exportLine.trim());
58
73
  indexContent = lines.join('\n');
59
- fs.writeFileSync(indexPath, indexContent, 'utf-8');
74
+ fs.writeFileSync(this._screensIndexPath, indexContent, 'utf-8');
60
75
  }
61
76
  }
62
77
 
@@ -149,6 +164,6 @@ export class ScreenInterfaceRefiner {
149
164
  }
150
165
 
151
166
  private getAllScreenInterfaceFiles(): string[] {
152
- return fs.readdirSync(this._screensDirectory).filter((f) => f.endsWith('.ts'));
167
+ return fs.readdirSync(this._screensDirectory).filter((f) => f.endsWith('.ts') && f !== 'index.ts');
153
168
  }
154
169
  }