Skip to content

Commit 9c446bd

Browse files
committed
feat: save query tests
1 parent 36a45ce commit 9c446bd

File tree

5 files changed

+112
-5
lines changed

5 files changed

+112
-5
lines changed

tests/suites/tenant/queryEditor/models/QueryEditor.ts

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

33
import type {QUERY_MODES} from '../../../../../src/utils/query';
44
import {VISIBILITY_TIMEOUT} from '../../TenantPage';
5+
import {QueriesHistoryTable} from '../../queryHistory/models/QueriesHistoryTable';
6+
import {SavedQueriesTable} from '../../savedQueries/models/SavedQueriesTable';
57

6-
import {QueriesHistoryTable} from './QueriesHistoryTable';
78
import {QueryTabsNavigation} from './QueryTabsNavigation';
89
import {PaneWrapper, ResultTable} from './ResultTable';
9-
import {SavedQueriesTable} from './SavedQueriesTable';
1010
import {SettingsDialog} from './SettingsDialog';
1111

1212
export enum ExplainResultType {
@@ -50,6 +50,7 @@ export class QueryEditor {
5050
private runButton: Locator;
5151
private explainButton: Locator;
5252
private stopButton: Locator;
53+
private saveButton: Locator;
5354
private gearButton: Locator;
5455
private indicatorIcon: Locator;
5556
private banner: Locator;
@@ -65,6 +66,7 @@ export class QueryEditor {
6566
this.runButton = this.selector.getByRole('button', {name: ButtonNames.Run});
6667
this.stopButton = this.selector.getByRole('button', {name: ButtonNames.Stop});
6768
this.explainButton = this.selector.getByRole('button', {name: ButtonNames.Explain});
69+
this.saveButton = this.selector.getByRole('button', {name: ButtonNames.Save});
6870
this.gearButton = this.selector.locator('.ydb-query-editor-controls__gear-button');
6971
this.executionStatus = this.selector.locator('.kv-query-execution-status');
7072
this.resultsControls = this.selector.locator('.ydb-query-result__controls');
@@ -119,6 +121,11 @@ export class QueryEditor {
119121
await this.explainButton.click();
120122
}
121123

124+
async clickSaveButton() {
125+
await this.saveButton.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
126+
await this.saveButton.click();
127+
}
128+
122129
async getExplainResult(type: ExplainResultType) {
123130
await this.selectResultTypeRadio(type);
124131
const resultArea = this.selector.locator('.ydb-query-result__result');

tests/suites/tenant/queryEditor/queryTemplates.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {expect, test} from '@playwright/test';
22

33
import {dsVslotsSchema, dsVslotsTableName, tenantName} from '../../../utils/constants';
44
import {TenantPage} from '../TenantPage';
5+
import {SavedQueriesTable} from '../savedQueries/models/SavedQueriesTable';
56
import {ObjectSummary} from '../summary/ObjectSummary';
67
import {RowTableAction} from '../summary/types';
78

@@ -13,7 +14,6 @@ import {
1314
} from './models/NewSqlDropdownMenu';
1415
import {QueryEditor, QueryTabs} from './models/QueryEditor';
1516
import {SaveQueryDialog} from './models/SaveQueryDialog';
16-
import {SavedQueriesTable} from './models/SavedQueriesTable';
1717
import {UnsavedChangesModal} from './models/UnsavedChangesModal';
1818

1919
test.describe('Query Templates', () => {

tests/suites/tenant/queryEditor/models/SavedQueriesTable.ts renamed to tests/suites/tenant/savedQueries/models/SavedQueriesTable.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,18 @@ export class SavedQueriesTable {
2727
}
2828

2929
async editQuery(name: string) {
30-
const row = await this.getQueryRow(name);
30+
const row = await this.waitForRow(name);
31+
await row.hover();
3132
const editButton = row.locator('button:has(svg)').first();
33+
await editButton.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
3234
await editButton.click();
3335
}
3436

3537
async deleteQuery(name: string) {
36-
const row = await this.getQueryRow(name);
38+
const row = await this.waitForRow(name);
39+
await row.hover();
3740
const deleteButton = row.locator('button:has(svg)').nth(1);
41+
await deleteButton.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
3842
await deleteButton.click();
3943
}
4044

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import {expect, test} from '@playwright/test';
2+
3+
import {dsVslotsSchema, tenantName} from '../../../utils/constants';
4+
import {TenantPage} from '../TenantPage';
5+
import {QueryEditor, QueryTabs} from '../queryEditor/models/QueryEditor';
6+
import {SaveQueryDialog} from '../queryEditor/models/SaveQueryDialog';
7+
import {UnsavedChangesModal} from '../queryEditor/models/UnsavedChangesModal';
8+
9+
import {SavedQueriesTable} from './models/SavedQueriesTable';
10+
11+
test.describe('Saved Queries', () => {
12+
let tenantPage: TenantPage;
13+
let queryEditor: QueryEditor;
14+
let saveQueryDialog: SaveQueryDialog;
15+
let savedQueriesTable: SavedQueriesTable;
16+
let unsavedChangesModal: UnsavedChangesModal;
17+
18+
test.beforeEach(async ({page}) => {
19+
const pageQueryParams = {
20+
schema: dsVslotsSchema,
21+
database: tenantName,
22+
general: 'query',
23+
};
24+
25+
tenantPage = new TenantPage(page);
26+
await tenantPage.goto(pageQueryParams);
27+
queryEditor = new QueryEditor(page);
28+
saveQueryDialog = new SaveQueryDialog(page);
29+
savedQueriesTable = new SavedQueriesTable(page);
30+
unsavedChangesModal = new UnsavedChangesModal(page);
31+
});
32+
33+
test('View list of saved queries', async () => {
34+
// First save a query to ensure there's something in the list
35+
const testQuery = 'SELECT 1 AS test_column;';
36+
const queryName = `Test Query ${Date.now()}`;
37+
38+
await queryEditor.setQuery(testQuery);
39+
await queryEditor.clickSaveButton();
40+
await saveQueryDialog.setQueryName(queryName);
41+
await saveQueryDialog.clickSave();
42+
43+
// Navigate to saved queries tab
44+
await queryEditor.queryTabs.selectTab(QueryTabs.Saved);
45+
await savedQueriesTable.isVisible();
46+
47+
// Verify saved queries list is displayed and contains our query
48+
const names = await savedQueriesTable.getQueryNames();
49+
expect(names).toContain(queryName);
50+
});
51+
52+
test('Open saved query in the Editor', async () => {
53+
// First save a query
54+
const testQuery = 'SELECT 2 AS editor_test;';
55+
const queryName = `Editor Test ${Date.now()}`;
56+
57+
await queryEditor.setQuery(testQuery);
58+
await queryEditor.clickSaveButton();
59+
await saveQueryDialog.setQueryName(queryName);
60+
await saveQueryDialog.clickSave();
61+
62+
// Navigate to saved queries tab
63+
await queryEditor.queryTabs.selectTab(QueryTabs.Saved);
64+
await savedQueriesTable.isVisible();
65+
66+
// Open the query in editor
67+
await savedQueriesTable.editQuery(queryName);
68+
69+
// Handle unsaved changes dialog
70+
await unsavedChangesModal.clickDontSave();
71+
72+
// Verify query is loaded in editor
73+
const editorValue = await queryEditor.editorTextArea.inputValue();
74+
expect(editorValue.trim()).toBe(testQuery.trim());
75+
});
76+
77+
test('Save a query from the Editor', async () => {
78+
const testQuery = 'SELECT 3 AS new_query;';
79+
const queryName = `New Query ${Date.now()}`;
80+
81+
// Write query in editor and save it
82+
await queryEditor.setQuery(testQuery);
83+
await queryEditor.clickSaveButton();
84+
await saveQueryDialog.setQueryName(queryName);
85+
await saveQueryDialog.clickSave();
86+
87+
// Navigate to saved queries tab to verify
88+
await queryEditor.queryTabs.selectTab(QueryTabs.Saved);
89+
await savedQueriesTable.isVisible();
90+
91+
// Verify query was saved correctly
92+
const row = await savedQueriesTable.getRowByName(queryName);
93+
expect(row).not.toBe(null);
94+
expect(row?.query.trim()).toBe(testQuery.trim());
95+
});
96+
});

0 commit comments

Comments
 (0)