Skip to content

Commit 7c22a18

Browse files
committed
fix: add test
1 parent 4cd79a6 commit 7c22a18

File tree

3 files changed

+187
-1
lines changed

3 files changed

+187
-1
lines changed

tests/suites/sidebar/Sidebar.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export class Sidebar {
6969

7070
async clickSettings() {
7171
await this.settingsButton.click();
72+
await this.drawer.waitFor({state: 'visible'});
7273
}
7374

7475
async clickInformation() {
@@ -176,4 +177,59 @@ export class Sidebar {
176177
const switchControl = experimentItem.locator('xpath=../../..//input[@type="checkbox"]');
177178
return switchControl.isChecked();
178179
}
180+
181+
async closeDrawer(): Promise<void> {
182+
await this.drawer.page().keyboard.press('Escape');
183+
await this.drawer.waitFor({state: 'hidden'});
184+
}
185+
186+
// ACL Syntax methods
187+
async getAclSyntaxRadioGroup(): Promise<Locator> {
188+
// First, find the settings item that contains the ACL syntax title
189+
const aclSettingsItem = this.drawer
190+
.locator('.gn-settings__item')
191+
.filter({hasText: 'ACL syntax format'});
192+
193+
// Then find the radio button group within that item
194+
return aclSettingsItem.locator('.g-radio-button');
195+
}
196+
197+
async getSelectedAclSyntax(): Promise<string> {
198+
const radioGroup = await this.getAclSyntaxRadioGroup();
199+
const checkedOption = radioGroup.locator('.g-radio-button__option_checked');
200+
const text = await checkedOption.textContent();
201+
return text?.trim() || '';
202+
}
203+
204+
async selectAclSyntax(syntax: 'KiKiMr' | 'YDB Short' | 'YDB' | 'YQL'): Promise<void> {
205+
// Ensure drawer is visible first
206+
await this.drawer.waitFor({state: 'visible'});
207+
208+
const radioGroup = await this.getAclSyntaxRadioGroup();
209+
const option = radioGroup.locator(`.g-radio-button__option:has-text("${syntax}")`);
210+
await option.click();
211+
// Small delay to ensure the setting is saved
212+
await this.drawer.page().waitForTimeout(100);
213+
}
214+
215+
async getAclSyntaxOptions(): Promise<string[]> {
216+
const radioGroup = await this.getAclSyntaxRadioGroup();
217+
const options = radioGroup.locator('.g-radio-button__option');
218+
const count = await options.count();
219+
const texts: string[] = [];
220+
for (let i = 0; i < count; i++) {
221+
const text = await options.nth(i).textContent();
222+
if (text) {
223+
texts.push(text.trim());
224+
}
225+
}
226+
return texts;
227+
}
228+
229+
async isAclSyntaxSettingVisible(): Promise<boolean> {
230+
const aclSetting = this.drawer
231+
.locator('.gn-settings__item')
232+
.filter({hasText: 'ACL syntax format'});
233+
return aclSetting.isVisible();
234+
}
179235
}

tests/suites/tenant/diagnostics/Diagnostics.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {Locator, Page} from '@playwright/test';
33
import {retryAction} from '../../../utils/retryAction';
44
import {MemoryViewer} from '../../memoryViewer/MemoryViewer';
55
import {NodesPage} from '../../nodes/NodesPage';
6+
import type {Sidebar} from '../../sidebar/Sidebar';
67
import {StoragePage} from '../../storage/StoragePage';
78
import {VISIBILITY_TIMEOUT} from '../TenantPage';
89

@@ -229,6 +230,33 @@ export const TopShardsHistoricalColumns = [
229230
TOP_SHARDS_COLUMNS_IDS.IntervalEnd,
230231
];
231232

233+
export const ACL_SYNTAX_TEST_CONFIGS = [
234+
{
235+
syntax: 'YQL' as const,
236+
patterns: {
237+
USERS: 'CONNECT',
238+
'METADATA-READERS': 'LIST',
239+
'DATA-READERS': 'SELECT ROW',
240+
},
241+
},
242+
{
243+
syntax: 'KiKiMr' as const,
244+
patterns: {
245+
USERS: 'ConnectDatabase',
246+
'METADATA-READERS': 'List',
247+
'DATA-READERS': 'SelectRow',
248+
},
249+
},
250+
{
251+
syntax: 'YDB Short' as const,
252+
patterns: {
253+
USERS: 'connect',
254+
'METADATA-READERS': 'list',
255+
'DATA-READERS': 'select_row',
256+
},
257+
},
258+
];
259+
232260
export class Diagnostics {
233261
table: Table;
234262
storage: StoragePage;
@@ -536,4 +564,71 @@ export class Diagnostics {
536564
.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
537565
return true;
538566
}
567+
568+
async getEffectiveRightsFromTable(): Promise<Record<string, string>> {
569+
const rightsTable = this.page.locator('.ydb-access-rights__rights-table');
570+
await rightsTable.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
571+
572+
const rows = await rightsTable.locator('tbody tr').all();
573+
const rights: Record<string, string> = {};
574+
575+
for (const row of rows) {
576+
const cells = await row.locator('td').all();
577+
if (cells.length >= 3) {
578+
// Get the subject name from the avatar component
579+
const subjectElement = cells[0].locator('.ydb-subject-with-avatar__subject');
580+
const subject = await subjectElement.textContent();
581+
const effectiveRights = await cells[2].textContent();
582+
if (subject && effectiveRights) {
583+
rights[subject.trim()] = effectiveRights.trim();
584+
}
585+
}
586+
}
587+
588+
return rights;
589+
}
590+
591+
async waitForTableDataToLoad(): Promise<void> {
592+
// Wait for the table to be visible and have at least one row of data
593+
const rightsTable = this.page.locator('.ydb-access-rights__rights-table');
594+
await rightsTable.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
595+
await rightsTable
596+
.locator('tbody tr')
597+
.first()
598+
.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
599+
// Additional small delay to ensure data is fully loaded
600+
await this.page.waitForTimeout(500);
601+
}
602+
603+
async getPermissionLabelsInGrantDialog(): Promise<string[]> {
604+
const labels = await this.page
605+
.locator('.ydb-grant-access__rights-wrapper .g-switch__text')
606+
.all();
607+
const texts: string[] = [];
608+
for (const label of labels) {
609+
const text = await label.textContent();
610+
if (text) {
611+
texts.push(text.trim());
612+
}
613+
}
614+
return texts;
615+
}
616+
617+
async switchAclSyntaxAndGetRights(
618+
sidebar: Sidebar,
619+
syntax: 'KiKiMr' | 'YDB Short' | 'YDB' | 'YQL',
620+
): Promise<Record<string, string>> {
621+
// Switch syntax
622+
await sidebar.clickSettings();
623+
await sidebar.selectAclSyntax(syntax);
624+
await sidebar.closeDrawer();
625+
626+
// Refresh the page data by navigating away and back
627+
await this.clickTab(DiagnosticsTab.Info);
628+
await this.clickTab(DiagnosticsTab.Access);
629+
await this.waitForTableDataToLoad();
630+
631+
// Get and return the rights
632+
return await this.getEffectiveRightsFromTable();
633+
}
539634
}

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {expect, test} from '@playwright/test';
22

3+
import {Sidebar} from '../../../sidebar/Sidebar';
34
import {TenantPage} from '../../TenantPage';
4-
import {Diagnostics, DiagnosticsTab} from '../Diagnostics';
5+
import {ACL_SYNTAX_TEST_CONFIGS, Diagnostics, DiagnosticsTab} from '../Diagnostics';
56

67
const newSubject = 'foo';
78

@@ -127,4 +128,38 @@ test.describe('Diagnostics Access tab', async () => {
127128
// Verify that "foo" appears in the rights table
128129
await expect(diagnostics.isSubjectInRightsTable(newSubject)).resolves.toBe(true);
129130
});
131+
132+
test('Effective rights display changes when switching ACL syntax', async ({page}) => {
133+
const pageQueryParams = {
134+
schema: '/local',
135+
database: '/local',
136+
tenantPage: 'diagnostics',
137+
diagnosticsTab: 'access',
138+
};
139+
const tenantPage = new TenantPage(page);
140+
await tenantPage.goto(pageQueryParams);
141+
142+
const diagnostics = new Diagnostics(page);
143+
const sidebar = new Sidebar(page);
144+
145+
// Run tests for each syntax configuration
146+
const results: Record<string, Record<string, string>> = {};
147+
148+
for (const config of ACL_SYNTAX_TEST_CONFIGS) {
149+
const rights = await diagnostics.switchAclSyntaxAndGetRights(sidebar, config.syntax);
150+
expect(rights).toBeTruthy();
151+
152+
// Verify expected patterns
153+
for (const [subject, pattern] of Object.entries(config.patterns)) {
154+
expect(rights[subject]).toContain(pattern);
155+
}
156+
157+
results[config.syntax] = rights;
158+
}
159+
160+
// Verify that permission formats are different between syntaxes
161+
expect(results.YQL?.['USERS']).not.toEqual(results.KiKiMr?.['USERS']);
162+
expect(results.KiKiMr?.['USERS']).not.toEqual(results['YDB Short']?.['USERS']);
163+
expect(results.YQL?.['DATA-READERS']).not.toEqual(results['YDB Short']?.['DATA-READERS']);
164+
});
130165
});

0 commit comments

Comments
 (0)