@@ -12,10 +12,12 @@ export enum ObjectSummaryTab {
1212 Schema = 'Schema' ,
1313}
1414export class ObjectSummary {
15+ private page : Page ;
1516 private tabs : Locator ;
1617 private schemaViewer : Locator ;
1718 private tree : Locator ;
1819 private treeRows : Locator ;
20+ private treeLoaders : Locator ;
1921 private primaryKeys : Locator ;
2022 private actionsMenu : ActionsMenu ;
2123 private aclWrapper : Locator ;
@@ -34,8 +36,10 @@ export class ObjectSummary {
3436 private overviewWrapper : Locator ;
3537
3638 constructor ( page : Page ) {
39+ this . page = page ;
3740 this . tree = page . locator ( '.ydb-object-summary__tree' ) ;
3841 this . treeRows = page . locator ( '.ydb-tree-view' ) ;
42+ this . treeLoaders = page . locator ( '.ydb-navigation-tree-view-loader' ) ;
3943 this . tabs = page . locator ( '.ydb-object-summary__tabs' ) ;
4044 this . schemaViewer = page . locator ( '.schema-viewer' ) ;
4145 this . primaryKeys = page . locator ( '.schema-viewer__keys_type_primary' ) ;
@@ -166,6 +170,16 @@ export class ObjectSummary {
166170 return true ;
167171 }
168172
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+
169183 async isTreeHidden ( ) {
170184 await this . tree . waitFor ( { state : 'hidden' , timeout : VISIBILITY_TIMEOUT } ) ;
171185 return true ;
@@ -181,8 +195,61 @@ export class ObjectSummary {
181195 return true ;
182196 }
183197
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+
184251 async isOpenPreviewIconVisibleOnHover ( text : string ) : Promise < boolean > {
185- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
252+ const treeItem = await this . getTreeItem ( text ) ;
186253 await treeItem . hover ( ) ;
187254
188255 const openPreviewIcon = treeItem . locator ( 'button[title="Open preview"]' ) ;
@@ -196,15 +263,15 @@ export class ObjectSummary {
196263 }
197264
198265 async clickPreviewButton ( text : string ) : Promise < void > {
199- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
266+ const treeItem = await this . getTreeItem ( text ) ;
200267 await treeItem . hover ( ) ;
201268
202269 const openPreviewIcon = treeItem . locator ( 'button[title="Open preview"]' ) ;
203270 await openPreviewIcon . click ( ) ;
204271 }
205272
206273 async clickActionsButton ( text : string ) : Promise < void > {
207- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
274+ const treeItem = await this . getTreeItem ( text ) ;
208275 await treeItem . hover ( ) ;
209276
210277 const actionsIcon = treeItem . locator ( '.g-dropdown-menu__switcher-button' ) ;
0 commit comments