@thinkwise/testwise 0.2.21 → 0.2.67

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 (234) hide show
  1. package/Testwise.ts +2 -0
  2. package/artifact-builder/SelectorBuilder.ts +2 -2
  3. package/artifact-builder/SubjectComponentGenerator.ts +21 -12
  4. package/artifact-builder/SubjectGenerator.ts +20 -6
  5. package/components/action-bar/ActionBar.ts +7 -7
  6. package/components/action-bar/CustomActionBar.ts +0 -5
  7. package/components/cardlist/Cardlist.ts +3 -3
  8. package/components/chart/Chart.ts +3 -3
  9. package/components/combined-filter/CombinedFilter.ts +3 -3
  10. package/components/cube-view-bar/CubeViewBar.ts +3 -3
  11. package/components/filter/ExcelStyleFilterPopup.ts +69 -0
  12. package/components/filter/ExcelStyleFilterPopupObjects.ts +46 -0
  13. package/components/filter/FilterForm.ts +3 -3
  14. package/components/filter/FilterPopup.ts +187 -0
  15. package/components/filter/FilterPopupObjects.ts +63 -0
  16. package/components/filter/ManagePrefilterPopup.ts +44 -0
  17. package/components/filter/ManagePrefilterPopupObjects.ts +28 -0
  18. package/components/form/Form.ts +3 -3
  19. package/components/grid/Grid.ts +48 -133
  20. package/components/grid/GridObjects.ts +0 -19
  21. package/components/index.ts +4 -0
  22. package/components/maps/Maps.ts +3 -3
  23. package/components/menu/ListBarMenuComponent.ts +11 -0
  24. package/components/menu/ListBarMenuComponentObjects.ts +6 -0
  25. package/components/pivot-grid/PivotGrid.ts +3 -3
  26. package/components/pivot-grid/PivotGridFieldList.ts +3 -3
  27. package/components/pop-up/AllRowsPopUp.ts +29 -0
  28. package/components/pop-up/AllRowsPopUpObjects.ts +22 -0
  29. package/components/prefilter-list/PrefilterList.ts +3 -3
  30. package/components/preview/Preview.ts +3 -3
  31. package/components/report-bar/ReportBar.ts +3 -3
  32. package/components/report-tiles/ReportTiles.ts +3 -3
  33. package/components/scheduler/Scheduler.ts +3 -3
  34. package/components/splitter/Splitter.ts +3 -3
  35. package/components/tab/BaseTab.ts +3 -3
  36. package/components/tab/DetailTabPage.ts +4 -4
  37. package/components/tab/Tab.ts +4 -4
  38. package/components/task/TaskBar.ts +3 -3
  39. package/components/task/TaskTiles.ts +3 -3
  40. package/components/topbar/TopBar.ts +2 -0
  41. package/components/tree-view/TreeView.ts +3 -3
  42. package/controls/DateControl.ts +13 -14
  43. package/controls/DateControlObjects.ts +15 -0
  44. package/controls/FormComboBox.ts +17 -30
  45. package/controls/FormComboBoxObjects.ts +27 -0
  46. package/controls/GridColumnControl.ts +68 -0
  47. package/controls/GridColumnControlObjects.ts +20 -0
  48. package/controls/InputFieldControl.ts +17 -20
  49. package/controls/InputFieldControlObjects.ts +19 -0
  50. package/controls/LookupDropdown.ts +65 -24
  51. package/controls/LookupDropdownObjects.ts +19 -0
  52. package/controls/index.ts +1 -0
  53. package/dist/Testwise.d.ts +1 -0
  54. package/dist/Testwise.js +1 -0
  55. package/dist/Testwise.js.map +1 -1
  56. package/dist/artifact-builder/SelectorBuilder.d.ts +1 -1
  57. package/dist/artifact-builder/SelectorBuilder.js +2 -2
  58. package/dist/artifact-builder/SelectorBuilder.js.map +1 -1
  59. package/dist/artifact-builder/SubjectComponentGenerator.js +18 -12
  60. package/dist/artifact-builder/SubjectComponentGenerator.js.map +1 -1
  61. package/dist/artifact-builder/SubjectGenerator.d.ts +1 -0
  62. package/dist/artifact-builder/SubjectGenerator.js +16 -6
  63. package/dist/artifact-builder/SubjectGenerator.js.map +1 -1
  64. package/dist/components/action-bar/ActionBar.d.ts +2 -2
  65. package/dist/components/action-bar/ActionBar.js +7 -7
  66. package/dist/components/action-bar/ActionBar.js.map +1 -1
  67. package/dist/components/action-bar/CustomActionBar.d.ts +0 -2
  68. package/dist/components/action-bar/CustomActionBar.js +0 -3
  69. package/dist/components/action-bar/CustomActionBar.js.map +1 -1
  70. package/dist/components/cardlist/Cardlist.d.ts +2 -2
  71. package/dist/components/cardlist/Cardlist.js +2 -2
  72. package/dist/components/cardlist/Cardlist.js.map +1 -1
  73. package/dist/components/chart/Chart.d.ts +2 -2
  74. package/dist/components/chart/Chart.js +2 -2
  75. package/dist/components/chart/Chart.js.map +1 -1
  76. package/dist/components/combined-filter/CombinedFilter.d.ts +2 -2
  77. package/dist/components/combined-filter/CombinedFilter.js +2 -2
  78. package/dist/components/combined-filter/CombinedFilter.js.map +1 -1
  79. package/dist/components/cube-view-bar/CubeViewBar.d.ts +2 -2
  80. package/dist/components/cube-view-bar/CubeViewBar.js +2 -2
  81. package/dist/components/cube-view-bar/CubeViewBar.js.map +1 -1
  82. package/dist/components/filter/ExcelStyleFilterPopup.d.ts +19 -0
  83. package/dist/components/filter/ExcelStyleFilterPopup.js +64 -0
  84. package/dist/components/filter/ExcelStyleFilterPopup.js.map +1 -0
  85. package/dist/components/filter/ExcelStyleFilterPopupObjects.d.ts +16 -0
  86. package/dist/components/filter/ExcelStyleFilterPopupObjects.js +26 -0
  87. package/dist/components/filter/ExcelStyleFilterPopupObjects.js.map +1 -0
  88. package/dist/components/filter/FilterForm.d.ts +2 -2
  89. package/dist/components/filter/FilterForm.js +2 -2
  90. package/dist/components/filter/FilterForm.js.map +1 -1
  91. package/dist/components/filter/FilterPopup.d.ts +41 -0
  92. package/dist/components/filter/FilterPopup.js +126 -0
  93. package/dist/components/filter/FilterPopup.js.map +1 -0
  94. package/dist/components/filter/FilterPopupObjects.d.ts +29 -0
  95. package/dist/components/filter/FilterPopupObjects.js +30 -0
  96. package/dist/components/filter/FilterPopupObjects.js.map +1 -0
  97. package/dist/components/filter/ManagePrefilterPopup.d.ts +14 -0
  98. package/dist/components/filter/ManagePrefilterPopup.js +33 -0
  99. package/dist/components/filter/ManagePrefilterPopup.js.map +1 -0
  100. package/dist/components/filter/ManagePrefilterPopupObjects.d.ts +11 -0
  101. package/dist/components/filter/ManagePrefilterPopupObjects.js +19 -0
  102. package/dist/components/filter/ManagePrefilterPopupObjects.js.map +1 -0
  103. package/dist/components/form/Form.d.ts +2 -2
  104. package/dist/components/form/Form.js +2 -2
  105. package/dist/components/form/Form.js.map +1 -1
  106. package/dist/components/grid/Grid.d.ts +7 -37
  107. package/dist/components/grid/Grid.js +32 -127
  108. package/dist/components/grid/Grid.js.map +1 -1
  109. package/dist/components/grid/GridObjects.d.ts +0 -6
  110. package/dist/components/grid/GridObjects.js +0 -8
  111. package/dist/components/grid/GridObjects.js.map +1 -1
  112. package/dist/components/index.d.ts +4 -0
  113. package/dist/components/index.js +4 -0
  114. package/dist/components/index.js.map +1 -1
  115. package/dist/components/maps/Maps.d.ts +2 -2
  116. package/dist/components/maps/Maps.js +2 -2
  117. package/dist/components/maps/Maps.js.map +1 -1
  118. package/dist/components/menu/ListBarMenuComponent.d.ts +6 -0
  119. package/dist/components/menu/ListBarMenuComponent.js +10 -0
  120. package/dist/components/menu/ListBarMenuComponent.js.map +1 -1
  121. package/dist/components/menu/ListBarMenuComponentObjects.d.ts +2 -0
  122. package/dist/components/menu/ListBarMenuComponentObjects.js +2 -0
  123. package/dist/components/menu/ListBarMenuComponentObjects.js.map +1 -1
  124. package/dist/components/pivot-grid/PivotGrid.d.ts +2 -2
  125. package/dist/components/pivot-grid/PivotGrid.js +2 -2
  126. package/dist/components/pivot-grid/PivotGrid.js.map +1 -1
  127. package/dist/components/pivot-grid/PivotGridFieldList.d.ts +2 -2
  128. package/dist/components/pivot-grid/PivotGridFieldList.js +2 -2
  129. package/dist/components/pivot-grid/PivotGridFieldList.js.map +1 -1
  130. package/dist/components/pop-up/AllRowsPopUp.d.ts +12 -0
  131. package/dist/components/pop-up/AllRowsPopUp.js +19 -0
  132. package/dist/components/pop-up/AllRowsPopUp.js.map +1 -0
  133. package/dist/components/pop-up/AllRowsPopUpObjects.d.ts +11 -0
  134. package/dist/components/pop-up/AllRowsPopUpObjects.js +13 -0
  135. package/dist/components/pop-up/AllRowsPopUpObjects.js.map +1 -0
  136. package/dist/components/prefilter-list/PrefilterList.d.ts +2 -2
  137. package/dist/components/prefilter-list/PrefilterList.js +2 -2
  138. package/dist/components/prefilter-list/PrefilterList.js.map +1 -1
  139. package/dist/components/preview/Preview.d.ts +2 -2
  140. package/dist/components/preview/Preview.js +2 -2
  141. package/dist/components/preview/Preview.js.map +1 -1
  142. package/dist/components/report-bar/ReportBar.d.ts +2 -2
  143. package/dist/components/report-bar/ReportBar.js +2 -2
  144. package/dist/components/report-bar/ReportBar.js.map +1 -1
  145. package/dist/components/report-tiles/ReportTiles.d.ts +2 -2
  146. package/dist/components/report-tiles/ReportTiles.js +2 -2
  147. package/dist/components/report-tiles/ReportTiles.js.map +1 -1
  148. package/dist/components/scheduler/Scheduler.d.ts +2 -2
  149. package/dist/components/scheduler/Scheduler.js +2 -2
  150. package/dist/components/scheduler/Scheduler.js.map +1 -1
  151. package/dist/components/splitter/Splitter.d.ts +2 -2
  152. package/dist/components/splitter/Splitter.js +2 -2
  153. package/dist/components/splitter/Splitter.js.map +1 -1
  154. package/dist/components/tab/BaseTab.d.ts +2 -2
  155. package/dist/components/tab/BaseTab.js +2 -2
  156. package/dist/components/tab/BaseTab.js.map +1 -1
  157. package/dist/components/tab/DetailTabPage.d.ts +2 -2
  158. package/dist/components/tab/DetailTabPage.js +3 -3
  159. package/dist/components/tab/DetailTabPage.js.map +1 -1
  160. package/dist/components/tab/Tab.d.ts +2 -2
  161. package/dist/components/tab/Tab.js +3 -3
  162. package/dist/components/tab/Tab.js.map +1 -1
  163. package/dist/components/task/TaskBar.d.ts +2 -2
  164. package/dist/components/task/TaskBar.js +2 -2
  165. package/dist/components/task/TaskBar.js.map +1 -1
  166. package/dist/components/task/TaskTiles.d.ts +2 -2
  167. package/dist/components/task/TaskTiles.js +2 -2
  168. package/dist/components/task/TaskTiles.js.map +1 -1
  169. package/dist/components/topbar/TopBar.d.ts +1 -0
  170. package/dist/components/topbar/TopBar.js +1 -0
  171. package/dist/components/topbar/TopBar.js.map +1 -1
  172. package/dist/components/tree-view/TreeView.d.ts +2 -2
  173. package/dist/components/tree-view/TreeView.js +2 -2
  174. package/dist/components/tree-view/TreeView.js.map +1 -1
  175. package/dist/controls/DateControl.d.ts +4 -5
  176. package/dist/controls/DateControl.js +11 -11
  177. package/dist/controls/DateControl.js.map +1 -1
  178. package/dist/controls/DateControlObjects.d.ts +8 -0
  179. package/dist/controls/DateControlObjects.js +9 -0
  180. package/dist/controls/DateControlObjects.js.map +1 -0
  181. package/dist/controls/FormComboBox.d.ts +2 -2
  182. package/dist/controls/FormComboBox.js +15 -20
  183. package/dist/controls/FormComboBox.js.map +1 -1
  184. package/dist/controls/FormComboBoxObjects.d.ts +12 -0
  185. package/dist/controls/FormComboBoxObjects.js +16 -0
  186. package/dist/controls/FormComboBoxObjects.js.map +1 -0
  187. package/dist/controls/GridColumnControl.d.ts +10 -0
  188. package/dist/controls/GridColumnControl.js +43 -0
  189. package/dist/controls/GridColumnControl.js.map +1 -0
  190. package/dist/controls/GridColumnControlObjects.d.ts +9 -0
  191. package/dist/controls/GridColumnControlObjects.js +13 -0
  192. package/dist/controls/GridColumnControlObjects.js.map +1 -0
  193. package/dist/controls/InputFieldControl.d.ts +4 -6
  194. package/dist/controls/InputFieldControl.js +14 -15
  195. package/dist/controls/InputFieldControl.js.map +1 -1
  196. package/dist/controls/InputFieldControlObjects.d.ts +10 -0
  197. package/dist/controls/InputFieldControlObjects.js +11 -0
  198. package/dist/controls/InputFieldControlObjects.js.map +1 -0
  199. package/dist/controls/LookupDropdown.d.ts +6 -1
  200. package/dist/controls/LookupDropdown.js +51 -19
  201. package/dist/controls/LookupDropdown.js.map +1 -1
  202. package/dist/controls/LookupDropdownObjects.d.ts +10 -0
  203. package/dist/controls/LookupDropdownObjects.js +11 -0
  204. package/dist/controls/LookupDropdownObjects.js.map +1 -0
  205. package/dist/controls/index.d.ts +1 -0
  206. package/dist/controls/index.js +1 -0
  207. package/dist/controls/index.js.map +1 -1
  208. package/dist/enums/ElementTypes.d.ts +1 -1
  209. package/dist/enums/ElementTypes.js +1 -1
  210. package/dist/enums/ElementTypes.js.map +1 -1
  211. package/dist/helpers/FlightTracker.d.ts +7 -0
  212. package/dist/helpers/FlightTracker.js +63 -11
  213. package/dist/helpers/FlightTracker.js.map +1 -1
  214. package/dist/helpers/LoginHelper.d.ts +11 -3
  215. package/dist/helpers/LoginHelper.js +59 -13
  216. package/dist/helpers/LoginHelper.js.map +1 -1
  217. package/dist/index.d.ts +1 -1
  218. package/dist/index.js +1 -1
  219. package/dist/index.js.map +1 -1
  220. package/dist/page-extensions/GlobalComponents.d.ts +2 -1
  221. package/dist/page-extensions/GlobalComponents.js +2 -1
  222. package/dist/page-extensions/GlobalComponents.js.map +1 -1
  223. package/dist/page-overrides/ClickOverride.d.ts +1 -0
  224. package/dist/page-overrides/ClickOverride.js +57 -46
  225. package/dist/page-overrides/ClickOverride.js.map +1 -1
  226. package/dist/types/Universal.d.ts +1 -0
  227. package/enums/ElementTypes.ts +1 -1
  228. package/helpers/FlightTracker.ts +71 -11
  229. package/helpers/LoginHelper.ts +79 -21
  230. package/index.ts +1 -1
  231. package/package.json +6 -5
  232. package/page-extensions/GlobalComponents.ts +3 -0
  233. package/page-overrides/ClickOverride.ts +69 -64
  234. package/types/Universal.ts +1 -0
