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

261 lines
8.5 KiB
TypeScript

import {
ActionPanelQA,
ConnectionsActionPanelControls,
ConnectionsBaseQA,
ConnectionsFormQA,
ConnectionsS3BaseQA,
ConnectionsYadocsQA,
DialogCreateWorkbookEntryQa,
EntryDialogQA,
SharedEntriesBaseQa,
} from '../../../src/shared/constants';
import {ActionPanelEntryContextMenuQa} from '../../../src/shared/constants/qa/action-panel';
import {v1 as uuidv1} from 'uuid';
import {slct, waitForCondition} from '../../utils';
import {BasePage} from '../BasePage';
import type {BasePageProps} from '../BasePage';
import type {ConsoleMessage, Request, FileChooser} from '@playwright/test';
import Revisions from '../common/Revisions';
import XLSX from '@datalens-tech/xlsx';
import {CSV_FILE, XLSX_FILE} from '../../constants/mock-data';
import os from 'os';
import path from 'path';
import fs from 'fs';
type ConnectionsPageProps = BasePageProps;
type FillInputArgs = {name: string; value: string};
type FillFormInputArgs = {id: 'input'} & FillInputArgs;
class ConnectionsPage extends BasePage {
revisions: Revisions;
private createQlChartButtonSelector = slct(
ConnectionsActionPanelControls.CREATE_QL_CHART_BUTTON,
);
private createDatasetButtonSelector = slct(
ConnectionsActionPanelControls.CREATE_DATASET_BUTTON,
);
constructor({page}: ConnectionsPageProps) {
super({page});
this.revisions = new Revisions(page);
}
async checkIsReadonlyState() {
await this.page.waitForSelector(slct(SharedEntriesBaseQa.OpenOriginalBtn));
}
async createQlChart() {
await this.page.click(this.createQlChartButtonSelector);
}
async createDataset() {
await this.page.click(this.createDatasetButtonSelector);
}
async fillCreateConnectionInFolder({name}: {name: string}) {
const textInput = this.page.locator(slct(EntryDialogQA.PathSelect)).locator('input');
// type connection name
await textInput.fill(name);
// create connection
await this.page.locator(slct(EntryDialogQA.Apply)).click();
try {
await this.page.waitForURL(() => this.page.url().includes(name));
} catch {
throw new Error("Connection wasn't created");
}
}
async createConnectionInFolder({name = uuidv1()}: {name?: string} = {}) {
// open creation dialog
await this.page.locator(slct(ConnectionsBaseQA.SUBMIT_ACTION_BUTTON)).click();
await this.fillCreateConnectionInFolder({name});
}
async createConnectionInWorkbookOrCollection({
name = uuidv1(),
collectionId,
}: {name?: string; collectionId?: string} = {}) {
const formSubmit = await this.page.waitForSelector(
slct(ConnectionsBaseQA.SUBMIT_ACTION_BUTTON),
);
// open creation dialog
await formSubmit.click();
const textInput = this.page
.locator(slct(DialogCreateWorkbookEntryQa.Input))
.locator('input');
// clear input
await textInput.press('Meta+A');
await textInput.press('Backspace');
// type connection 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("Connection wasn't created");
}
}
async checkClientValidationErrors() {
let hasValidationErrors = false;
const onConsoleLog = (msg: ConsoleMessage) => {
if (msg.text().includes('Validation errors')) {
hasValidationErrors = true;
}
};
this.page.on('console', onConsoleLog);
const formSubmit = await this.page.waitForSelector(
slct(ConnectionsBaseQA.SUBMIT_ACTION_BUTTON),
);
await formSubmit.click();
await waitForCondition(async () => {
return hasValidationErrors;
});
this.page.off('console', onConsoleLog);
}
getFieldSelector(name: string) {
return `conn-input-${name}`;
}
async fillInput({name, value}: {name: string; value: string}) {
const selector = this.getFieldSelector(name);
const input = await this.page.waitForSelector(slct(selector));
// focus input
await input.click();
await input.type(value);
}
async fillForm(args: FillFormInputArgs[]) {
for (const control of args) {
const {id, name, value} = control;
switch (id) {
case 'input': {
await this.fillInput({name, value});
break;
}
}
}
}
async fillAndSubmitAddYadocDialog(fileUrl: string) {
const fileInput = await this.page.waitForSelector(
`${slct(ConnectionsYadocsQA.ADD_DOCUMENT_DIALOG_INPUT)} input`,
);
await fileInput.click();
await fileInput.fill(fileUrl);
const addFileDialogSubmitButton = await this.page.waitForSelector(
slct(ConnectionsYadocsQA.ADD_DOCUMENT_DIALOG_SUBMIT_BUTTON),
);
await addFileDialogSubmitButton.click();
}
async applyS3SourceDialogAndForSourcesUpdating() {
const updateFileSourceRequests: Request[] = [];
this.page.on('request', (request) => {
if (request.url().includes('updateFileSource')) {
updateFileSourceRequests.push(request);
}
});
const submitButton = await this.page.waitForSelector(
slct(ConnectionsS3BaseQA.S3_SOURCE_DIALOG_SUBMIT_BUTTON),
);
await submitButton.click();
await Promise.all(
updateFileSourceRequests.map(async (request) => {
const response = await request.response();
expect(response?.status()).toBe(200);
}),
);
}
async saveUpdatedConnection() {
await this.page.locator(slct(ConnectionsBaseQA.SUBMIT_ACTION_BUTTON)).click();
}
async removeConnection() {
const moreButton = this.page.locator(slct(ActionPanelQA.MoreBtn));
expect(moreButton).toBeVisible();
await moreButton.click();
const menuItemRemove = this.page
.locator(slct(ActionPanelEntryContextMenuQa.Menu))
.locator(slct(ActionPanelEntryContextMenuQa.Remove));
expect(menuItemRemove).toBeVisible();
await menuItemRemove.click();
const applyButton = this.page.locator(slct(EntryDialogQA.Apply));
expect(applyButton).toBeVisible();
await applyButton.click();
}
async disableAutoCreateDashInBillingConnection() {
const checkbox = await this.page.waitForSelector(
slct(ConnectionsFormQA.AUTO_CREATE_DASH_CHECKBOX),
);
await checkbox.click();
}
async uploadCsvFile({
fileName = `${uuidv1()}.csv`,
file = CSV_FILE,
}: {fileName?: string; file?: string[][]} = {}) {
// make file
os.tmpdir();
const csvFile = path.join(os.tmpdir(), fileName);
fs.writeFileSync(csvFile, file.map((row) => row.join(',')).join('\n'));
await this.uploadS3File(csvFile);
return {fileName, file};
}
async uploadXlsxFile({
fileName = `${uuidv1()}.xlsx`,
sheets = XLSX_FILE,
}: {fileName?: string; sheets?: Record<string, string[][]>} = {}) {
// make file
const workbook = XLSX.utils.book_new();
for (const [sheetName, data] of Object.entries(sheets)) {
const worksheet = XLSX.utils.aoa_to_sheet(data);
XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
}
const xlsxFile = path.join(os.tmpdir(), fileName);
XLSX.writeFile(workbook, xlsxFile);
await this.uploadS3File(xlsxFile);
return {fileName, sheets};
}
private async uploadS3File(file: string) {
const onFileChoose = (fileChooser: FileChooser) => {
fileChooser.setFiles([file]);
};
this.page.on('filechooser', onFileChoose);
await this.page.click(slct(ConnectionsBaseQA.S3_UPLOAD_BUTTON));
this.page.off('filechooser', onFileChoose);
}
}
export default ConnectionsPage;