Skip to content
Closed
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
36 changes: 36 additions & 0 deletions tests/suites/tenant/diagnostics/Diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,19 @@ export class Diagnostics {
await this.refreshButton.click();
}

async waitForTableDataWithRefresh(maxRetries = 10, refreshInterval = 1000): Promise<boolean> {
for (let i = 0; i < maxRetries; i++) {
await this.clickRefreshButton();
await this.page.waitForTimeout(refreshInterval);

const rowCount = await this.table.getRowCount();
if (rowCount > 0) {
return true;
}
}
return false;
}

async setAutoRefresh(option: string): Promise<void> {
await this.autoRefreshSelect.click();
const optionLocator = this.autoRefreshSelect.locator(`text=${option}`);
Expand Down Expand Up @@ -433,6 +446,29 @@ export class Diagnostics {
return rowElementClass?.includes('kv-top-queries__row_active') || false;
}

async waitForActiveRow(timeout = 10000): Promise<boolean> {
try {
await this.dataTable.locator('.kv-top-queries__row_active').waitFor({
state: 'visible',
timeout: timeout,
});
return true;
} catch {
return false;
}
}

async getActiveRowIndex(): Promise<number | null> {
const rows = await this.dataTable.locator('tr.data-table__row').all();
for (let i = 0; i < rows.length; i++) {
const className = await rows[i].getAttribute('class');
if (className?.includes('kv-top-queries__row_active')) {
return i + 1; // Return 1-based index
}
}
return null;
}

async isOwnerCardVisible(): Promise<boolean> {
await this.ownerCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
return true;
Expand Down
83 changes: 64 additions & 19 deletions tests/suites/tenant/diagnostics/tabs/queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {expect, test} from '@playwright/test';

import {tenantName} from '../../../../utils/constants';
import {NavigationTabs, TenantPage} from '../../TenantPage';
import {longRunningQuery} from '../../constants';
import {longRunningQuery, longTableSelect, simpleQuery} from '../../constants';
import {QueryEditor} from '../../queryEditor/models/QueryEditor';
import {
Diagnostics,
Expand Down Expand Up @@ -98,22 +98,48 @@ test.describe('Diagnostics Queries tab', async () => {
});

test('Query tab first row has values for all columns in Top mode', async ({page}) => {
// First, navigate to query page and run some queries to populate the Top queries data
const queryPageParams = {
schema: tenantName,
database: tenantName,
tenantPage: 'query',
};
const tenantPage = new TenantPage(page);
await tenantPage.goto(queryPageParams);

const queryEditor = new QueryEditor(page);

const queries = [simpleQuery, longTableSelect(10)];

for (const query of queries) {
await queryEditor.setQuery(query);
await queryEditor.clickRunButton();
// Wait for query to complete
await queryEditor.waitForStatus('Completed');
}

// Now navigate to diagnostics to check the top queries
const pageQueryParams = {
schema: tenantName,
database: tenantName,
tenantPage: 'diagnostics',
diagnosticsTab: 'topQueries',
};
const tenantPage = new TenantPage(page);
await tenantPage.goto(pageQueryParams);

const diagnostics = new Diagnostics(page);

// Verify table has data
await expect(diagnostics.table.isVisible()).resolves.toBe(true);
await expect(diagnostics.table.getRowCount()).resolves.toBeGreaterThan(0);
// Switch to "Per minute" view for testing
await diagnostics.selectQueryPeriod(QueryPeriod.PerMinute);

// Verify first row has non-empty values for key columns (test first 4 columns)
// Wait for the table to refresh with new data
await page.waitForTimeout(2000);

// Wait for data to appear with active refreshing
const hasData = await diagnostics.waitForTableDataWithRefresh();
expect(hasData).toBe(true);

// Verify first row has non-empty values for key columns in "Per minute" view
for (const column of QueryTopColumns.slice(0, 4)) {
const columnValue = await diagnostics.table.getCellValueByHeader(1, column);
expect(columnValue.trim()).toBeTruthy();
Expand Down Expand Up @@ -244,12 +270,20 @@ test.describe('Diagnostics Queries tab', async () => {
const diagnostics = new Diagnostics(page);
await expect(diagnostics.table.isVisible()).resolves.toBe(true);

// Get the number of rows and select a row that requires scrolling (should be 100 from mock)
const rowCount = await diagnostics.table.getRowCount();
expect(rowCount).toBe(8); // Verify we have the expected 100 rows from mock
// Get the number of visible rows (should be around 8 due to virtualization)
const visibleRowCount = await diagnostics.table.getRowCount();
expect(visibleRowCount).toBeGreaterThan(0);
expect(visibleRowCount).toBeLessThanOrEqual(10); // Due to virtualization

// Target a row further down that requires scrolling
const targetRowIndex = 8;
// Target a row that's visible (use row 5 or 6 to ensure it's in the viewport)
const targetRowIndex = Math.min(5, visibleRowCount);

// Store the query hash of the target row to verify later
const targetQueryHash = await diagnostics.table.getCellValueByHeader(
targetRowIndex,
'Query Hash',
);
expect(targetQueryHash).toBeTruthy();

// Click on the target row to open the drawer
await diagnostics.table.clickRow(targetRowIndex);
Expand All @@ -261,21 +295,32 @@ test.describe('Diagnostics Queries tab', async () => {
await expect(diagnostics.isCopyLinkButtonVisible()).resolves.toBe(true);
await diagnostics.clickCopyLinkButton();

// Small wait for clipboard operation
await page.waitForTimeout(200);

// Get the copied URL from clipboard
const clipboardText = await page.evaluate(() => navigator.clipboard.readText());
expect(clipboardText).toBeTruthy();
expect(clipboardText).toContain('/tenant');

// Navigate to the copied URL
await page.goto(clipboardText);
await page.waitForTimeout(1000);

const firstVisibleRowIndex = 4;
// Verify the row is highlighted/selected (if applicable)
await page.waitForTimeout(1000);

const hasActiveClass = await diagnostics.isRowActive(firstVisibleRowIndex);

expect(hasActiveClass).toBe(true);
// Wait for the active row to appear
const hasActiveRow = await diagnostics.waitForActiveRow();
expect(hasActiveRow).toBe(true);

// Get the index of the active row
const activeRowIndex = await diagnostics.getActiveRowIndex();
expect(activeRowIndex).not.toBeNull();

// Verify the active row has the same query hash as the one we selected
if (activeRowIndex) {
const activeRowQueryHash = await diagnostics.table.getCellValueByHeader(
activeRowIndex,
'Query Hash',
);
expect(activeRowQueryHash).toBe(targetQueryHash);
}
});
});
Loading