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 { 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 { 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; }): Promise { let list: ElementHandle[] = []; 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(); } }