@@ -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,49 @@ export class ObjectSummary {
181195 return true ;
182196 }
183197
198+ async getTreeItem ( text : string ) {
199+ await this . isTreeVisible ( ) ;
200+ await this . isTreeLoaded ( ) ;
201+
202+ const itemLocator = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
203+
204+ if ( await itemLocator . isVisible ( { timeout : 1000 } ) ) {
205+ return itemLocator ;
206+ }
207+
208+ // Element could be in not rendered (virtualized) part of the tree
209+ // Such element cannot be found by playwright
210+ // Scroll 200px * 10 from top to bottom to find element
211+ await this . tree . hover ( ) ;
212+ await this . tree . evaluate ( ( e ) => {
213+ e . scrollTo ( { top : 0 , behavior : 'instant' } ) ;
214+ } ) ;
215+
216+ // Wait after scroll for elements to become stable
217+ await this . page . waitForTimeout ( 50 ) ;
218+
219+ let i = 0 ;
220+ while ( i < 10 ) {
221+ i ++ ;
222+
223+ await this . page . mouse . wheel ( 0 , 200 ) ;
224+
225+ // Wait after scroll for elements to become stable
226+ await this . page . waitForTimeout ( 50 ) ;
227+
228+ // Some nested nodes could be loading
229+ await this . isTreeLoaded ( ) ;
230+
231+ if ( await itemLocator . isVisible ( { timeout : 500 } ) ) {
232+ return itemLocator ;
233+ }
234+ }
235+
236+ throw new Error ( `Tree item ${ text } was not found` ) ;
237+ }
238+
184239 async isOpenPreviewIconVisibleOnHover ( text : string ) : Promise < boolean > {
185- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
240+ const treeItem = await this . getTreeItem ( text ) ;
186241 await treeItem . hover ( ) ;
187242
188243 const openPreviewIcon = treeItem . locator ( 'button[title="Open preview"]' ) ;
@@ -196,15 +251,15 @@ export class ObjectSummary {
196251 }
197252
198253 async clickPreviewButton ( text : string ) : Promise < void > {
199- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
254+ const treeItem = await this . getTreeItem ( text ) ;
200255 await treeItem . hover ( ) ;
201256
202257 const openPreviewIcon = treeItem . locator ( 'button[title="Open preview"]' ) ;
203258 await openPreviewIcon . click ( ) ;
204259 }
205260
206261 async clickActionsButton ( text : string ) : Promise < void > {
207- const treeItem = this . treeRows . filter ( { hasText : text } ) . first ( ) ;
262+ const treeItem = await this . getTreeItem ( text ) ;
208263 await treeItem . hover ( ) ;
209264
210265 const actionsIcon = treeItem . locator ( '.g-dropdown-menu__switcher-button' ) ;
0 commit comments