Skip to content

Commit 07bd3f6

Browse files
Anton StandrikAnton Standrik
authored andcommitted
fix: tests for templates
1 parent cbc146b commit 07bd3f6

File tree

12 files changed

+578
-162
lines changed

12 files changed

+578
-162
lines changed

tests/suites/tenant/queryEditor/QueryEditor.ts

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

33
import {VISIBILITY_TIMEOUT} from '../TenantPage';
44

5+
import {QueryTabsNavigation} from './models/QueryTabsNavigation';
6+
import {PaneWrapper, ResultTable} from './models/ResultTable';
7+
import {SavedQueriesTable} from './models/SavedQueriesTable';
8+
import {SettingsDialog} from './models/SettingsDialog';
9+
510
export enum QueryMode {
611
YQLScript = 'YQL Script',
712
Data = 'DML',
@@ -35,175 +40,16 @@ export enum QueryTabs {
3540
Saved = 'Saved',
3641
}
3742

38-
export class QueryTabsNavigation {
39-
private tabsContainer: Locator;
40-
41-
constructor(page: Page) {
42-
this.tabsContainer = page.locator('.ydb-query__tabs');
43-
}
44-
45-
async selectTab(tabName: QueryTabs) {
46-
const tab = this.tabsContainer.locator(`role=tab[name="${tabName}"]`);
47-
await tab.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
48-
await tab.click();
49-
}
50-
51-
async isTabSelected(tabName: QueryTabs): Promise<boolean> {
52-
const tab = this.tabsContainer.locator(`role=tab[name="${tabName}"]`);
53-
await tab.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
54-
const isSelected = await tab.getAttribute('aria-selected');
55-
return isSelected === 'true';
56-
}
57-
58-
async getTabHref(tabName: QueryTabs): Promise<string | null> {
59-
const link = this.tabsContainer.locator(`a:has(div[role="tab"][title="${tabName}"])`);
60-
await link.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
61-
return link.getAttribute('href');
62-
}
63-
}
64-
65-
export class SettingsDialog {
66-
private dialog: Locator;
67-
private page: Page;
68-
69-
constructor(page: Page) {
70-
this.page = page;
71-
this.dialog = page.locator('.ydb-query-settings-dialog');
72-
}
73-
74-
async changeQueryMode(mode: QueryMode) {
75-
const dropdown = this.dialog.locator(
76-
'.ydb-query-settings-dialog__control-wrapper_queryMode',
77-
);
78-
await dropdown.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
79-
await dropdown.click();
80-
const popup = this.page.locator('.ydb-query-settings-select__popup');
81-
await popup.getByText(mode).first().click();
82-
await this.page.waitForTimeout(1000);
83-
}
84-
85-
async changeTransactionMode(level: string) {
86-
const dropdown = this.dialog.locator(
87-
'.ydb-query-settings-dialog__control-wrapper_transactionMode',
88-
);
89-
await dropdown.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
90-
await dropdown.click();
91-
const popup = this.page.locator('.ydb-query-settings-select__popup');
92-
await popup.getByText(level).first().click();
93-
await this.page.waitForTimeout(1000);
94-
}
95-
96-
async changeStatsLevel(mode: string) {
97-
const dropdown = this.dialog.locator(
98-
'.ydb-query-settings-dialog__control-wrapper_statisticsMode',
99-
);
100-
await dropdown.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
101-
await dropdown.click();
102-
const popup = this.page.locator('.ydb-query-settings-select__popup');
103-
await popup.getByText(mode).first().click();
104-
await this.page.waitForTimeout(1000);
105-
}
106-
107-
async changeLimitRows(limitRows: number) {
108-
const limitRowsInput = this.dialog.locator('.ydb-query-settings-dialog__limit-rows input');
109-
await limitRowsInput.fill(limitRows.toString());
110-
await this.page.waitForTimeout(1000);
111-
}
112-
113-
async clickButton(buttonName: ButtonNames) {
114-
const button = this.dialog.getByRole('button', {name: buttonName});
115-
await button.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
116-
await button.click();
117-
}
118-
119-
async isVisible() {
120-
await this.dialog.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
121-
return true;
122-
}
123-
124-
async isHidden() {
125-
await this.dialog.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
126-
return true;
127-
}
128-
}
129-
130-
class PaneWrapper {
131-
paneWrapper: Locator;
132-
private radioButton: Locator;
133-
134-
constructor(page: Page) {
135-
this.paneWrapper = page.locator('.query-editor__pane-wrapper');
136-
this.radioButton = this.paneWrapper.locator('.g-radio-button');
137-
}
138-
139-
async selectTab(tabName: ResultTabNames) {
140-
const tab = this.radioButton.getByLabel(tabName);
141-
await tab.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
142-
await tab.click();
143-
}
144-
}
145-
146-
export class ResultTable {
147-
private table: Locator;
148-
private preview: Locator;
149-
private resultHead: Locator;
150-
151-
constructor(selector: Locator) {
152-
this.table = selector.locator('.ydb-query-execute-result__result');
153-
this.preview = selector.locator('.kv-preview__result');
154-
this.resultHead = selector.locator('.ydb-query-execute-result__result-head');
155-
}
156-
157-
async isVisible() {
158-
await this.table.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
159-
return true;
160-
}
161-
162-
async isHidden() {
163-
await this.table.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
164-
return true;
165-
}
166-
167-
async isPreviewVisible() {
168-
await this.preview.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
169-
return true;
170-
}
171-
172-
async isPreviewHidden() {
173-
await this.preview.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
174-
return true;
175-
}
176-
177-
async getRowCount() {
178-
const rows = this.table.locator('tr');
179-
return rows.count();
180-
}
181-
182-
async getCellValue(row: number, col: number) {
183-
const cell = this.table.locator(`tr:nth-child(${row}) td:nth-child(${col})`);
184-
return cell.innerText();
185-
}
186-
187-
async isResultHeaderHidden() {
188-
await this.resultHead.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
189-
return true;
190-
}
191-
192-
async getResultHeadText() {
193-
await this.resultHead.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
194-
return this.resultHead.innerText();
195-
}
196-
}
197-
19843
export class QueryEditor {
19944
settingsDialog: SettingsDialog;
20045
paneWrapper: PaneWrapper;
20146
queryTabs: QueryTabsNavigation;
20247
resultTable: ResultTable;
48+
savedQueries: SavedQueriesTable;
49+
editorTextArea: Locator;
20350

20451
private page: Page;
20552
private selector: Locator;
206-
private editorTextArea: Locator;
20753
private runButton: Locator;
20854
private explainButton: Locator;
20955
private stopButton: Locator;
@@ -236,6 +82,7 @@ export class QueryEditor {
23682
this.resultTable = new ResultTable(this.selector);
23783
this.paneWrapper = new PaneWrapper(page);
23884
this.queryTabs = new QueryTabsNavigation(page);
85+
this.savedQueries = new SavedQueriesTable(page);
23986
}
24087

24188
async run(query: string, mode: QueryMode) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type {Locator, Page} from '@playwright/test';
2+
3+
import {VISIBILITY_TIMEOUT} from '../../TenantPage';
4+
import type {QueryTabs} from '../QueryEditor';
5+
6+
export class QueryTabsNavigation {
7+
private tabsContainer: Locator;
8+
9+
constructor(page: Page) {
10+
this.tabsContainer = page.locator('.ydb-query__tabs');
11+
}
12+
13+
async selectTab(tabName: QueryTabs) {
14+
const tab = this.tabsContainer.locator(`role=tab[name="${tabName}"]`);
15+
await tab.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
16+
await tab.click();
17+
}
18+
19+
async isTabSelected(tabName: QueryTabs): Promise<boolean> {
20+
const tab = this.tabsContainer.locator(`role=tab[name="${tabName}"]`);
21+
await tab.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
22+
const isSelected = await tab.getAttribute('aria-selected');
23+
return isSelected === 'true';
24+
}
25+
26+
async getTabHref(tabName: QueryTabs): Promise<string | null> {
27+
const link = this.tabsContainer.locator(`a:has(div[role="tab"][title="${tabName}"])`);
28+
await link.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
29+
return link.getAttribute('href');
30+
}
31+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import type {Locator, Page} from '@playwright/test';
2+
3+
import {VISIBILITY_TIMEOUT} from '../../TenantPage';
4+
import type {ResultTabNames} from '../QueryEditor';
5+
6+
export class PaneWrapper {
7+
paneWrapper: Locator;
8+
private radioButton: Locator;
9+
10+
constructor(page: Page) {
11+
this.paneWrapper = page.locator('.query-editor__pane-wrapper');
12+
this.radioButton = this.paneWrapper.locator('.g-radio-button');
13+
}
14+
15+
async selectTab(tabName: ResultTabNames) {
16+
const tab = this.radioButton.getByLabel(tabName);
17+
await tab.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
18+
await tab.click();
19+
}
20+
}
21+
22+
export class ResultTable {
23+
private table: Locator;
24+
private preview: Locator;
25+
private resultHead: Locator;
26+
27+
constructor(selector: Locator) {
28+
this.table = selector.locator('.ydb-query-execute-result__result');
29+
this.preview = selector.locator('.kv-preview__result');
30+
this.resultHead = selector.locator('.ydb-query-execute-result__result-head');
31+
}
32+
33+
async isVisible() {
34+
await this.table.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
35+
return true;
36+
}
37+
38+
async isHidden() {
39+
await this.table.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
40+
return true;
41+
}
42+
43+
async isPreviewVisible() {
44+
await this.preview.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
45+
return true;
46+
}
47+
48+
async isPreviewHidden() {
49+
await this.preview.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
50+
return true;
51+
}
52+
53+
async getRowCount() {
54+
const rows = this.table.locator('tr');
55+
return rows.count();
56+
}
57+
58+
async getCellValue(row: number, col: number) {
59+
const cell = this.table.locator(`tr:nth-child(${row}) td:nth-child(${col})`);
60+
return cell.innerText();
61+
}
62+
63+
async isResultHeaderHidden() {
64+
await this.resultHead.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
65+
return true;
66+
}
67+
68+
async getResultHeadText() {
69+
await this.resultHead.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
70+
return this.resultHead.innerText();
71+
}
72+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type {Locator, Page} from '@playwright/test';
2+
3+
import {VISIBILITY_TIMEOUT} from '../../TenantPage';
4+
5+
export class SaveQueryDialog {
6+
private dialogBody: Locator;
7+
private dialogFooter: Locator;
8+
9+
constructor(page: Page) {
10+
this.dialogBody = page.locator('.ydb-save-query__dialog-body').last();
11+
this.dialogFooter = page.locator('.ydb-save-query__dialog-body + .g-dialog-footer').last();
12+
}
13+
14+
async setQueryName(name: string) {
15+
const input = this.dialogBody.locator('#queryName');
16+
await input.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
17+
// Ensure input is ready for interaction
18+
await input.click();
19+
await input.clear();
20+
await input.fill(name);
21+
}
22+
23+
async clickSave() {
24+
const saveButton = this.dialogFooter.getByRole('button', {name: 'Save', exact: true});
25+
await saveButton.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
26+
await saveButton.click();
27+
}
28+
29+
async isVisible() {
30+
try {
31+
await this.dialogBody.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
32+
return true;
33+
} catch {
34+
return false;
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)