@@ -12,10 +12,12 @@ export enum ObjectSummaryTab {
12
12
Schema = 'Schema' ,
13
13
}
14
14
export class ObjectSummary {
15
+ private page : Page ;
15
16
private tabs : Locator ;
16
17
private schemaViewer : Locator ;
17
18
private tree : Locator ;
18
19
private treeRows : Locator ;
20
+ private treeLoaders : Locator ;
19
21
private primaryKeys : Locator ;
20
22
private actionsMenu : ActionsMenu ;
21
23
private aclWrapper : Locator ;
@@ -34,8 +36,10 @@ export class ObjectSummary {
34
36
private overviewWrapper : Locator ;
35
37
36
38
constructor ( page : Page ) {
39
+ this . page = page ;
37
40
this . tree = page . locator ( '.ydb-object-summary__tree' ) ;
38
41
this . treeRows = page . locator ( '.ydb-tree-view' ) ;
42
+ this . treeLoaders = page . locator ( '.ydb-navigation-tree-view-loader' ) ;
39
43
this . tabs = page . locator ( '.ydb-object-summary__tabs' ) ;
40
44
this . schemaViewer = page . locator ( '.schema-viewer' ) ;
41
45
this . primaryKeys = page . locator ( '.schema-viewer__keys_type_primary' ) ;
@@ -166,6 +170,16 @@ export class ObjectSummary {
166
170
return true ;
167
171
}
168
172
173
+ async isTreeLoaded ( ) {
174
+ const loaders = await this . treeLoaders . all ( ) ;
175
+
176
+ for ( const loader of loaders ) {
177
+ await loader . waitFor ( { state : 'hidden' , timeout : VISIBILITY_TIMEOUT } ) ;
178
+ }
179
+
180
+ return true ;
181
+ }
182
+
169
183
async isTreeHidden ( ) {
170
184
await this . tree . waitFor ( { state : 'hidden' , timeout : VISIBILITY_TIMEOUT } ) ;
171
185
return true ;
@@ -181,8 +195,61 @@ export class ObjectSummary {
181
195
return true ;
182
196
}
183
197
198
+ async getTreeItem ( text : string ) {
199
+ // Ensure tree is ready for the search
200
+ await this . isTreeVisible ( ) ;
201
+ await this . isTreeLoaded ( ) ;
202
+
203
+ const itemLocator = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
204
+
205
+ // Default timeout is too big for such case
206
+ const timeout = 500 ;
207
+
208
+ if ( await itemLocator . isVisible ( { timeout} ) ) {
209
+ return itemLocator ;
210
+ }
211
+
212
+ // Element could be in not rendered (virtualized) part of the tree
213
+ // Such element cannot be found by playwright
214
+ // Scroll 200px * 10 from top to bottom to find element
215
+ // Firstly scroll to top in case tree was already scrolled down
216
+ await this . tree . evaluate ( ( e ) => {
217
+ e . scrollTo ( { top : 0 , behavior : 'instant' } ) ;
218
+ } ) ;
219
+
220
+ // Wait after scroll for elements to become stable
221
+ await this . page . waitForTimeout ( 50 ) ;
222
+
223
+ if ( await itemLocator . isVisible ( { timeout} ) ) {
224
+ return itemLocator ;
225
+ }
226
+
227
+ // Hover element so page.mouse.wheel work for it
228
+ await this . tree . hover ( ) ;
229
+
230
+ // Start scrolling from top to bottom untill desired element is found
231
+ let i = 0 ;
232
+ while ( i < 10 ) {
233
+ i ++ ;
234
+
235
+ await this . page . mouse . wheel ( 0 , 200 ) ;
236
+
237
+ // Wait after scroll for elements to become stable
238
+ await this . page . waitForTimeout ( 50 ) ;
239
+
240
+ // Some nested nodes could be loading
241
+ await this . isTreeLoaded ( ) ;
242
+
243
+ if ( await itemLocator . isVisible ( { timeout} ) ) {
244
+ return itemLocator ;
245
+ }
246
+ }
247
+
248
+ throw new Error ( `Tree item ${ text } was not found` ) ;
249
+ }
250
+
184
251
async isOpenPreviewIconVisibleOnHover ( text : string ) : Promise < boolean > {
185
- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
252
+ const treeItem = await this . getTreeItem ( text ) ;
186
253
await treeItem . hover ( ) ;
187
254
188
255
const openPreviewIcon = treeItem . locator ( 'button[title="Open preview"]' ) ;
@@ -196,15 +263,15 @@ export class ObjectSummary {
196
263
}
197
264
198
265
async clickPreviewButton ( text : string ) : Promise < void > {
199
- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
266
+ const treeItem = await this . getTreeItem ( text ) ;
200
267
await treeItem . hover ( ) ;
201
268
202
269
const openPreviewIcon = treeItem . locator ( 'button[title="Open preview"]' ) ;
203
270
await openPreviewIcon . click ( ) ;
204
271
}
205
272
206
273
async clickActionsButton ( text : string ) : Promise < void > {
207
- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
274
+ const treeItem = await this . getTreeItem ( text ) ;
208
275
await treeItem . hover ( ) ;
209
276
210
277
const actionsIcon = treeItem . locator ( '.g-dropdown-menu__switcher-button' ) ;
0 commit comments