2026-06-24 20:31:05 +05:00

474 lines
20 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {Page, Response, expect} from '@playwright/test';
import {clickSelectOption, openTestPage, slct} from '../../../utils';
import datalensTest from '../../../utils/playwright/globalTestDefinition';
import {TestParametrizationConfig} from '../../../types/config';
import {getUrlStateParam} from '../../../suites/dash/helpers';
import {CommonUrls} from '../../../page-objects/constants/common-urls';
import {ChartkitMenuDialogsQA, ControlQA, ControlType, WizardType} from '../../../../src/shared';
import DashboardPage from '../../../page-objects/dashboard/DashboardPage';
const SELECTORS = {
TAB_SELECTOR_TEXT: '.yc-select-control__tokens-text',
EMPTY_SELECTOR_VAL: '.yc-select-control__tokens-text_empty',
};
const PARAMS = {
TAB_1_SELECT_VALUE_1: 'Abilene',
TAB_1_SELECT_VALUE_2: 'Aberdeen',
TAB_2_SELECT_VALUE_1: 'Allen',
TAB_4_SELECT_VALUE_1: 'Akron',
EMPTY_SELECTOR_VAL_TEXT: '—',
EMPTY_SELECTOR_VAL_FULL_TEXT: 'No selected values',
TAB_1_NAME: 'Tab 1',
TAB_2_NAME: 'Tab 2',
TAB_4_NAME: 'Tab 4',
};
const TIMEOUT = 4000;
const getStateFromResponse = async (response: Promise<Response>) => {
const receivedResponse = await response;
const jsonResponse = await receivedResponse.json();
return jsonResponse.hash;
};
const selectOptionAndGetState = async ({
page,
selector,
value,
}: {
page: Page;
selector: string;
value: string;
}) => {
const stateChangeResponse = page.waitForResponse(CommonUrls.CreateDashState);
await Promise.all([page.waitForNavigation(), clickSelectOption(page, selector, value)]);
const stateFromRequest = await getStateFromResponse(stateChangeResponse);
const stateParam = getUrlStateParam(page);
expect(stateParam).toEqual(stateFromRequest);
return stateFromRequest;
};
const waitBackGetUrlStateParam = async (page: Page): Promise<string | null> => {
await Promise.all([page.waitForNavigation(), page.goBack()]);
await page.waitForTimeout(TIMEOUT);
return getUrlStateParam(page);
};
const waitForWidgetsRunAndGetChartResponse = async (
page: Page,
action?: () => Promise<void>,
): Promise<Response | undefined> => {
let chartResponseData;
const chartResponse = page.waitForResponse(async (response: Response) => {
if (response.url().includes(CommonUrls.ApiRun)) {
expect(response.status()).toEqual(200);
const jsonResponse = await response.json();
if (
jsonResponse.type === WizardType.GraphWizardNode ||
jsonResponse.type === WizardType.GravityChartsWizardNode
) {
chartResponseData = response;
return true;
}
}
return false;
});
const controlResponse = page.waitForResponse(async (response: Response) => {
if (response.url().includes(CommonUrls.ApiRun)) {
expect(response.status()).toEqual(200);
const jsonResponse = await response.json();
if (jsonResponse.type === ControlType.Dash) {
return true;
}
}
return false;
});
await action?.();
await Promise.all([chartResponse, controlResponse]);
return chartResponseData;
};
const checkChartWithValuesAndGetResponse = async ({
page,
rightValues,
wrongValues,
action,
}: {
page: Page;
rightValues: string[];
wrongValues?: string[];
action?: () => Promise<void>;
}) => {
// Wait for load of chart and selector
const chartResponseData = await waitForWidgetsRunAndGetChartResponse(page, action);
const graph = page
.locator(`${slct(ChartkitMenuDialogsQA.chartWidget)} svg:first-child`)
.first();
await expect(graph).toBeVisible();
// Check that the chart has been drawn with the applied values of the selector parameters based on the dataset
for (const rightValue of rightValues) {
const chartWidgetWithRightValue = page
.locator(`${slct(ChartkitMenuDialogsQA.chartWidget)} >> text=${rightValue}`)
.first();
await expect(chartWidgetWithRightValue).toBeAttached();
}
if (wrongValues) {
for (const wrongValue of wrongValues) {
const chartWidgetWithRightValue = page
.locator(`${slct(ChartkitMenuDialogsQA.chartWidget)} >> text=${wrongValue}`)
.first();
await expect(chartWidgetWithRightValue).toBeHidden();
}
}
return chartResponseData;
};
datalensTest.describe('Dashboards - States with tabs', () => {
datalensTest.beforeEach(
async ({page, config}: {page: Page; config: TestParametrizationConfig}) => {
// waiting for api/run for selector and chart
await waitForWidgetsRunAndGetChartResponse(page, async () => {
await openTestPage(page, config.dash.urls.DashboardWithTabsAndSelectors);
});
},
);
datalensTest(
'Checking that the state parameter was added when the selector was changed and reset when switching to another tab',
async ({page}: {page: Page}) => {
const dashboardPage = new DashboardPage({page});
// Check that the state parameter has been updated
await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_1_SELECT_VALUE_1,
});
// Click on another tab
await dashboardPage.changeTab({tabName: PARAMS.TAB_2_NAME});
// Waiting for rendering on the second tab
await page.waitForSelector(`${slct(ControlQA.controlSelect)}`);
// Check that the state parameter has been reset
expect(getUrlStateParam(page)).toEqual(null);
},
);
datalensTest(
'Checking that the state changes correctly and resets when switching between tabs using the browser\'s "Back" button',
async ({page}: {page: Page}) => {
const dashboardPage = new DashboardPage({page});
// Check that the state parameter has been updated
const firstTabState = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_1_SELECT_VALUE_1,
});
// Click on another tab
await dashboardPage.changeTab({tabName: PARAMS.TAB_2_NAME});
// Waiting for rendering on the second tab
await page.waitForSelector(slct(ControlQA.controlSelect));
// Check that the state parameter has been reset
expect(getUrlStateParam(page)).toEqual(null);
// Click on the fourth tab and wait for the page url to change
const urlParam = await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_4_NAME,
timeout: TIMEOUT,
});
// Check that the state parameter has been reset
expect(urlParam).toEqual(null);
// Select the value of the external selector on the fourth tab and
// waiting for the deferred request to create a state and add it to the url to pass
const fourthTabState = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_4_SELECT_VALUE_1,
});
// Check that the state parameter was updated when the external selector was changed
expect(fourthTabState).not.toEqual(firstTabState);
// Click on the native browser button "Back" and wait for the reset of the state
await page.goBack();
expect(getUrlStateParam(page)).toEqual(null);
// Click on the native browser button "Back" and wait for the transition to the second tab that did not have a state
await page.goBack();
await page.waitForSelector(slct(ControlQA.controlSelect));
expect(getUrlStateParam(page)).toEqual(null);
// Click on the native browser button "Back" and wait for the transition to the first tab that has a state
await waitForWidgetsRunAndGetChartResponse(page, async () => {
await page.goBack();
});
expect(getUrlStateParam(page)).toEqual(firstTabState);
// Click on the native browser button "Forward" and wait for the transition to the second tab that did not have a state
await page.goForward();
await page.waitForSelector(slct(ControlQA.controlSelect));
expect(getUrlStateParam(page)).toEqual(null);
// Double-click on the native browser button "Forward" and wait for the transition to the fourth tab with the restored state
await page.goForward();
await page.goForward();
await page.waitForSelector(slct(ControlQA.controlSelect, PARAMS.TAB_4_SELECT_VALUE_1));
expect(getUrlStateParam(page)).toEqual(fourthTabState);
},
);
datalensTest(
'Checking whether the state parameter is saved when changing different types of selectors and when switching to another tab and back',
async ({page}: {page: Page}) => {
const dashboardPage = new DashboardPage({page});
// Check that the state parameter has been updated
const firstTabState = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_1_SELECT_VALUE_1,
});
// Select another selector value on the first tab and
// waiting for the deferred request to create a state and add it to the url to pass
const firstTabStateAfterUpdate = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_1_SELECT_VALUE_2,
});
// Check that the state parameter has changed after a new selection in the selector based on the dataset
expect(firstTabStateAfterUpdate).not.toEqual(firstTabState);
// Click on the second tab and wait for the update in the url
let urlParam = await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_2_NAME,
timeout: TIMEOUT,
});
// Check that the state parameter was reset when switching to the second tab
expect(urlParam).toEqual(null);
// Click on the first tab and wait for the page url to change
await checkChartWithValuesAndGetResponse({
page,
rightValues: [PARAMS.TAB_1_SELECT_VALUE_2],
wrongValues: [PARAMS.TAB_1_SELECT_VALUE_1],
action: async () => {
const changedUrl = await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_1_NAME,
timeout: TIMEOUT,
});
// Check that the state parameter has been preserved after returning to the previous tab
expect(changedUrl).toEqual(firstTabStateAfterUpdate);
},
});
// Click on the fourth tab and wait for the page url to change
urlParam = await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_4_NAME,
timeout: TIMEOUT,
});
// Check that the state parameter has been reset
expect(urlParam).toEqual(null);
// Select the value of the external selector on the fourth tab and
// waiting for the deferred request to create a state and add it to the url to pass
const fourthTabState = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_4_SELECT_VALUE_1,
});
// Check that the state parameter was updated when the external selector was changed
expect(fourthTabState).not.toEqual(firstTabStateAfterUpdate);
// Click on the second tab and wait for the update in the url
urlParam = await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_2_NAME,
timeout: TIMEOUT,
});
// Check that the state parameter has been reset
expect(urlParam).toEqual(null);
// Select the value of the manual selector on the second tab and
// waiting for the deferred request to create a state and add it to the url to pass
const secondTabState = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_2_SELECT_VALUE_1,
});
// Check that the state parameter has been updated after selecting the value of the manual selector
expect(secondTabState).not.toEqual(fourthTabState);
// Click on the fourth tab and wait for the page url to change
urlParam = await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_4_NAME,
timeout: TIMEOUT,
});
// Check that the state parameter has been restored
expect(urlParam).toEqual(fourthTabState);
// Click on the second tab and wait for the page url to change
urlParam = await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_2_NAME,
timeout: TIMEOUT,
});
// Check that the state parameter has been restored
expect(urlParam).toEqual(secondTabState);
},
);
datalensTest(
'Checking backward transitions in the browser and consistency of the state parameter when changing different types of selectors and when switching to another tab',
async ({page}: {page: Page}) => {
const dashboardPage = new DashboardPage({page});
// Check that the state parameter has been updated
const firstTabState = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_1_SELECT_VALUE_1,
});
// Select another selector value on the first tab and
// waiting for the deferred request to create a state and add it to the url to pass
const firstTabStateUpdated = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_1_SELECT_VALUE_2,
});
expect(firstTabStateUpdated).not.toEqual(firstTabState);
await checkChartWithValuesAndGetResponse({
page,
rightValues: [PARAMS.TAB_1_SELECT_VALUE_1],
wrongValues: [PARAMS.TAB_1_SELECT_VALUE_2],
action: async () => {
// We return to the browser by clicking the back button
const urlParam = await waitBackGetUrlStateParam(page);
// Check that when switching back, the state parameter returned to the state of the first selected
expect(urlParam).toEqual(firstTabState);
},
});
// Click on the second tab and wait for the update in the url
await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_2_NAME,
timeout: TIMEOUT,
});
// Select the value of the manual selector on the second tab and
// waiting for the deferred request to create a state and add it to the url to pass
const secondTabState = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_2_SELECT_VALUE_1,
});
// Check that the state parameter has been updated after selecting the value of the manual selector
expect(secondTabState).not.toEqual(firstTabState);
// Click on the fourth tab and wait for the page url to change
let urlParam = await dashboardPage.changeTabAndGetState({
tabName: PARAMS.TAB_4_NAME,
timeout: TIMEOUT,
});
// Check that the state parameter has been reset
expect(urlParam).toEqual(null);
// Select the value of the external selector on the fourth tab and
// waiting for the deferred request to create a state and add it to the url to pass
const fourthTabState = await selectOptionAndGetState({
page,
selector: ControlQA.controlSelect,
value: PARAMS.TAB_4_SELECT_VALUE_1,
});
// Check that the state parameter was updated when the external selector was changed
expect(fourthTabState).not.toEqual(secondTabState);
// We return to the browser by clicking the back button
urlParam = await waitBackGetUrlStateParam(page);
// Check that when switching back, the state parameter returned to the state of the not selected selector on the third tab
expect(urlParam).toEqual(null);
let selector = await page.$(
`${slct(ControlQA.controlSelect)} >> ${SELECTORS.TAB_SELECTOR_TEXT}`,
);
let selectorText = await selector?.innerText();
// EMPTY_SELECTOR_VAL_FULL_TEXT for common selectors
// EMPTY_SELECTOR_VAL_TEXT for editor selectors
expect(selectorText).toMatch(
new RegExp(
`${PARAMS.EMPTY_SELECTOR_VAL_FULL_TEXT}|${PARAMS.EMPTY_SELECTOR_VAL_TEXT}`,
),
);
// We return to the browser by clicking the back button
urlParam = await waitBackGetUrlStateParam(page);
// Check that when switching back, the state parameter returned to the state of the selector on the second tab
expect(urlParam).toEqual(secondTabState);
selector = await page.$(
`${slct(ControlQA.controlSelect)} >> ${SELECTORS.TAB_SELECTOR_TEXT}`,
);
selectorText = await selector?.innerText();
// Check that when switching back, the selector value has returned to the state on the second tab
expect(selectorText).toEqual(PARAMS.TAB_2_SELECT_VALUE_1);
// We return to the browser by clicking the back button
urlParam = await waitBackGetUrlStateParam(page);
// Check that when switching back, the state parameter returned to the state of the not selected selector on the second tab
expect(urlParam).toEqual(null);
selector = await page.$(
`${slct(ControlQA.controlSelect)} >> ${SELECTORS.TAB_SELECTOR_TEXT}`,
);
selectorText = await selector?.innerText();
// Check that when switching back, the selector value has returned to the state on the second tab
const defaultValue = await page.$(`${SELECTORS.EMPTY_SELECTOR_VAL}`);
const defaultValueText = await defaultValue?.innerText();
expect(selectorText).toEqual(defaultValueText);
await checkChartWithValuesAndGetResponse({
page,
rightValues: [PARAMS.TAB_1_SELECT_VALUE_1],
wrongValues: [PARAMS.TAB_1_SELECT_VALUE_2],
action: async () => {
// We return to the browser by clicking the back button
const urlAfterBack = await waitBackGetUrlStateParam(page);
// Check that when switching back, the state parameter returned to the state of the first selected
expect(urlAfterBack).toEqual(firstTabState);
},
});
const chartResponse = await checkChartWithValuesAndGetResponse({
page,
rightValues: [PARAMS.TAB_1_SELECT_VALUE_2],
action: async () => {
// We return to the browser by clicking the back button
const urlAfterBack = await waitBackGetUrlStateParam(page);
// Check that when switching back, the selector value has returned to the unselected state on the first tab
expect(urlAfterBack).toEqual(null);
},
});
// сhart must have one empty param
if (chartResponse) {
const requestDataParams = chartResponse.request().postDataJSON().params;
expect(Object.values(requestDataParams)[0]).toBeFalsy();
}
},
);
});