package/Testwise.ts CHANGED
@@ -7,6 +7,8 @@ import { ClickOverride } from './page-overrides/ClickOverride.js';
7
7
  import { FillOverride } from './page-overrides/FillOverride.js';
8
8
  import type { Test } from './types/Test.js';
9
9
 
10
+ export * from '@playwright/test';
11
+
10
12
  function combineExtensions(baseTest: Test, ...extensions: { new (test: Test): { test: Test } }[]) {
11
13
  return extensions.reduce((test, Extension) => new Extension(test).test, baseTest);
12
14
  }
@@ -60,7 +60,7 @@ export class SelectorBuilder {
60
60
  );
61
61
  }
62
62
 
63
- public getPageLocatorString(property: string, componentName: SubjectComponents): string {
63
+ public getLocatorString(property: string, componentName: SubjectComponents): string {
64
64
  let elementId = this.getElementId(property, componentName);
65
65
 
66
66
  if (componentName === 'Grid') elementId = elementId.replace(/-/g, '_');
@@ -69,7 +69,7 @@ export class SelectorBuilder {
69
69
  const defaultSuffix = this.getDefaultSuffix(componentName);
70
70
  const selectorSuffix = this.determineSelectorSuffix(property, componentName) || defaultSuffix;
71
71
 
72
- return `page.${this.getLocatorType(componentName)}('${selectorPrefix}${elementId}${selectorSuffix}')`;
72
+ return `this._context.${this.getLocatorType(componentName)}('${selectorPrefix}${elementId}${selectorSuffix}')`;
73
73
  }
74
74
 
75
75
  private getLocatorType(componentName: SubjectComponents): LocatorType {
@@ -118,9 +118,12 @@ export class SubjectComponentGenerator {
118
118
  const classBody =
119
119
  componentName === 'Grid'
120
120
  ? `\nexport class ${mainInterface}Component extends ${componentName} implements ${mainInterface} {\n\n` +
121
- ` constructor(page: Page, context: Locator | null = null) {\n super(page, context);\n }\n\n${gridGetters}}\n`
122
- : `\nexport class ${mainInterface}Component extends ${componentName} implements ${mainInterface} {\n${propertyDeclarations}\n\n` +
123
- ` constructor(page: Page, context: Locator | null = null) {\n super(page, context);\n${assignments}\n }\n}\n`;
121
+ ` private _context: Locator;\n\n` +
122
+ ` constructor(context: Locator) {\n super(context);\n this._context = context;\n }\n\n${gridGetters}}\n`
123
+ : `\nexport class ${mainInterface}Component extends ${componentName} implements ${mainInterface} {\n\n` +
124
+ ` private _context: Locator;\n` +
125
+ `${propertyDeclarations}\n\n` +
126
+ ` constructor(context: Locator) {\n super(context);\n this._context = context;\n${assignments}\n }\n}\n`;
124
127
 
125
128
  componentFile.content += classBody;
126
129
  }
@@ -145,7 +148,7 @@ export class SubjectComponentGenerator {
145
148
  const interfaceRegex = /export interface \w+ extends Grid \{([\s\S]*?)\}/g;
146
149
 
147
150
  componentFile.content = componentFile.content.replace(interfaceRegex, (match, body) => {
148
- const transformedBody = body.replace(/(\w+)\s*:\s*Locator(?:\[\])?;/g, 'readonly $1: Promise<Locator[]>;');
151
+ const transformedBody = body.replace(/(\w+)\s*:\s*Locator(?:\[\])?;/g, 'readonly $1: IGridColumnControl;');
149
152
  return match.replace(body, transformedBody);
150
153
  });
151
154
  }
@@ -154,9 +157,9 @@ export class SubjectComponentGenerator {
154
157
  return propertyLines
155
158
  .map((line) => {
156
159
  const property = line.replace('readonly', '').split(':')[0].trim();
157
- const pageLocatorString = this._selectorBuilder.getPageLocatorString(property, componentName);
160
+ const columnId = this._selectorBuilder.getElementId(property, componentName);
158
161
 
159
- return ` get ${property}(): Promise<Locator[]> {\n return this.${pageLocatorString}.all();\n }\n`;
162
+ return ` public get ${property}(): IGridColumnControl {\n return createGridColumnControl(this._context, '${columnId}');\n }\n`;
160
163
  })
161
164
  .join('\n');
162
165
  }
@@ -178,19 +181,20 @@ export class SubjectComponentGenerator {
178
181
  return propertyLines
179
182
  .map((line) => {
180
183
  const property = line.split(':')[0].replace(/\?$/, '').trim();
181
- const pageLocatorString = this._selectorBuilder.getPageLocatorString(property, componentName);
184
+ const pageLocatorString = this._selectorBuilder.getLocatorString(property, componentName);
182
185
 
183
186
  if (componentName === 'Form') {
184
- if (property.endsWith('Lookup')) return ` this.${property} = createLookupDropdown(${pageLocatorString});`;
187
+ if (property.endsWith('Lookup'))
188
+ return ` this.${property} = createLookupDropdown(this._context, '${this._selectorBuilder.getElementId(property, componentName)}');`;
185
189
 
186
190
  if (property.endsWith('DatePicker'))
187
- return ` this.${property} = createDateControl(page, '${this._selectorBuilder.getElementId(property, componentName)}');`;
191
+ return ` this.${property} = createDateControl(this._context, '${this._selectorBuilder.getElementId(property, componentName)}');`;
188
192
 
189
193
  if (property.endsWith('ComboBox'))
190
- return ` this.${property} = createFormComboBox(page, '${this._selectorBuilder.getElementId(property, componentName)}');`;
194
+ return ` this.${property} = createFormComboBox(this._context, '${this._selectorBuilder.getElementId(property, componentName)}');`;
191
195
 
192
196
  if (property.endsWith('Field'))
193
- return ` this.${property} = createInputFieldControl(page, '${this._selectorBuilder.getElementId(property, componentName)}');`;
197
+ return ` this.${property} = createInputFieldControl(this._context, '${this._selectorBuilder.getElementId(property, componentName)}');`;
194
198
  }
195
199
 
196
200
  return ` this.${property} = ${pageLocatorString};`;
@@ -304,7 +308,12 @@ export class SubjectComponentGenerator {
304
308
 
305
309
  private addComponentImports(componentFile: { content: string }, componentName: string): void {
306
310
  // biome-ignore lint/style/useTemplate: reason 42
307
- componentFile.content = `import type { Locator, Page } from '@playwright/test';\n\n` + componentFile.content;
311
+ componentFile.content = `import type { Locator } from '@playwright/test';\n\n` + componentFile.content;
312
+
313
+ if (componentName === 'Grid') {
314
+ componentFile.content = `import { createGridColumnControl, type IGridColumnControl } from '../../../../controls/GridColumnControl.js';\n${componentFile.content}`;
315
+ }
316
+
308
317
  componentFile.content = `import { ${componentName} } from '../../../../components/index.js';\n${componentFile.content}`;
309
318
  }
310
319
 
@@ -98,11 +98,20 @@ export class SubjectGenerator {
98
98
  this.addClassExport(subjectClass, screenInterfaceName);
99
99
  this.addComponentDeclarations(subjectClass, componentDictionary, subjectFolderName);
100
100
  this.addConstructor(subjectClass, componentDictionary, subjectFolderName, subject);
101
+ this.addGoToMethod(subjectClass, subject);
101
102
  this.addSubjectClassLineEndings(subjectClass);
102
103
  this.verifyDirectoryExists(subjectFolderPath);
103
104
  fs.writeFileSync(path.join(subjectFolderPath, `${subjectClass.name}.ts`), subjectClass.content, 'utf-8');
104
105
  }
105
106
 
107
+ private addGoToMethod(subjectClass: { content: string }, subject: ISubject): void {
108
+ let url = `subject=${subject.subject}`;
109
+
110
+ if (subject.variant !== '') url = `${url}/subjectVariant=${subject.variant}`;
111
+
112
+ subjectClass.content += `\n public async goTo() {\n await this._subjectPage.goToDeepLink(\`${url}\`);\n await this._subjectPage.waitForLoadState('networkidle');\n }\n`;
113
+ }
114
+
106
115
  private getAllComponentsFromInterface(
107
116
  screenFileContent: string,
108
117
  screenInterfaceName: string,
@@ -266,6 +275,8 @@ export class SubjectGenerator {
266
275
  const componentType = `${subjectFolderName}${component.type}`;
267
276
  subjectClass.content += ` ${propertyName}: ${componentType};\n`;
268
277
  });
278
+
279
+ subjectClass.content += ` private _subjectPage: Page;\n`;
269
280
  }
270
281
 
271
282
  private addConstructor(
@@ -290,8 +301,11 @@ export class SubjectGenerator {
290
301
  }
291
302
 
292
303
  const componentName = component.type;
293
- subjectClass.content += ` this.${propertyName} = new ${subjectFolderName}${componentName}Component(page, ${component.context});\n`;
304
+ subjectClass.content += ` this.${propertyName} = new ${subjectFolderName}${componentName}Component(${component.context});\n`;
294
305
  });
306
+
307
+ subjectClass.content += ` this._subjectPage = this.context.page();\n`;
308
+ subjectClass.content += ` }\n`;
295
309
  }
296
310
 
297
311
  private getComponentInitializer(component: { type: string; context: string }, componentId: string): string {
@@ -309,7 +323,7 @@ export class SubjectGenerator {
309
323
  case 'ReportBar':
310
324
  case 'ReportTiles':
311
325
  case 'Preview':
312
- return `new ${component.type}(page, this.context.locator('.${component.type}.${componentNamePascal}'))`;
326
+ return `new ${component.type}(this.context.locator('.${component.type}.${componentNamePascal}'))`;
313
327
  case 'CombinedFilter':
314
328
  case 'CustomActionBar':
315
329
  case 'ActionBar':
@@ -318,17 +332,17 @@ export class SubjectGenerator {
318
332
  case 'Tab':
319
333
  case 'FilterForm':
320
334
  case 'Scheduler':
321
- return `new ${component.type}(page, ${component.context})`;
335
+ return `new ${component.type}(${component.context})`;
322
336
  case 'TreeView':
323
- return `new ${component.type}(page, this.context.locator('.Tree.${componentNamePascal}'))`;
337
+ return `new ${component.type}(this.context.locator('.Tree.${componentNamePascal}'))`;
324
338
  case 'TaskBar':
325
- return `new ${component.type}(page, this.context.locator('.ActionBar.${componentId}'))`;
339
+ return `new ${component.type}(this.context.locator('.ActionBar.${componentId}'))`;
326
340
  default:
327
341
  throw new Error(`Unknown core component type: ${component.type}`);
328
342
  }
329
343
  }
330
344
 
331
345
  private addSubjectClassLineEndings(subjectClass: { content: string }): void {
332
- subjectClass.content += ` }\n}\n`;
346
+ subjectClass.content += `}\n`;
333
347
  }
334
348
  }
@@ -4,8 +4,8 @@ import { ActionBarObjects, ActionBarOverflowableObjects } from './ActionBarObjec
4
4
  class ActionBarActions {
5
5
  private _objects: ActionBarOverflowableObjects;
6
6
 
7
- constructor(page: Page, context: Locator | null = null) {
8
- this._objects = new ActionBarOverflowableObjects(page, context);
7
+ constructor(context: Locator) {
8
+ this._objects = new ActionBarOverflowableObjects(context.page(), context);
9
9
  }
10
10
 
11
11
  public getSearchInput = (): Locator => this._objects.searchInput();
@@ -90,10 +90,10 @@ export class ActionBar extends ActionBarActions {
90
90
  private _actionBarObjects: ActionBarObjects;
91
91
  private _overflowMenu: ActionBarOverflow;
92
92
 
93
- constructor(page: Page, actionBarContext: Locator | null = null) {
94
- super(page, actionBarContext);
95
- this._actionBarObjects = new ActionBarObjects(page, actionBarContext);
96
- this._overflowMenu = new ActionBarOverflow(page);
93
+ constructor(actionBarContext: Locator) {
94
+ super(actionBarContext);
95
+ this._actionBarObjects = new ActionBarObjects(actionBarContext.page(), actionBarContext);
96
+ this._overflowMenu = new ActionBarOverflow(actionBarContext.page());
97
97
  }
98
98
 
99
99
  public openOverflowMenu = async (): Promise<void> => {
@@ -148,7 +148,7 @@ export class ActionBar extends ActionBarActions {
148
148
 
149
149
  export class ActionBarOverflow extends ActionBarActions {
150
150
  constructor(page: Page) {
151
- super(page, page.getByTestId('actionbar__overflow-menu__context'));
151
+ super(page.getByTestId('actionbar__overflow-menu__context'));
152
152
  }
153
153
  }
154
154
 
@@ -1,10 +1,5 @@
1
- import type { Locator, Page } from '@playwright/test';
2
1
  import { ActionBar } from './ActionBar.js';
3
2
 
4
3
  export class CustomActionBar extends ActionBar {
5
- constructor(page: Page, context: Locator | null = null) {
6
- super(page, context);
7
- }
8
-
9
4
  // What should this do differently?
10
5
  }
@@ -1,11 +1,11 @@
1
- import type { Locator, Page } from '@playwright/test';
1
+ import type { Locator } from '@playwright/test';
2
2
  import { CardlistObjects } from './CardlistObjects.js';
3
3
 
4
4
  export class Cardlist {
5
5
  cardlistObjects: CardlistObjects;
6
6
 
7
- constructor(page: Page, context: Locator | null = null) {
8
- this.cardlistObjects = new CardlistObjects(page, context);
7
+ constructor(context: Locator) {
8
+ this.cardlistObjects = new CardlistObjects(context.page(), context);
9
9
  }
10
10
 
11
11
  public get context(): Locator | null {
@@ -1,11 +1,11 @@
1
- import type { Locator, Page } from '@playwright/test';
1
+ import type { Locator } from '@playwright/test';
2
2
  import { ChartObjects } from './ChartObjects.js';
3
3
 
4
4
  export class Chart {
5
5
  chartObjects: ChartObjects;
6
6
 
7
- constructor(page: Page, context: Locator | null = null) {
8
- this.chartObjects = new ChartObjects(page, context);
7
+ constructor(context: Locator) {
8
+ this.chartObjects = new ChartObjects(context.page(), context);
9
9
  }
10
10
 
11
11
  public get context(): Locator | null {
@@ -1,11 +1,11 @@
1
- import type { Locator, Page } from '@playwright/test';
1
+ import type { Locator } from '@playwright/test';
2
2
  import { CombinedFilterObjects } from './CombinedFIlterObjects.js';
3
3
 
4
4
  export class CombinedFilter {
5
5
  combinedFilterObjects: CombinedFilterObjects;
6
6
 
7
- constructor(page: Page, context: Locator | null = null) {
8
- this.combinedFilterObjects = new CombinedFilterObjects(page, context);
7
+ constructor(context: Locator) {
8
+ this.combinedFilterObjects = new CombinedFilterObjects(context.page(), context);
9
9
  }
10
10
 
11
11
  public get context(): Locator | null {
@@ -1,11 +1,11 @@
1
- import type { Locator, Page } from '@playwright/test';
1
+ import type { Locator } from '@playwright/test';
2
2
  import { CubeViewBarObjects } from './CubeViewBarObjects.js';
3
3
 
4
4
  export class CubeViewBar {
5
5
  cubeViewBarObjects: CubeViewBarObjects;
6
6
 
7
- constructor(page: Page, context: Locator | null = null) {
8
- this.cubeViewBarObjects = new CubeViewBarObjects(page, context);
7
+ constructor(context: Locator) {
8
+ this.cubeViewBarObjects = new CubeViewBarObjects(context.page(), context);
9
9
  }
10
10
 
11
11
  public get context(): Locator | null {
@@ -0,0 +1,69 @@
1
+ import type { Locator, Page } from '@playwright/test';
2
+ import { ExcelStyleFilterPopupObjects } from './ExcelStyleFilterPopupObjects.js';
3
+
4
+ export class ExcelStyleFilterPopup {
5
+ private _objects: ExcelStyleFilterPopupObjects;
6
+
7
+ constructor(page: Page) {
8
+ this._objects = new ExcelStyleFilterPopupObjects(page);
9
+ }
10
+
11
+ public async waitForOpen(): Promise<void> {
12
+ await (await this._objects.popup().all()).filter(async (element) => await element.isVisible());
13
+ }
14
+
15
+ public intervalFilters(): Locator {
16
+ return this._objects.intervalFilters();
17
+ }
18
+
19
+ public fromDateInput(fieldTestId: string): Locator {
20
+ return this._objects.fromDateInput(fieldTestId);
21
+ }
22
+
23
+ public toDateInput(fieldTestId: string): Locator {
24
+ return this._objects.toDateInput(fieldTestId);
25
+ }
26
+
27
+ public async waitForClose(): Promise<void> {
28
+ await (await this._objects.popup().all()).filter(async (element) => !(await element.isVisible()));
29
+ }
30
+
31
+ public async clickSelectAll(fieldTestId: string): Promise<void> {
32
+ await this.waitForOpen();
33
+ await this._objects.checkboxSelectAllButton(fieldTestId).click();
34
+ }
35
+
36
+ public async clickCheckboxItem(fieldTestId: string, value: string): Promise<void> {
37
+ await this.waitForOpen();
38
+
39
+ await this._objects.checkboxItemButtons(fieldTestId).filter({ hasText: value }).click();
40
+ }
41
+
42
+ public checkboxItem(fieldTestId: string, value: string): Locator {
43
+ return this._objects.checkboxItemCheckboxes(fieldTestId).filter({ hasText: value });
44
+ }
45
+
46
+ public fromTimeInput(fieldTestId: string): Locator {
47
+ return this._objects.fromTimeInput(fieldTestId);
48
+ }
49
+
50
+ public toTimeInput(fieldTestId: string): Locator {
51
+ return this._objects.toTimeInput(fieldTestId);
52
+ }
53
+
54
+ public setFromTime = async (fieldTestId: string, value: string): Promise<void> => this.fillAndEnter(fieldTestId, value);
55
+
56
+ public setToTime = async (fieldTestId: string, value: string): Promise<void> => this.fillAndEnter(fieldTestId, value);
57
+
58
+ public setFromDate = async (fieldTestId: string, value: string): Promise<void> => this.fillAndEnter(fieldTestId, value);
59
+
60
+ public setToDate = async (fieldTestId: string, value: string): Promise<void> => this.fillAndEnter(fieldTestId, value);
61
+
62
+ private async fillAndEnter(fieldTestId: string, value: string): Promise<void> {
63
+ const input = this._objects.fromDateInput(fieldTestId);
64
+
65
+ await this.waitForOpen();
66
+ await input.fill(value);
67
+ await input.press('Enter');
68
+ }
69
+ }
@@ -0,0 +1,46 @@
1
+ import type { Page } from '@playwright/test';
2
+ import { BaseComponentObjects } from '../BaseComponentObjects.js';
3
+
4
+ export class ExcelStyleFilterPopupObjects extends BaseComponentObjects {
5
+ private _page: Page;
6
+
7
+ constructor(page: Page) {
8
+ super(page);
9
+ this._page = page;
10
+ }
11
+ public popup = () => this._page.locator('[data-testid*="-excel-filter__"]');
12
+
13
+ public intervalFilters = () => this._page.getByTestId('excel-style-filter-popup__interval-filters');
14
+
15
+ public fromDateInput = (fieldTestId: string) =>
16
+ this._page
17
+ .getByTestId(`date-time-excel-filter__${fieldTestId}__from`)
18
+ .getByTestId(`form-field__${fieldTestId}__date__input`);
19
+
20
+ public toDateInput = (fieldTestId: string) =>
21
+ this._page
22
+ .getByTestId(`date-time-excel-filter__${fieldTestId}__to`)
23
+ .getByTestId(`form-field__${fieldTestId}__date__input`);
24
+
25
+ public checkboxList = (fieldTestId: string) =>
26
+ this._page.locator(`[data-testid*="-excel-filter__${fieldTestId}__list"]`);
27
+
28
+ public checkboxSelectAllButton = (fieldTestId: string) =>
29
+ this._page.locator(`[data-testid*="-excel-filter__${fieldTestId}__list-item-select-all-checkbox"]`);
30
+
31
+ public checkboxItemButtons = (fieldTestId: string) =>
32
+ this._page.locator(`[data-testid*="-excel-filter__${fieldTestId}__list-item-button__"]`);
33
+
34
+ public checkboxItemCheckboxes = (fieldTestId: string) =>
35
+ this._page.locator(`[data-testid*="-excel-filter__${fieldTestId}__list-item-checkbox__"]`);
36
+
37
+ public fromTimeInput = (fieldTestId: string) =>
38
+ this._page
39
+ .getByTestId(`date-time-excel-filter__${fieldTestId}__from`)
40
+ .getByTestId(`form-field__${fieldTestId}__time__input`);
41
+
42
+ public toTimeInput = (fieldTestId: string) =>
43
+ this._page
44
+ .getByTestId(`date-time-excel-filter__${fieldTestId}__to`)
45
+ .getByTestId(`form-field__${fieldTestId}__time__input`);
46
+ }
@@ -1,11 +1,11 @@
1
- import type { Locator, Page } from '@playwright/test';
1
+ import type { Locator } from '@playwright/test';
2
2
  import { FilterFormObjects } from './FilterFormObjects.js';
3
3
 
4
4
  export class FilterForm {
5
5
  filterFormObjects: FilterFormObjects;
6
6
 
7
- constructor(page: Page, context: Locator | null = null) {
8
- this.filterFormObjects = new FilterFormObjects(page, context);
7
+ constructor(context: Locator) {
8
+ this.filterFormObjects = new FilterFormObjects(context.page(), context);
9
9
  }
10
10
 
11
11
  public get context(): Locator | null {
@@ -0,0 +1,187 @@
1
+ import type { Locator, Page } from '@playwright/test';
2
+ import { PopUpComponent } from '../pop-up/PopUpComponent.js';
3
+ import { FilterPopupObjects } from './FilterPopupObjects.js';
4
+
5
+ export type IntervalType =
6
+ | 'date'
7
+ | 'date-and-time'
8
+ | 'time'
9
+ | 'year'
10
+ | 'quarter'
11
+ | 'month'
12
+ | 'week-of-the-year'
13
+ | 'day-of-the-month';
14
+
15
+ export type AutocompleteKey =
16
+ | IntervalType
17
+ | 'equal-to'
18
+ | 'smaller-than'
19
+ | 'q1'
20
+ | 'q2'
21
+ | 'q3'
22
+ | 'q4'
23
+ | 'january'
24
+ | 'february'
25
+ | 'march'
26
+ | 'april'
27
+ | 'may'
28
+ | 'june'
29
+ | 'july'
30
+ | 'august'
31
+ | 'september'
32
+ | 'october'
33
+ | 'november'
34
+ | 'december'
35
+ | 'all-of-the-following'
36
+ | 'any-of-the-following';
37
+
38
+ export class FilterPopup {
39
+ readonly page: Page;
40
+ private _filterPopupObjects: FilterPopupObjects;
41
+ private _body: Locator;
42
+
43
+ constructor(page: Page) {
44
+ this.page = page;
45
+ this._body = new PopUpComponent(page).getContentBody();
46
+ this._filterPopupObjects = new FilterPopupObjects(page, this._body);
47
+ }
48
+
49
+ // Root content locator (useful for occasional assertions)
50
+ public content(): Locator {
51
+ return this._body;
52
+ }
53
+
54
+ public async waitForOpen(): Promise<void> {
55
+ await this._filterPopupObjects.applyFilterButton().waitFor();
56
+ }
57
+
58
+ public async applyFilter(): Promise<void> {
59
+ await this.waitForOpen();
60
+ await this._filterPopupObjects.applyFilterButton().click();
61
+ }
62
+
63
+ public async applySaveAsPrefilterWithName(name: string): Promise<void> {
64
+ await this.waitForOpen();
65
+ await this._filterPopupObjects.applySaveButton().click();
66
+ await this._filterPopupObjects.saveAsOption().click();
67
+ await this.saveAsPrefilterPopup(name);
68
+ }
69
+
70
+ public async saveAsPrefilterPopup(name: string): Promise<void> {
71
+ await this.waitForOpen();
72
+ await this._filterPopupObjects.prefilterNameInput().fill(name);
73
+ await this._filterPopupObjects.saveButton().click();
74
+ }
75
+ public async setAdvanced(enabled: boolean): Promise<void> {
76
+ await this.waitForOpen();
77
+ const checkbox = this._filterPopupObjects.advancedToggleCheckbox();
78
+ if (enabled) await checkbox.check();
79
+ else await checkbox.uncheck();
80
+ }
81
+
82
+ public advancedGroupSelect(): Locator {
83
+ return this._filterPopupObjects.advancedGroupSelect();
84
+ }
85
+
86
+ public async setGroupCondition(key: 'all-of-the-following' | 'any-of-the-following'): Promise<void> {
87
+ await this.waitForOpen();
88
+ await this._filterPopupObjects.advancedGroupSelect().click();
89
+ await this._filterPopupObjects.groupConditionOption(key).click();
90
+ }
91
+
92
+ public fieldInput(fieldId: string): Locator {
93
+ return this._filterPopupObjects.fieldInput(fieldId);
94
+ }
95
+
96
+ public valueInput(fieldId: string, part: string): Locator {
97
+ return this._filterPopupObjects.valueInput(fieldId, part);
98
+ }
99
+
100
+ public dateInput(fieldId: string): Locator {
101
+ return this._filterPopupObjects.dateInput(fieldId);
102
+ }
103
+
104
+ public async setText(fieldId: string, value: string): Promise<void> {
105
+ await this.waitForOpen();
106
+ const input = this._filterPopupObjects.fieldInput(fieldId);
107
+ await input.click();
108
+ await input.press('ControlOrMeta+a');
109
+ await input.fill(value);
110
+ }
111
+
112
+ public async setValue(args: { fieldId: string; part: string; value: string }): Promise<void> {
113
+ await this.waitForOpen();
114
+ const input = this._filterPopupObjects.valueInput(args.fieldId, args.part);
115
+ await input.click();
116
+ await input.press('ControlOrMeta+a');
117
+ await input.fill(args.value);
118
+ }
119
+
120
+ // Some inputs (date picker) need a blur/commit to apply the value
121
+ public async commit(args: { fieldId: string; part: string }): Promise<void> {
122
+ await this.waitForOpen();
123
+ await this._filterPopupObjects.valueInput(args.fieldId, args.part).press('Tab');
124
+ }
125
+
126
+ public async openControl(fieldId: string, part: string): Promise<void> {
127
+ await this.waitForOpen();
128
+ await this._filterPopupObjects.fieldControl(fieldId, part).click();
129
+ }
130
+
131
+ public async openOperator(fieldId: string): Promise<void> {
132
+ await this.waitForOpen();
133
+ await this._filterPopupObjects.operatorControl(fieldId).click();
134
+ }
135
+
136
+ public async openTimeOperator(): Promise<void> {
137
+ await this.waitForOpen();
138
+ await this._filterPopupObjects.timeOperatorControl().click();
139
+ }
140
+
141
+ public intervalSelector(rowIndex: number, colId: string): Locator {
142
+ return this._filterPopupObjects.intervalSelector(rowIndex, colId);
143
+ }
144
+
145
+ public intervalSelectorInput(rowIndex: number, colId: string): Locator {
146
+ return this._filterPopupObjects.intervalSelectorInput(rowIndex, colId);
147
+ }
148
+
149
+ public async openInterval(rowIndex: number, colId: string): Promise<void> {
150
+ await this.waitForOpen();
151
+ await this._filterPopupObjects.intervalSelectorInput(rowIndex, colId).click();
152
+ }
153
+
154
+ public async setInterval(rowIndex: number, colId: string, kind: IntervalType): Promise<void> {
155
+ await this.openInterval(rowIndex, colId);
156
+ await this.pickAutocomplete(kind);
157
+ }
158
+
159
+ public autocompleteOption(key: AutocompleteKey): Locator {
160
+ return this._filterPopupObjects.autocompleteOption(key);
161
+ }
162
+
163
+ public async pickAutocomplete(key: AutocompleteKey): Promise<void> {
164
+ const option = this._filterPopupObjects.autocompleteOption(key);
165
+ await option.click();
166
+ }
167
+
168
+ public async selectField(field: string): Promise<void> {
169
+ await this.waitForOpen();
170
+ const emptyRow = this._filterPopupObjects.emptySelectFieldRow();
171
+
172
+ if (await emptyRow.count()) {
173
+ await this._filterPopupObjects.emptySelectFieldRowButton().click();
174
+ } else {
175
+ await this._filterPopupObjects.selectFieldButton().click();
176
+ }
177
+
178
+ await this._filterPopupObjects.colIdOption(field).click();
179
+ }
180
+
181
+ // In advanced mode: add a new row, then select a field into it
182
+ public async addField(field: string): Promise<void> {
183
+ await this.waitForOpen();
184
+ await this._filterPopupObjects.addFieldButton().click();
185
+ await this.selectField(field);
186
+ }
187
+ }