Skip to content

Commit 7fca7d2

Browse files
authored
chore: add e2e tests for database info (#1786)
1 parent 01b8424 commit 7fca7d2

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed

tests/suites/paginatedTable/paginatedTable.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,9 @@ export class ClusterStorageTable extends PaginatedTable {
245245
super(page, '.ydb-cluster');
246246
}
247247
}
248+
249+
export class DiagnosticsNodesTable extends PaginatedTable {
250+
constructor(page: Page) {
251+
super(page, '.kv-tenant-diagnostics__page-wrapper');
252+
}
253+
}

tests/suites/tenant/diagnostics/Diagnostics.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import type {Locator, Page} from '@playwright/test';
22

33
import {retryAction} from '../../../utils/retryAction';
4+
import {MemoryViewer} from '../../memoryViewer/MemoryViewer';
5+
import {NodesPage} from '../../nodes/NodesPage';
6+
import {StoragePage} from '../../storage/StoragePage';
47
import {VISIBILITY_TIMEOUT} from '../TenantPage';
58

69
export enum DiagnosticsTab {
@@ -13,6 +16,7 @@ export enum DiagnosticsTab {
1316
Tablets = 'Tablets',
1417
HotKeys = 'Hot keys',
1518
Describe = 'Describe',
19+
Storage = 'Storage',
1620
}
1721

1822
export class Table {
@@ -114,6 +118,9 @@ export enum QueriesSwitch {
114118

115119
export class Diagnostics {
116120
table: Table;
121+
storage: StoragePage;
122+
nodes: NodesPage;
123+
memoryViewer: MemoryViewer;
117124

118125
private tabs: Locator;
119126
private schemaViewer: Locator;
@@ -122,8 +129,15 @@ export class Diagnostics {
122129
private primaryKeys: Locator;
123130
private refreshButton: Locator;
124131
private autoRefreshSelect: Locator;
132+
private cpuCard: Locator;
133+
private storageCard: Locator;
134+
private memoryCard: Locator;
135+
private healthcheckCard: Locator;
125136

126137
constructor(page: Page) {
138+
this.storage = new StoragePage(page);
139+
this.nodes = new NodesPage(page);
140+
this.memoryViewer = new MemoryViewer(page);
127141
this.tabs = page.locator('.kv-tenant-diagnostics__tabs');
128142
this.tableControls = page.locator('.ydb-table-with-controls-layout__controls');
129143
this.schemaViewer = page.locator('.schema-viewer');
@@ -132,6 +146,12 @@ export class Diagnostics {
132146
this.refreshButton = page.locator('button[aria-label="Refresh"]');
133147
this.autoRefreshSelect = page.locator('.g-select');
134148
this.table = new Table(page.locator('.object-general'));
149+
150+
// Info tab cards
151+
this.cpuCard = page.locator('.metrics-cards__tab:has-text("CPU")');
152+
this.storageCard = page.locator('.metrics-cards__tab:has-text("Storage")');
153+
this.memoryCard = page.locator('.metrics-cards__tab:has-text("Memory")');
154+
this.healthcheckCard = page.locator('.metrics-cards__tab:has-text("Healthcheck")');
135155
}
136156

137157
async isSchemaViewerVisible() {
@@ -184,4 +204,47 @@ export class Diagnostics {
184204
const optionLocator = this.autoRefreshSelect.locator(`text=${option}`);
185205
await optionLocator.click();
186206
}
207+
208+
async areInfoCardsVisible() {
209+
await this.cpuCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
210+
await this.storageCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
211+
await this.memoryCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
212+
await this.healthcheckCard.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
213+
return true;
214+
}
215+
216+
async getResourceUtilization() {
217+
const cpuSystem = await this.cpuCard
218+
.locator('.ydb-metrics-card__metric:has-text("System") .progress-viewer__text')
219+
.textContent();
220+
const cpuUser = await this.cpuCard
221+
.locator('.ydb-metrics-card__metric:has-text("User") .progress-viewer__text')
222+
.textContent();
223+
const cpuIC = await this.cpuCard
224+
.locator('.ydb-metrics-card__metric:has-text("IC") .progress-viewer__text')
225+
.textContent();
226+
const storage = await this.storageCard
227+
.locator('.ydb-metrics-card__metric:has-text("SSD") .progress-viewer__text')
228+
.textContent();
229+
const memory = await this.memoryCard
230+
.locator('.ydb-metrics-card__metric:has-text("Process") .progress-viewer__text')
231+
.textContent();
232+
233+
return {
234+
cpu: {
235+
system: cpuSystem?.trim() || '',
236+
user: cpuUser?.trim() || '',
237+
ic: cpuIC?.trim() || '',
238+
},
239+
storage: storage?.trim() || '',
240+
memory: memory?.trim() || '',
241+
};
242+
}
243+
244+
async getHealthcheckStatus() {
245+
const statusElement = this.healthcheckCard.locator(
246+
'.healthcheck__self-check-status-indicator',
247+
);
248+
return (await statusElement.textContent())?.trim() || '';
249+
}
187250
}

tests/suites/tenant/diagnostics/diagnostics.test.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,114 @@
11
import {expect, test} from '@playwright/test';
22

33
import {dsVslotsSchema, tenantName} from '../../../utils/constants';
4+
import {DiagnosticsNodesTable} from '../../paginatedTable/paginatedTable';
45
import {NavigationTabs, TenantPage} from '../TenantPage';
56
import {longRunningQuery} from '../constants';
67
import {QueryEditor} from '../queryEditor/models/QueryEditor';
78

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

1011
test.describe('Diagnostics tab', async () => {
12+
test('Info tab shows main page elements', async ({page}) => {
13+
const pageQueryParams = {
14+
schema: tenantName,
15+
database: tenantName,
16+
tenantPage: 'diagnostics',
17+
};
18+
const tenantPage = new TenantPage(page);
19+
await tenantPage.goto(pageQueryParams);
20+
21+
const diagnostics = new Diagnostics(page);
22+
await diagnostics.clickTab(DiagnosticsTab.Info);
23+
await expect(diagnostics.areInfoCardsVisible()).resolves.toBe(true);
24+
});
25+
26+
test('Info tab shows resource utilization', async ({page}) => {
27+
const pageQueryParams = {
28+
schema: tenantName,
29+
database: tenantName,
30+
tenantPage: 'diagnostics',
31+
};
32+
const tenantPage = new TenantPage(page);
33+
await tenantPage.goto(pageQueryParams);
34+
35+
const diagnostics = new Diagnostics(page);
36+
await diagnostics.clickTab(DiagnosticsTab.Info);
37+
38+
const utilization = await diagnostics.getResourceUtilization();
39+
expect(utilization.cpu.system).toMatch(/\d+(\.\d+)? \/ \d+/);
40+
expect(utilization.cpu.user).toMatch(/\d+(\.\d+)? \/ \d+/);
41+
expect(utilization.cpu.ic).toMatch(/\d+(\.\d+)? \/ \d+/);
42+
expect(utilization.storage).toBeTruthy();
43+
expect(utilization.memory).toMatch(/\d+ \/ \d+\s*GB/);
44+
});
45+
46+
test('Info tab shows healthcheck status', async ({page}) => {
47+
const pageQueryParams = {
48+
schema: tenantName,
49+
database: tenantName,
50+
tenantPage: 'diagnostics',
51+
};
52+
const tenantPage = new TenantPage(page);
53+
await tenantPage.goto(pageQueryParams);
54+
55+
const diagnostics = new Diagnostics(page);
56+
await diagnostics.clickTab(DiagnosticsTab.Info);
57+
58+
const status = await diagnostics.getHealthcheckStatus();
59+
expect(status).toBe('GOOD');
60+
});
61+
62+
test('Storage tab shows Groups and Nodes views', async ({page}) => {
63+
const pageQueryParams = {
64+
schema: tenantName,
65+
database: tenantName,
66+
tenantPage: 'diagnostics',
67+
};
68+
const tenantPage = new TenantPage(page);
69+
await tenantPage.goto(pageQueryParams);
70+
71+
const diagnostics = new Diagnostics(page);
72+
await diagnostics.clickTab(DiagnosticsTab.Storage);
73+
74+
// Check Groups view
75+
await diagnostics.storage.selectEntityType('Groups');
76+
await expect(diagnostics.storage.table).toBeVisible();
77+
78+
// Check Nodes view
79+
await diagnostics.storage.selectEntityType('Nodes');
80+
await expect(diagnostics.storage.table).toBeVisible();
81+
});
82+
83+
test('Nodes tab shows nodes table with memory viewer', async ({page}) => {
84+
const pageQueryParams = {
85+
schema: tenantName,
86+
database: tenantName,
87+
tenantPage: 'diagnostics',
88+
};
89+
const tenantPage = new TenantPage(page);
90+
await tenantPage.goto(pageQueryParams);
91+
92+
const diagnostics = new Diagnostics(page);
93+
await diagnostics.clickTab(DiagnosticsTab.Nodes);
94+
95+
// Check nodes table is visible
96+
await expect(diagnostics.nodes.table).toBeVisible();
97+
98+
// Enable Memory column to show memory viewer
99+
const paginatedTable = new DiagnosticsNodesTable(page);
100+
await paginatedTable.waitForTableVisible();
101+
await paginatedTable.waitForTableData();
102+
const controls = paginatedTable.getControls();
103+
await controls.openColumnSetup();
104+
await controls.setColumnChecked('Memory');
105+
await controls.applyColumnVisibility();
106+
107+
// Check memory viewer is present and visible
108+
await diagnostics.memoryViewer.waitForVisible();
109+
await expect(diagnostics.memoryViewer.isVisible()).resolves.toBe(true);
110+
});
111+
11112
test('Primary keys header is visible in Schema tab', async ({page}) => {
12113
const pageQueryParams = {
13114
schema: dsVslotsSchema,

0 commit comments

Comments
 (0)