@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.
Files changed (152) hide show
  1. package/.ci/azure-pipelines.yaml +80 -0
  2. package/.eslintcache +1 -0
  3. package/.gitattributes +3 -0
  4. package/.gitconfig +2 -0
  5. package/.vscode/settings.json +18 -0
  6. package/Testwise.ts +22 -0
  7. package/components/BaseComponent.ts +95 -0
  8. package/components/BaseComponentObjects.ts +10 -0
  9. package/components/IComponentObjects.ts +5 -0
  10. package/components/Splitter.ts +11 -0
  11. package/components/TSFComponent.ts +8 -0
  12. package/components/actionbar/Actionbar.ts +57 -0
  13. package/components/actionbar/ActionbarObjects.ts +67 -0
  14. package/components/export/ExportComponent.ts +70 -0
  15. package/components/export/ExportComponentObjects.ts +23 -0
  16. package/components/filter/FilterForm.ts +11 -0
  17. package/components/filter/FindForm.ts +11 -0
  18. package/components/form/Form.ts +31 -0
  19. package/components/grid/Grid.ts +221 -0
  20. package/components/grid/GridObjects.ts +45 -0
  21. package/components/index.ts +6 -0
  22. package/components/pop-up/PopUpComponent.ts +14 -0
  23. package/components/pop-up/PopUpComponentModels.ts +13 -0
  24. package/components/tab/Tab.ts +29 -0
  25. package/components/task/TaskBar.ts +11 -0
  26. package/components/task/TaskTiles.ts +11 -0
  27. package/config.json +10 -0
  28. package/dist/Testwise.d.ts +2 -0
  29. package/dist/Testwise.js +14 -0
  30. package/dist/Testwise.js.map +1 -0
  31. package/dist/components/BaseComponent.d.ts +29 -0
  32. package/dist/components/BaseComponent.js +67 -0
  33. package/dist/components/BaseComponent.js.map +1 -0
  34. package/dist/components/BaseComponentObjects.d.ts +6 -0
  35. package/dist/components/BaseComponentObjects.js +6 -0
  36. package/dist/components/BaseComponentObjects.js.map +1 -0
  37. package/dist/components/IComponentObjects.d.ts +4 -0
  38. package/dist/components/IComponentObjects.js +2 -0
  39. package/dist/components/IComponentObjects.js.map +1 -0
  40. package/dist/components/Splitter.d.ts +5 -0
  41. package/dist/components/Splitter.js +10 -0
  42. package/dist/components/Splitter.js.map +1 -0
  43. package/dist/components/TSFComponent.d.ts +6 -0
  44. package/dist/components/TSFComponent.js +2 -0
  45. package/dist/components/TSFComponent.js.map +1 -0
  46. package/dist/components/actionbar/Actionbar.d.ts +27 -0
  47. package/dist/components/actionbar/Actionbar.js +35 -0
  48. package/dist/components/actionbar/Actionbar.js.map +1 -0
  49. package/dist/components/actionbar/ActionbarObjects.d.ts +24 -0
  50. package/dist/components/actionbar/ActionbarObjects.js +30 -0
  51. package/dist/components/actionbar/ActionbarObjects.js.map +1 -0
  52. package/dist/components/export/ExportComponent.d.ts +12 -0
  53. package/dist/components/export/ExportComponent.js +55 -0
  54. package/dist/components/export/ExportComponent.js.map +1 -0
  55. package/dist/components/export/ExportComponentObjects.d.ts +11 -0
  56. package/dist/components/export/ExportComponentObjects.js +12 -0
  57. package/dist/components/export/ExportComponentObjects.js.map +1 -0
  58. package/dist/components/form/Form.d.ts +7 -0
  59. package/dist/components/form/Form.js +31 -0
  60. package/dist/components/form/Form.js.map +1 -0
  61. package/dist/components/grid/Grid.d.ts +93 -0
  62. package/dist/components/grid/Grid.js +183 -0
  63. package/dist/components/grid/Grid.js.map +1 -0
  64. package/dist/components/grid/GridObjects.d.ts +20 -0
  65. package/dist/components/grid/GridObjects.js +25 -0
  66. package/dist/components/grid/GridObjects.js.map +1 -0
  67. package/dist/components/index.d.ts +6 -0
  68. package/dist/components/index.js +7 -0
  69. package/dist/components/index.js.map +1 -0
  70. package/dist/components/pop-up/PopUpComponent.d.ts +7 -0
  71. package/dist/components/pop-up/PopUpComponent.js +9 -0
  72. package/dist/components/pop-up/PopUpComponent.js.map +1 -0
  73. package/dist/components/pop-up/PopUpComponentModels.d.ts +7 -0
  74. package/dist/components/pop-up/PopUpComponentModels.js +8 -0
  75. package/dist/components/pop-up/PopUpComponentModels.js.map +1 -0
  76. package/dist/config.json +10 -0
  77. package/dist/enums/ActionbarRegions.d.ts +5 -0
  78. package/dist/enums/ActionbarRegions.js +7 -0
  79. package/dist/enums/ActionbarRegions.js.map +1 -0
  80. package/dist/enums/ButtonEnums.d.ts +24 -0
  81. package/dist/enums/ButtonEnums.js +29 -0
  82. package/dist/enums/ButtonEnums.js.map +1 -0
  83. package/dist/enums/ExportFormat.d.ts +5 -0
  84. package/dist/enums/ExportFormat.js +7 -0
  85. package/dist/enums/ExportFormat.js.map +1 -0
  86. package/dist/enums/LogLevel.d.ts +8 -0
  87. package/dist/enums/LogLevel.js +11 -0
  88. package/dist/enums/LogLevel.js.map +1 -0
  89. package/dist/example-code/TestifyService.d.ts +22 -0
  90. package/dist/example-code/TestifyService.js +191 -0
  91. package/dist/example-code/TestifyService.js.map +1 -0
  92. package/dist/helpers/InflightRequestTracker.d.ts +10 -0
  93. package/dist/helpers/InflightRequestTracker.js +26 -0
  94. package/dist/helpers/InflightRequestTracker.js.map +1 -0
  95. package/dist/helpers/LoginHelper.d.ts +38 -0
  96. package/dist/helpers/LoginHelper.js +112 -0
  97. package/dist/helpers/LoginHelper.js.map +1 -0
  98. package/dist/helpers/UserSimulationHelper.d.ts +20 -0
  99. package/dist/helpers/UserSimulationHelper.js +62 -0
  100. package/dist/helpers/UserSimulationHelper.js.map +1 -0
  101. package/dist/index.d.ts +34 -0
  102. package/dist/index.js +26 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/page-extensions/GoToDeepLink.d.ts +11 -0
  105. package/dist/page-extensions/GoToDeepLink.js +17 -0
  106. package/dist/page-extensions/GoToDeepLink.js.map +1 -0
  107. package/dist/page-extensions/LoginFeatures.d.ts +16 -0
  108. package/dist/page-extensions/LoginFeatures.js +30 -0
  109. package/dist/page-extensions/LoginFeatures.js.map +1 -0
  110. package/dist/page-extensions/UserSimulation.d.ts +15 -0
  111. package/dist/page-extensions/UserSimulation.js +30 -0
  112. package/dist/page-extensions/UserSimulation.js.map +1 -0
  113. package/dist/page-overrides/ClickOverride.d.ts +6 -0
  114. package/dist/page-overrides/ClickOverride.js +73 -0
  115. package/dist/page-overrides/ClickOverride.js.map +1 -0
  116. package/dist/services/ConfigBuilder.d.ts +12 -0
  117. package/dist/services/ConfigBuilder.js +30 -0
  118. package/dist/services/ConfigBuilder.js.map +1 -0
  119. package/dist/services/Logger.d.ts +8 -0
  120. package/dist/services/Logger.js +106 -0
  121. package/dist/services/Logger.js.map +1 -0
  122. package/dist/services/ReportingService.d.ts +8 -0
  123. package/dist/services/ReportingService.js +29 -0
  124. package/dist/services/ReportingService.js.map +1 -0
  125. package/dist/types/CoreTypes.d.ts +2 -0
  126. package/dist/types/CoreTypes.js +2 -0
  127. package/dist/types/CoreTypes.js.map +1 -0
  128. package/dist/types/universal.d.ts +25 -0
  129. package/dist/types/universal.js +2 -0
  130. package/dist/types/universal.js.map +1 -0
  131. package/enums/ActionbarRegions.ts +5 -0
  132. package/enums/ButtonEnums.ts +28 -0
  133. package/enums/ExportFormat.ts +5 -0
  134. package/enums/LogLevel.ts +9 -0
  135. package/example-code/TestifyService.ts +201 -0
  136. package/helpers/InflightRequestTracker.ts +33 -0
  137. package/helpers/LoginHelper.ts +140 -0
  138. package/helpers/UserSimulationHelper.ts +72 -0
  139. package/index.ts +28 -0
  140. package/package.json +40 -0
  141. package/page-extensions/GoToDeepLink.ts +29 -0
  142. package/page-extensions/LoginFeatures.ts +50 -0
  143. package/page-extensions/UserSimulation.ts +49 -0
  144. package/page-overrides/ClickOverride.ts +89 -0
  145. package/promptCredentials.js +113 -0
  146. package/scripts/Testwise.template.json +19 -0
  147. package/scripts/add-config.js +23 -0
  148. package/services/ConfigBuilder.ts +40 -0
  149. package/services/Logger.ts +125 -0
  150. package/services/ReportingService.ts +41 -0
  151. package/types/CoreTypes.ts +9 -0
  152. 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
@@ -0,0 +1,3 @@
1
+ *.ts eol=lf
2
+ *.tsx eol=lf
3
+ *.yaml eol=lf
package/.gitconfig ADDED
@@ -0,0 +1,2 @@
1
+ [core]
2
+ ignorecase = false
@@ -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,5 @@
1
+ import type { Locator } from '@playwright/test';
2
+
3
+ export interface IComponentObjects {
4
+ context: Locator;
5
+ }
@@ -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,8 @@
1
+ import type { Locator } from '@playwright/test';
2
+
3
+ export interface TSFComponent {
4
+ id: string;
5
+
6
+ getComponent(): Promise<Locator>;
7
+ getLocator(): Promise<Locator>;
8
+ }
@@ -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
+ }