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

318 lines
10 KiB
TypeScript

import {ElementHandle} from '@playwright/test';
import {
ChartSaveControlsQA,
ControlQA,
DialogConfirmQA,
DlNavigationQA,
EntryDialogQA,
SaveChartControlsQa,
VisualizationsQa,
WizardPageQa,
} from '../../src/shared';
import {copyEntity, deleteEntity, entryDialogFillAndSave, slct, waitForCondition} from '../utils';
import {BasePage, BasePageProps} from './BasePage';
import {ChartContainer} from './common/ChartContainer';
import Revisions from './common/Revisions';
import ChartKit from './wizard/ChartKit';
export enum ChartType {
Wizard = 'Wizard',
QL = 'QL',
}
const CURRENT_REVISION_CLASSNAME = 'revisions-list__row_current';
export class ChartPage extends BasePage {
revisions: Revisions;
chartkit: ChartKit;
chartContainer: ChartContainer;
constructor(props: BasePageProps) {
super(props);
this.revisions = new Revisions(props.page);
this.chartkit = new ChartKit(props.page);
this.chartContainer = new ChartContainer(props.page);
}
async deleteEntry() {
await deleteEntity(this.page);
}
async copyEntry(entryName: string) {
await copyEntity(this.page, entryName);
}
async applySavingWarning() {
await this.page.click(
`${slct(DialogConfirmQA.Dialog)} ${slct(DialogConfirmQA.ApplyButton)}`,
);
}
async getVisualizationSelectorItems() {
await this.page.click(slct('visualization-select-btn'));
await waitForCondition(async () => {
return await this.page.locator(slct(WizardPageQa.VisualizationSelectPopup)).isVisible();
});
const items = await this.page.$$(
`${slct(WizardPageQa.VisualizationSelectPopup)} .visualization-item`,
);
return await Promise.all(items.map((item) => item.getAttribute('data-qa')));
}
async setVisualization(ids: string | string[]) {
await this.page.click(`${slct('visualization-select-btn')}`);
const visualizationIds = Array.isArray(ids) ? ids : [ids];
const selector = visualizationIds.map((id) => slct(`visualization-item-${id}`)).join(', ');
return await this.page
.locator(slct(WizardPageQa.VisualizationSelectPopup))
.locator(selector)
.click();
}
async getVisualizations(): Promise<string[]> {
await this.page.click(slct('visualization-select-btn'));
await this.page.waitForSelector(
`${slct(WizardPageQa.VisualizationSelectPopup)} .g-menu__list-item`,
);
const visualizationsNodes = await this.page.$$(
`${slct(WizardPageQa.VisualizationSelectPopup)} .g-menu__list-item .visualization-item`,
);
const visualizations = await Promise.all(
visualizationsNodes.map((item) => item.getAttribute('data-qa')),
);
await this.page.click(slct('visualization-select-btn'));
return visualizations.filter((s): s is string => s !== null);
}
async checkSelectedVisualization(id: VisualizationsQa): Promise<boolean> {
const switcher = this.page.locator(slct('visualization-select-btn'));
const visualization = switcher.getByTestId(slct(id));
return visualization.isVisible();
}
async openSaveDialogAndGetPath() {
const saveButtonLocator = this.getSaveButtonLocator();
await saveButtonLocator.click();
const element = await this.page.waitForSelector('.dl-path-select__path-text');
return element.innerText();
}
async saveInFolder(folderName: string, entryName: string, filter?: string) {
const saveButtonLocator = this.getSaveButtonLocator();
await saveButtonLocator.click();
const folderSelect = await this.page.waitForSelector(slct(EntryDialogQA.FolderSelect));
await folderSelect.click();
await this.page.waitForSelector(slct(DlNavigationQA.NavigationMinimal));
if (filter) {
const searchInput = this.page
.locator(slct(DlNavigationQA.SearchInput))
.locator('input');
await searchInput.fill(filter);
}
const folderRow = this.page.locator(`${slct(DlNavigationQA.Row)} >> text=${folderName}`);
await folderRow.click();
const navigationDoneBtn = await this.page.waitForSelector(
slct(DlNavigationQA.MinimalDoneBtn),
);
await navigationDoneBtn.click();
await entryDialogFillAndSave(this.page, entryName);
}
async checkApplyAndResetParams(
startParam: string,
finishParam: string,
tempParam: string,
resetButtonLabel: string,
applyButtonLabel: string,
) {
// looking for an input
const controlInput = await this.page.waitForSelector(
`${slct(ControlQA.controlInput)} input`,
);
// check that the entered value is equal to the specified
await this.checkInputValue(controlInput, startParam);
// setting a temporary value
await this.applyTempParam(controlInput, tempParam, applyButtonLabel);
// press the reset button
await this.clickResetButton(resetButtonLabel);
// check that the final value is equal to the specified
await this.checkInputValue(controlInput, finishParam);
}
async checkResetParams(
startParam: string,
finishParam: string,
tempParam: string,
resetButtonLabel: string,
) {
const controlSelect = await this.page.waitForSelector(slct(ControlQA.controlSelect));
// check that the selected value is equal to the specified
await controlSelect.waitForSelector(`div >> text=${startParam}`);
await this.setSelectActiveItem(controlSelect, tempParam);
await controlSelect.waitForSelector(`div >> text=${tempParam}`);
await this.clickResetButton(resetButtonLabel);
await controlSelect.waitForSelector(`div >> text=${finishParam}`);
}
getSaveButtonLocator() {
return this.page.locator(slct(SaveChartControlsQa.SaveButton));
}
protected async switchToSecondRevision({
waitForConditionPromise,
}: {
waitForConditionPromise: Promise<void>;
}): Promise<void> {
let list: ElementHandle<HTMLElement | SVGElement>[] = [];
const apiRunSuccessfulPromise = this.waitForSuccessfulResponse('/api/run');
await waitForCondition(async () => {
await this.revisions.openList();
list = await this.revisions.getRevisions();
return list.length > 0;
});
const listItemClassAttributes: (string | null)[] = await Promise.all(
list.map((item) => item.getAttribute('class')),
);
const indexNotCurrentRevisionItem = listItemClassAttributes.findIndex(
(item) => !item?.includes(CURRENT_REVISION_CLASSNAME),
);
const notCurrentRevisionItem = list[indexNotCurrentRevisionItem];
await notCurrentRevisionItem.click();
await apiRunSuccessfulPromise;
await waitForConditionPromise;
}
protected async saveEntry({
entryName,
chartType,
customUrlsForValidation,
}:
| {
entryName: string;
chartType?: never;
customUrlsForValidation: string[];
}
| {entryName: string; chartType?: ChartType; customUrlsForValidation?: never}) {
let urlsForValidation: string[] = [];
if (customUrlsForValidation) {
urlsForValidation = customUrlsForValidation;
} else {
switch (chartType) {
case ChartType.Wizard:
urlsForValidation = ['/api/charts/v1/charts', '/api/run'];
break;
case ChartType.QL:
urlsForValidation = ['/api/charts/v1/charts', '/getEntry'];
break;
default:
throw new Error('Unknown chart type');
}
}
const promises = Promise.all(
urlsForValidation.map((url) => this.waitForSuccessfulResponse(url)),
);
const saveButtonLocator = this.getSaveButtonLocator();
await saveButtonLocator.click();
await entryDialogFillAndSave(this.page, entryName);
await promises;
}
protected async saveExistentEntry() {
const entryId = this.getEntryIdFromUrl();
const successfulSaveResponse = this.waitForSuccessfulResponse(`/${entryId}`);
await this.page.click(slct(SaveChartControlsQa.SaveButton));
await successfulSaveResponse;
}
protected async saveAsNewChart(entryName: string) {
const urlsForValidation: string[] = ['/api/charts/v1/charts', '/api/run'];
const promises = Promise.all(
urlsForValidation.map((url) => this.waitForSuccessfulResponse(url)),
);
await this.page.click(slct(ChartSaveControlsQA.SaveMoreDropdown));
await this.page.click(slct('save-as-new-chart'));
await entryDialogFillAndSave(this.page, entryName);
await promises;
}
protected async checkInputValue(controlInput: ElementHandle, expectedValue: string) {
const controlInputValue = await controlInput.inputValue();
expect(controlInputValue).toBe(expectedValue);
}
protected async applyTempParam(controlInput: ElementHandle, tempParam: string, apply: string) {
await controlInput.fill(tempParam);
const applyButton = await this.page.waitForSelector(
`${slct(ControlQA.chartkitControl)} >> text=${apply}`,
);
await applyButton.click();
await this.checkInputValue(controlInput, tempParam);
}
protected async setSelectActiveItem(controlSelect: ElementHandle, itemValue: string) {
await controlSelect.click();
const selectItem = await this.page.waitForSelector(`[data-value="${itemValue}"]`);
await selectItem.click();
}
protected async clickResetButton(reset: string) {
const resetButton = await this.page.waitForSelector(
`${slct(ControlQA.chartkitControl)} >> text=${reset}`,
);
await resetButton.click();
}
}