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

295 lines
10 KiB
TypeScript

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<void> => {
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<typeof DATASET_TAB>) {
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;