Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: tests for disabled statistics #1660

Merged
merged 6 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ jobs:

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Fetch gh-pages branch
run: |
Expand All @@ -222,6 +224,34 @@ jobs:
destination_dir: .
force_orphan: true

- name: Count new tests
id: count_tests
run: |
git fetch origin main:main
new_tests=0

# Get list of changed test files
for file in $(git diff --name-only main...HEAD | grep -E '^tests/suites/.*\.(spec|test)\.(ts|tsx|js|jsx)$'); do
# Count tests in current version
if git show HEAD:"$file" > /dev/null 2>&1; then
current_tests=$(git show HEAD:"$file" | grep -E "test\([\'\"]" | wc -l)
else
current_tests=0
fi

# Count tests in main version
if git show main:"$file" > /dev/null 2>&1; then
base_tests=$(git show main:"$file" | grep -E "test\([\'\"]" | wc -l)
else
base_tests=0
fi

# Add difference to total
((new_tests += current_tests - base_tests))
done

echo "new_tests=$new_tests" >> $GITHUB_OUTPUT

- name: Update PR description
uses: actions/github-script@v6
with:
Expand Down Expand Up @@ -266,14 +296,17 @@ jobs:
parseFloat(percent) > 0 ? 'πŸ”Ί' :
parseFloat(percent) < 0 ? 'πŸ”½' : 'βœ…';

const newTests = parseInt('${{ steps.count_tests.outputs.new_tests }}');
const testsStatus = newTests > 0 ? '✨' : 'βž–';

const ciSection = `## CI Results

### Test Status: <span style="color: ${statusColor};">${status}</span>
πŸ“Š [Full Report](${reportUrl})

| Total | Passed | Failed | Flaky | Skipped |
|:-----:|:------:|:------:|:-----:|:-------:|
| ${testResults.total} | ${testResults.passed} | ${testResults.failed} | ${testResults.flaky} | ${testResults.skipped} |
| Total | Passed | Failed | Flaky | Skipped | New Tests |
|:-----:|:------:|:------:|:-----:|:-------:|:---------:|
| ${testResults.total} | ${testResults.passed} | ${testResults.failed} | ${testResults.flaky} | ${testResults.skipped} | ${testsStatus} ${newTests} |

### Bundle Size: ${bundleStatus}
Current: ${formatSize(currentSize)} | Main: ${formatSize(mainSize)}
Expand All @@ -292,6 +325,7 @@ jobs:
- Bundle size is measured for the entire 'dist' directory.
- πŸ“Š indicates links to detailed reports.
- πŸ”Ί indicates increase, πŸ”½ decrease, and βœ… no change in bundle size.
- ${testsStatus} indicates ${newTests} new test cases added in this PR.
</details>`;

