@thinkwise/testwise 0.2.67 → 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.
- package/Testwise.ts +35 -0
- package/artifact-builder/ArtifactManager.ts +25 -2
- package/artifact-builder/ComponentClassModelBuilder.ts +148 -0
- package/artifact-builder/InterfaceGenerator.ts +31 -33
- package/artifact-builder/ModelDataBuilder.ts +18 -20
- package/artifact-builder/ModelDataRefiner.ts +23 -3
- package/artifact-builder/SchemaGenerator.ts +45 -35
- package/artifact-builder/ScreenInterfaceRefiner.ts +25 -10
- package/artifact-builder/SelectorBuilder.ts +30 -24
- package/artifact-builder/SubjectClassModelBuilder.ts +209 -0
- package/artifact-builder/SubjectComponentGenerator.ts +67 -246
- package/artifact-builder/SubjectGenerator.ts +117 -230
- package/artifact-builder/SubjectRegistration.ts +41 -32
- package/artifact-builder/TsFileModel.ts +94 -0
- package/artifact-builder/TsFileSerializer.ts +247 -0
- package/artifact-builder/helpers/DataRetriever.ts +64 -27
- package/artifact-builder/helpers/NamingHandler.ts +23 -78
- package/artifact-builder/helpers/PipelinePaths.ts +123 -0
- package/artifact-builder/helpers/Stopwatch.ts +10 -0
- package/artifact-builder/helpers/index.ts +1 -0
- package/artifact-builder/index.ts +4 -0
- package/components/BaseComponentObjects.ts +17 -0
- package/components/action-bar/ActionBar.ts +35 -47
- package/components/action-bar/ActionBarObjects.ts +2 -0
- package/components/action-bar/CustomActionBar.ts +6 -0
- package/components/cardlist/Cardlist.ts +6 -0
- package/components/chart/Chart.ts +6 -0
- package/components/combined-filter/CombinedFilter.ts +9 -0
- package/components/cube-view-bar/CubeViewBar.ts +6 -0
- package/components/export/ExportComponent.ts +12 -0
- package/components/filter/ExcelStyleFilterPopup.ts +35 -2
- package/components/filter/FilterForm.ts +10 -0
- package/components/filter/FilterPopup.ts +30 -9
- package/components/filter/FilterPopupObjects.ts +10 -3
- package/components/filter/FindForm.ts +7 -0
- package/components/filter/ManagePrefilterPopup.ts +11 -0
- package/components/form/Form.ts +16 -0
- package/components/grid/Grid.ts +18 -1
- package/components/maps/Maps.ts +6 -0
- package/components/menu/ListBarMenuComponent.ts +10 -0
- package/components/pivot-grid/PivotGrid.ts +6 -0
- package/components/pivot-grid/PivotGridFieldList.ts +7 -0
- package/components/pop-up/AllRowsPopUp.ts +12 -0
- package/components/pop-up/PopUpComponent.ts +11 -0
- package/components/prefilter-list/PrefilterList.ts +9 -0
- package/components/preview/Preview.ts +6 -0
- package/components/report-bar/ReportBar.ts +6 -0
- package/components/report-tiles/ReportTiles.ts +6 -0
- package/components/scheduler/Scheduler.ts +6 -0
- package/components/snackbar/SnackBar.ts +12 -0
- package/components/splitter/Splitter.ts +6 -0
- package/components/tab/BaseTab.ts +5 -0
- package/components/tab/DetailTabPage.ts +11 -0
- package/components/tab/Tab.ts +10 -0
- package/components/task/TaskBar.ts +13 -3
- package/components/task/TaskTiles.ts +12 -3
- package/components/topbar/TopBar.ts +10 -0
- package/components/tree-view/TreeView.ts +9 -0
- package/controls/DateControl.ts +40 -1
- package/controls/FormComboBox.ts +30 -0
- package/controls/GridColumnControl.ts +34 -3
- package/controls/InputFieldControl.ts +49 -0
- package/controls/LookupDropdown.ts +29 -0
- package/dist/Testwise.js +35 -0
- package/dist/Testwise.js.map +1 -1
- package/dist/artifact-builder/ArtifactManager.d.ts +18 -1
- package/dist/artifact-builder/ArtifactManager.js +24 -2
- package/dist/artifact-builder/ArtifactManager.js.map +1 -1
- package/dist/artifact-builder/ComponentClassModelBuilder.d.ts +22 -0
- package/dist/artifact-builder/ComponentClassModelBuilder.js +115 -0
- package/dist/artifact-builder/ComponentClassModelBuilder.js.map +1 -0
- package/dist/artifact-builder/InterfaceGenerator.d.ts +15 -6
- package/dist/artifact-builder/InterfaceGenerator.js +27 -26
- package/dist/artifact-builder/InterfaceGenerator.js.map +1 -1
- package/dist/artifact-builder/ModelDataBuilder.d.ts +7 -0
- package/dist/artifact-builder/ModelDataBuilder.js +13 -5
- package/dist/artifact-builder/ModelDataBuilder.js.map +1 -1
- package/dist/artifact-builder/ModelDataRefiner.d.ts +18 -1
- package/dist/artifact-builder/ModelDataRefiner.js +18 -3
- package/dist/artifact-builder/ModelDataRefiner.js.map +1 -1
- package/dist/artifact-builder/SchemaGenerator.d.ts +21 -5
- package/dist/artifact-builder/SchemaGenerator.js +38 -26
- package/dist/artifact-builder/SchemaGenerator.js.map +1 -1
- package/dist/artifact-builder/ScreenInterfaceRefiner.d.ts +18 -1
- package/dist/artifact-builder/ScreenInterfaceRefiner.js +23 -9
- package/dist/artifact-builder/ScreenInterfaceRefiner.js.map +1 -1
- package/dist/artifact-builder/SelectorBuilder.d.ts +18 -5
- package/dist/artifact-builder/SelectorBuilder.js +29 -14
- package/dist/artifact-builder/SelectorBuilder.js.map +1 -1
- package/dist/artifact-builder/SubjectClassModelBuilder.d.ts +38 -0
- package/dist/artifact-builder/SubjectClassModelBuilder.js +158 -0
- package/dist/artifact-builder/SubjectClassModelBuilder.js.map +1 -0
- package/dist/artifact-builder/SubjectComponentGenerator.d.ts +25 -14
- package/dist/artifact-builder/SubjectComponentGenerator.js +65 -189
- package/dist/artifact-builder/SubjectComponentGenerator.js.map +1 -1
- package/dist/artifact-builder/SubjectGenerator.d.ts +32 -13
- package/dist/artifact-builder/SubjectGenerator.js +81 -165
- package/dist/artifact-builder/SubjectGenerator.js.map +1 -1
- package/dist/artifact-builder/SubjectRegistration.d.ts +22 -8
- package/dist/artifact-builder/SubjectRegistration.js +29 -14
- package/dist/artifact-builder/SubjectRegistration.js.map +1 -1
- package/dist/artifact-builder/TsFileModel.d.ts +86 -0
- package/dist/artifact-builder/TsFileModel.js +2 -0
- package/dist/artifact-builder/TsFileModel.js.map +1 -0
- package/dist/artifact-builder/TsFileSerializer.d.ts +19 -0
- package/dist/artifact-builder/TsFileSerializer.js +225 -0
- package/dist/artifact-builder/TsFileSerializer.js.map +1 -0
- package/dist/artifact-builder/helpers/DataRetriever.d.ts +22 -3
- package/dist/artifact-builder/helpers/DataRetriever.js +56 -26
- package/dist/artifact-builder/helpers/DataRetriever.js.map +1 -1
- package/dist/artifact-builder/helpers/NamingHandler.d.ts +18 -6
- package/dist/artifact-builder/helpers/NamingHandler.js +20 -61
- package/dist/artifact-builder/helpers/NamingHandler.js.map +1 -1
- package/dist/artifact-builder/helpers/PipelinePaths.d.ts +52 -0
- package/dist/artifact-builder/helpers/PipelinePaths.js +99 -0
- package/dist/artifact-builder/helpers/PipelinePaths.js.map +1 -0
- package/dist/artifact-builder/helpers/Stopwatch.d.ts +10 -0
- package/dist/artifact-builder/helpers/Stopwatch.js +10 -0
- package/dist/artifact-builder/helpers/Stopwatch.js.map +1 -1
- package/dist/artifact-builder/helpers/index.d.ts +1 -0
- package/dist/artifact-builder/helpers/index.js +1 -0
- package/dist/artifact-builder/helpers/index.js.map +1 -1
- package/dist/artifact-builder/index.d.ts +4 -0
- package/dist/artifact-builder/index.js +4 -0
- package/dist/artifact-builder/index.js.map +1 -1
- package/dist/components/BaseComponentObjects.d.ts +17 -0
- package/dist/components/BaseComponentObjects.js +17 -0
- package/dist/components/BaseComponentObjects.js.map +1 -1
- package/dist/components/action-bar/ActionBar.d.ts +21 -24
- package/dist/components/action-bar/ActionBar.js +31 -24
- package/dist/components/action-bar/ActionBar.js.map +1 -1
- package/dist/components/action-bar/ActionBarObjects.d.ts +1 -0
- package/dist/components/action-bar/ActionBarObjects.js +1 -0
- package/dist/components/action-bar/ActionBarObjects.js.map +1 -1
- package/dist/components/action-bar/CustomActionBar.d.ts +6 -0
- package/dist/components/action-bar/CustomActionBar.js +6 -0
- package/dist/components/action-bar/CustomActionBar.js.map +1 -1
- package/dist/components/cardlist/Cardlist.d.ts +6 -0
- package/dist/components/cardlist/Cardlist.js +6 -0
- package/dist/components/cardlist/Cardlist.js.map +1 -1
- package/dist/components/chart/Chart.d.ts +6 -0
- package/dist/components/chart/Chart.js +6 -0
- package/dist/components/chart/Chart.js.map +1 -1
- package/dist/components/combined-filter/CombinedFilter.d.ts +9 -0
- package/dist/components/combined-filter/CombinedFilter.js +9 -0
- package/dist/components/combined-filter/CombinedFilter.js.map +1 -1
- package/dist/components/cube-view-bar/CubeViewBar.d.ts +6 -0
- package/dist/components/cube-view-bar/CubeViewBar.js +6 -0
- package/dist/components/cube-view-bar/CubeViewBar.js.map +1 -1
- package/dist/components/export/ExportComponent.d.ts +12 -0
- package/dist/components/export/ExportComponent.js +12 -0
- package/dist/components/export/ExportComponent.js.map +1 -1
- package/dist/components/filter/ExcelStyleFilterPopup.d.ts +17 -4
- package/dist/components/filter/ExcelStyleFilterPopup.js +35 -23
- package/dist/components/filter/ExcelStyleFilterPopup.js.map +1 -1
- package/dist/components/filter/ExcelStyleFilterPopupObjects.d.ts +1 -1
- package/dist/components/filter/ExcelStyleFilterPopupObjects.js +2 -2
- package/dist/components/filter/ExcelStyleFilterPopupObjects.js.map +1 -1
- package/dist/components/filter/FilterForm.d.ts +10 -0
- package/dist/components/filter/FilterForm.js +10 -0
- package/dist/components/filter/FilterForm.js.map +1 -1
- package/dist/components/filter/FilterPopup.d.ts +22 -4
- package/dist/components/filter/FilterPopup.js +17 -9
- package/dist/components/filter/FilterPopup.js.map +1 -1
- package/dist/components/filter/FilterPopupObjects.d.ts +5 -2
- package/dist/components/filter/FilterPopupObjects.js +5 -2
- package/dist/components/filter/FilterPopupObjects.js.map +1 -1
- package/dist/components/filter/FindForm.d.ts +7 -0
- package/dist/components/filter/FindForm.js +7 -0
- package/dist/components/filter/FindForm.js.map +1 -1
- package/dist/components/filter/ManagePrefilterPopup.d.ts +11 -0
- package/dist/components/filter/ManagePrefilterPopup.js +11 -0
- package/dist/components/filter/ManagePrefilterPopup.js.map +1 -1
- package/dist/components/form/Form.d.ts +16 -0
- package/dist/components/form/Form.js +16 -0
- package/dist/components/form/Form.js.map +1 -1
- package/dist/components/grid/Grid.d.ts +17 -0
- package/dist/components/grid/Grid.js +18 -1
- package/dist/components/grid/Grid.js.map +1 -1
- package/dist/components/maps/Maps.d.ts +6 -0
- package/dist/components/maps/Maps.js +6 -0
- package/dist/components/maps/Maps.js.map +1 -1
- package/dist/components/menu/ListBarMenuComponent.d.ts +10 -0
- package/dist/components/menu/ListBarMenuComponent.js +10 -0
- package/dist/components/menu/ListBarMenuComponent.js.map +1 -1
- package/dist/components/pivot-grid/PivotGrid.d.ts +6 -0
- package/dist/components/pivot-grid/PivotGrid.js +6 -0
- package/dist/components/pivot-grid/PivotGrid.js.map +1 -1
- package/dist/components/pivot-grid/PivotGridFieldList.d.ts +7 -0
- package/dist/components/pivot-grid/PivotGridFieldList.js +7 -0
- package/dist/components/pivot-grid/PivotGridFieldList.js.map +1 -1
- package/dist/components/pop-up/AllRowsPopUp.d.ts +12 -0
- package/dist/components/pop-up/AllRowsPopUp.js +12 -0
- package/dist/components/pop-up/AllRowsPopUp.js.map +1 -1
- package/dist/components/pop-up/PopUpComponent.d.ts +11 -0
- package/dist/components/pop-up/PopUpComponent.js +11 -0
- package/dist/components/pop-up/PopUpComponent.js.map +1 -1
- package/dist/components/prefilter-list/PrefilterList.d.ts +9 -0
- package/dist/components/prefilter-list/PrefilterList.js +9 -0
- package/dist/components/prefilter-list/PrefilterList.js.map +1 -1
- package/dist/components/preview/Preview.d.ts +6 -0
- package/dist/components/preview/Preview.js +6 -0
- package/dist/components/preview/Preview.js.map +1 -1
- package/dist/components/report-bar/ReportBar.d.ts +6 -0
- package/dist/components/report-bar/ReportBar.js +6 -0
- package/dist/components/report-bar/ReportBar.js.map +1 -1
- package/dist/components/report-tiles/ReportTiles.d.ts +6 -0
- package/dist/components/report-tiles/ReportTiles.js +6 -0
- package/dist/components/report-tiles/ReportTiles.js.map +1 -1
- package/dist/components/scheduler/Scheduler.d.ts +6 -0
- package/dist/components/scheduler/Scheduler.js +6 -0
- package/dist/components/scheduler/Scheduler.js.map +1 -1
- package/dist/components/snackbar/SnackBar.d.ts +12 -0
- package/dist/components/snackbar/SnackBar.js +12 -0
- package/dist/components/snackbar/SnackBar.js.map +1 -1
- package/dist/components/splitter/Splitter.d.ts +6 -0
- package/dist/components/splitter/Splitter.js +6 -0
- package/dist/components/splitter/Splitter.js.map +1 -1
- package/dist/components/tab/BaseTab.d.ts +5 -0
- package/dist/components/tab/BaseTab.js +5 -0
- package/dist/components/tab/BaseTab.js.map +1 -1
- package/dist/components/tab/DetailTabPage.d.ts +11 -0
- package/dist/components/tab/DetailTabPage.js +11 -0
- package/dist/components/tab/DetailTabPage.js.map +1 -1
- package/dist/components/tab/Tab.d.ts +10 -0
- package/dist/components/tab/Tab.js +10 -0
- package/dist/components/tab/Tab.js.map +1 -1
- package/dist/components/task/TaskBar.d.ts +12 -2
- package/dist/components/task/TaskBar.js +13 -3
- package/dist/components/task/TaskBar.js.map +1 -1
- package/dist/components/task/TaskTiles.d.ts +11 -2
- package/dist/components/task/TaskTiles.js +12 -3
- package/dist/components/task/TaskTiles.js.map +1 -1
- package/dist/components/topbar/TopBar.d.ts +10 -0
- package/dist/components/topbar/TopBar.js +10 -0
- package/dist/components/topbar/TopBar.js.map +1 -1
- package/dist/components/tree-view/TreeView.d.ts +9 -0
- package/dist/components/tree-view/TreeView.js +9 -0
- package/dist/components/tree-view/TreeView.js.map +1 -1
- package/dist/controls/DateControl.d.ts +39 -0
- package/dist/controls/DateControl.js +18 -1
- package/dist/controls/DateControl.js.map +1 -1
- package/dist/controls/FormComboBox.d.ts +30 -0
- package/dist/controls/FormComboBox.js +8 -0
- package/dist/controls/FormComboBox.js.map +1 -1
- package/dist/controls/GridColumnControl.d.ts +30 -0
- package/dist/controls/GridColumnControl.js +12 -3
- package/dist/controls/GridColumnControl.js.map +1 -1
- package/dist/controls/InputFieldControl.d.ts +49 -0
- package/dist/controls/InputFieldControl.js +30 -0
- package/dist/controls/InputFieldControl.js.map +1 -1
- package/dist/controls/LookupDropdown.d.ts +29 -0
- package/dist/controls/LookupDropdown.js +8 -0
- package/dist/controls/LookupDropdown.js.map +1 -1
- package/dist/enums/ElementTypes.d.ts +18 -0
- package/dist/enums/ElementTypes.js +18 -0
- package/dist/enums/ElementTypes.js.map +1 -1
- package/dist/enums/ExportFormat.d.ts +8 -0
- package/dist/enums/ExportFormat.js +8 -0
- package/dist/enums/ExportFormat.js.map +1 -1
- package/dist/enums/LogLevel.d.ts +17 -0
- package/dist/enums/LogLevel.js +17 -1
- package/dist/enums/LogLevel.js.map +1 -1
- package/dist/enums/index.d.ts +1 -0
- package/dist/enums/index.js +1 -0
- package/dist/enums/index.js.map +1 -1
- package/dist/helpers/ConfigChecker.d.ts +13 -0
- package/dist/helpers/ConfigChecker.js +13 -0
- package/dist/helpers/ConfigChecker.js.map +1 -1
- package/dist/helpers/Ensure.d.ts +13 -0
- package/dist/helpers/Ensure.js +13 -0
- package/dist/helpers/Ensure.js.map +1 -1
- package/dist/helpers/FlightTracker.d.ts +13 -3
- package/dist/helpers/FlightTracker.js +103 -17
- package/dist/helpers/FlightTracker.js.map +1 -1
- package/dist/helpers/GlobalWaitEventHandler.d.ts +13 -0
- package/dist/helpers/GlobalWaitEventHandler.js +13 -0
- package/dist/helpers/GlobalWaitEventHandler.js.map +1 -1
- package/dist/helpers/LoginHelper.d.ts +35 -1
- package/dist/helpers/LoginHelper.js +46 -11
- package/dist/helpers/LoginHelper.js.map +1 -1
- package/dist/helpers/PathResolver.d.ts +22 -0
- package/dist/helpers/PathResolver.js +22 -0
- package/dist/helpers/PathResolver.js.map +1 -1
- package/dist/helpers/Poll.d.ts +13 -1
- package/dist/helpers/Poll.js +12 -0
- package/dist/helpers/Poll.js.map +1 -1
- package/dist/helpers/RegexHelper.d.ts +15 -0
- package/dist/helpers/RegexHelper.js +15 -3
- package/dist/helpers/RegexHelper.js.map +1 -1
- package/dist/helpers/SubjectNavigator.d.ts +26 -0
- package/dist/helpers/SubjectNavigator.js +51 -0
- package/dist/helpers/SubjectNavigator.js.map +1 -0
- package/dist/helpers/UserSimulationHelper.d.ts +14 -0
- package/dist/helpers/UserSimulationHelper.js +14 -0
- package/dist/helpers/UserSimulationHelper.js.map +1 -1
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/helpers/index.js.map +1 -1
- package/dist/index.d.ts +6 -20
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/IComponentObjects.d.ts +12 -0
- package/dist/interfaces/IComponentSchemaMeta.d.ts +15 -0
- package/dist/interfaces/IComponentSchemaMeta.js +2 -0
- package/dist/interfaces/IComponentSchemaMeta.js.map +1 -0
- package/dist/interfaces/IProperty.d.ts +13 -0
- package/dist/interfaces/IRegisteredSubjects.d.ts +12 -0
- package/dist/interfaces/ISeedSubjectDraft.d.ts +16 -0
- package/dist/interfaces/ISeedSubjectDraft.js +2 -0
- package/dist/interfaces/ISeedSubjectDraft.js.map +1 -0
- package/dist/interfaces/ISubject.d.ts +13 -0
- package/dist/interfaces/ISubjectDetail.d.ts +11 -0
- package/dist/interfaces/ISubjectDetail.js +2 -0
- package/dist/interfaces/ISubjectDetail.js.map +1 -0
- package/dist/mcp/ArtifactResolver.d.ts +152 -0
- package/dist/mcp/ArtifactResolver.js +232 -0
- package/dist/mcp/ArtifactResolver.js.map +1 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/page-extensions/GlobalComponents.d.ts +30 -0
- package/dist/page-extensions/GlobalComponents.js +30 -0
- package/dist/page-extensions/GlobalComponents.js.map +1 -1
- package/dist/page-extensions/GoToDeepLink.d.ts +9 -0
- package/dist/page-extensions/GoToDeepLink.js +9 -0
- package/dist/page-extensions/GoToDeepLink.js.map +1 -1
- package/dist/page-extensions/LoginFeatures.d.ts +8 -0
- package/dist/page-extensions/LoginFeatures.js +8 -0
- package/dist/page-extensions/LoginFeatures.js.map +1 -1
- package/dist/page-extensions/SubjectRegistry.d.ts +31 -0
- package/dist/page-extensions/SubjectRegistry.js +31 -0
- package/dist/page-extensions/SubjectRegistry.js.map +1 -1
- package/dist/page-extensions/UserSimulation.d.ts +21 -0
- package/dist/page-extensions/UserSimulation.js +21 -0
- package/dist/page-extensions/UserSimulation.js.map +1 -1
- package/dist/page-extensions/WaitEventHandler.d.ts +20 -0
- package/dist/page-extensions/WaitEventHandler.js +20 -0
- package/dist/page-extensions/WaitEventHandler.js.map +1 -1
- package/dist/page-overrides/ClickOverride.d.ts +23 -2
- package/dist/page-overrides/ClickOverride.js +34 -50
- package/dist/page-overrides/ClickOverride.js.map +1 -1
- package/dist/page-overrides/FillOverride.d.ts +23 -0
- package/dist/page-overrides/FillOverride.js +46 -66
- package/dist/page-overrides/FillOverride.js.map +1 -1
- package/dist/services/ConfigBuilder.d.ts +24 -0
- package/dist/services/ConfigBuilder.js +24 -0
- package/dist/services/ConfigBuilder.js.map +1 -1
- package/dist/services/IndiciumApi.service.d.ts +26 -0
- package/dist/services/IndiciumApi.service.js +40 -5
- package/dist/services/IndiciumApi.service.js.map +1 -1
- package/dist/services/Logger.d.ts +13 -0
- package/dist/services/Logger.js +39 -0
- package/dist/services/Logger.js.map +1 -1
- package/dist/types/Components.d.ts +18 -1
- package/dist/types/Components.js +0 -1
- package/dist/types/Components.js.map +1 -1
- package/dist/types/LocatorType.d.ts +5 -0
- package/dist/types/LocatorType.js +2 -0
- package/dist/types/LocatorType.js.map +1 -0
- package/dist/types/PollTypes.d.ts +8 -0
- package/dist/types/Test.d.ts +18 -0
- package/dist/types/Universal.d.ts +12 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/enums/ElementTypes.ts +18 -0
- package/enums/ExportFormat.ts +8 -0
- package/enums/LogLevel.ts +17 -1
- package/enums/index.ts +1 -0
- package/helpers/ConfigChecker.ts +13 -0
- package/helpers/Ensure.ts +13 -0
- package/helpers/FlightTracker.ts +109 -20
- package/helpers/GlobalWaitEventHandler.ts +13 -0
- package/helpers/LoginHelper.ts +49 -12
- package/helpers/PathResolver.ts +22 -0
- package/helpers/Poll.ts +13 -1
- package/helpers/RegexHelper.ts +15 -3
- package/helpers/SubjectNavigator.ts +57 -0
- package/helpers/UserSimulationHelper.ts +14 -0
- package/helpers/index.ts +1 -0
- package/index.ts +1 -0
- package/interfaces/IComponentObjects.ts +12 -0
- package/interfaces/IComponentSchemaMeta.ts +17 -0
- package/interfaces/IProperty.ts +13 -0
- package/interfaces/IRegisteredSubjects.ts +12 -0
- package/interfaces/ISeedSubjectDraft.ts +17 -0
- package/interfaces/ISubject.ts +13 -0
- package/interfaces/ISubjectDetail.ts +12 -0
- package/mcp/ArtifactResolver.ts +296 -0
- package/mcp/index.ts +2 -0
- package/package.json +20 -8
- package/page-extensions/GlobalComponents.ts +30 -0
- package/page-extensions/GoToDeepLink.ts +9 -0
- package/page-extensions/LoginFeatures.ts +8 -0
- package/page-extensions/SubjectRegistry.ts +32 -0
- package/page-extensions/UserSimulation.ts +21 -0
- package/page-extensions/WaitEventHandler.ts +20 -0
- package/page-overrides/ClickOverride.ts +36 -55
- package/page-overrides/FillOverride.ts +59 -73
- package/promptCredentials.js +1 -1
- package/scripts/Testwise.template.json +1 -1
- package/scripts/diagram.js +2267 -0
- package/scripts/main.js +84 -63
- package/scripts/postinstall.js +55 -42
- package/scripts/setup.js +91 -37
- package/scripts/sync.js +767 -748
- package/services/ConfigBuilder.ts +24 -0
- package/services/IndiciumApi.service.ts +44 -6
- package/services/Logger.ts +40 -0
- package/templates/copilot-instructions.md +130 -0
- package/templates/mcp.json +9 -0
- package/templates/testwise-test-expert.agent.md +453 -0
- package/tests/tsconfig.json +12 -0
- package/tsconfig.json +6 -2
- package/types/Components.ts +17 -2
- package/types/LocatorType.ts +5 -0
- package/types/PollTypes.ts +8 -0
- package/types/Test.ts +18 -0
- package/types/Universal.ts +12 -0
- package/types/index.ts +2 -0
- package/dist/interfaces/IStoredTestResults.d.ts +0 -5
- package/dist/interfaces/IStoredTestResults.js +0 -2
- package/dist/interfaces/IStoredTestResults.js.map +0 -1
- package/dist/templates/test-artifacts/SubjectPageBase.d.ts +0 -5
- package/dist/templates/test-artifacts/SubjectPageBase.js +0 -6
- package/dist/templates/test-artifacts/SubjectPageBase.js.map +0 -1
- package/dist/templates/test-artifacts/screens/index.d.ts +0 -1
- package/dist/templates/test-artifacts/screens/index.js +0 -2
- package/dist/templates/test-artifacts/screens/index.js.map +0 -1
- package/dist/templates/test-artifacts/subjects/index.d.ts +0 -1
- package/dist/templates/test-artifacts/subjects/index.js +0 -2
- package/dist/templates/test-artifacts/subjects/index.js.map +0 -1
- 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 {
|
|
7
|
-
|
|
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
|
|
12
|
-
private
|
|
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.
|
|
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 =
|
|
31
|
+
const screenOutputDirectory = this._paths.screens;
|
|
24
32
|
this.verifyOutputDirectory(screenOutputDirectory);
|
|
25
33
|
|
|
26
|
-
const schemasDirectory = this.
|
|
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 =
|
|
35
|
-
const subjectOutputDirectory =
|
|
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
|
-
|
|
11
|
-
type Subjects = {
|
|
10
|
+
interface IPropertyWithSubjectIdentifiers extends IProperty {
|
|
12
11
|
subject: string;
|
|
13
12
|
variant: string;
|
|
14
|
-
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
|
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
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
89
|
-
const
|
|
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
|
-
|
|
126
|
-
|
|
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
|
-
|
|
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
|
|
11
|
-
|
|
12
|
-
this.
|
|
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
|
-
|
|
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(
|
|
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
|
}
|