Browse Source

fix: Integarted new pw setup changes to OSS

pull/6414/head
Muhammed Mustafa 1 year ago
parent
commit
3c11b4a9f8
  1. 72
      tests/playwright/pages/Dashboard/TreeView.ts
  2. 7
      tests/playwright/pages/Dashboard/common/Cell/index.ts
  3. 5
      tests/playwright/pages/Dashboard/common/LeftSidebar/index.ts
  4. 2
      tests/playwright/quickTests/commonTest.ts
  5. 2
      tests/playwright/setup/index.ts
  6. 1
      tests/playwright/tests/db/columns/columnLinkToAnotherRecord.spec.ts
  7. 1
      tests/playwright/tests/db/features/baseShare.spec.ts
  8. 2
      tests/playwright/tests/db/features/erd.spec.ts
  9. 8
      tests/playwright/tests/db/features/import.spec.ts
  10. 4
      tests/playwright/tests/db/features/metaLTAR.spec.ts
  11. 34
      tests/playwright/tests/db/general/projectOperations.spec.ts
  12. 2
      tests/playwright/tests/db/general/tableOperations.spec.ts
  13. 2
      tests/playwright/tests/db/views/viewForm.spec.ts

72
tests/playwright/pages/Dashboard/TreeView.ts

@ -1,6 +1,8 @@
import { expect, Locator } from '@playwright/test';
import { DashboardPage } from '.';
import BasePage from '../Base';
import { NcContext } from '../../setup';
import { isEE } from '../../setup/db';
export class TreeViewPage extends BasePage {
readonly dashboard: DashboardPage;
@ -25,7 +27,7 @@ export class TreeViewPage extends BasePage {
.locator('[data-testid="nc-sidebar-add-project-entity"]');
}
getProjectContextMenu({ projectTitle }: { projectTitle: string }) {
private getProjectContextMenu({ projectTitle }: { projectTitle: string }) {
return this.dashboard
.get()
.getByTestId(`nc-sidebar-project-title-${projectTitle}`)
@ -214,7 +216,9 @@ export class TreeViewPage extends BasePage {
await settingsMenu.locator(`.nc-sidebar-project-project-settings`).click();
}
async quickImport({ title, projectTitle }: { title: string; projectTitle: string }) {
async quickImport({ title, projectTitle, context }: { title: string; projectTitle: string; context: NcContext }) {
projectTitle = this.scopedProjectTitle({ title: projectTitle, context });
await this.getProjectContextMenu({ projectTitle }).hover();
await this.getProjectContextMenu({ projectTitle }).click();
const importMenu = this.dashboard.get().locator('.ant-dropdown-menu');
@ -269,9 +273,12 @@ export class TreeViewPage extends BasePage {
).toHaveCount(1);
}
async validateRoleAccess(param: { role: string; projectTitle?: string; tableTitle?: string }) {
async validateRoleAccess(param: { role: string; projectTitle?: string; tableTitle?: string; context: NcContext }) {
const context = param.context;
param.projectTitle = param.projectTitle ?? context.project.title;
const count = param.role.toLowerCase() === 'creator' || param.role.toLowerCase() === 'owner' ? 1 : 0;
const pjtNode = await this.getProject({ index: 0, title: param.projectTitle });
const pjtNode = await this.getProject({ title: param.projectTitle });
await pjtNode.hover();
// add new table button & context menu is visible only for owner & creator
@ -284,59 +291,46 @@ export class TreeViewPage extends BasePage {
await expect(tblNode.locator('.nc-tbl-context-menu')).toHaveCount(count);
}
async openProject({ title, projectCount }: { title: string; projectCount?: number }) {
const nodes = this.get().locator(`.project-title-node`);
// at times, page is not rendered yet when trying to open project
// hence retry logic to wait for expected number of projects to be available
if (projectCount) {
let retryCount = 0;
while (retryCount < 5) {
if ((await nodes.count()) === projectCount) break;
await this.rootPage.waitForTimeout(retryCount * 500);
retryCount++;
}
}
async openProject({ title, context }: { title: string; context: NcContext }) {
title = this.scopedProjectTitle({ title, context });
// loop through nodes.count() to find the node with title
for (let i = 0; i < (await nodes.count()); i++) {
const node = nodes.nth(i);
const nodeTitle = await node.innerText();
// check if nodeTitle contains title
if (nodeTitle.toLowerCase().includes(title.toLowerCase())) {
// click on node
await node.waitFor({ state: 'visible' });
await node.click();
break;
}
}
await this.get().getByTestId(`nc-sidebar-project-title-${title}`).click();
await this.rootPage.waitForTimeout(1000);
}
private async getProject(param: { index: number; title?: string }) {
if (param.title) {
return this.get().getByTestId(`nc-sidebar-project-title-${param.title}`);
}
scopedProjectTitle({ title, context }: { title: string; context: NcContext }) {
if (isEE()) return title;
return this.get().locator(`.project-title-node`).nth(param.index);
if (title.toLowerCase().startsWith('xcdb')) return `${title}`;
return title === context.project.title ? context.project.title : `nc-${context.workerId}-${title}`;
}
private async getProject(param: { title?: string }) {
return this.get().getByTestId(`nc-sidebar-project-title-${param.title}`);
}
async renameProject(param: { newTitle: string; title: string }) {
async renameProject(param: { newTitle: string; title: string; context: NcContext }) {
param.title = this.scopedProjectTitle({ title: param.title, context: param.context });
param.newTitle = this.scopedProjectTitle({ title: param.newTitle, context: param.context });
await this.getProjectContextMenu({ projectTitle: param.title }).hover();
await this.getProjectContextMenu({ projectTitle: param.title }).click();
const contextMenu = this.dashboard.get().locator('.ant-dropdown-menu.nc-scrollbar-md:visible').last();
await contextMenu.waitFor();
await contextMenu.locator(`.ant-dropdown-menu-item:has-text("Rename")`).click();
const projectNodeInput = (await this.getProject({ index: 0, title: param.title })).locator('input');
const projectNodeInput = (await this.getProject({ title: param.title })).locator('input');
await projectNodeInput.clear();
await projectNodeInput.fill(param.newTitle);
await projectNodeInput.press('Enter');
}
async deleteProject(param: { title: string }) {
async deleteProject(param: { title: string; context: NcContext }) {
param.title = this.scopedProjectTitle({ title: param.title, context: param.context });
await this.getProjectContextMenu({ projectTitle: param.title }).hover();
await this.getProjectContextMenu({ projectTitle: param.title }).click();
const contextMenu = this.dashboard.get().locator('.ant-dropdown-menu.nc-scrollbar-md:visible').last();
@ -346,7 +340,9 @@ export class TreeViewPage extends BasePage {
await this.rootPage.locator('div.ant-modal-content').locator(`button.ant-btn:has-text("Delete")`).click();
}
async duplicateProject(param: { title: string }) {
async duplicateProject(param: { title: string; context: NcContext }) {
param.title = this.scopedProjectTitle({ title: param.title, context: param.context });
await this.getProjectContextMenu({ projectTitle: param.title }).hover();
await this.getProjectContextMenu({ projectTitle: param.title }).click();
const contextMenu = this.dashboard.get().locator('.ant-dropdown-menu.nc-scrollbar-md:visible');

7
tests/playwright/pages/Dashboard/common/Cell/index.ts

@ -366,10 +366,9 @@ export class CellPageObject extends BasePage {
await cell.locator('.nc-datatype-link').click();
await this.waitForResponse({
uiAction: async () =>
this.rootPage
.locator(`[data-testid="nc-child-list-item"]`)
.nth((await this.rootPage.locator(`[data-testid="nc-child-list-item"]`).count()) - 1)
.click(),
this.rootPage.locator(`[data-testid="nc-child-list-item"]`).last().click({
force: true,
}),
requestUrlPathToMatch: '/api/v1/db/data/noco/',
httpMethodsToMatch: ['GET'],
});

5
tests/playwright/pages/Dashboard/common/LeftSidebar/index.ts

@ -2,6 +2,8 @@ import { Locator } from '@playwright/test';
import { DashboardPage } from '../../index';
import BasePage from '../../../Base';
import { getTextExcludeIconText } from '../../../../tests/utils/general';
import { isEE } from '../../../../setup/db';
import { NcContext } from '../../../../setup';
export class LeftSidebarPage extends BasePage {
readonly project: any;
@ -30,7 +32,8 @@ export class LeftSidebarPage extends BasePage {
return this.dashboard.get().locator('.nc-sidebar');
}
async createProject({ title }: { title: string }) {
async createProject({ title, context }: { title: string; context: NcContext }) {
title = isEE() ? title : `nc-${context.workerId}-${title}`;
await this.btn_newProject.click();
await this.rootPage.locator('.ant-modal-content:has-text(" Create Database")').waitFor();
await this.rootPage.locator('.ant-modal-content:has-text(" Create Database")').locator('input').fill(title);

2
tests/playwright/quickTests/commonTest.ts

@ -249,7 +249,7 @@ const quickVerify = async ({
// await dashboard.clickHome();
// const workspacePage = new WorkspacePage(dashboard.rootPage);
// await workspacePage.projectDelete({ title: context.project.title });
await dashboard.treeView.deleteProject({ title: context.project.title });
await dashboard.treeView.deleteProject({ title: context.project.title, context });
}
};

2
tests/playwright/setup/index.ts

@ -244,7 +244,7 @@ async function localInit({
for (const p of projects.list) {
// check if p.title starts with projectTitle
if (
p.title.startsWith(`pgExtREST_p${process.env.TEST_PARALLEL_INDEX}`) ||
p.title.startsWith(`pgExtREST${process.env.TEST_PARALLEL_INDEX}`) ||
p.title.startsWith(`xcdb_p${process.env.TEST_PARALLEL_INDEX}`)
) {
try {

1
tests/playwright/tests/db/columns/columnLinkToAnotherRecord.spec.ts

@ -170,6 +170,7 @@ test.describe('LTAR create & update', () => {
// Unlink LTAR cells
for (let i = 0; i < expected2.length; i++) {
for (let j = 0; j < expected2[i].length; j++) {
await dashboard.rootPage.waitForTimeout(500);
await dashboard.grid.cell.unlinkVirtualCell({
index: j,
columnHeader: colHeaders2[i],

1
tests/playwright/tests/db/features/baseShare.spec.ts

@ -35,6 +35,7 @@ test.describe('Shared base', () => {
await dashboard.treeView.validateRoleAccess({
role: role.toLowerCase(),
context,
});
await dashboard.grid.verifyRoleAccess({

2
tests/playwright/tests/db/features/erd.spec.ts

@ -279,7 +279,7 @@ test.describe('Erd', () => {
// Create table and verify ERD
await dashboard.treeView.createTable({ title: 'Test', projectTitle: context.project.title });
// Verify in Settings ERD and table ERD
await dashboard.treeView.openProject({ title: context.project.title });
await dashboard.treeView.openProject({ title: context.project.title, context });
await openProjectErd();
await dashboard.details.relations.verifyNode({
tableName: `Test`,

8
tests/playwright/tests/db/features/import.spec.ts

@ -21,7 +21,7 @@ test.describe('Import', () => {
});
test('Airtable', async () => {
await dashboard.treeView.quickImport({ title: 'Airtable', projectTitle: context.project.title });
await dashboard.treeView.quickImport({ title: 'Airtable', projectTitle: context.project.title, context });
await dashboard.importAirtable.import({
key: airtableApiKey,
baseId: airtableApiBase,
@ -31,7 +31,7 @@ test.describe('Import', () => {
});
test('CSV', async () => {
await dashboard.treeView.quickImport({ title: 'CSV file', projectTitle: context.project.title });
await dashboard.treeView.quickImport({ title: 'CSV file', projectTitle: context.project.title, context });
});
test('Excel', async () => {
@ -46,7 +46,7 @@ test.describe('Import', () => {
{ name: 'Sheet4', columns: col },
];
await dashboard.treeView.quickImport({ title: 'Microsoft Excel', projectTitle: context.project.title });
await dashboard.treeView.quickImport({ title: 'Microsoft Excel', projectTitle: context.project.title, context });
await dashboard.importTemplate.import({
file: `${process.cwd()}/fixtures/sampleFiles/simple.xlsx`,
result: expected,
@ -66,6 +66,6 @@ test.describe('Import', () => {
});
test('JSON', async () => {
await dashboard.treeView.quickImport({ title: 'JSON file', projectTitle: context.project.title });
await dashboard.treeView.quickImport({ title: 'JSON file', projectTitle: context.project.title, context });
});
});

4
tests/playwright/tests/db/features/metaLTAR.spec.ts

@ -58,7 +58,7 @@ test.describe.serial('Test table', () => {
// create a new xcdb project
const xcdb = await createXcdb(context);
await dashboard.rootPage.reload();
await dashboard.treeView.openProject({ title: 'Xcdb', projectCount: 2 });
await dashboard.treeView.openProject({ title: 'xcdb', context });
api = new Api({
baseURL: `http://localhost:8080/`,
@ -216,7 +216,7 @@ test.describe.serial('Test table', () => {
});
test('Delete record - single, over UI', async () => {
await dashboard.treeView.openProject({ title: 'Xcdb', projectCount: 2 });
await dashboard.treeView.openProject({ title: 'xcdb', context });
await dashboard.treeView.openTable({ title: 'Table0' });
await grid.deleteRow(0);

34
tests/playwright/tests/db/general/projectOperations.spec.ts

@ -13,7 +13,7 @@ test.describe('Project operations', () => {
let api: Api<any>;
test.setTimeout(100000);
async function getProjectList(workspaceId: string) {
async function getProjectList(workspaceId?: string) {
let projectList: ProjectListType;
if (isEE() && api['workspaceProject']) {
projectList = await api['workspaceProject'].list(workspaceId);
@ -25,9 +25,9 @@ test.describe('Project operations', () => {
}
async function createTestProjectWithData(testProjectName: string) {
await dashboard.leftSidebar.createProject({ title: testProjectName });
await dashboard.treeView.openProject({ title: testProjectName });
await dashboard.treeView.quickImport({ title: 'Airtable', projectTitle: testProjectName });
await dashboard.leftSidebar.createProject({ title: testProjectName, context });
await dashboard.treeView.openProject({ title: testProjectName, context });
await dashboard.treeView.quickImport({ title: 'Airtable', projectTitle: testProjectName, context });
await dashboard.importAirtable.import({
key: airtableApiKey,
baseId: airtableApiBase,
@ -36,8 +36,8 @@ test.describe('Project operations', () => {
}
async function cleanupTestData(dupeProjectName: string, testProjectName: string) {
await dashboard.treeView.deleteProject({ title: dupeProjectName });
await dashboard.treeView.deleteProject({ title: testProjectName });
await dashboard.treeView.deleteProject({ title: dupeProjectName, context });
await dashboard.treeView.deleteProject({ title: testProjectName, context });
}
test.beforeEach(async ({ page }) => {
@ -58,29 +58,33 @@ test.describe('Project operations', () => {
});
test('rename, delete', async () => {
await dashboard.leftSidebar.createProject({ title: 'project-firstName' });
await dashboard.treeView.renameProject({ title: 'project-firstName', newTitle: 'project-rename' });
await dashboard.treeView.openProject({ title: 'project-rename' });
await dashboard.treeView.deleteProject({ title: 'project-rename' });
await dashboard.leftSidebar.createProject({ title: 'project-firstName', context });
await dashboard.treeView.renameProject({ title: 'project-firstName', newTitle: 'project-rename', context });
await dashboard.treeView.openProject({ title: 'project-rename', context });
await dashboard.treeView.deleteProject({ title: 'project-rename', context });
});
test('project_duplicate', async () => {
// if project already exists, delete it to avoid test failures due to residual data
const random = Math.floor(Math.random() * 1000000);
const testProjectName = `Project-To-Import-Export-${random}`;
const scopedProjectName = dashboard.treeView.scopedProjectTitle({
title: testProjectName,
context,
});
// // data creation for original test project
await createTestProjectWithData(testProjectName);
// duplicate duplicate
await dashboard.treeView.duplicateProject({ title: testProjectName });
await dashboard.treeView.openProject({ title: testProjectName });
await dashboard.treeView.duplicateProject({ title: testProjectName, context });
await dashboard.treeView.openProject({ title: testProjectName, context });
// compare
const projectList = await getProjectList(context.workspace.id);
const projectList = await getProjectList(context.workspace?.id);
const testProjectId = projectList.list.find((p: any) => p.title === testProjectName);
const dupeProjectId = projectList.list.find((p: any) => p.title.startsWith(testProjectName + ' copy'));
const testProjectId = projectList.list.find((p: any) => p.title === scopedProjectName);
const dupeProjectId = projectList.list.find((p: any) => p.title.startsWith(scopedProjectName + ' copy'));
const projectInfoOp: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token);
const original: Promise<ProjectInfo> = projectInfoOp.extractProjectInfo(testProjectId.id);
const duplicate: Promise<ProjectInfo> = projectInfoOp.extractProjectInfo(dupeProjectId.id);

2
tests/playwright/tests/db/general/tableOperations.spec.ts

@ -31,7 +31,7 @@ test.describe('Table Operations', () => {
if (!isEE()) {
// Audit logs in clickhouse; locally wont be accessible
await dashboard.treeView.openProject({ title: context.project.title });
await dashboard.treeView.openProject({ title: context.project.title, context });
await dashboard.projectView.tab_dataSources.click();
await dashboard.projectView.dataSources.openAudit({ rowIndex: 0 });

2
tests/playwright/tests/db/views/viewForm.spec.ts

@ -381,7 +381,7 @@ test.describe('Form view with LTAR', () => {
await dashboard.leftSidebar.openWorkspace({ title: context.workspace.title });
await dashboard.rootPage.waitForTimeout(500);
}
await dashboard.treeView.openProject({ title: context.project.title });
await dashboard.treeView.openProject({ title: context.project.title, context });
await dashboard.rootPage.waitForTimeout(500);
await dashboard.treeView.openTable({ title: 'Country' });

Loading…
Cancel
Save