Skip to content
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

chore: add e2e tests for database info #1786

Merged
merged 1 commit into from
Dec 26, 2024
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
6 changes: 6 additions & 0 deletions tests/suites/paginatedTable/paginatedTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,9 @@ export class ClusterStorageTable extends PaginatedTable {
super(page, '.ydb-cluster');
}
}

export class DiagnosticsNodesTable extends PaginatedTable {
constructor(page: Page) {
super(page, '.kv-tenant-diagnostics__page-wrapper');
}
}
63 changes: 63 additions & 0 deletions tests/suites/tenant/diagnostics/Diagnostics.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type {Locator, Page} from '@playwright/test';

import {retryAction} from '../../../utils/retryAction';
import {MemoryViewer} from '../../memoryViewer/MemoryViewer';
import {NodesPage} from '../../nodes/NodesPage';
import {StoragePage} from '../../storage/StoragePage';
import {VISIBILITY_TIMEOUT} from '../TenantPage';

export enum DiagnosticsTab {
Expand All @@ -13,6 +16,7 @@ export enum DiagnosticsTab {
Tablets = 'Tablets',
HotKeys = 'Hot keys',
Describe = 'Describe',
Storage = 'Storage',
}

export class Table {
Expand Down Expand Up @@ -114,6 +118,9 @@ export enum QueriesSwitch {

export class Diagnostics {
table: Table;
storage: StoragePage;
nodes: NodesPage;
memoryViewer: MemoryViewer;

private tabs: Locator;
private schemaViewer: Locator;
Expand All @@ -122,8 +129,15 @@ export class Diagnostics {
private primaryKeys: Locator;
private refreshButton: Locator;
private autoRefreshSelect: Locator;
private cpuCard: Locator;
private storageCard: Locator;
private memoryCard: Locator;
private healthcheckCard: Locator;

constructor(page: Page) {
this.storage = new StoragePage(page);
this.nodes = new NodesPage(page);
this.memoryViewer = new MemoryViewer(page);
this.tabs = page.locator('.kv-tenant-diagnostics__tabs');
this.tableControls = page.locator('.ydb-table-with-controls-layout__controls');
this.schemaViewer = page.locator('.schema-viewer');
Expand All @@ -132,6 +146,12 @@ export class Diagnostics {
this.refreshButton = page.locator('button[aria-label="Refresh"]');
this.autoRefreshSelect = page.locator('.g-select');
this.table = new Table(page.locator('.object-general'));

// Info tab cards
this.cpuCard = page.locator('.metrics-cards__tab:has-text("CPU")');
this.storageCard = page.locator('.metrics-cards__tab:has-text("Storage")');
this.memoryCard = page.locator('.metrics-cards__tab:has-text("Memory")');
this.healthcheckCard = page.locator('.metrics-cards__tab:has-text("Healthcheck")');
}

async isSchemaViewerVisible() {
Expand Down Expand Up @@ -184,4 +204,47 @@ export class Diagnostics {
const optionLocator = this.autoRefreshSelect.locator(`text=${option}`);
await optionLocator.click();
}

async areInfoCardsVisible() {
await this.cpuCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.storageCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.memoryCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.healthcheckCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
return true;
}

async getResourceUtilization() {
const cpuSystem = await this.cpuCard
.locator('.ydb-metrics-card__metric:has-text("System") .progress-viewer__text')
.textContent();
const cpuUser = await this.cpuCard
.locator('.ydb-metrics-card__metric:has-text("User") .progress-viewer__text')
.textContent();
const cpuIC = await this.cpuCard
.locator('.ydb-metrics-card__metric:has-text("IC") .progress-viewer__text')
.textContent();
const storage = await this.storageCard
.locator('.ydb-metrics-card__metric:has-text("SSD") .progress-viewer__text')
.textContent();
const memory = await this.memoryCard
.locator('.ydb-metrics-card__metric:has-text("Process") .progress-viewer__text')
.textContent();

return {
cpu: {
system: cpuSystem?.trim() || '',
user: cpuUser?.trim() || '',
ic: cpuIC?.trim() || '',
},
storage: storage?.trim() || '',
memory: memory?.trim() || '',
};
}

async getHealthcheckStatus() {
const statusElement = this.healthcheckCard.locator(
'.healthcheck__self-check-status-indicator',
);
return (await statusElement.textContent())?.trim() || '';
}
}
101 changes: 101 additions & 0 deletions tests/suites/tenant/diagnostics/diagnostics.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,114 @@
import {expect, test} from '@playwright/test';

import {dsVslotsSchema, tenantName} from '../../../utils/constants';
import {DiagnosticsNodesTable} from '../../paginatedTable/paginatedTable';
import {NavigationTabs, TenantPage} from '../TenantPage';
import {longRunningQuery} from '../constants';
import {QueryEditor} from '../queryEditor/models/QueryEditor';

import {Diagnostics, DiagnosticsTab, QueriesSwitch} from './Diagnostics';

test.describe('Diagnostics tab', async () => {
test('Info tab shows main page elements', async ({page}) => {
const pageQueryParams = {
schema: tenantName,
database: tenantName,
tenantPage: 'diagnostics',
};
const tenantPage = new TenantPage(page);
await tenantPage.goto(pageQueryParams);

const diagnostics = new Diagnostics(page);
await diagnostics.clickTab(DiagnosticsTab.Info);
await expect(diagnostics.areInfoCardsVisible()).resolves.toBe(true);
});

test('Info tab shows resource utilization', async ({page}) => {
const pageQueryParams = {
schema: tenantName,
database: tenantName,
tenantPage: 'diagnostics',
};
const tenantPage = new TenantPage(page);
await tenantPage.goto(pageQueryParams);

const diagnostics = new Diagnostics(page);
await diagnostics.clickTab(DiagnosticsTab.Info);

const utilization = await diagnostics.getResourceUtilization();
expect(utilization.cpu.system).toMatch(/\d+(\.\d+)? \/ \d+/);
expect(utilization.cpu.user).toMatch(/\d+(\.\d+)? \/ \d+/);
expect(utilization.cpu.ic).toMatch(/\d+(\.\d+)? \/ \d+/);
expect(utilization.storage).toBeTruthy();
expect(utilization.memory).toMatch(/\d+ \/ \d+\s*GB/);
});

test('Info tab shows healthcheck status', async ({page}) => {
const pageQueryParams = {
schema: tenantName,
database: tenantName,
tenantPage: 'diagnostics',
};
const tenantPage = new TenantPage(page);
await tenantPage.goto(pageQueryParams);

const diagnostics = new Diagnostics(page);
await diagnostics.clickTab(DiagnosticsTab.Info);

const status = await diagnostics.getHealthcheckStatus();
expect(status).toBe('GOOD');
});

test('Storage tab shows Groups and Nodes views', async ({page}) => {
const pageQueryParams = {
schema: tenantName,
database: tenantName,
tenantPage: 'diagnostics',
};
const tenantPage = new TenantPage(page);
await tenantPage.goto(pageQueryParams);

const diagnostics = new Diagnostics(page);
await diagnostics.clickTab(DiagnosticsTab.Storage);

// Check Groups view
await diagnostics.storage.selectEntityType('Groups');
await expect(diagnostics.storage.table).toBeVisible();

// Check Nodes view
await diagnostics.storage.selectEntityType('Nodes');
await expect(diagnostics.storage.table).toBeVisible();
});

test('Nodes tab shows nodes table with memory viewer', async ({page}) => {
const pageQueryParams = {
schema: tenantName,
database: tenantName,
tenantPage: 'diagnostics',
};
const tenantPage = new TenantPage(page);
await tenantPage.goto(pageQueryParams);

const diagnostics = new Diagnostics(page);
await diagnostics.clickTab(DiagnosticsTab.Nodes);

// Check nodes table is visible
await expect(diagnostics.nodes.table).toBeVisible();

// Enable Memory column to show memory viewer
const paginatedTable = new DiagnosticsNodesTable(page);
await paginatedTable.waitForTableVisible();
await paginatedTable.waitForTableData();
const controls = paginatedTable.getControls();
await controls.openColumnSetup();
await controls.setColumnChecked('Memory');
await controls.applyColumnVisibility();

// Check memory viewer is present and visible
await diagnostics.memoryViewer.waitForVisible();
await expect(diagnostics.memoryViewer.isVisible()).resolves.toBe(true);
});

test('Primary keys header is visible in Schema tab', async ({page}) => {
const pageQueryParams = {
schema: dsVslotsSchema,
Expand Down
Loading