diff --git a/tests/sanity/tests/drive/drive.spec.ts b/tests/sanity/tests/drive/drive.spec.ts new file mode 100644 index 0000000000..fd072741b5 --- /dev/null +++ b/tests/sanity/tests/drive/drive.spec.ts @@ -0,0 +1,81 @@ +import { test } from '@playwright/test' +import { PlatformSetting, PlatformURI } from '../utils' +import { Drive } from '../model/drive/types' +import { faker } from '@faker-js/faker' +import { DriveLeftMenu } from '../model/drive/drive-left-menu' +import { DriveCreateEditPopup } from '../model/drive/drive-create-edit-popup' +import { DrivesPage } from '../model/drive/drive-drives-page' +import { DriveFilesPage } from '../model/drive/drive-files-page' + +test.use({ + storageState: PlatformSetting +}) + +test.describe('Drive tests', () => { + let leftMenu: DriveLeftMenu + let popupDrive: DriveCreateEditPopup + let drivesPage: DrivesPage + let filesPage: DriveFilesPage + let drive: Drive + + test.beforeEach(async ({ page }) => { + popupDrive = new DriveCreateEditPopup(page) + leftMenu = new DriveLeftMenu(page) + drivesPage = new DrivesPage(page) + filesPage = new DriveFilesPage(page) + drive = { + name: faker.word.noun() + } + await (await page.goto(`${PlatformURI}/workbench/sanity-ws/drive`))?.finished() + await leftMenu.clickCreateNewDrive() + await popupDrive.createOrEditDrive(drive) + await leftMenu.clickDrives() + }) + + test('Check if drive exists at drives page', async () => { + await drivesPage.checkDriveExists(drive) + }) + + test('Create new folder, check if folder exists in drive tree', async () => { + const folder = faker.word.noun() + await drivesPage.createFolder(drive, folder) + await leftMenu.checkFolderExists(drive, folder) + }) + + test('Edit drive, rename drive, check if it was renamed', async () => { + const newDrive: Drive = { + name: faker.word.noun() + } + await drivesPage.clickEditDrive(drive) + await popupDrive.createOrEditDrive(newDrive) + await drivesPage.checkDriveExists(newDrive) + await drivesPage.checkDriveNotExists(drive) + }) + + test('Archive/unarchive drive, check drive archive status', async () => { + await drivesPage.archiveDrive(drive) + await drivesPage.checkIsArchived(drive) + await drivesPage.unarchiveDrive(drive) + await drivesPage.checkIsNotArchived(drive) + }) + + test('Leave/Join drive, check if user leaved/joined drive', async () => { + await drivesPage.leaveDrive(drive) + await drivesPage.checkUserNotJoinedDrive(drive) + await drivesPage.joinDrive(drive) + await drivesPage.checkUserJoinedDrive(drive) + }) + + test('Upload/rename/delete file, check file was uploaded, renamed and deleted', async () => { + await drivesPage.clickOnDrive(drive) + await leftMenu.clickUploadFiles() + const fileName = 'cat.jpeg' + await filesPage.uploadFile(fileName) + await filesPage.checkFileExists(fileName) + const newFileName = 'dog.jpeg' + await filesPage.renameFile(fileName, newFileName) + await filesPage.checkFileExists(newFileName) + await filesPage.deleteFile(newFileName) + await filesPage.checkFileNotExists(newFileName) + }) +}) diff --git a/tests/sanity/tests/model/drive/drive-create-edit-popup.ts b/tests/sanity/tests/model/drive/drive-create-edit-popup.ts new file mode 100644 index 0000000000..73e7f06898 --- /dev/null +++ b/tests/sanity/tests/model/drive/drive-create-edit-popup.ts @@ -0,0 +1,27 @@ +import { type Locator, type Page } from '@playwright/test' +import { Drive } from './types' + +export class DriveCreateEditPopup { + readonly page: Page + + constructor (page: Page) { + this.page = page + } + + readonly popup = (): Locator => this.page.locator('div.popup') + readonly form = (): Locator => this.popup().locator('form[id^="drive:string:"]') + readonly buttonSelectSpaceType = (): Locator => this.form().locator('div.antiGrid-row:has-text("Space type") button') + readonly inputName = (): Locator => this.form().locator('div.antiGrid-row:has-text("Name") input') + readonly inputDescription = (): Locator => this.form().locator('div.antiGrid-row:has-text("Description") input') + readonly buttonSelectOwners = (): Locator => this.form().locator('div.antiGrid-row:has-text("Owners") button') + readonly togglePrivate = (): Locator => + this.form().locator('div.antiGrid-row:has-text("Make private") .toggle-switch') + + readonly buttonSelectMembers = (): Locator => this.form().locator('div.antiGrid-row:has-text("Members") button') + readonly buttonSubmit = (): Locator => this.form().locator('button[type="submit"]') + + async createOrEditDrive (drive: Drive): Promise { + await this.inputName().fill(drive.name) + await this.buttonSubmit().click() + } +} diff --git a/tests/sanity/tests/model/drive/drive-drives-page.ts b/tests/sanity/tests/model/drive/drive-drives-page.ts new file mode 100644 index 0000000000..e2d411abb9 --- /dev/null +++ b/tests/sanity/tests/model/drive/drive-drives-page.ts @@ -0,0 +1,95 @@ +import { expect, type Locator, type Page } from '@playwright/test' +import { ButtonDrivesContextMenu, Drive } from './types' +import { CommonPage } from '../common-page' + +export class DrivesPage extends CommonPage { + page: Page + + constructor (page: Page) { + super(page) + this.page = page + } + + readonly cellDriveName = (driveName: string): Locator => this.page.getByRole('cell', { name: driveName }).first() + + readonly buttonContextMenu = (buttonText: ButtonDrivesContextMenu): Locator => + this.page.locator('div.antiPopup').getByRole('button', { name: buttonText }) + + readonly popupCreateFolder = (): Locator => this.page.locator('div.popup form[id="drive:string:CreateFolder"]') + + readonly rowDrive = (driveName: string): Locator => + this.page.locator('tbody tr').filter({ + has: this.cellDriveName(driveName) + }) + + readonly buttonJoinDriveRow = (driveName: string): Locator => + this.rowDrive(driveName).locator('td').nth(2).getByRole('button', { name: 'Join' }) + + readonly popupArchive = (): Locator => this.page.locator('.popup.endShow:text("archive")').first() + + readonly cellArchiveStatusYes = (driveName: string): Locator => + this.rowDrive(driveName).locator('td').last().locator(':text("Yes")') + + async checkDriveExists (drive: Drive): Promise { + await expect(this.cellDriveName(drive.name)).toBeVisible() + } + + async checkDriveNotExists (drive: Drive): Promise { + await expect(this.cellDriveName(drive.name)).not.toBeVisible() + } + + async clickButtonDriveContextMenu (drive: Drive, buttonText: ButtonDrivesContextMenu): Promise { + await this.cellDriveName(drive.name).click({ button: 'right' }) + await this.buttonContextMenu(buttonText).click() + } + + async createFolder (drive: Drive, folderName: string): Promise { + await this.clickButtonDriveContextMenu(drive, 'Create folder') + await this.popupCreateFolder().locator('input').fill(folderName) + await this.popupCreateFolder().getByRole('button', { name: 'Create' }).last().click() + } + + async clickEditDrive (drive: Drive): Promise { + await this.clickButtonDriveContextMenu(drive, 'Edit drive') + } + + async archiveDrive (drive: Drive): Promise { + await this.clickButtonDriveContextMenu(drive, 'Archive') + await this.popupSubmitButton().click() + await this.popupArchive().waitFor({ state: 'detached' }) + } + + async unarchiveDrive (drive: Drive): Promise { + await this.clickButtonDriveContextMenu(drive, 'Unarchive') + await this.popupSubmitButton().click() + await this.popupArchive().waitFor({ state: 'detached' }) + } + + async checkIsArchived (drive: Drive): Promise { + await expect(this.cellArchiveStatusYes(drive.name)).toBeVisible() + } + + async checkIsNotArchived (drive: Drive): Promise { + await expect(this.cellArchiveStatusYes(drive.name)).not.toBeVisible() + } + + async leaveDrive (drive: Drive): Promise { + await this.clickButtonDriveContextMenu(drive, 'Leave') + } + + async joinDrive (drive: Drive): Promise { + await this.clickButtonDriveContextMenu(drive, 'Join') + } + + async checkUserJoinedDrive (drive: Drive): Promise { + await expect(this.buttonJoinDriveRow(drive.name)).not.toBeVisible() + } + + async checkUserNotJoinedDrive (drive: Drive): Promise { + await this.buttonJoinDriveRow(drive.name).waitFor({ state: 'visible' }) + } + + async clickOnDrive (drive: Drive): Promise { + await this.cellDriveName(drive.name).locator('a').click() + } +} diff --git a/tests/sanity/tests/model/drive/drive-files-page.ts b/tests/sanity/tests/model/drive/drive-files-page.ts new file mode 100644 index 0000000000..063ecff242 --- /dev/null +++ b/tests/sanity/tests/model/drive/drive-files-page.ts @@ -0,0 +1,48 @@ +import { expect, type Locator, type Page } from '@playwright/test' +import { ButtonFilesContextMenu } from './types' +import { uploadFile } from '../../utils' +import { CommonPage } from '../common-page' + +export class DriveFilesPage extends CommonPage { + page: Page + + constructor (page: Page) { + super(page) + this.page = page + } + + readonly leftMenu = (): Locator => this.page.locator('.antiPanel-wrap__content.hulyNavPanel-container') + readonly buttonConfirmUpload = (): Locator => this.page.locator('.popup button').last() + readonly linkFile = (fileName: string): Locator => this.page.locator(`td:has(span:text-is("${fileName}")) a`).first() + readonly buttonContextMenu = (buttonText: ButtonFilesContextMenu): Locator => + this.page.locator('div.antiPopup').getByRole('button', { name: buttonText }) + + async uploadFile (fileName: string): Promise { + await uploadFile(this.page, fileName, 'My device') + await this.buttonConfirmUpload().click() + } + + async checkFileExists (fileName: string): Promise { + await expect(this.linkFile(fileName)).toBeVisible() + } + + async checkFileNotExists (fileName: string): Promise { + await expect(this.linkFile(fileName)).not.toBeVisible() + } + + async clickFilesContextMenu (fileName: string, buttonText: ButtonFilesContextMenu): Promise { + await this.linkFile(fileName).click({ button: 'right' }) + await this.buttonContextMenu(buttonText).click() + } + + async renameFile (fileName: string, newFileName: string): Promise { + await this.clickFilesContextMenu(fileName, 'Rename') + await this.page.locator('.popup input').fill(newFileName) + await this.pressYesForPopup(this.page) + } + + async deleteFile (fileName: string): Promise { + await this.clickFilesContextMenu(fileName, 'Delete') + await this.pressYesForPopup(this.page) + } +} diff --git a/tests/sanity/tests/model/drive/drive-left-menu.ts b/tests/sanity/tests/model/drive/drive-left-menu.ts new file mode 100644 index 0000000000..bc469c2fb2 --- /dev/null +++ b/tests/sanity/tests/model/drive/drive-left-menu.ts @@ -0,0 +1,46 @@ +import { expect, type Locator, type Page } from '@playwright/test' +import { Drive } from './types' + +export class DriveLeftMenu { + page: Page + + constructor (page: Page) { + this.page = page + } + + readonly leftMenu = (): Locator => this.page.locator('.antiPanel-wrap__content.hulyNavPanel-container') + readonly buttonCreateDrive = (): Locator => this.page.locator('button#tree-drives') + readonly buttonUploadFiles = (): Locator => this.leftMenu().getByRole('button', { name: 'Upload files' }) + readonly buttonDrives = (): Locator => this.page.getByRole('link', { name: 'Drives' }).getByRole('button') + readonly groupHeaderDrive = (): Locator => this.page.getByRole('button', { name: 'Drive', exact: true }) + readonly treeDrives = (): Locator => this.leftMenu().locator('#navGroup-tree-drives') + readonly buttonDriveInTree = (drive: Drive): Locator => + this.treeDrives().locator('.hulyNavGroup-container').getByRole('button', { name: drive.name }) + + readonly driveContainer = (drive: Drive): Locator => + this.treeDrives() + .locator('.hulyNavGroup-container') + .filter({ + has: this.page.locator(':scope').getByRole('button', { name: drive.name }) + }) + + readonly buttonFolderInDrive = (drive: Drive, folder: string): Locator => + this.driveContainer(drive).getByRole('button', { name: folder }) + + async clickCreateNewDrive (): Promise { + await this.groupHeaderDrive().hover() + await this.buttonCreateDrive().click() + } + + async clickDrives (): Promise { + await this.buttonDrives().click() + } + + async checkFolderExists (drive: Drive, folder: string): Promise { + await expect(this.buttonFolderInDrive(drive, folder)).toBeVisible() + } + + async clickUploadFiles (): Promise { + await this.buttonUploadFiles().click() + } +} diff --git a/tests/sanity/tests/model/drive/types.ts b/tests/sanity/tests/model/drive/types.ts new file mode 100644 index 0000000000..812c485bae --- /dev/null +++ b/tests/sanity/tests/model/drive/types.ts @@ -0,0 +1,12 @@ +export interface Drive { + spaceType?: string + name: string + description?: string + owners?: string[] + private?: boolean + members?: string[] +} + +export type ButtonDrivesContextMenu = 'Create folder' | 'Edit drive' | 'Archive' | 'Unarchive' | 'Leave' | 'Join' + +export type ButtonFilesContextMenu = 'Rename' | 'Download' | 'Move' | 'Delete'