Skip to content

test(ObjectSummary): properly find virtualized tree element #1863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 70 additions & 3 deletions tests/suites/tenant/summary/ObjectSummary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ export enum ObjectSummaryTab {
Schema = 'Schema',
}
export class ObjectSummary {
private page: Page;
private tabs: Locator;
private schemaViewer: Locator;
private tree: Locator;
private treeRows: Locator;
private treeLoaders: Locator;
private primaryKeys: Locator;
private actionsMenu: ActionsMenu;
private aclWrapper: Locator;
Expand All @@ -34,8 +36,10 @@ export class ObjectSummary {
private overviewWrapper: Locator;

constructor(page: Page) {
this.page = page;
this.tree = page.locator('.ydb-object-summary__tree');
this.treeRows = page.locator('.ydb-tree-view');
this.treeLoaders = page.locator('.ydb-navigation-tree-view-loader');
this.tabs = page.locator('.ydb-object-summary__tabs');
this.schemaViewer = page.locator('.schema-viewer');
this.primaryKeys = page.locator('.schema-viewer__keys_type_primary');
Expand Down Expand Up @@ -166,6 +170,16 @@ export class ObjectSummary {
return true;
}

async isTreeLoaded() {
const loaders = await this.treeLoaders.all();

for (const loader of loaders) {
await loader.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
}

return true;
}

async isTreeHidden() {
await this.tree.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
return true;
Expand All @@ -181,8 +195,61 @@ export class ObjectSummary {
return true;
}

async getTreeItem(text: string) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can locate elements both in visible and in virtualized part of the tree (first 2000px only)

// Ensure tree is ready for the search
await this.isTreeVisible();
await this.isTreeLoaded();

const itemLocator = this.treeRows.filter({hasText: text}).first();

// Default timeout is too big for such case
const timeout = 500;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't use default timeouts here because they are too big for such case. In this method we assume, that the tree is present and already loaded with isTreeVisible and isTreeLoaded. We spend little time to check elements, since in the worst scenario there will be 10 loops - with default timeout (VISIBILITY_TIMEOUT) it may be more than 100 seconds for one function call (in my version max is about 7 seconds)


if (await itemLocator.isVisible({timeout})) {
return itemLocator;
}

// Element could be in not rendered (virtualized) part of the tree
// Such element cannot be found by playwright
// Scroll 200px * 10 from top to bottom to find element
// Firstly scroll to top in case tree was already scrolled down
await this.tree.evaluate((e) => {
e.scrollTo({top: 0, behavior: 'instant'});
});

// Wait after scroll for elements to become stable
await this.page.waitForTimeout(50);

if (await itemLocator.isVisible({timeout})) {
return itemLocator;
}

// Hover element so page.mouse.wheel work for it
await this.tree.hover();

// Start scrolling from top to bottom untill desired element is found
let i = 0;
while (i < 10) {
i++;

await this.page.mouse.wheel(0, 200);

// Wait after scroll for elements to become stable
await this.page.waitForTimeout(50);

// Some nested nodes could be loading
await this.isTreeLoaded();

if (await itemLocator.isVisible({timeout})) {
return itemLocator;
}
}

throw new Error(`Tree item ${text} was not found`);
}

async isOpenPreviewIconVisibleOnHover(text: string): Promise<boolean> {
const treeItem = this.treeRows.filter({hasText: text}).first();
const treeItem = await this.getTreeItem(text);
await treeItem.hover();

const openPreviewIcon = treeItem.locator('button[title="Open preview"]');
Expand All @@ -196,15 +263,15 @@ export class ObjectSummary {
}

async clickPreviewButton(text: string): Promise<void> {
const treeItem = this.treeRows.filter({hasText: text}).first();
const treeItem = await this.getTreeItem(text);
await treeItem.hover();

const openPreviewIcon = treeItem.locator('button[title="Open preview"]');
await openPreviewIcon.click();
}

async clickActionsButton(text: string): Promise<void> {
const treeItem = this.treeRows.filter({hasText: text}).first();
const treeItem = await this.getTreeItem(text);
await treeItem.hover();

const actionsIcon = treeItem.locator('.g-dropdown-menu__switcher-button');
Expand Down
11 changes: 7 additions & 4 deletions tests/suites/tenant/summary/objectSummary.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ test.describe('Object Summary', async () => {
await objectSummary.createDirectory(directoryName);

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

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

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

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

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

Expand Down
Loading