diff --git a/src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx b/src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx
index 54a70ac904..d2b6b5d1b1 100644
--- a/src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx
+++ b/src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx
@@ -119,24 +119,28 @@ export function ExecuteResult({
/>
)}
-
-
-
- {currentResult?.truncated
- ? i18n('title.truncated')
- : i18n('title.result')}
-
-
{`(${currentResult?.result?.length})`}
+ {currentResult && (
+
+
+
+ {currentResult?.truncated
+ ? i18n('title.truncated')
+ : i18n('title.result')}
+
+ {currentResult.result && (
+ {`(${currentResult.result.length})`}
+ )}
+
+
-
-
+ )}
);
};
diff --git a/tests/suites/tenant/constants.ts b/tests/suites/tenant/constants.ts
index be9ca373c5..5dfcc89eca 100644
--- a/tests/suites/tenant/constants.ts
+++ b/tests/suites/tenant/constants.ts
@@ -1,7 +1,40 @@
// Long running query for tests
// May cause Memory exceed on real database
-const simpleQuery = 'SELECT 1;';
+export const simpleQuery = 'SELECT 1;';
+export const longTableSelect = 'SELECT * FROM `.sys/pg_class`';
// 400 is pretty enough
export const longRunningQuery = new Array(400).fill(simpleQuery).join('');
+
+export const createTableQuery = `
+CREATE TABLE \`/local/ydb_row_table\` (
+ category_id Uint64 NOT NULL,
+ id Uint64,
+ expire_at Datetime,
+ updated_on Datetime,
+ name Text,
+ \`binary-payload\` Bytes,
+ attributes JsonDocument,
+ -- uncomment to add a secondary index
+ -- INDEX idx_row_table_id GLOBAL SYNC ON ( id ) COVER ( name, attributes ), -- Secondary indexes docs https://ydb.tech/en/docs/yql/reference/syntax/create_table#secondary_index
+ PRIMARY KEY (category_id, id)
+)
+WITH (
+ AUTO_PARTITIONING_BY_SIZE = ENABLED,
+ AUTO_PARTITIONING_PARTITION_SIZE_MB = 2048,
+ AUTO_PARTITIONING_BY_LOAD = ENABLED,
+ AUTO_PARTITIONING_MIN_PARTITIONS_COUNT = 4,
+ AUTO_PARTITIONING_MAX_PARTITIONS_COUNT = 1024
+ -- uncomment to create a table with predefined partitions
+ -- , UNIFORM_PARTITIONS = 4 -- The number of partitions for uniform initial table partitioning.
+ -- The primary key's first column must have type Uint64 or Uint32.
+ -- A created table is immediately divided into the specified number of partitions
+ -- uncomment to launch read only replicas in every AZ
+ -- , READ_REPLICAS_SETTINGS = 'PER_AZ:1' -- Enable read replicas for stale read, launch one replica in every availability zone
+ -- uncomment to enable ttl
+ -- , TTL = Interval("PT1H") ON expire_at -- Enable background deletion of expired rows https://ydb.tech/en/docs/concepts/ttl
+ -- uncomment to create a table with a bloom filter
+ -- , KEY_BLOOM_FILTER = ENABLED -- With a Bloom filter, you can more efficiently determine
+ -- if some keys are missing in a table when making multiple single queries by the primary key.
+)`;
diff --git a/tests/suites/tenant/queryEditor/QueryEditor.ts b/tests/suites/tenant/queryEditor/QueryEditor.ts
index 2083335bbf..b15c1a7064 100644
--- a/tests/suites/tenant/queryEditor/QueryEditor.ts
+++ b/tests/suites/tenant/queryEditor/QueryEditor.ts
@@ -104,6 +104,12 @@ export class SettingsDialog {
await this.page.waitForTimeout(1000);
}
+ async changeLimitRows(limitRows: number) {
+ const limitRowsInput = this.dialog.locator('.ydb-query-settings-dialog__limit-rows input');
+ await limitRowsInput.fill(limitRows.toString());
+ await this.page.waitForTimeout(1000);
+ }
+
async clickButton(buttonName: ButtonNames) {
const button = this.dialog.getByRole('button', {name: buttonName});
await button.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
@@ -140,10 +146,12 @@ class PaneWrapper {
export class ResultTable {
private table: Locator;
private preview: Locator;
+ private resultHead: Locator;
constructor(selector: Locator) {
this.table = selector.locator('.ydb-query-execute-result__result');
this.preview = selector.locator('.kv-preview__result');
+ this.resultHead = selector.locator('.ydb-query-execute-result__result-head');
}
async isVisible() {
@@ -175,6 +183,16 @@ export class ResultTable {
const cell = this.table.locator(`tr:nth-child(${row}) td:nth-child(${col})`);
return cell.innerText();
}
+
+ async isResultHeaderHidden() {
+ await this.resultHead.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
+ return true;
+ }
+
+ async getResultHeadText() {
+ await this.resultHead.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
+ return this.resultHead.innerText();
+ }
}
export class QueryEditor {
diff --git a/tests/suites/tenant/queryEditor/queryEditor.test.ts b/tests/suites/tenant/queryEditor/queryEditor.test.ts
index 5c3f404d81..1db10a9a11 100644
--- a/tests/suites/tenant/queryEditor/queryEditor.test.ts
+++ b/tests/suites/tenant/queryEditor/queryEditor.test.ts
@@ -2,7 +2,7 @@ import {expect, test} from '@playwright/test';
import {tenantName} from '../../../utils/constants';
import {NavigationTabs, TenantPage, VISIBILITY_TIMEOUT} from '../TenantPage';
-import {longRunningQuery} from '../constants';
+import {createTableQuery, longRunningQuery, longTableSelect} from '../constants';
import {
ButtonNames,
@@ -377,4 +377,29 @@ test.describe('Test Query Editor', async () => {
await tenantPage.selectNavigationTab(NavigationTabs.Query);
await expect(queryEditor.resultTable.isVisible()).resolves.toBe(true);
});
+
+ test('Result head value is 1 for 1 row result', async ({page}) => {
+ const queryEditor = new QueryEditor(page);
+ await queryEditor.setQuery(testQuery);
+ await queryEditor.clickRunButton();
+ await expect(queryEditor.resultTable.getResultHeadText()).resolves.toBe('Result(1)');
+ });
+
+ test('No result head value for no result', async ({page}) => {
+ const queryEditor = new QueryEditor(page);
+ await queryEditor.setQuery(createTableQuery);
+ await queryEditor.clickRunButton();
+ await page.waitForTimeout(1000);
+ await expect(queryEditor.resultTable.isResultHeaderHidden()).resolves.toBe(true);
+ });
+
+ test('Truncated head value is 1 for 1 row truncated result', async ({page}) => {
+ const queryEditor = new QueryEditor(page);
+ await queryEditor.setQuery(longTableSelect);
+ await queryEditor.clickGearButton();
+ await queryEditor.settingsDialog.changeLimitRows(1);
+ await queryEditor.settingsDialog.clickButton(ButtonNames.Save);
+ await queryEditor.clickRunButton();
+ await expect(queryEditor.resultTable.getResultHeadText()).resolves.toBe('Truncated(1)');
+ });
});