Skip to content

Commit

Permalink
testsuite/playwright-ui: added bucket and object browser tests for V2…
Browse files Browse the repository at this point in the history
… app

Added tests for bucket and object related functionality.

Issue:
#6598

Change-Id: I8cc9dfd8c82af12402af5a438e61fe9491d85e6b
  • Loading branch information
VitaliiShpital committed Jan 10, 2024
1 parent 14def22 commit 9648e03
Show file tree
Hide file tree
Showing 25 changed files with 388 additions and 14 deletions.
29 changes: 25 additions & 4 deletions testsuite/playwright-ui/lib/BaseTest.ts
Expand Up @@ -4,22 +4,28 @@
import { test as baseTest } from '@playwright/test';
import { LoginPage, LoginPageV2 } from '@pages/LoginPage';
import { DashboardPage } from '@pages/DashboardPage';
import { NavigationMenu } from '@pages/NavigationMenu';
import { BucketsPage } from '@pages/BucketsPage';
import { NavigationMenu, NavigationMenuV2 } from '@pages/NavigationMenu';
import { BucketsPage, BucketsPageV2 } from '@pages/BucketsPage';
import { SignupPage, SignupPageV2 } from '@pages/SignupPage';
import { AllProjectsPage } from '@pages/AllProjectsPage';
import { Common } from '@pages/Common';
import { AllProjectsPage, AllProjectsPageV2 } from '@pages/AllProjectsPage';
import { Common, CommonV2 } from '@pages/Common';
import { ObjectBrowserPage } from '@pages/ObjectBrowserPage';

