@thinkwise/testwise 0.0.2-alpha.2
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/.ci/azure-pipelines.yaml +80 -0
- package/.eslintcache +1 -0
- package/.gitattributes +3 -0
- package/.gitconfig +2 -0
- package/.vscode/settings.json +18 -0
- package/Testwise.ts +22 -0
- package/components/BaseComponent.ts +95 -0
- package/components/BaseComponentObjects.ts +10 -0
- package/components/IComponentObjects.ts +5 -0
- package/components/Splitter.ts +11 -0
- package/components/TSFComponent.ts +8 -0
- package/components/actionbar/Actionbar.ts +57 -0
- package/components/actionbar/ActionbarObjects.ts +67 -0
- package/components/export/ExportComponent.ts +70 -0
- package/components/export/ExportComponentObjects.ts +23 -0
- package/components/filter/FilterForm.ts +11 -0
- package/components/filter/FindForm.ts +11 -0
- package/components/form/Form.ts +31 -0
- package/components/grid/Grid.ts +221 -0
- package/components/grid/GridObjects.ts +45 -0
- package/components/index.ts +6 -0
- package/components/pop-up/PopUpComponent.ts +14 -0
- package/components/pop-up/PopUpComponentModels.ts +13 -0
- package/components/tab/Tab.ts +29 -0
- package/components/task/TaskBar.ts +11 -0
- package/components/task/TaskTiles.ts +11 -0
- package/config.json +10 -0
- package/dist/Testwise.d.ts +2 -0
- package/dist/Testwise.js +14 -0
- package/dist/Testwise.js.map +1 -0
- package/dist/components/BaseComponent.d.ts +29 -0
- package/dist/components/BaseComponent.js +67 -0
- package/dist/components/BaseComponent.js.map +1 -0
- package/dist/components/BaseComponentObjects.d.ts +6 -0
- package/dist/components/BaseComponentObjects.js +6 -0
- package/dist/components/BaseComponentObjects.js.map +1 -0
- package/dist/components/IComponentObjects.d.ts +4 -0
- package/dist/components/IComponentObjects.js +2 -0
- package/dist/components/IComponentObjects.js.map +1 -0
- package/dist/components/Splitter.d.ts +5 -0
- package/dist/components/Splitter.js +10 -0
- package/dist/components/Splitter.js.map +1 -0
- package/dist/components/TSFComponent.d.ts +6 -0
- package/dist/components/TSFComponent.js +2 -0
- package/dist/components/TSFComponent.js.map +1 -0
- package/dist/components/actionbar/Actionbar.d.ts +27 -0
- package/dist/components/actionbar/Actionbar.js +35 -0
- package/dist/components/actionbar/Actionbar.js.map +1 -0
- package/dist/components/actionbar/ActionbarObjects.d.ts +24 -0
- package/dist/components/actionbar/ActionbarObjects.js +30 -0
- package/dist/components/actionbar/ActionbarObjects.js.map +1 -0
- package/dist/components/export/ExportComponent.d.ts +12 -0
- package/dist/components/export/ExportComponent.js +55 -0
- package/dist/components/export/ExportComponent.js.map +1 -0
- package/dist/components/export/ExportComponentObjects.d.ts +11 -0
- package/dist/components/export/ExportComponentObjects.js +12 -0
- package/dist/components/export/ExportComponentObjects.js.map +1 -0
- package/dist/components/form/Form.d.ts +7 -0
- package/dist/components/form/Form.js +31 -0
- package/dist/components/form/Form.js.map +1 -0
- package/dist/components/grid/Grid.d.ts +93 -0
- package/dist/components/grid/Grid.js +183 -0
- package/dist/components/grid/Grid.js.map +1 -0
- package/dist/components/grid/GridObjects.d.ts +20 -0
- package/dist/components/grid/GridObjects.js +25 -0
- package/dist/components/grid/GridObjects.js.map +1 -0
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.js +7 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/pop-up/PopUpComponent.d.ts +7 -0
- package/dist/components/pop-up/PopUpComponent.js +9 -0
- package/dist/components/pop-up/PopUpComponent.js.map +1 -0
- package/dist/components/pop-up/PopUpComponentModels.d.ts +7 -0
- package/dist/components/pop-up/PopUpComponentModels.js +8 -0
- package/dist/components/pop-up/PopUpComponentModels.js.map +1 -0
- package/dist/config.json +10 -0
- package/dist/enums/ActionbarRegions.d.ts +5 -0
- package/dist/enums/ActionbarRegions.js +7 -0
- package/dist/enums/ActionbarRegions.js.map +1 -0
- package/dist/enums/ButtonEnums.d.ts +24 -0
- package/dist/enums/ButtonEnums.js +29 -0
- package/dist/enums/ButtonEnums.js.map +1 -0
- package/dist/enums/ExportFormat.d.ts +5 -0
- package/dist/enums/ExportFormat.js +7 -0
- package/dist/enums/ExportFormat.js.map +1 -0
- package/dist/enums/LogLevel.d.ts +8 -0
- package/dist/enums/LogLevel.js +11 -0
- package/dist/enums/LogLevel.js.map +1 -0
- package/dist/example-code/TestifyService.d.ts +22 -0
- package/dist/example-code/TestifyService.js +191 -0
- package/dist/example-code/TestifyService.js.map +1 -0
- package/dist/helpers/InflightRequestTracker.d.ts +10 -0
- package/dist/helpers/InflightRequestTracker.js +26 -0
- package/dist/helpers/InflightRequestTracker.js.map +1 -0
- package/dist/helpers/LoginHelper.d.ts +38 -0
- package/dist/helpers/LoginHelper.js +112 -0
- package/dist/helpers/LoginHelper.js.map +1 -0
- package/dist/helpers/UserSimulationHelper.d.ts +20 -0
- package/dist/helpers/UserSimulationHelper.js +62 -0
- package/dist/helpers/UserSimulationHelper.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/page-extensions/GoToDeepLink.d.ts +11 -0
- package/dist/page-extensions/GoToDeepLink.js +17 -0
- package/dist/page-extensions/GoToDeepLink.js.map +1 -0
- package/dist/page-extensions/LoginFeatures.d.ts +16 -0
- package/dist/page-extensions/LoginFeatures.js +30 -0
- package/dist/page-extensions/LoginFeatures.js.map +1 -0
- package/dist/page-extensions/UserSimulation.d.ts +15 -0
- package/dist/page-extensions/UserSimulation.js +30 -0
- package/dist/page-extensions/UserSimulation.js.map +1 -0
- package/dist/page-overrides/ClickOverride.d.ts +6 -0
- package/dist/page-overrides/ClickOverride.js +73 -0
- package/dist/page-overrides/ClickOverride.js.map +1 -0
- package/dist/services/ConfigBuilder.d.ts +12 -0
- package/dist/services/ConfigBuilder.js +30 -0
- package/dist/services/ConfigBuilder.js.map +1 -0
- package/dist/services/Logger.d.ts +8 -0
- package/dist/services/Logger.js +106 -0
- package/dist/services/Logger.js.map +1 -0
- package/dist/services/ReportingService.d.ts +8 -0
- package/dist/services/ReportingService.js +29 -0
- package/dist/services/ReportingService.js.map +1 -0
- package/dist/types/CoreTypes.d.ts +2 -0
- package/dist/types/CoreTypes.js +2 -0
- package/dist/types/CoreTypes.js.map +1 -0
- package/dist/types/universal.d.ts +25 -0
- package/dist/types/universal.js +2 -0
- package/dist/types/universal.js.map +1 -0
- package/enums/ActionbarRegions.ts +5 -0
- package/enums/ButtonEnums.ts +28 -0
- package/enums/ExportFormat.ts +5 -0
- package/enums/LogLevel.ts +9 -0
- package/example-code/TestifyService.ts +201 -0
- package/helpers/InflightRequestTracker.ts +33 -0
- package/helpers/LoginHelper.ts +140 -0
- package/helpers/UserSimulationHelper.ts +72 -0
- package/index.ts +28 -0
- package/package.json +40 -0
- package/page-extensions/GoToDeepLink.ts +29 -0
- package/page-extensions/LoginFeatures.ts +50 -0
- package/page-extensions/UserSimulation.ts +49 -0
- package/page-overrides/ClickOverride.ts +89 -0
- package/promptCredentials.js +113 -0
- package/scripts/Testwise.template.json +19 -0
- package/scripts/add-config.js +23 -0
- package/services/ConfigBuilder.ts +40 -0
- package/services/Logger.ts +125 -0
- package/services/ReportingService.ts +41 -0
- package/types/CoreTypes.ts +9 -0
- package/types/universal.ts +26 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
trigger:
|
|
2
|
+
- develop
|
|
3
|
+
|
|
4
|
+
pr:
|
|
5
|
+
- develop
|
|
6
|
+
|
|
7
|
+
pool: qa-testwise
|
|
8
|
+
|
|
9
|
+
variables:
|
|
10
|
+
- name: nodejs-version
|
|
11
|
+
value: 20.x
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
# - job: build
|
|
15
|
+
# steps:
|
|
16
|
+
# - task: NodeTool@0
|
|
17
|
+
# inputs:
|
|
18
|
+
# versionSpec: $(nodejs-version)
|
|
19
|
+
# displayName: "Install Node.js version $(nodejs-version)"
|
|
20
|
+
#
|
|
21
|
+
# - task: Npm@1
|
|
22
|
+
# inputs:
|
|
23
|
+
# command: ...
|
|
24
|
+
#
|
|
25
|
+
# - task: PublishBuildArtifacts@1
|
|
26
|
+
# inputs:
|
|
27
|
+
# PathtoPublish: "$(Build.ArtifactStagingDirectory)"
|
|
28
|
+
# ArtifactName: "$(Build.Repository.Name)_$(Build.BuildId)"
|
|
29
|
+
|
|
30
|
+
- job: test_format
|
|
31
|
+
displayName: Test formatting
|
|
32
|
+
steps:
|
|
33
|
+
- task: NodeTool@0
|
|
34
|
+
inputs:
|
|
35
|
+
versionSpec: $(nodejs-version)
|
|
36
|
+
displayName: "Install Node.js version $(nodejs-version)"
|
|
37
|
+
|
|
38
|
+
- script: |
|
|
39
|
+
npm install @biomejs/biome @eslint/js eslint eslint-plugin-playwright typescript-eslint npm-run-all
|
|
40
|
+
displayName: "Install rule package dependencies"
|
|
41
|
+
|
|
42
|
+
- script: |
|
|
43
|
+
npm run format:check
|
|
44
|
+
displayName: "Run format:check command"
|
|
45
|
+
|
|
46
|
+
# - job: test
|
|
47
|
+
# displayName: Test
|
|
48
|
+
# steps:
|
|
49
|
+
# - task: NodeTool@0
|
|
50
|
+
# inputs:
|
|
51
|
+
# versionSpec: $(nodejs-version)
|
|
52
|
+
# displayName: "Install Node.js version $(nodejs-version)"
|
|
53
|
+
|
|
54
|
+
# - script: |
|
|
55
|
+
# npm install @biomejs/biome @eslint/js eslint eslint-plugin-playwright typescript-eslint npm-run-all
|
|
56
|
+
# displayName: "Install rule package dependencies"
|
|
57
|
+
|
|
58
|
+
# - script: |
|
|
59
|
+
# npm run test
|
|
60
|
+
# displayName: "Run test command"
|
|
61
|
+
|
|
62
|
+
- job: publish
|
|
63
|
+
displayName: Publish NPM package
|
|
64
|
+
condition: and(succeeded(), eq(variables['Publish'], 'true'))
|
|
65
|
+
steps:
|
|
66
|
+
- task: DownloadBuildArtifacts@1
|
|
67
|
+
inputs:
|
|
68
|
+
buildType: current
|
|
69
|
+
artifactName: $(Build.Repository.Name)_$(Build.BuildId)
|
|
70
|
+
|
|
71
|
+
- task: npmAuthenticate@0
|
|
72
|
+
displayName: Authenticate with npm
|
|
73
|
+
inputs:
|
|
74
|
+
workingFile: $(System.DefaultWorkingDirectory)/.npmrc
|
|
75
|
+
|
|
76
|
+
- task: Npm@1
|
|
77
|
+
name: publish
|
|
78
|
+
displayName: Publish NPM package to feed
|
|
79
|
+
inputs:
|
|
80
|
+
command: publish
|
package/.eslintcache
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"C:\\Repos\\Testwise\\components\\actionbar\\Actionbar.ts":"1","C:\\Repos\\Testwise\\components\\actionbar\\ActionbarObjects.ts":"2","C:\\Repos\\Testwise\\components\\BaseComponent.ts":"3","C:\\Repos\\Testwise\\components\\filter\\FilterForm.ts":"4","C:\\Repos\\Testwise\\components\\filter\\FindForm.ts":"5","C:\\Repos\\Testwise\\components\\form\\Form.ts":"6","C:\\Repos\\Testwise\\components\\grid\\Grid.ts":"7","C:\\Repos\\Testwise\\components\\index.ts":"8","C:\\Repos\\Testwise\\components\\Splitter.ts":"9","C:\\Repos\\Testwise\\components\\tab\\Tab.ts":"10","C:\\Repos\\Testwise\\components\\task\\TaskBar.ts":"11","C:\\Repos\\Testwise\\components\\task\\TaskTiles.ts":"12","C:\\Repos\\Testwise\\components\\TSFComponent.ts":"13","C:\\Repos\\Testwise\\enums\\ActionbarRegions.ts":"14","C:\\Repos\\Testwise\\enums\\ButtonEnums.ts":"15","C:\\Repos\\Testwise\\enums\\LogLevel.ts":"16","C:\\Repos\\Testwise\\eslint-plugin-custom\\index.js":"17","C:\\Repos\\Testwise\\eslint-plugin-custom\\lib\\rules\\no-click-override.js":"18","C:\\Repos\\Testwise\\example-code\\TestifyService.ts":"19","C:\\Repos\\Testwise\\helpers\\InflightRequestTracker.ts":"20","C:\\Repos\\Testwise\\helpers\\LoginHelper.ts":"21","C:\\Repos\\Testwise\\helpers\\UserSimulationHelper.ts":"22","C:\\Repos\\Testwise\\index.ts":"23","C:\\Repos\\Testwise\\page-extensions\\GoToDeepLink.ts":"24","C:\\Repos\\Testwise\\page-extensions\\LoginFeatures.ts":"25","C:\\Repos\\Testwise\\page-extensions\\UserSimulation.ts":"26","C:\\Repos\\Testwise\\page-overrides\\ClickOverride.ts":"27","C:\\Repos\\Testwise\\promptCredentials.js":"28","C:\\Repos\\Testwise\\scripts\\add-config.js":"29","C:\\Repos\\Testwise\\services\\ConfigBuilder.ts":"30","C:\\Repos\\Testwise\\services\\Logger.ts":"31","C:\\Repos\\Testwise\\services\\ReportingService.ts":"32","C:\\Repos\\Testwise\\Testwise.ts":"33","C:\\Repos\\Testwise\\types\\CoreTypes.ts":"34","C:\\Repos\\Testwise\\types\\universal.ts":"35","C:\\Repos\\Testwise\\components\\BaseComponentObjects.ts":"36","C:\\Repos\\Testwise\\components\\export\\ExportComponent.ts":"37","C:\\Repos\\Testwise\\components\\export\\ExportComponentObjects.ts":"38","C:\\Repos\\Testwise\\components\\grid\\GridObjects.ts":"39","C:\\Repos\\Testwise\\components\\IComponentObjects.ts":"40","C:\\Repos\\Testwise\\components\\pop-up\\PopUpComponent.ts":"41","C:\\Repos\\Testwise\\components\\pop-up\\PopUpComponentModels.ts":"42","C:\\Repos\\Testwise\\enums\\ExportFormat.ts":"43"},{"size":2021,"mtime":1751522769257,"results":"44","hashOfConfig":"45"},{"size":2576,"mtime":1751528778595,"results":"46","hashOfConfig":"45"},{"size":3122,"mtime":1751522279073,"results":"47","hashOfConfig":"45"},{"size":330,"mtime":1748942441174,"results":"48","hashOfConfig":"45"},{"size":328,"mtime":1748942446381,"results":"49","hashOfConfig":"45"},{"size":1009,"mtime":1751522352486,"results":"50","hashOfConfig":"45"},{"size":8734,"mtime":1751550578515,"results":"51","hashOfConfig":"45"},{"size":226,"mtime":1751436619558,"results":"52","hashOfConfig":"45"},{"size":400,"mtime":1751522923371,"results":"53","hashOfConfig":"45"},{"size":818,"mtime":1748942461699,"results":"54","hashOfConfig":"45"},{"size":327,"mtime":1748942467360,"results":"55","hashOfConfig":"45"},{"size":329,"mtime":1748942472010,"results":"56","hashOfConfig":"45"},{"size":169,"mtime":1751522237806,"results":"57","hashOfConfig":"45"},{"size":88,"mtime":1750674713040,"results":"58","hashOfConfig":"45"},{"size":784,"mtime":1751264923809,"results":"59","hashOfConfig":"45"},{"size":155,"mtime":1748416363345,"results":"60","hashOfConfig":"45"},{"size":149,"mtime":1750248769915,"results":"61","hashOfConfig":"62"},{"size":926,"mtime":1750248769917,"results":"63","hashOfConfig":"62"},{"size":6919,"mtime":1749656149481,"results":"64","hashOfConfig":"45"},{"size":937,"mtime":1750164017577,"results":"65","hashOfConfig":"45"},{"size":4069,"mtime":1750674713042,"results":"66","hashOfConfig":"45"},{"size":2279,"mtime":1750674713045,"results":"67","hashOfConfig":"45"},{"size":1218,"mtime":1751375510261,"results":"68","hashOfConfig":"45"},{"size":672,"mtime":1748956696562,"results":"69","hashOfConfig":"45"},{"size":1335,"mtime":1748956696562,"results":"70","hashOfConfig":"45"},{"size":1293,"mtime":1748956696562,"results":"71","hashOfConfig":"45"},{"size":3582,"mtime":1750674713054,"results":"72","hashOfConfig":"45"},{"size":3269,"mtime":1750674713057,"results":"73","hashOfConfig":"62"},{"size":813,"mtime":1750674713059,"results":"74","hashOfConfig":"62"},{"size":1085,"mtime":1750248769941,"results":"75","hashOfConfig":"45"},{"size":4147,"mtime":1750674713062,"results":"76","hashOfConfig":"45"},{"size":1316,"mtime":1749656024091,"results":"77","hashOfConfig":"45"},{"size":726,"mtime":1750674713026,"results":"78","hashOfConfig":"79"},{"size":272,"mtime":1748956696592,"results":"80","hashOfConfig":"45"},{"size":731,"mtime":1748956696594,"results":"81","hashOfConfig":"45"},{"size":343,"mtime":1751522308836,"results":"82","hashOfConfig":"45"},{"size":2359,"mtime":1751375510251,"results":"83","hashOfConfig":"45"},{"size":869,"mtime":1751522504772,"results":"84","hashOfConfig":"45"},{"size":1851,"mtime":1751550591615,"results":"85","hashOfConfig":"45"},{"size":109,"mtime":1751522250137,"results":"86","hashOfConfig":"45"},{"size":437,"mtime":1751436619568,"results":"87","hashOfConfig":"45"},{"size":360,"mtime":1751436619568,"results":"88","hashOfConfig":"45"},{"size":75,"mtime":1751375510258,"results":"89","hashOfConfig":"45"},{"filePath":"90","messages":"91","suppressedMessages":"92","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"18jtond",{"filePath":"93","messages":"94","suppressedMessages":"95","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"96","messages":"97","suppressedMessages":"98","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"99","messages":"100","suppressedMessages":"101","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"102","messages":"103","suppressedMessages":"104","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"105","messages":"106","suppressedMessages":"107","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"108","messages":"109","suppressedMessages":"110","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"111","messages":"112","suppressedMessages":"113","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"114","messages":"115","suppressedMessages":"116","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"117","messages":"118","suppressedMessages":"119","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"120","messages":"121","suppressedMessages":"122","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"123","messages":"124","suppressedMessages":"125","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"126","messages":"127","suppressedMessages":"128","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"129","messages":"130","suppressedMessages":"131","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"132","messages":"133","suppressedMessages":"134","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"135","messages":"136","suppressedMessages":"137","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"138","messages":"139","suppressedMessages":"140","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1fztyz0",{"filePath":"141","messages":"142","suppressedMessages":"143","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"144","messages":"145","suppressedMessages":"146","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"147","messages":"148","suppressedMessages":"149","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"150","messages":"151","suppressedMessages":"152","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"153","messages":"154","suppressedMessages":"155","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"156","messages":"157","suppressedMessages":"158","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"159","messages":"160","suppressedMessages":"161","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"162","messages":"163","suppressedMessages":"164","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"165","messages":"166","suppressedMessages":"167","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"168","messages":"169","suppressedMessages":"170","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"171","messages":"172","suppressedMessages":"173","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"174","messages":"175","suppressedMessages":"176","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"177","messages":"178","suppressedMessages":"179","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"180","messages":"181","suppressedMessages":"182","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"183","messages":"184","suppressedMessages":"185","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"186","messages":"187","suppressedMessages":"188","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"fxl6v2",{"filePath":"189","messages":"190","suppressedMessages":"191","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"192","messages":"193","suppressedMessages":"194","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"195","messages":"196","suppressedMessages":"197","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"198","messages":"199","suppressedMessages":"200","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"201","messages":"202","suppressedMessages":"203","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"204","messages":"205","suppressedMessages":"206","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"207","messages":"208","suppressedMessages":"209","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"210","messages":"211","suppressedMessages":"212","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"213","messages":"214","suppressedMessages":"215","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"216","messages":"217","suppressedMessages":"218","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Repos\\Testwise\\components\\actionbar\\Actionbar.ts",[],[],"C:\\Repos\\Testwise\\components\\actionbar\\ActionbarObjects.ts",[],[],"C:\\Repos\\Testwise\\components\\BaseComponent.ts",[],[],"C:\\Repos\\Testwise\\components\\filter\\FilterForm.ts",[],[],"C:\\Repos\\Testwise\\components\\filter\\FindForm.ts",[],[],"C:\\Repos\\Testwise\\components\\form\\Form.ts",[],[],"C:\\Repos\\Testwise\\components\\grid\\Grid.ts",[],[],"C:\\Repos\\Testwise\\components\\index.ts",[],[],"C:\\Repos\\Testwise\\components\\Splitter.ts",[],[],"C:\\Repos\\Testwise\\components\\tab\\Tab.ts",[],[],"C:\\Repos\\Testwise\\components\\task\\TaskBar.ts",[],[],"C:\\Repos\\Testwise\\components\\task\\TaskTiles.ts",[],[],"C:\\Repos\\Testwise\\components\\TSFComponent.ts",[],[],"C:\\Repos\\Testwise\\enums\\ActionbarRegions.ts",[],[],"C:\\Repos\\Testwise\\enums\\ButtonEnums.ts",[],[],"C:\\Repos\\Testwise\\enums\\LogLevel.ts",[],[],"C:\\Repos\\Testwise\\eslint-plugin-custom\\index.js",[],[],"C:\\Repos\\Testwise\\eslint-plugin-custom\\lib\\rules\\no-click-override.js",[],["219"],"C:\\Repos\\Testwise\\example-code\\TestifyService.ts",[],["220","221","222","223","224"],"C:\\Repos\\Testwise\\helpers\\InflightRequestTracker.ts",[],[],"C:\\Repos\\Testwise\\helpers\\LoginHelper.ts",[],[],"C:\\Repos\\Testwise\\helpers\\UserSimulationHelper.ts",[],[],"C:\\Repos\\Testwise\\index.ts",[],[],"C:\\Repos\\Testwise\\page-extensions\\GoToDeepLink.ts",[],[],"C:\\Repos\\Testwise\\page-extensions\\LoginFeatures.ts",[],[],"C:\\Repos\\Testwise\\page-extensions\\UserSimulation.ts",[],[],"C:\\Repos\\Testwise\\page-overrides\\ClickOverride.ts",[],[],"C:\\Repos\\Testwise\\promptCredentials.js",[],[],"C:\\Repos\\Testwise\\scripts\\add-config.js",[],["225","226","227","228"],"C:\\Repos\\Testwise\\services\\ConfigBuilder.ts",[],[],"C:\\Repos\\Testwise\\services\\Logger.ts",[],["229"],"C:\\Repos\\Testwise\\services\\ReportingService.ts",[],[],"C:\\Repos\\Testwise\\Testwise.ts",[],[],"C:\\Repos\\Testwise\\types\\CoreTypes.ts",[],[],"C:\\Repos\\Testwise\\types\\universal.ts",[],[],"C:\\Repos\\Testwise\\components\\BaseComponentObjects.ts",[],[],"C:\\Repos\\Testwise\\components\\export\\ExportComponent.ts",[],[],"C:\\Repos\\Testwise\\components\\export\\ExportComponentObjects.ts",[],[],"C:\\Repos\\Testwise\\components\\grid\\GridObjects.ts",[],[],"C:\\Repos\\Testwise\\components\\IComponentObjects.ts",[],[],"C:\\Repos\\Testwise\\components\\pop-up\\PopUpComponent.ts",[],[],"C:\\Repos\\Testwise\\components\\pop-up\\PopUpComponentModels.ts",[],[],"C:\\Repos\\Testwise\\enums\\ExportFormat.ts",[],[],{"ruleId":"230","severity":2,"message":"231","line":21,"column":7,"nodeType":"232","messageId":"233","endLine":21,"endColumn":27,"suppressions":"234"},{"ruleId":"235","severity":2,"message":"236","line":49,"column":43,"nodeType":"237","messageId":"238","endLine":49,"endColumn":46,"suggestions":"239","suppressions":"240"},{"ruleId":"235","severity":2,"message":"236","line":120,"column":38,"nodeType":"237","messageId":"238","endLine":120,"endColumn":41,"suggestions":"241","suppressions":"242"},{"ruleId":"235","severity":2,"message":"236","line":132,"column":41,"nodeType":"237","messageId":"238","endLine":132,"endColumn":44,"suggestions":"243","suppressions":"244"},{"ruleId":"235","severity":2,"message":"236","line":160,"column":37,"nodeType":"237","messageId":"238","endLine":160,"endColumn":40,"suggestions":"245","suppressions":"246"},{"ruleId":"235","severity":2,"message":"236","line":170,"column":41,"nodeType":"237","messageId":"238","endLine":170,"endColumn":44,"suggestions":"247","suppressions":"248"},{"ruleId":"249","severity":2,"message":"250","line":9,"column":5,"nodeType":"232","messageId":"251","endLine":9,"endColumn":12,"suppressions":"252"},{"ruleId":"230","severity":2,"message":"253","line":10,"column":9,"nodeType":"232","messageId":"254","endLine":10,"endColumn":19,"suppressions":"255"},{"ruleId":"230","severity":2,"message":"256","line":11,"column":9,"nodeType":"232","messageId":"254","endLine":11,"endColumn":18,"suppressions":"257"},{"ruleId":"249","severity":2,"message":"250","line":12,"column":35,"nodeType":"232","messageId":"251","endLine":12,"endColumn":42,"suppressions":"258"},{"ruleId":"259","severity":2,"message":"260","line":27,"column":3,"nodeType":null,"messageId":"261","endLine":27,"endColumn":22,"suppressions":"262"},"@typescript-eslint/naming-convention","Object Literal Method name `AssignmentExpression` must match one of the following formats: camelCase","Identifier","doesNotMatchFormat",["263"],"@typescript-eslint/no-explicit-any","Unexpected any. Specify a different type.","TSAnyKeyword","unexpectedAny",["264","265"],["266"],["267","268"],["269"],["270","271"],["272"],["273","274"],["275"],["276","277"],["278"],"no-undef","'process' is not defined.","undef",["279"],"Variable name `__filename` trimmed as `_filename` must match one of the following formats: camelCase","doesNotMatchFormatTrimmed",["280"],"Variable name `__dirname` trimmed as `_dirname` must match one of the following formats: camelCase",["281"],["282"],"@typescript-eslint/no-unused-vars","'linesAlreadyWritten' is assigned a value but never used.","unusedVar",["283"],{"kind":"284","justification":"285"},{"messageId":"286","fix":"287","desc":"288"},{"messageId":"289","fix":"290","desc":"291"},{"kind":"284","justification":"285"},{"messageId":"286","fix":"292","desc":"288"},{"messageId":"289","fix":"293","desc":"291"},{"kind":"284","justification":"285"},{"messageId":"286","fix":"294","desc":"288"},{"messageId":"289","fix":"295","desc":"291"},{"kind":"284","justification":"285"},{"messageId":"286","fix":"296","desc":"288"},{"messageId":"289","fix":"297","desc":"291"},{"kind":"284","justification":"285"},{"messageId":"286","fix":"298","desc":"288"},{"messageId":"289","fix":"299","desc":"291"},{"kind":"284","justification":"285"},{"kind":"284","justification":"285"},{"kind":"284","justification":"285"},{"kind":"284","justification":"285"},{"kind":"284","justification":"285"},{"kind":"284","justification":"285"},"directive","","suggestUnknown",{"range":"300","text":"301"},"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct.","suggestNever",{"range":"302","text":"303"},"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of.",{"range":"304","text":"301"},{"range":"305","text":"303"},{"range":"306","text":"301"},{"range":"307","text":"303"},{"range":"308","text":"301"},{"range":"309","text":"303"},{"range":"310","text":"301"},{"range":"311","text":"303"},[1685,1688],"unknown",[1685,1688],"never",[4281,4284],[4281,4284],[4713,4716],[4713,4716],[5701,5704],[5701,5704],[6041,6044],[6041,6044]]
|
package/.gitattributes
ADDED
package/.gitconfig
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"editor.codeActionsOnSave": {
|
|
3
|
+
"source.fixAll.eslint": "explicit",
|
|
4
|
+
"source.organizeImports.biome": "explicit",
|
|
5
|
+
"source.fixAll.biome": "explicit"
|
|
6
|
+
},
|
|
7
|
+
"[typescript]": {
|
|
8
|
+
"editor.defaultFormatter": "biomejs.biome"
|
|
9
|
+
},
|
|
10
|
+
"cSpell.words": [
|
|
11
|
+
// Add words in alphabetical order
|
|
12
|
+
"Actionbar",
|
|
13
|
+
"Testwise",
|
|
14
|
+
"Thinkwise",
|
|
15
|
+
"translatemessage"
|
|
16
|
+
],
|
|
17
|
+
"files.eol": "\n",
|
|
18
|
+
}
|
package/Testwise.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { test as base } from '@playwright/test';
|
|
2
|
+
import { GoToDeepLink } from './page-extensions/GoToDeepLink.js';
|
|
3
|
+
import { LoginFeatures } from './page-extensions/LoginFeatures.js';
|
|
4
|
+
import { UserSimulation } from './page-extensions/UserSimulation.js';
|
|
5
|
+
import { ClickOverride } from './page-overrides/ClickOverride.js';
|
|
6
|
+
import type { Test } from './types/CoreTypes.js';
|
|
7
|
+
|
|
8
|
+
function combineExtensions(baseTest: Test, ...extensions: { new (test: Test): { test: Test } }[]) {
|
|
9
|
+
return extensions.reduce((test, Extension) => new Extension(test).test, baseTest);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const test: Test = combineExtensions(
|
|
13
|
+
base,
|
|
14
|
+
|
|
15
|
+
// Override section
|
|
16
|
+
ClickOverride,
|
|
17
|
+
|
|
18
|
+
// Extend section
|
|
19
|
+
GoToDeepLink,
|
|
20
|
+
LoginFeatures,
|
|
21
|
+
UserSimulation
|
|
22
|
+
);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Locator, Page } from '@playwright/test';
|
|
2
|
+
import type { TSFComponent } from './TSFComponent.js';
|
|
3
|
+
|
|
4
|
+
export abstract class BaseComponent implements TSFComponent {
|
|
5
|
+
protected page: Page;
|
|
6
|
+
protected parentComponent!: BaseComponent;
|
|
7
|
+
|
|
8
|
+
public id: string;
|
|
9
|
+
|
|
10
|
+
constructor(page: Page, testid: string, parentComponent?: BaseComponent) {
|
|
11
|
+
this.page = page;
|
|
12
|
+
this.id = testid;
|
|
13
|
+
|
|
14
|
+
if (parentComponent) {
|
|
15
|
+
this.addParentComponent(parentComponent);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
protected addParentComponent(parentComponent: BaseComponent): void {
|
|
20
|
+
this.parentComponent = parentComponent;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Abstract method to retrieve the locator for the component. Implementations should define how to locate the component
|
|
25
|
+
* within the given context or the page.
|
|
26
|
+
*
|
|
27
|
+
* @param {Locator} [context] - Optional context within which to locate the component.
|
|
28
|
+
* @returns {Promise<Locator>} A promise that resolves to the component's locator.
|
|
29
|
+
*/
|
|
30
|
+
public abstract getLocator(context?: Locator): Promise<Locator>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves the component's locator. If the component's context locator exists, it waits for it to be available
|
|
34
|
+
* and returns it. Otherwise, it falls back to retrieving the locator without context.
|
|
35
|
+
*
|
|
36
|
+
* @returns {Promise<Locator>} A promise that resolves to the component's locator.
|
|
37
|
+
*/
|
|
38
|
+
public async getComponent(): Promise<Locator> {
|
|
39
|
+
const timeout = 250; // per attempt
|
|
40
|
+
const retries = 3;
|
|
41
|
+
const delayMs = 500;
|
|
42
|
+
// Try to get the component locator with existing context
|
|
43
|
+
const componentLocator = await this.getComponentContext();
|
|
44
|
+
|
|
45
|
+
if (componentLocator) {
|
|
46
|
+
// If the component locator can be found on the page, return it
|
|
47
|
+
const found = await this.waitForWithRetry(componentLocator, timeout, retries, delayMs);
|
|
48
|
+
if (found) {
|
|
49
|
+
return componentLocator;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// If no context locator is found, return the component locator without context
|
|
54
|
+
return await this.getLocator();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Helper to wait for a locator with retries.
|
|
59
|
+
*/
|
|
60
|
+
private async waitForWithRetry(
|
|
61
|
+
locator: Locator,
|
|
62
|
+
timeout: number,
|
|
63
|
+
retries: number,
|
|
64
|
+
delayMs: number
|
|
65
|
+
): Promise<boolean> {
|
|
66
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
67
|
+
try {
|
|
68
|
+
await locator.waitFor({ timeout });
|
|
69
|
+
return true;
|
|
70
|
+
} catch {
|
|
71
|
+
if (attempt < retries - 1) {
|
|
72
|
+
await new Promise((res) => setTimeout(res, delayMs));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private async getComponentContext(): Promise<Locator | undefined> {
|
|
80
|
+
// If there is no parent component, check if the current locator exists and return it
|
|
81
|
+
if (!this.parentComponent) {
|
|
82
|
+
const currentLocator = await this.getLocator();
|
|
83
|
+
return currentLocator;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Recursively call the method on the parent component
|
|
87
|
+
const parentLocator = await this.parentComponent.getComponentContext();
|
|
88
|
+
if (parentLocator) {
|
|
89
|
+
const currentLocator = await this.getLocator(parentLocator);
|
|
90
|
+
return currentLocator;
|
|
91
|
+
}
|
|
92
|
+
// If neither the parent nor the current locator exists, return undefined
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Locator, Page } from '@playwright/test';
|
|
2
|
+
import type { IComponentObjects } from './IComponentObjects.js';
|
|
3
|
+
|
|
4
|
+
export abstract class BaseComponentObjects implements IComponentObjects {
|
|
5
|
+
context: Locator;
|
|
6
|
+
|
|
7
|
+
constructor(page: Page, context: Locator | null = null) {
|
|
8
|
+
this.context = context ? context : page.locator('body');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
import { BaseComponent } from './BaseComponent.js';
|
|
3
|
+
|
|
4
|
+
export class Splitter extends BaseComponent {
|
|
5
|
+
public async getLocator(context?: Locator): Promise<Locator> {
|
|
6
|
+
if (context) {
|
|
7
|
+
return context.locator(`[data-type="SplitPane"][class*="${this.id}"]`);
|
|
8
|
+
}
|
|
9
|
+
return this.page.locator(`[data-type="SplitPane"][class*="${this.id}"]`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Locator, Page } from '@playwright/test';
|
|
2
|
+
import { ActionbarObjects } from './ActionbarObjects.js';
|
|
3
|
+
|
|
4
|
+
export class Actionbar {
|
|
5
|
+
private _objects: ActionbarObjects;
|
|
6
|
+
|
|
7
|
+
constructor(page: Page, actionbarContext: Locator | null = null) {
|
|
8
|
+
this._objects = new ActionbarObjects(page, actionbarContext);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Opens the Actionbar’s overflow menu and clicks on the 'Export' button inside it.
|
|
13
|
+
*/
|
|
14
|
+
public async clickExportButton(): Promise<void> {
|
|
15
|
+
await this._objects.overflowMenuButton().click();
|
|
16
|
+
await this._objects.exportButton().click();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// CRUD Buttons
|
|
20
|
+
public getAddButton = (): Locator => this._objects.addButton();
|
|
21
|
+
|
|
22
|
+
public getCancelButton = (): Locator => this._objects.cancelButton();
|
|
23
|
+
|
|
24
|
+
public getCopyButton = (): Locator => this._objects.copyButton();
|
|
25
|
+
|
|
26
|
+
public getDeleteButton = (): Locator => this._objects.deleteButton();
|
|
27
|
+
|
|
28
|
+
public getRefreshButton = (): Locator => this._objects.refreshButton();
|
|
29
|
+
|
|
30
|
+
public getSaveButton = (): Locator => this._objects.saveButton();
|
|
31
|
+
|
|
32
|
+
public getUpdateButton = (): Locator => this._objects.updateButton();
|
|
33
|
+
|
|
34
|
+
// Overflow Menu
|
|
35
|
+
public getOverflowMenuButton = (): Locator => this._objects.overflowMenuButton();
|
|
36
|
+
|
|
37
|
+
public getExportButton = (): Locator => this._objects.exportButton();
|
|
38
|
+
|
|
39
|
+
public getImportButton = (): Locator => this._objects.importButton();
|
|
40
|
+
|
|
41
|
+
public getExportImmediatelyButton = (): Locator => this._objects.exportImmediatelyButton();
|
|
42
|
+
|
|
43
|
+
public getMassUpdateButton = (): Locator => this._objects.massUpdateButton();
|
|
44
|
+
|
|
45
|
+
public getQuickFilterButton = (): Locator => this._objects.quickFilterButton();
|
|
46
|
+
|
|
47
|
+
public getFilterButton = (): Locator => this._objects.filterButton();
|
|
48
|
+
|
|
49
|
+
public getClearAllFiltersButton = (): Locator => this._objects.clearAllFiltersButton();
|
|
50
|
+
|
|
51
|
+
public getRestoreSortOrderButton = (): Locator => this._objects.restoreSortOrderButton();
|
|
52
|
+
|
|
53
|
+
public getSortButton = (): Locator => this._objects.sortButton();
|
|
54
|
+
|
|
55
|
+
// Other Elements
|
|
56
|
+
public getSearchInput = (): Locator => this._objects.searchInput();
|
|
57
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Locator, Page } from '@playwright/test';
|
|
2
|
+
import { BaseComponentObjects } from '../BaseComponentObjects.js';
|
|
3
|
+
|
|
4
|
+
export class ActionbarObjects extends BaseComponentObjects {
|
|
5
|
+
private _page: Page;
|
|
6
|
+
|
|
7
|
+
constructor(page: Page, context: Locator | null = null) {
|
|
8
|
+
super(page, context);
|
|
9
|
+
this._page = page;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// CRUD Buttons
|
|
13
|
+
public addButton = () => this.context.locator('[data-testid="actionbar__add"]');
|
|
14
|
+
|
|
15
|
+
public cancelButton = () => this.context.locator(' [data-testid="actionbar__cancel"]');
|
|
16
|
+
|
|
17
|
+
public copyButton = () => this.context.locator(' [data-testid="actionbar__copy"]');
|
|
18
|
+
|
|
19
|
+
public deleteButton = () => this.context.locator(' [data-testid="actionbar__delete"]');
|
|
20
|
+
|
|
21
|
+
public refreshButton = () => this.context.locator(' [data-testid="actionbar__refresh"]');
|
|
22
|
+
|
|
23
|
+
public saveButton = () => this.context.locator(' [data-testid="actionbar__save"]');
|
|
24
|
+
|
|
25
|
+
public updateButton = () => this.context.locator(' [data-testid="actionbar__update"]');
|
|
26
|
+
|
|
27
|
+
// Overflow Menu Button
|
|
28
|
+
public overflowMenuButton = () => this.context.locator(' [data-testid="actionbar__overflow-menu__button"]');
|
|
29
|
+
|
|
30
|
+
// Overflow Menu Items
|
|
31
|
+
|
|
32
|
+
public exportButton = () =>
|
|
33
|
+
this._page.locator('[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__export"]');
|
|
34
|
+
|
|
35
|
+
public importButton = () =>
|
|
36
|
+
this._page.locator('[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__import"]');
|
|
37
|
+
|
|
38
|
+
public exportImmediatelyButton = () =>
|
|
39
|
+
this._page.locator(
|
|
40
|
+
'[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__export-immediately"]'
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
public massUpdateButton = () =>
|
|
44
|
+
this._page.locator('[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__mass-update"]');
|
|
45
|
+
|
|
46
|
+
public quickFilterButton = () =>
|
|
47
|
+
this._page.locator('[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__quick-filter"]');
|
|
48
|
+
|
|
49
|
+
public filterButton = () =>
|
|
50
|
+
this._page.locator('[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__filter"]');
|
|
51
|
+
|
|
52
|
+
public clearAllFiltersButton = () =>
|
|
53
|
+
this._page.locator(
|
|
54
|
+
'[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__clear-all-filters"]'
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
public restoreSortOrderButton = () =>
|
|
58
|
+
this._page.locator(
|
|
59
|
+
'[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__restore-sort-order"]'
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
public sortButton = () =>
|
|
63
|
+
this._page.locator('[data-testid="actionbar__overflow-menu__context"] [data-testid="actionbar__sort"]');
|
|
64
|
+
|
|
65
|
+
// Other Elements
|
|
66
|
+
public searchInput = () => this.context.locator(' [data-testid="actionbar__search__input"] input');
|
|
67
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
|
+
import { parse } from 'csv-parse/sync';
|
|
3
|
+
import type { ExportFormat } from '../../enums/ExportFormat.js';
|
|
4
|
+
import { ExportComponentObjects } from './ExportComponentObjects.js';
|
|
5
|
+
|
|
6
|
+
// ToDo: Expand on the selectColumns to select by columnId/testId, or what makes sense to empower the end-user
|
|
7
|
+
// ToDo: Make changes to completeExport be able to parse based on the data type selected
|
|
8
|
+
export class ExportComponent {
|
|
9
|
+
private _page: Page;
|
|
10
|
+
private _objects: ExportComponentObjects;
|
|
11
|
+
|
|
12
|
+
constructor(page: Page) {
|
|
13
|
+
this._page = page;
|
|
14
|
+
this._objects = new ExportComponentObjects(page);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public async exportAllRows(): Promise<void> {
|
|
18
|
+
await this._objects.exportAllRowsRadioButton().click();
|
|
19
|
+
await this.nextStep();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public async nextStep(): Promise<void> {
|
|
23
|
+
await this._objects.nextButton().click();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async selectColumns(columns: string[]): Promise<void> {
|
|
27
|
+
for (const column of columns) {
|
|
28
|
+
const checkbox = this._objects.selectColumnsCheckbox(column);
|
|
29
|
+
await checkbox.check();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public async selectExportFormat(format: ExportFormat): Promise<void> {
|
|
34
|
+
await this._objects.exportFormatDropdown().click();
|
|
35
|
+
await this._objects.exportFormatOption(format).click();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async completeExport(): Promise<Record<string, string>[]> {
|
|
39
|
+
const [download] = await Promise.all([this._page.waitForEvent('download'), this._objects.completeButton().click()]);
|
|
40
|
+
|
|
41
|
+
const readableStream = await download.createReadStream();
|
|
42
|
+
const chunks: Buffer[] = [];
|
|
43
|
+
|
|
44
|
+
if (!readableStream) {
|
|
45
|
+
throw new Error('Failed to create a readable stream for the download.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for await (const chunk of readableStream) {
|
|
49
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
50
|
+
}
|
|
51
|
+
const csvContent = Buffer.concat(chunks).toString('utf-8');
|
|
52
|
+
|
|
53
|
+
const records = parse(csvContent, {
|
|
54
|
+
columns: true,
|
|
55
|
+
skip_empty_lines: true,
|
|
56
|
+
delimiter: ',',
|
|
57
|
+
onRecord: (record) => {
|
|
58
|
+
const trimmed: Record<string, string> = {};
|
|
59
|
+
for (const [key, value] of Object.entries(record)) {
|
|
60
|
+
const trimmedKey = key.trim();
|
|
61
|
+
const trimmedValue = typeof value === 'string' ? value.trim() : '';
|
|
62
|
+
trimmed[trimmedKey] = trimmedValue;
|
|
63
|
+
}
|
|
64
|
+
return trimmed;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return records;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Locator, Page } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export class ExportComponentObjects {
|
|
4
|
+
private _page: Page;
|
|
5
|
+
|
|
6
|
+
constructor(page: Page) {
|
|
7
|
+
this._page = page;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public exportAllRowsRadioButton = (): Locator =>
|
|
11
|
+
this._page.getByTestId('radio-button-option__export-all-rows-in-the-grid__title');
|
|
12
|
+
|
|
13
|
+
public nextButton = (): Locator => this._page.getByTestId('stepper-next-button');
|
|
14
|
+
|
|
15
|
+
public selectColumnsCheckbox = (columnName: string): Locator =>
|
|
16
|
+
this._page.locator('.ag-cell', { hasText: columnName }).locator('input[type="checkbox"]');
|
|
17
|
+
|
|
18
|
+
public exportFormatDropdown = (): Locator => this._page.getByTestId('export-format-select');
|
|
19
|
+
|
|
20
|
+
public exportFormatOption = (format: string): Locator => this._page.getByTestId(`export-format-select__${format}`);
|
|
21
|
+
|
|
22
|
+
public completeButton = (): Locator => this._page.getByTestId('stepper-complete-button');
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
import { BaseComponent } from '../BaseComponent';
|
|
3
|
+
|
|
4
|
+
export class FilterForm extends BaseComponent {
|
|
5
|
+
public async getLocator(context?: Locator): Promise<Locator> {
|
|
6
|
+
if (context) {
|
|
7
|
+
return context.getByTestId(this.id);
|
|
8
|
+
}
|
|
9
|
+
return this.page.getByTestId(this.id);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
import { BaseComponent } from '../BaseComponent';
|
|
3
|
+
|
|
4
|
+
export class FindForm extends BaseComponent {
|
|
5
|
+
public async getLocator(context?: Locator): Promise<Locator> {
|
|
6
|
+
if (context) {
|
|
7
|
+
return context.getByTestId(this.id);
|
|
8
|
+
}
|
|
9
|
+
return this.page.getByTestId(this.id);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
import { BaseComponent } from '../BaseComponent.js';
|
|
3
|
+
|
|
4
|
+
export class Form extends BaseComponent {
|
|
5
|
+
public async getLocator(context?: Locator): Promise<Locator> {
|
|
6
|
+
if (context) {
|
|
7
|
+
return context.getByTestId(this.id);
|
|
8
|
+
}
|
|
9
|
+
return this.page.getByTestId(this.id);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public getFieldByColId = (colId: string): Locator => {
|
|
13
|
+
this.getComponent().then((component) => {
|
|
14
|
+
if (component) {
|
|
15
|
+
return component.getByTestId(`form-field__${colId}`);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
// Fallback to page locator if component is not found
|
|
19
|
+
return this.page.getByTestId(`form-field__${colId}`);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
public getFieldByValue = (value: string): Locator => {
|
|
23
|
+
this.getComponent().then((component) => {
|
|
24
|
+
if (component) {
|
|
25
|
+
return component.locator('[data-form="field"]', { hasText: value });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
// Fallback to page locator if component is not found
|
|
29
|
+
return this.page.locator('[data-form="field"]', { hasText: value });
|
|
30
|
+
};
|
|
31
|
+
}
|