Skip to content

Commit 0b16f6e

Browse files
test(ObjectSummary): properly find virtualized tree element
1 parent 7e0429b commit 0b16f6e

File tree

2 files changed

+65
-7
lines changed

2 files changed

+65
-7
lines changed

tests/suites/tenant/summary/ObjectSummary.ts

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ export enum ObjectSummaryTab {
1212
Schema = 'Schema',
1313
}
1414
export 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');

tests/suites/tenant/summary/objectSummary.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ test.describe('Object Summary', async () => {
251251
await objectSummary.createDirectory(directoryName);
252252

253253
// Verify the new directory appears in the tree
254-
const treeItem = page.locator('.ydb-tree-view').filter({hasText: directoryName});
254+
const treeItem = await objectSummary.getTreeItem(directoryName);
255255
await expect(treeItem).toBeVisible();
256256
});
257257

@@ -276,14 +276,17 @@ test.describe('Object Summary', async () => {
276276
await queryEditor.waitForStatus('Completed');
277277

278278
// Verify table is not visible before refresh
279-
const treeItemBeforeRefresh = page.locator('.ydb-tree-view').filter({hasText: tableName});
280-
await expect(treeItemBeforeRefresh).not.toBeVisible();
279+
try {
280+
await objectSummary.getTreeItem(tableName);
281+
} catch (error) {
282+
expect(error).toBeTruthy();
283+
}
281284

282285
// Click refresh button to update tree view
283286
await objectSummary.clickRefreshButton();
284287

285288
// Verify table appears in tree
286-
const treeItemAfterRefresh = page.locator('.ydb-tree-view').filter({hasText: tableName});
289+
const treeItemAfterRefresh = await objectSummary.getTreeItem(tableName);
287290
await expect(treeItemAfterRefresh).toBeVisible();
288291
});
289292

0 commit comments

Comments
 (0)