mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
8.1 KiB
221 lines
8.1 KiB
import BasePage from '../Base'; |
|
import { WorkspacePage } from './'; |
|
import { expect } from '@playwright/test'; |
|
import { Locator } from '@playwright/test'; |
|
import { getTextExcludeIconText } from '../../tests/utils/general'; |
|
|
|
/* |
|
nc-workspace-settings |
|
nc-workspace-avatar |
|
nc-workspace-title |
|
button:has-text("New Project") |
|
|> .ant-dropdown-menu-vertical |
|
|> .ant-dropdown-menu-item : Database nc-create-project-btn-db |
|
nc-shortcut-label-wrapper.nc-shortcut-label |
|
|> .ant-dropdown-menu-item : Documentation nc-create-project-btn-docs |
|
nc-shortcut-label-wrapper.nc-shortcut-label |
|
|
|
ant-tabs-nav-list |
|
ant-tabs-tab : All Projects |
|
ant-tabs-tab : Collaborators |
|
|
|
thead.ant-table-thead |
|
tr.ant-table-row |
|
td.ant-table-cell (nc-project-title) |
|
material-symbols : database |
|
span : project title |
|
nc-icon : favourites icon |
|
td.ant-table-cell (color) |
|
td.ant-table-cell (last accessed) |
|
td.ant-table-cell (my role) |
|
td.ant-table-cell (actions) |
|
nc-icon (...) : click |
|
|> .ant-dropdown-menu-item : Rename Project |
|
|> .ant-dropdown-menu-item : Move Project |
|
|> .ant-dropdown-menu-item : Delete Project |
|
*/ |
|
|
|
export class ContainerPage extends BasePage { |
|
readonly workspace: WorkspacePage; |
|
readonly newProjectButton: Locator; |
|
|
|
// tabs |
|
readonly projects: Locator; |
|
readonly collaborators: Locator; |
|
readonly billing: Locator; |
|
readonly settings: Locator; |
|
|
|
// list |
|
readonly moreActions: Locator; |
|
|
|
constructor(workspace: WorkspacePage) { |
|
super(workspace.rootPage); |
|
this.workspace = workspace; |
|
this.newProjectButton = this.get().locator('button:has-text("New Project")'); |
|
|
|
// tabs |
|
this.projects = this.get().locator('.ant-tabs-tab:has-text("Projects")'); |
|
this.collaborators = this.get().locator('.ant-tabs-tab:has-text("Members")'); |
|
this.billing = this.get().locator('.ant-tabs-tab:has-text("Billing")'); |
|
this.settings = this.get().locator('.ant-tabs-tab:has-text("Settings")'); |
|
|
|
// list |
|
this.moreActions = this.get().locator('td.ant-table-cell >> .nc-workspace-menu'); |
|
} |
|
|
|
get() { |
|
return this.workspace.get().locator('.nc-workspace-settings'); |
|
} |
|
|
|
async waitFor({ state }) { |
|
await this.get().waitFor({ state }); |
|
} |
|
|
|
async verifyStaticElements() { |
|
const tableHeaderCells = this.get().locator('.ant-table-thead > tr > th.ant-table-cell'); |
|
expect(await tableHeaderCells.count()).toBe(5); |
|
expect(await tableHeaderCells.nth(0).innerText()).toBe('Project Name'); |
|
expect(await tableHeaderCells.nth(1).innerText()).toBe('Role'); |
|
expect(await tableHeaderCells.nth(2).innerText()).toBe('Last Opened'); |
|
// actions column |
|
expect(await tableHeaderCells.nth(3).innerText()).toBe(''); |
|
|
|
const tabs = this.get().locator('.ant-tabs-tab-btn'); |
|
expect(await tabs.count()).toBe(3); |
|
await expect(this.projects).toBeVisible(); |
|
await expect(this.collaborators).toBeVisible(); |
|
await expect(this.billing).toBeVisible(); |
|
|
|
await expect(this.newProjectButton).toBeVisible(); |
|
} |
|
|
|
async getProjectRowData({ index, skipWs = false }: { index: number; skipWs: boolean }) { |
|
const rows = this.get().locator('.ant-table-tbody > tr.ant-table-row'); |
|
const title = await getTextExcludeIconText(rows.nth(index).locator('.nc-project-title')); |
|
const role = await rows |
|
.nth(index) |
|
.locator('.ant-table-cell') |
|
.nth(1 + (skipWs ? 1 : 0)) |
|
.innerText(); |
|
const lastAccessed = await rows |
|
.nth(index) |
|
.locator('.ant-table-cell') |
|
.nth(2 + (skipWs ? 1 : 0)) |
|
.innerText(); |
|
return { title, lastAccessed, role }; |
|
} |
|
|
|
// returns row locator based on project title |
|
// |
|
async getProjectRow({ title }: { title: string }) { |
|
const titles = []; |
|
const rows = this.get().locator('.ant-table-tbody > tr.ant-table-row'); |
|
const count = await rows.count(); |
|
|
|
for (let i = 0; i < count; i++) { |
|
titles.push(await getTextExcludeIconText(rows.nth(i).locator('.nc-project-title'))); |
|
} |
|
|
|
return rows.nth(titles.indexOf(title)); |
|
} |
|
|
|
// returns number of project rows |
|
// |
|
async getProjectRowCount() { |
|
const rows = this.get().locator('.ant-table-tbody > tr.ant-table-row'); |
|
return await rows.count(); |
|
} |
|
|
|
async verifyDynamicElements({ title, lastAccessed, role }) { |
|
expect(await this.get().locator('.nc-workspace-title').innerText()).toBe(`ws_${title}`); |
|
expect(await this.getProjectRowData({ index: 0, skipWs: false })).toEqual({ title, lastAccessed, role }); |
|
} |
|
|
|
// create project |
|
// |
|
async projectCreate({ title, type }: { title: string; type: 'db' | 'docs' }) { |
|
await this.newProjectButton.click(); |
|
await this.rootPage.locator(`.nc-create-project-btn-${type}`).click(); |
|
await this.rootPage.locator('.nc-metadb-project-name').fill(title); |
|
await this.waitForResponse({ |
|
uiAction: () => this.rootPage.locator('.nc-metadb-project-name').press('Enter'), |
|
httpMethodsToMatch: ['POST'], |
|
requestUrlPathToMatch: `api/v1/db/meta/projects`, |
|
}); |
|
} |
|
|
|
// rename project |
|
// |
|
async projectRename({ title, newTitle }: { title: string; newTitle: string }) { |
|
const row = await this.getProjectRow({ title }); |
|
await row.locator('td.ant-table-cell').nth(4).locator('.nc-icon').click(); |
|
await this.rootPage.locator('.ant-dropdown-menu-item:has-text("Rename Project")').click(); |
|
await row.locator('td.ant-table-cell').nth(0).locator('input').fill(newTitle); |
|
await this.waitForResponse({ |
|
uiAction: () => row.locator('td.ant-table-cell').nth(0).locator('input').press('Enter'), |
|
httpMethodsToMatch: ['PATCH'], |
|
requestUrlPathToMatch: `api/v1/db/meta/projects/`, |
|
}); |
|
} |
|
|
|
// move project |
|
// |
|
async projectMove({ title, newWorkspace }: { title: string; newWorkspace: string }) { |
|
const row = await this.getProjectRow({ title }); |
|
await row.locator('td.ant-table-cell').nth(4).locator('.nc-icon').click(); |
|
await this.rootPage.locator('.ant-dropdown-menu-item:has-text("Move Project")').click(); |
|
|
|
await this.rootPage.locator('.ant-modal.active').locator('input').click(); |
|
await this.rootPage.locator('.ant-select-dropdown').locator(`.ant-select-item:has-text("${newWorkspace}")`).click(); |
|
|
|
await this.waitForResponse({ |
|
uiAction: () => this.rootPage.locator('.ant-modal.active').locator('button:has-text("Move")').click(), |
|
httpMethodsToMatch: ['GET'], |
|
requestUrlPathToMatch: `/api/v1/workspaces/`, |
|
}); |
|
} |
|
|
|
// delete project |
|
// |
|
async projectDelete({ title }: { title: string }) { |
|
await this.rootPage.waitForTimeout(1000); |
|
const row = await this.getProjectRow({ title }); |
|
await row.locator('td.ant-table-cell').nth(3).locator('.nc-icon').click(); |
|
await this.rootPage.locator('.ant-dropdown-menu-item:has-text("Delete")').click(); |
|
await this.waitForResponse({ |
|
uiAction: () => this.rootPage.locator('.ant-modal-content').locator('button:has-text("Delete")').click(), |
|
httpMethodsToMatch: ['DELETE'], |
|
requestUrlPathToMatch: `api/v1/db/meta/projects/`, |
|
}); |
|
} |
|
|
|
async projectOpen(param: { title: any }) { |
|
const row = await this.getProjectRow({ title: param.title }); |
|
|
|
// use index 1, as 0 contains icon to mark favourite |
|
await row.locator('td.ant-table-cell').nth(1).waitFor({ state: 'visible' }); |
|
await row.locator('td.ant-table-cell').nth(1).click(); |
|
} |
|
|
|
async projectAddToFavourites({ title }: { title: string }) { |
|
const row = await this.getProjectRow({ title }); |
|
await row.locator('td.ant-table-cell').nth(0).locator('.nc-icon').click({ force: true }); |
|
} |
|
|
|
async getMoreActionsSubMenuDetails() { |
|
await this.moreActions.click(); |
|
const menuItems = await this.rootPage.locator('.ant-dropdown-menu-item'); |
|
const count = await menuItems.count(); |
|
const menuItemsText = []; |
|
for (let i = 0; i < count; i++) { |
|
menuItemsText.push(await menuItems.nth(i).innerText()); |
|
} |
|
return menuItemsText; |
|
} |
|
|
|
async deleteWorkspace({ title }: { title: string }) { |
|
await this.get().locator('.ant-checkbox-input').click(); |
|
await this.get().locator('.ant-btn-danger:visible').waitFor(); |
|
await this.get().locator('.ant-btn-danger:visible').click(); |
|
} |
|
}
|
|
|