const { data: pullRequest } = await github.rest.pulls.get({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ function QuerySettingsForm({initialValues, onSubmit, onClose}: QuerySettingsForm
{QUERY_SETTINGS_FIELD_SETTINGS.statisticsMode.title}
</label>
<Tooltip
className={b('statistics-mode-tooltip')}
disabled={!useShowPlanToSvg}
openDelay={0}
content={i18n('tooltip_plan-to-svg-statistics')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function QuerySettingsSelect<T extends SelectType>(props: QuerySettingsSe
getOptionHeight={getOptionHeight}
popupClassName={b('popup')}
renderOption={(option: QuerySettingSelectOption<T>) => (
<div className={b('item')}>
<div className={b('item', {type: option.value})}>
<div className={b('item-title')}>
{option.content}
{option.isDefault ? i18n('description.default') : ''}
Expand Down
11 changes: 3 additions & 8 deletions tests/suites/tenant/queryEditor/models/QueryEditor.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import type {Locator, Page} from '@playwright/test';

import type {QUERY_MODES} from '../../../../../src/utils/query';
import {VISIBILITY_TIMEOUT} from '../../TenantPage';

import {QueryTabsNavigation} from './QueryTabsNavigation';
import {PaneWrapper, ResultTable} from './ResultTable';
import {SavedQueriesTable} from './SavedQueriesTable';
import {SettingsDialog} from './SettingsDialog';

export enum QueryMode {
YQLScript = 'YQL Script',
Data = 'DML',
Scan = 'Scan',
}

export enum ExplainResultType {
Schema = 'Schema',
JSON = 'JSON',
Expand Down Expand Up @@ -85,15 +80,15 @@ export class QueryEditor {
this.savedQueries = new SavedQueriesTable(page);
}

async run(query: string, mode: QueryMode) {
async run(query: string, mode: keyof typeof QUERY_MODES) {
await this.clickGearButton();
await this.settingsDialog.changeQueryMode(mode);
await this.settingsDialog.clickButton(ButtonNames.Save);
await this.setQuery(query);
await this.clickRunButton();
}

async explain(query: string, mode: QueryMode) {
async explain(query: string, mode: keyof typeof QUERY_MODES) {
await this.clickGearButton();
await this.settingsDialog.changeQueryMode(mode);
await this.settingsDialog.clickButton(ButtonNames.Save);
Expand Down
94 changes: 68 additions & 26 deletions tests/suites/tenant/queryEditor/models/SettingsDialog.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,81 @@
import type {Locator, Page} from '@playwright/test';

import type {
QUERY_MODES,
STATISTICS_MODES,
TRANSACTION_MODES,
} from '../../../../../src/utils/query';
import {VISIBILITY_TIMEOUT} from '../../TenantPage';

import type {ButtonNames, QueryMode} from './QueryEditor';
import type {ButtonNames} from './QueryEditor';

export class SettingsDialog {
private dialog: Locator;
private page: Page;
private selectPopup: Locator;
private limitRowsInput: Locator;

private queryModeSelect: Locator;
private transactionModeSelect: Locator;
private statisticsModeSelect: Locator;
private statisticsModeTooltip: Locator;

constructor(page: Page) {
this.page = page;
this.dialog = page.locator('.ydb-query-settings-dialog');
}

async changeQueryMode(mode: QueryMode) {
const dropdown = this.dialog.locator(
this.limitRowsInput = this.dialog.locator('.ydb-query-settings-dialog__limit-rows input');
this.selectPopup = page.locator('.ydb-query-settings-select__popup');

// Define distinct locators for selects
this.queryModeSelect = this.dialog.locator(
'.ydb-query-settings-dialog__control-wrapper_queryMode',
);
await dropdown.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await dropdown.click();
const popup = this.page.locator('.ydb-query-settings-select__popup');
await popup.getByText(mode).first().click();
this.transactionModeSelect = this.dialog.locator(
'.ydb-query-settings-dialog__control-wrapper_transactionMode',
);
this.statisticsModeSelect = this.dialog.locator(
'.ydb-query-settings-dialog__control-wrapper_statisticsMode',
);
this.statisticsModeTooltip = this.page.locator(
'.ydb-query-settings-dialog__statistics-mode-tooltip',
);
}

async changeQueryMode(mode: (typeof QUERY_MODES)[keyof typeof QUERY_MODES]) {
await this.queryModeSelect.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.queryModeSelect.click();
await this.selectPopup.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.page.locator(`.ydb-query-settings-select__item_type_${mode}`).click();
await this.page.waitForTimeout(1000);
}

async changeTransactionMode(level: string) {
const dropdown = this.dialog.locator(
'.ydb-query-settings-dialog__control-wrapper_transactionMode',
);
await dropdown.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await dropdown.click();
const popup = this.page.locator('.ydb-query-settings-select__popup');
await popup.getByText(level).first().click();
async changeTransactionMode(level: (typeof TRANSACTION_MODES)[keyof typeof TRANSACTION_MODES]) {
await this.transactionModeSelect.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.transactionModeSelect.click();
await this.selectPopup.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.page.locator(`.ydb-query-settings-select__item_type_${level}`).click();
await this.page.waitForTimeout(1000);
}

async changeStatsLevel(mode: string) {
const dropdown = this.dialog.locator(
'.ydb-query-settings-dialog__control-wrapper_statisticsMode',
);
await dropdown.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await dropdown.click();
const popup = this.page.locator('.ydb-query-settings-select__popup');
await popup.getByText(mode).first().click();
async changeStatsLevel(mode: (typeof STATISTICS_MODES)[keyof typeof STATISTICS_MODES]) {
await this.statisticsModeSelect.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.statisticsModeSelect.click();
await this.selectPopup.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.page.locator(`.ydb-query-settings-select__item_type_${mode}`).click();
await this.page.waitForTimeout(1000);
}

async getStatsLevel() {
await this.statisticsModeSelect.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
const selectedText = await this.statisticsModeSelect
.locator('.g-select-control__option-text')
.textContent();
return selectedText;
}

async changeLimitRows(limitRows: number) {
const limitRowsInput = this.dialog.locator('.ydb-query-settings-dialog__limit-rows input');
await limitRowsInput.fill(limitRows.toString());
await this.limitRowsInput.fill(limitRows.toString());
await this.page.waitForTimeout(1000);
}

Expand All @@ -63,8 +90,23 @@ export class SettingsDialog {
return true;
}

async isStatsTooltipVisible() {
await this.statisticsModeTooltip.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
return true;
}

async isHidden() {
await this.dialog.waitFor({state: 'hidden', timeout: VISIBILITY_TIMEOUT});
return true;
}

async isStatisticsSelectDisabled() {
await this.statisticsModeSelect.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
return this.statisticsModeSelect.locator('.g-select-control_disabled').isVisible();
}

async hoverStatisticsSelect() {
await this.statisticsModeSelect.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
await this.statisticsModeSelect.hover();
}
}
62 changes: 61 additions & 1 deletion tests/suites/tenant/queryEditor/planToSvg.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {expect, test} from '@playwright/test';

import {STATISTICS_MODES} from '../../../../src/utils/query';
import {tenantName} from '../../../utils/constants';
import {toggleExperiment} from '../../../utils/toggleExperiment';
import {TenantPage} from '../TenantPage';

import {QueryEditor} from './models/QueryEditor';
import {ButtonNames, QueryEditor} from './models/QueryEditor';

test.describe('Test Plan to SVG functionality', async () => {
const testQuery = 'SELECT 1;'; // Simple query that will generate a plan
Expand Down Expand Up @@ -46,4 +47,63 @@ test.describe('Test Plan to SVG functionality', async () => {
const svgElement = page.locator('svg').first();
await expect(svgElement).toBeVisible();
});

test('Statistics setting becomes disabled when execution plan experiment is enabled', async ({
page,
}) => {
const queryEditor = new QueryEditor(page);

// Open settings dialog
await queryEditor.clickGearButton();

// Statistics is enabled
await expect(queryEditor.settingsDialog.isStatisticsSelectDisabled()).resolves.toBe(false);

await queryEditor.settingsDialog.clickButton(ButtonNames.Cancel);

// Turn on execution plan experiment
await toggleExperiment(page, 'on', 'Execution plan');

// Open settings dialog
await queryEditor.clickGearButton();

// Verify statistics mode is disabled
await expect(queryEditor.settingsDialog.isStatisticsSelectDisabled()).resolves.toBe(true);
});

test('Statistics mode changes when toggling execution plan experiment', async ({page}) => {
const queryEditor = new QueryEditor(page);

// Set initial state
await queryEditor.clickGearButton();
await queryEditor.settingsDialog.changeStatsLevel(STATISTICS_MODES.none);
await queryEditor.settingsDialog.clickButton(ButtonNames.Save);

// Turn on execution plan experiment
await toggleExperiment(page, 'on', 'Execution plan');

// Verify statistics changed to Full
await queryEditor.clickGearButton();
await expect(queryEditor.settingsDialog.getStatsLevel()).resolves.toBe('Full');
await queryEditor.settingsDialog.clickButton(ButtonNames.Cancel);

// Turn off execution plan experiment
await toggleExperiment(page, 'off', 'Execution plan');

// Verify statistics returned to None
await queryEditor.clickGearButton();
await expect(queryEditor.settingsDialog.getStatsLevel()).resolves.toBe('None');
await queryEditor.settingsDialog.clickButton(ButtonNames.Cancel);
});

test('Statistics setting shows tooltip when disabled by execution plan experiment', async ({
page,
}) => {
const queryEditor = new QueryEditor(page);

await toggleExperiment(page, 'on', 'Execution plan');
await queryEditor.clickGearButton();
await queryEditor.settingsDialog.hoverStatisticsSelect();
await expect(queryEditor.settingsDialog.isStatsTooltipVisible()).resolves.toBe(true);
});
});
Loading
Loading