import {Page, Response, expect} from '@playwright/test'; import {v1 as uuidv1} from 'uuid'; import { DialogCreateWorkbookEntryQa, EntryDialogQA, } from '../../../src/shared/constants/qa/components'; import { DatasetPanelQA, DatasetActionQA, DatasetSourcesTableQa, DatasetSourcesLeftPanelQA, } from '../../../src/shared/constants/qa/datasets'; import { CollectionFiltersQa, DialogCollectionStructureQa, SharedEntriesBaseQa, SharedEntriesPermissionsDialogQa, ValueOf, DATASET_TAB, } from '../../../src/shared'; import {deleteEntity, slct} from '../../utils'; import {BasePage, BasePageProps} from '../BasePage'; import DialogParameter from '../common/DialogParameter'; import Revisions from '../common/Revisions'; import DatasetTabSection from './DatasetTabSection'; import DatasetConnectionSection, {SetConnectionProps} from './DatasetConnectionSection'; import DatasetFieldsTable from './DatasetFieldsTable'; import {VALIDATE_DATASET_URL} from './constants'; import {NavigationMinimalPopup} from '../workbook/NavigationMinimalPopup'; export interface DatasetPageProps extends BasePageProps {} export const waitForBiValidateDatasetResponses = (page: Page, timeout: number): Promise => { return new Promise((resolve: any) => { const timerId = setTimeout(() => { page.off('response', onResponse); resolve(); }, timeout); async function onResponse(response: Response) { if (!response.url().match('validateDataset')) { return; } const request = await response.request(); const requestData = JSON.parse(request.postData() || ''); // When the page loads, the validation request with empty updates initially goes away // We are only interested in the one that leaves after the avatar is deleted if (!requestData.data.updates.length) { return; } clearTimeout(timerId); if (response.status() !== 200) { throw new Error( 'After deleting the avatar, the dataset validation returned an error', ); } resolve(); } page.on('response', onResponse); }); }; class DatasetPage extends BasePage { datasetTabSection: DatasetTabSection; datasetConnectionSection: DatasetConnectionSection; datasetFieldsTable: DatasetFieldsTable; workbookNavigationMinimal: NavigationMinimalPopup; dialogParameter: DialogParameter; revisions: Revisions; constructor({page}: DatasetPageProps) { super({page}); this.workbookNavigationMinimal = new NavigationMinimalPopup(page); this.datasetConnectionSection = new DatasetConnectionSection(page); this.datasetFieldsTable = new DatasetFieldsTable(page); this.datasetTabSection = new DatasetTabSection(page); this.dialogParameter = new DialogParameter(page); this.revisions = new Revisions(page); } async addAvatarByDragAndDrop(sourceTitle?: string) { const selector = sourceTitle ? `${slct(DatasetSourcesTableQa.Source)} span >> text=${sourceTitle}` : slct(DatasetSourcesTableQa.Source); const source = await this.page.$(selector); if (!source) { throw new Error("Couldn't find the table"); } const targetSelector = slct('ds-relations-map'); const target = await this.page.$(targetSelector); if (!target) { throw new Error("Couldn't find an area to drag"); } await this.page.dragAndDrop(selector, targetSelector); } async openTab(tab: ValueOf) { await this.page.click(`.dataset-panel input[value=${tab}]`); } async createDatasetInWorkbookOrCollection({ name = uuidv1(), collectionId, }: {name?: string; collectionId?: string} = {}) { const dsCreateBtn = this.page.locator(slct(DatasetActionQA.CreateButton)); await dsCreateBtn.click(); const textInput = this.page .locator(slct(DialogCreateWorkbookEntryQa.Input)) .locator('input'); // clear input await textInput.press('Meta+A'); await textInput.press('Backspace'); // type dataset name await textInput.fill(name); const dialogApplyButton = await this.page.waitForSelector( slct(DialogCreateWorkbookEntryQa.ApplyButton), ); // create connection await dialogApplyButton.click(); try { if (collectionId) { await this.page.waitForURL(() => { return this.page.url().endsWith(collectionId); }); } else { await this.page.waitForURL(() => { return this.page.url().includes(name); }); } return name; } catch { throw new Error("Dataset wasn't created"); } } async createDatasetInFolder({name = uuidv1()}: {name?: string} = {}) { // open creation dialog await this.page.locator(slct(DatasetActionQA.CreateButton)).click(); // type dataset name await this.page.locator(slct(EntryDialogQA.PathSelect)).locator('input').fill(name); const dialogApplyButton = await this.page.waitForSelector(slct(EntryDialogQA.Apply)); // create dataset await dialogApplyButton.click(); try { await this.page.waitForURL(() => this.page.url().includes(name)); } catch { throw new Error("Dataset wasn't created"); } } async deleteEntry() { await deleteEntity(this.page); } async getCurrentTabName() { const input = await this.page.waitForSelector( `${slct(DatasetPanelQA.TabRadio)} input[aria-checked="true"]`, ); return await input.inputValue(); } async setConnectionDelegation({ delegation = true, }: { delegation?: boolean; } = {}) { if (delegation) { const delegateBtn = await this.page.waitForSelector( slct(SharedEntriesPermissionsDialogQa.DelegateBtn), ); await delegateBtn.click(); } else { const delegateBtn = await this.page.waitForSelector( slct(SharedEntriesPermissionsDialogQa.NotDelegateBtn), ); await delegateBtn.click(); } const delegationApplyBtn = this.page.locator( slct(SharedEntriesPermissionsDialogQa.ApplyBtn), ); await delegationApplyBtn.click(); } async saveSharedDataset({name, collectionId}: {name?: string; collectionId: string}) { await this.page.waitForSelector(slct(DatasetSourcesTableQa.Source)); await this.addAvatarByDragAndDrop(); const dsName = await this.createDatasetInWorkbookOrCollection({ collectionId, name, }); return dsName; } async setConnectionInWorkbookDataset({method, connectionName}: SetConnectionProps) { await this.datasetConnectionSection.openConnectionSelectViaMethod(method); await this.workbookNavigationMinimal.fillInput(connectionName); await this.workbookNavigationMinimal.selectListItem({innerText: connectionName}); } async setSharedConnection({connectionName, method}: SetConnectionProps) { await this.datasetConnectionSection.openConnectionSelectViaMethod(method); await this.page.waitForSelector(slct(CollectionFiltersQa.SearchInput)); const search = this.page.locator(slct(CollectionFiltersQa.SearchInput)).locator('input'); await search.press('Meta+A'); await search.press('Backspace'); await search.fill(connectionName); await this.waitForSuccessfulResponse('/getCollectionBreadcrumbs'); await this.page.waitForSelector(slct(DialogCollectionStructureQa.ListItem)); const sharedConn = this.page .locator(slct(DialogCollectionStructureQa.ListItem)) .filter({hasText: connectionName}); await sharedConn.click(); } async checkIsReadonlyState() { await this.page.waitForSelector(slct(SharedEntriesBaseQa.OpenOriginalBtn)); } async scrollSourcesList({scrollHeight = 99999}: {scrollHeight?: number} = {}) { const sourcesList = await this.page.waitForSelector( slct(DatasetSourcesLeftPanelQA.SourcesList), ); await this.page.waitForSelector(slct(DatasetSourcesTableQa.Source)); await sourcesList.hover(); await this.page.mouse.wheel(0, scrollHeight); } async changeDbName({namePattern}: {namePattern?: string} = {}) { const select = await this.page.waitForSelector( slct(DatasetSourcesLeftPanelQA.SelectSourcesDbName), ); await this.page.waitForFunction( async (element) => { return !(element as HTMLSelectElement).disabled; }, select, {polling: 500}, ); const disabled = await select.isDisabled(); expect(disabled).toBe(false); await select.click(); await this.page.waitForSelector(slct('select-popup')); const popup = this.page.locator(slct('select-popup')); const option = popup.locator('[role="option"]', {hasText: namePattern}); await option.click(); } async renameFirstField({value}: {value?: string} = {}) { const fieldInput = this.datasetFieldsTable.getFieldNameInput(); const originalValue = await fieldInput.inputValue(); const newValue = value || `${originalValue}_modified`; await fieldInput.fill(newValue); const validatePromise = this.waitForSuccessfulResponse(VALIDATE_DATASET_URL); await this.page.keyboard.press('Enter'); await validatePromise; return {newValue, originalValue}; } async saveUpdatedDataset() { const getEntrySuccessfulPromise = this.waitForSuccessfulResponse( '/gateway/root/us/getEntryMeta', ); const saveBtn = await this.page.locator(slct(DatasetActionQA.CreateButton)); await expect(saveBtn).toBeEnabled(); await saveBtn.click(); await getEntrySuccessfulPromise; } } export default DatasetPage;