const test = baseTest.extend<{
loginPage: LoginPage;
loginPageV2: LoginPageV2;
dashboardPage: DashboardPage;
navigationMenu: NavigationMenu;
navigationMenuV2: NavigationMenuV2;
objectBrowserPage: ObjectBrowserPage;
bucketsPage: BucketsPage;
bucketsPageV2: BucketsPageV2;
signupPage: SignupPage;
signupPageV2: SignupPageV2;
allProjectsPage: AllProjectsPage;
allProjectsPageV2: AllProjectsPageV2;
common: Common;
commonV2: CommonV2;
}>({
loginPage: async ({ page }, use) => {
await use(new LoginPage(page));
Expand All @@ -33,9 +39,18 @@ const test = baseTest.extend<{
navigationMenu: async ({ page }, use) => {
await use(new NavigationMenu(page));
},
navigationMenuV2: async ({ page }, use) => {
await use(new NavigationMenuV2(page));
},
objectBrowserPage: async ({ page }, use) => {
await use(new ObjectBrowserPage(page));
},
bucketsPage: async ({ page }, use) => {
await use(new BucketsPage(page));
},
bucketsPageV2: async ({ page }, use) => {
await use(new BucketsPageV2(page));
},
signupPage: async ({ page }, use) => {
await use(new SignupPage(page));
},
Expand All @@ -45,9 +60,15 @@ const test = baseTest.extend<{
allProjectsPage: async ({ page }, use) => {
await use(new AllProjectsPage(page));
},
allProjectsPageV2: async ({ page }, use) => {
await use(new AllProjectsPageV2(page));
},
common: async ({ page }, use) => {
await use(new Common(page));
},
commonV2: async ({ page }, use) => {
await use(new CommonV2(page));
},
});

export default test;
Expand Up @@ -10,3 +10,9 @@ export class AllProjectsPageObjects {
static NEW_PROJECT_NAME_FIELD_XPATH = `//input[@id='Project Name']`;
static SKIP_ONBOARDING_LABEL = ` Skip and go directly to dashboard `;
}

export class AllProjectsPageObjectsV2 {
static CREATE_PROJECT_BUTTON_XPATH = `//button[span[text()=' Create Project ']]`;
static CONFIRM_CREATE_PROJECT_BUTTON_XPATH = `//button[span[text()='Create Project']]`;
static NEW_PROJECT_NAME_FIELD_XPATH = `//input[@id='Project Name']`;
}
Expand Up @@ -28,3 +28,14 @@ export class BucketsPageObjects {
static CONFIRM_DELETE_BUTTON_XPATH = `//div[contains(@class, 'container') and contains(.//span, 'Delete Bucket')]`;
static DELETE_BUCKET_XPATH = `//p[contains(text(),'Delete Bucket')]`;
}

export class BucketsPageObjectsV2 {
static NEW_BUCKET_BUTTON_XPATH = `//button[span[text()=' New Bucket ']]`;
static BUCKET_NAME_INPUT_FIELD_XPATH = `//input[@id='Bucket Name']`;
static CONFIRM_BUTTON_CREATE_BUCKET_FLOW_XPATH = `//button[span[text()=' Create Bucket ']]`;
static BUCKET_ROW_MORE_BUTTON_XPATH = `//button[@title='Bucket Actions']`;
static VIEW_BUCKET_DETAILS_BUTTON_XPATH = `//div[div[div[text()=' Bucket Details ']]]`;
static SHARE_BUCKET_BUTTON_XPATH = `//div[div[div[text()=' Share Bucket ']]]`;
static DELETE_BUCKET_BUTTON_XPATH = `//div[div[div[text()=' Delete Bucket ']]]`;
static CONFIRM_BUTTON_DELETE_BUCKET_FLOW_XPATH = `//button[span[text()=' Delete ']]`;
}
Expand Up @@ -5,3 +5,7 @@ export class CommonObjects {
static CLOSE_MODAL_BUTTON_XPATH = `.mask__wrapper__container__close`;
static LOADER_XPATH = `//div[contains(@class, 'loader')]`;
}

export class CommonObjectsV2 {
static CLOSE_MODAL_BUTTON_XPATH = `//button[@id='Close']`;
}
Expand Up @@ -4,3 +4,12 @@
export class NavigationMenuObject {
static BUCKETS_XPATH = `//a/div/p[contains(text(),'Buckets')]`;
}

export class NavigationMenuObjectV2 {
static BUCKETS_XPATH = `//a/div/div[contains(text(),'Buckets')]`;
static PROJECT_SELECT_XPATH = `//div[div[div[text()='Project']]]`;
static MANAGE_PASSPHRASE_ACTION_XPATH = `//div/div/div[contains(text(),' Manage Passphrase ')]`;
static SWITCH_PASSPHRASE_ACTION_XPATH = `//div/div/div/p[contains(text(),'Switch active passphrase')]`;
static PASSPHRASE_INPUT_XPATH = `//input[@id='Encryption Passphrase']`;
static CONFIRM_SWITCH_PASSPHRASE_BUTTON_XPATH = `//button[span[text()=' Continue ']]`;
}
@@ -0,0 +1,21 @@
// Copyright (C) 2024 Storj Labs, Inc.
// See LICENSE for copying information.

export class ObjectBrowserPageObjects {
static DOWNLOAD_BUTTON_XPATH = `//button[@id='Download']`;
static DISTRIBUTION_BUTTON_XPATH = `//button[@id='Distribution']`;
static SHARE_BUTTON_XPATH = `//button[@id='Share']`;
static COPY_LINK_BUTTON_XPATH = `//button[span[text()='Copy Link']]`;
static COPIED_TEXT = `Copied`;
static SHARE_MODAL_LOADER_CLASS = `.share-dialog__content--loading`;
static OBJECT_MAP_IMAGE_XPATH = `//img[@id='Map']`;
static OBJECT_ROW_MORE_BUTTON_XPATH = `//button[@title='More Actions']`;
static DELETE_ROW_ACTION_BUTTON_XPATH = `//div[div[div[text()=' Delete ']]]`;
static CONFIRM_DELETE_BUTTON_XPATH = `//button[span[text()=' Delete ']]`;
static FILE_INPUT_XPATH = `//input[@id='File Input']`;
static FOLDER_INPUT_XPATH = `//input[@id='Folder Input']`;
static LOADING_ITEMS_LABEL_XPATH = `//td[text()='Loading items...']`;
static CREATE_FOLDER_BUTTON_XPATH = `//button[span[text()=' New Folder ']]`;
static FOLDER_NAME_INPUT_XPATH = `//input[@id='Folder Name']`;
static CONFIRM_CREATE_FOLDER_BUTTON_XPATH = `//button[span[text()=' Create Folder ']]`;
}
@@ -1,7 +1,7 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.

import { AllProjectsPageObjects } from '@objects/AllProjectsPageObjects';
import { AllProjectsPageObjects, AllProjectsPageObjectsV2 } from '@objects/AllProjectsPageObjects';
import type { Page } from '@playwright/test';

export class AllProjectsPage {
Expand All @@ -21,3 +21,13 @@ export class AllProjectsPage {
await button.click();
}
}

export class AllProjectsPageV2 {
constructor(readonly page: Page) {}

async createProject(name: string): Promise<void> {
await this.page.locator(AllProjectsPageObjectsV2.CREATE_PROJECT_BUTTON_XPATH).click();
await this.page.locator(AllProjectsPageObjectsV2.NEW_PROJECT_NAME_FIELD_XPATH).fill(name);
await this.page.locator(AllProjectsPageObjectsV2.CONFIRM_CREATE_PROJECT_BUTTON_XPATH).click();
}
}
@@ -1,9 +1,11 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.

import { BucketsPageObjects } from '@objects/BucketsPageObjects';
import { BucketsPageObjects, BucketsPageObjectsV2 } from '@objects/BucketsPageObjects';
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
import { CommonObjectsV2 } from '@objects/CommonObjects';
import { ObjectBrowserPageObjects } from '@objects/ObjectBrowserPageObjects';

export class BucketsPage {
constructor(readonly page: Page) {}
Expand Down Expand Up @@ -152,3 +154,38 @@ export class BucketsPage {
await this.page.locator(BucketsPageObjects.CONFIRM_DELETE_BUTTON_XPATH).click();
}
}

export class BucketsPageV2 {
constructor(readonly page: Page) {}

async createBucket(name: string): Promise<void> {
await this.page.locator(BucketsPageObjectsV2.NEW_BUCKET_BUTTON_XPATH).click();
await this.page.locator(BucketsPageObjectsV2.BUCKET_NAME_INPUT_FIELD_XPATH).fill(name);
await this.page.locator(BucketsPageObjectsV2.CONFIRM_BUTTON_CREATE_BUCKET_FLOW_XPATH).click();
}

async openBucketSettings(): Promise<void> {
await this.page.locator(BucketsPageObjectsV2.BUCKET_ROW_MORE_BUTTON_XPATH).click();
}

async verifyBucketDetails(name: string): Promise<void> {
await this.page.locator(BucketsPageObjectsV2.VIEW_BUCKET_DETAILS_BUTTON_XPATH).click();
const elems = await this.page.getByText(name).all();
expect(elems).toHaveLength(2);
}

async verifyShareBucket(): Promise<void> {
await this.page.locator(BucketsPageObjectsV2.SHARE_BUCKET_BUTTON_XPATH).click();
const loader = this.page.locator(ObjectBrowserPageObjects.SHARE_MODAL_LOADER_CLASS);
await expect(loader).toBeHidden();
await this.page.locator(ObjectBrowserPageObjects.COPY_LINK_BUTTON_XPATH).click();
await this.page.locator('span').filter({ hasText: ObjectBrowserPageObjects.COPIED_TEXT }).isVisible();
await this.page.locator(CommonObjectsV2.CLOSE_MODAL_BUTTON_XPATH).click();
}

async verifyDeleteBucket(name: string): Promise<void> {
await this.page.locator(BucketsPageObjectsV2.DELETE_BUCKET_BUTTON_XPATH).click();
await this.page.locator(BucketsPageObjectsV2.CONFIRM_BUTTON_DELETE_BUCKET_FLOW_XPATH).click();
await expect(this.page.getByRole('button', { name: `Bucket ${name}` })).toBeHidden();
}
}
10 changes: 9 additions & 1 deletion testsuite/playwright-ui/pageFactory/pageRepository/Common.ts
Expand Up @@ -2,7 +2,7 @@
// See LICENSE for copying information.

import { expect, Page } from '@playwright/test';
import { CommonObjects } from '@objects/CommonObjects';
import { CommonObjects, CommonObjectsV2 } from '@objects/CommonObjects';
import { testConfig } from '../../testConfig';

export class Common {
Expand All @@ -23,3 +23,11 @@ export class Common {
}
}
}

export class CommonV2 {
constructor(readonly page: Page) {}

async closeModal(): Promise<void> {
await this.page.locator(CommonObjectsV2.CLOSE_MODAL_BUTTON_XPATH).click();
}
}
Expand Up @@ -65,4 +65,8 @@ export class LoginPageV2 {
const label = this.page.locator(LoginPageObjectsV2.SETUP_SUCCESS_LABEL_XPATH);
await expect(label).toBeVisible();
}

async finishSetup(): Promise<void> {
await this.page.locator(LoginPageObjectsV2.CONTINUE_BUTTON_XPATH).nth(1).click();
}
}
@@ -1,7 +1,7 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.

import { NavigationMenuObject } from '@objects/NavigationMenuObject';
import { NavigationMenuObject, NavigationMenuObjectV2 } from '@objects/NavigationMenuObject';
import type { Page } from '@playwright/test';

export class NavigationMenu {
Expand All @@ -11,3 +11,19 @@ export class NavigationMenu {
await this.page.locator(NavigationMenuObject.BUCKETS_XPATH).click();
}
}

export class NavigationMenuV2 {
constructor(readonly page: Page) {}

async clickOnBuckets(): Promise<void> {
await this.page.locator(NavigationMenuObjectV2.BUCKETS_XPATH).click();
}

async switchPassphrase(passphrase: string): Promise<void> {
await this.page.locator(NavigationMenuObjectV2.PROJECT_SELECT_XPATH).click();
await this.page.locator(NavigationMenuObjectV2.MANAGE_PASSPHRASE_ACTION_XPATH).click();
await this.page.locator(NavigationMenuObjectV2.SWITCH_PASSPHRASE_ACTION_XPATH).click();
await this.page.locator(NavigationMenuObjectV2.PASSPHRASE_INPUT_XPATH).fill(passphrase);
await this.page.locator(NavigationMenuObjectV2.CONFIRM_SWITCH_PASSPHRASE_BUTTON_XPATH).click();
}
}
@@ -0,0 +1,87 @@
// Copyright (C) 2024 Storj Labs, Inc.
// See LICENSE for copying information.

import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
import { ObjectBrowserPageObjects } from '@objects/ObjectBrowserPageObjects';
import { CommonObjectsV2 } from '@objects/CommonObjects';

export class ObjectBrowserPage {
constructor(readonly page: Page) {}

async waitLoading(): Promise<void> {
const loader = this.page.locator(ObjectBrowserPageObjects.LOADING_ITEMS_LABEL_XPATH);
await expect(loader).toBeHidden();
}

async uploadFile(name: string, format: string): Promise<void> {
await this.page.setInputFiles(ObjectBrowserPageObjects.FILE_INPUT_XPATH, {
name: name,
mimeType: format,
buffer: Buffer.from('Test,T'),
}, { strict: true });
}

async uploadFolder(folder: string, filename: string, format: string): Promise<void> {
await this.page.setInputFiles(ObjectBrowserPageObjects.FOLDER_INPUT_XPATH, {
name: folder + '/' + filename,
mimeType: format,
buffer: Buffer.from('Test,T'),
});
await expect(this.page.getByRole('button', { name: `Foldericon ${folder}` })).toBeVisible();
}

async openObjectPreview(name: string, type: string): Promise<void> {
const uiTestFile = this.page.getByRole('button', { name: `${type}icon ${name}` });
await expect(uiTestFile).toBeVisible();
await uiTestFile.click();
}

async closePreview(name: string): Promise<void> {
await this.page.locator('header').filter({ hasText: name }).locator('#Close').click();
}

async downloadFromPreview(): Promise<void> {
await Promise.all([
this.page.waitForEvent('download'),
this.page.locator(ObjectBrowserPageObjects.DOWNLOAD_BUTTON_XPATH).click(),
]);
await expect(this.page.getByText('Keep this download link private.')).toBeVisible();
}

async verifyObjectMapIsVisible(): Promise<void> {
await this.page.locator(ObjectBrowserPageObjects.DISTRIBUTION_BUTTON_XPATH).click();
await this.page.locator(ObjectBrowserPageObjects.OBJECT_MAP_IMAGE_XPATH).isVisible();
await this.page.locator(CommonObjectsV2.CLOSE_MODAL_BUTTON_XPATH).nth(1).click();
}

async verifyShareLink(): Promise<void> {
await this.page.locator(ObjectBrowserPageObjects.SHARE_BUTTON_XPATH).click();
const loader = this.page.locator(ObjectBrowserPageObjects.SHARE_MODAL_LOADER_CLASS);
await expect(loader).toBeHidden();
await this.page.locator(ObjectBrowserPageObjects.COPY_LINK_BUTTON_XPATH).click();
await this.page.locator('span').filter({ hasText: ObjectBrowserPageObjects.COPIED_TEXT }).isVisible();
await this.page.locator(CommonObjectsV2.CLOSE_MODAL_BUTTON_XPATH).nth(1).click();
}

async deleteSingleObject(): Promise<void> {
await this.page.locator(ObjectBrowserPageObjects.OBJECT_ROW_MORE_BUTTON_XPATH).click();
await this.page.locator(ObjectBrowserPageObjects.DELETE_ROW_ACTION_BUTTON_XPATH).click();
await this.page.locator(ObjectBrowserPageObjects.CONFIRM_DELETE_BUTTON_XPATH).click();
}

async deleteObjectByName(name: string, type: string): Promise<void> {
await this.deleteSingleObject();
await this.page.getByRole('button', { name: `${type}icon ${name}` }).waitFor({ state: 'hidden' });
}

async createFolder(folderName: string): Promise<void> {
await this.page.locator(ObjectBrowserPageObjects.CREATE_FOLDER_BUTTON_XPATH).click();
await this.page.locator(ObjectBrowserPageObjects.FOLDER_NAME_INPUT_XPATH).fill(folderName);
await this.page.locator(ObjectBrowserPageObjects.CONFIRM_CREATE_FOLDER_BUTTON_XPATH).click();
}

async verifyImagePreviewIsVisible(): Promise<void> {
await this.page.getByRole('img', { name: 'preview' }).isVisible();
}
}
2 changes: 1 addition & 1 deletion testsuite/playwright-ui/playwright.config.ts
Expand Up @@ -99,7 +99,7 @@ export default defineConfig({
],
retries: process.env.CI ? 1 : 0, // Retry on CI only.
testDir: './tests', // Directory where tests are located.
timeout: 10 * 1000, // Maximum time one test can run for.
timeout: 20 * 1000, // Maximum time one test can run for.
use: {
actionTimeout: 0, // Maximum time each action can take.
// baseURL: 'http://127.0.0.1:10000',
Expand Down

0 comments on commit 9648e03

Please sign in to comment.