Browse Source

Merge pull request #6414 from nocodb/nc-fix/pw-upgrade-and-reset-logic-cleanup

Pw upgrade and reset logic cleanup
pull/6427/head
Muhammed Mustafa 1 year ago committed by GitHub
parent
commit
9be5855122
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      tests/playwright/pages/Dashboard/Gallery/index.ts
  2. 74
      tests/playwright/pages/Dashboard/TreeView.ts
  3. 7
      tests/playwright/pages/Dashboard/common/Cell/index.ts
  4. 5
      tests/playwright/pages/Dashboard/common/LeftSidebar/index.ts
  5. 2
      tests/playwright/quickTests/commonTest.ts
  6. 65
      tests/playwright/setup/index.ts
  7. 2
      tests/playwright/setup/knexHelper.ts
  8. 1
      tests/playwright/tests/db/columns/columnLinkToAnotherRecord.spec.ts
  9. 1
      tests/playwright/tests/db/features/baseShare.spec.ts
  10. 2
      tests/playwright/tests/db/features/erd.spec.ts
  11. 8
      tests/playwright/tests/db/features/import.spec.ts
  12. 4
      tests/playwright/tests/db/features/metaLTAR.spec.ts
  13. 64
      tests/playwright/tests/db/general/projectOperations.spec.ts
  14. 2
      tests/playwright/tests/db/general/tableOperations.spec.ts
  15. 2
      tests/playwright/tests/db/views/viewForm.spec.ts

7
tests/playwright/pages/Dashboard/Gallery/index.ts

@ -24,7 +24,12 @@ export class GalleryPage extends BasePage {
} }
async openExpandedRow({ index }: { index: number }) { async openExpandedRow({ index }: { index: number }) {
await this.card(index).click(); await this.card(index).click({
position: {
x: 1,
y: 1,
},
});
await (await this.rootPage.locator('.ant-drawer-body').elementHandle())?.waitForElementState('stable'); await (await this.rootPage.locator('.ant-drawer-body').elementHandle())?.waitForElementState('stable');
} }

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

@ -1,6 +1,8 @@
import { expect, Locator } from '@playwright/test'; import { expect, Locator } from '@playwright/test';
import { DashboardPage } from '.'; import { DashboardPage } from '.';
import BasePage from '../Base'; import BasePage from '../Base';
import { NcContext } from '../../setup';
import { isEE } from '../../setup/db';
export class TreeViewPage extends BasePage { export class TreeViewPage extends BasePage {
readonly dashboard: DashboardPage; readonly dashboard: DashboardPage;
@ -25,7 +27,7 @@ export class TreeViewPage extends BasePage {
.locator('[data-testid="nc-sidebar-add-project-entity"]'); .locator('[data-testid="nc-sidebar-add-project-entity"]');
} }
getProjectContextMenu({ projectTitle }: { projectTitle: string }) { private getProjectContextMenu({ projectTitle }: { projectTitle: string }) {
return this.dashboard return this.dashboard
.get() .get()
.getByTestId(`nc-sidebar-project-title-${projectTitle}`) .getByTestId(`nc-sidebar-project-title-${projectTitle}`)
@ -214,7 +216,9 @@ export class TreeViewPage extends BasePage {
await settingsMenu.locator(`.nc-sidebar-project-project-settings`).click(); 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 }).hover();
await this.getProjectContextMenu({ projectTitle }).click(); await this.getProjectContextMenu({ projectTitle }).click();
const importMenu = this.dashboard.get().locator('.ant-dropdown-menu'); const importMenu = this.dashboard.get().locator('.ant-dropdown-menu');
@ -269,9 +273,12 @@ export class TreeViewPage extends BasePage {
).toHaveCount(1); ).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 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(); await pjtNode.hover();
// add new table button & context menu is visible only for owner & creator // 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); await expect(tblNode.locator('.nc-tbl-context-menu')).toHaveCount(count);
} }
async openProject({ title, projectCount }: { title: string; projectCount?: number }) { async openProject({ title, context }: { title: string; context: NcContext }) {
const nodes = this.get().locator(`.project-title-node`); title = this.scopedProjectTitle({ title, context });
// 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++;
}
}
// loop through nodes.count() to find the node with title // loop through nodes.count() to find the node with title
for (let i = 0; i < (await nodes.count()); i++) { await this.get().getByTestId(`nc-sidebar-project-title-${title}`).click();
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.rootPage.waitForTimeout(1000); await this.rootPage.waitForTimeout(1000);
} }
private async getProject(param: { index: number; title?: string }) { scopedProjectTitle({ title, context }: { title: string; context: NcContext }) {
if (param.title) { if (isEE()) return title;
return this.get().getByTestId(`nc-sidebar-project-title-${param.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 }).hover();
await this.getProjectContextMenu({ projectTitle: param.title }).click(); await this.getProjectContextMenu({ projectTitle: param.title }).click();
const contextMenu = this.dashboard.get().locator('.ant-dropdown-menu.nc-scrollbar-md:visible').last(); const contextMenu = this.dashboard.get().locator('.ant-dropdown-menu.nc-scrollbar-md:visible').last();
await contextMenu.waitFor(); await contextMenu.waitFor();
await contextMenu.locator(`.ant-dropdown-menu-item:has-text("Rename")`).click(); 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.clear();
await projectNodeInput.fill(param.newTitle); await projectNodeInput.fill(param.newTitle);
await projectNodeInput.press('Enter'); 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 }).hover();
await this.getProjectContextMenu({ projectTitle: param.title }).click(); await this.getProjectContextMenu({ projectTitle: param.title }).click();
const contextMenu = this.dashboard.get().locator('.ant-dropdown-menu.nc-scrollbar-md:visible').last(); 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(); 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 }).hover();
await this.getProjectContextMenu({ projectTitle: param.title }).click(); await this.getProjectContextMenu({ projectTitle: param.title }).click();
const contextMenu = this.dashboard.get().locator('.ant-dropdown-menu.nc-scrollbar-md:visible'); const contextMenu = this.dashboard.get().locator('.ant-dropdown-menu.nc-scrollbar-md:visible');
@ -354,5 +350,7 @@ export class TreeViewPage extends BasePage {
await contextMenu.locator(`.ant-dropdown-menu-item:has-text("Duplicate")`).click(); await contextMenu.locator(`.ant-dropdown-menu-item:has-text("Duplicate")`).click();
await this.rootPage.locator('div.ant-modal-content').locator(`button.ant-btn:has-text("Confirm")`).click(); await this.rootPage.locator('div.ant-modal-content').locator(`button.ant-btn:has-text("Confirm")`).click();
await this.rootPage.waitForTimeout(10000);
} }
} }

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 cell.locator('.nc-datatype-link').click();
await this.waitForResponse({ await this.waitForResponse({
uiAction: async () => uiAction: async () =>
this.rootPage this.rootPage.locator(`[data-testid="nc-child-list-item"]`).last().click({
.locator(`[data-testid="nc-child-list-item"]`) force: true,
.nth((await this.rootPage.locator(`[data-testid="nc-child-list-item"]`).count()) - 1) }),
.click(),
requestUrlPathToMatch: '/api/v1/db/data/noco/', requestUrlPathToMatch: '/api/v1/db/data/noco/',
httpMethodsToMatch: ['GET'], 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 { DashboardPage } from '../../index';
import BasePage from '../../../Base'; import BasePage from '../../../Base';
import { getTextExcludeIconText } from '../../../../tests/utils/general'; import { getTextExcludeIconText } from '../../../../tests/utils/general';
import { isEE } from '../../../../setup/db';
import { NcContext } from '../../../../setup';
export class LeftSidebarPage extends BasePage { export class LeftSidebarPage extends BasePage {
readonly project: any; readonly project: any;
@ -30,7 +32,8 @@ export class LeftSidebarPage extends BasePage {
return this.dashboard.get().locator('.nc-sidebar'); 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.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")').waitFor();
await this.rootPage.locator('.ant-modal-content:has-text(" Create Database")').locator('input').fill(title); 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(); // await dashboard.clickHome();
// const workspacePage = new WorkspacePage(dashboard.rootPage); // const workspacePage = new WorkspacePage(dashboard.rootPage);
// await workspacePage.projectDelete({ title: context.project.title }); // await workspacePage.projectDelete({ title: context.project.title });
await dashboard.treeView.deleteProject({ title: context.project.title }); await dashboard.treeView.deleteProject({ title: context.project.title, context });
} }
}; };

65
tests/playwright/setup/index.ts

@ -8,9 +8,6 @@ import { isEE } from './db';
import { resetSakilaPg } from './knexHelper'; import { resetSakilaPg } from './knexHelper';
import path from 'path'; import path from 'path';
// Use local reset logic instead of remote
const enableLocalInit = true;
// MySQL Configuration // MySQL Configuration
const mysqlConfig = { const mysqlConfig = {
client: 'mysql2', client: 'mysql2',
@ -217,8 +214,18 @@ async function localInit({
const ws = await api['workspace'].list(); const ws = await api['workspace'].list();
for (const w of ws.list) { for (const w of ws.list) {
// check if w.title starts with workspaceTitle // check if w.title starts with workspaceTitle
if (w.title.startsWith(`ws_pgExtREST_p${process.env.TEST_PARALLEL_INDEX}`)) { if (w.title.startsWith(`ws_pgExtREST${process.env.TEST_PARALLEL_INDEX}`)) {
try { try {
const projects = await api.workspaceProject.list(w.id);
for (const project of projects.list) {
try {
await api.project.delete(project.id);
} catch (e) {
console.log(`Error deleting project: ws delete`, project);
}
}
await api['workspace'].delete(w.id); await api['workspace'].delete(w.id);
} catch (e) { } catch (e) {
console.log(`Error deleting workspace: ${w.id}`, `user-${parallelId}@nocodb.com`, isSuperUser); console.log(`Error deleting workspace: ${w.id}`, `user-${parallelId}@nocodb.com`, isSuperUser);
@ -237,7 +244,7 @@ async function localInit({
for (const p of projects.list) { for (const p of projects.list) {
// check if p.title starts with projectTitle // check if p.title starts with projectTitle
if ( 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}`) p.title.startsWith(`xcdb_p${process.env.TEST_PARALLEL_INDEX}`)
) { ) {
try { try {
@ -349,38 +356,25 @@ const setup = async ({
const workerIndex = process.env.TEST_WORKER_INDEX; const workerIndex = process.env.TEST_WORKER_INDEX;
const parallelIndex = process.env.TEST_PARALLEL_INDEX; const parallelIndex = process.env.TEST_PARALLEL_INDEX;
const workerId = `_p${parallelIndex}_w${workerIndex}_c${(+workerIndex + 1) * 1000 + workerCount[parallelIndex]}`; const workerId = parallelIndex;
workerCount[+parallelIndex]++;
// console.log(process.env.TEST_PARALLEL_INDEX, '#Setup', workerId); // console.log(process.env.TEST_PARALLEL_INDEX, '#Setup', workerId);
try { try {
// Localised reset logic // Localised reset logic
if (enableLocalInit) { response = await localInit({
response = await localInit({ workerId: parallelIndex,
workerId, isEmptyProject,
isEmptyProject, projectType,
projectType, isSuperUser,
isSuperUser, dbType,
dbType, });
});
}
// Remote reset logic
else {
response = await axios.post(`http://localhost:8080/api/v1/meta/test/reset`, {
parallelId: process.env.TEST_PARALLEL_INDEX,
workerId: workerId,
dbType,
projectType,
isEmptyProject,
});
}
} catch (e) { } catch (e) {
console.error(`Error resetting project: ${process.env.TEST_PARALLEL_INDEX}`, e); console.error(`Error resetting project: ${process.env.TEST_PARALLEL_INDEX}`, e);
} }
if (response.status !== 200 || !response.data?.token || !response.data?.project) { if (response.status !== 200 || !response.data?.token || !response.data?.project) {
console.error('Failed to reset test data', response.data, response.status, enableLocalInit, dbType); console.error('Failed to reset test data', response.data, response.status, dbType);
throw new Error('Failed to reset test data'); throw new Error('Failed to reset test data');
} }
const token = response.data.token; const token = response.data.token;
@ -445,22 +439,7 @@ const setup = async ({
return { project, token, dbType, workerId, rootUser, workspace } as NcContext; return { project, token, dbType, workerId, rootUser, workspace } as NcContext;
}; };
export const unsetup = async (context: NcContext): Promise<void> => { export const unsetup = async (context: NcContext): Promise<void> => {};
if (context.token && context.project) {
// try to delete the project
try {
// Init SDK using token
const api = new Api({
baseURL: `http://localhost:8080/`,
headers: {
'xc-auth': context.token,
},
});
await api.project.delete(context.project.id);
} catch (e) {}
}
};
// Reference // Reference
// packages/nocodb/src/lib/services/test/TestResetService/resetPgSakilaProject.ts // packages/nocodb/src/lib/services/test/TestResetService/resetPgSakilaProject.ts

2
tests/playwright/setup/knexHelper.ts

@ -36,7 +36,7 @@ export async function resetSakilaPg(database: string) {
try { try {
await initializeSakilaPg(database); await initializeSakilaPg(database);
} catch (e) { } catch (e) {
console.error(`Error resetting pg sakila db: Worker ${database}`); console.error(`Error resetting pg sakila db: Worker ${database}`, e);
} }
} }

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

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

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

@ -35,6 +35,7 @@ test.describe('Shared base', () => {
await dashboard.treeView.validateRoleAccess({ await dashboard.treeView.validateRoleAccess({
role: role.toLowerCase(), role: role.toLowerCase(),
context,
}); });
await dashboard.grid.verifyRoleAccess({ 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 // Create table and verify ERD
await dashboard.treeView.createTable({ title: 'Test', projectTitle: context.project.title }); await dashboard.treeView.createTable({ title: 'Test', projectTitle: context.project.title });
// Verify in Settings ERD and table ERD // 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 openProjectErd();
await dashboard.details.relations.verifyNode({ await dashboard.details.relations.verifyNode({
tableName: `Test`, tableName: `Test`,

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

@ -21,7 +21,7 @@ test.describe('Import', () => {
}); });
test('Airtable', async () => { 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({ await dashboard.importAirtable.import({
key: airtableApiKey, key: airtableApiKey,
baseId: airtableApiBase, baseId: airtableApiBase,
@ -31,7 +31,7 @@ test.describe('Import', () => {
}); });
test('CSV', async () => { 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 () => { test('Excel', async () => {
@ -46,7 +46,7 @@ test.describe('Import', () => {
{ name: 'Sheet4', columns: col }, { 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({ await dashboard.importTemplate.import({
file: `${process.cwd()}/fixtures/sampleFiles/simple.xlsx`, file: `${process.cwd()}/fixtures/sampleFiles/simple.xlsx`,
result: expected, result: expected,
@ -66,6 +66,6 @@ test.describe('Import', () => {
}); });
test('JSON', async () => { 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 // create a new xcdb project
const xcdb = await createXcdb(context); const xcdb = await createXcdb(context);
await dashboard.rootPage.reload(); await dashboard.rootPage.reload();
await dashboard.treeView.openProject({ title: 'Xcdb', projectCount: 2 }); await dashboard.treeView.openProject({ title: 'xcdb', context });
api = new Api({ api = new Api({
baseURL: `http://localhost:8080/`, baseURL: `http://localhost:8080/`,
@ -216,7 +216,7 @@ test.describe.serial('Test table', () => {
}); });
test('Delete record - single, over UI', async () => { 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 dashboard.treeView.openTable({ title: 'Table0' });
await grid.deleteRow(0); await grid.deleteRow(0);

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

@ -1,7 +1,7 @@
import { expect, test } from '@playwright/test'; import { expect, test } from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard'; import { DashboardPage } from '../../../pages/Dashboard';
import { airtableApiBase, airtableApiKey } from '../../../constants'; import { airtableApiBase, airtableApiKey } from '../../../constants';
import setup, { unsetup } from '../../../setup'; import setup, { NcContext, unsetup } from '../../../setup';
import { Api, ProjectListType } from 'nocodb-sdk'; import { Api, ProjectListType } from 'nocodb-sdk';
import { ProjectInfo, ProjectInfoApiUtil } from '../../../tests/utils/projectInfoApiUtil'; import { ProjectInfo, ProjectInfoApiUtil } from '../../../tests/utils/projectInfoApiUtil';
import { deepCompare } from '../../../tests/utils/objectCompareUtil'; import { deepCompare } from '../../../tests/utils/objectCompareUtil';
@ -9,38 +9,25 @@ import { isEE } from '../../../setup/db';
test.describe('Project operations', () => { test.describe('Project operations', () => {
let dashboard: DashboardPage; let dashboard: DashboardPage;
let context: any; let context: NcContext;
let api: Api<any>; let api: Api<any>;
test.setTimeout(100000); test.setTimeout(100000);
async function getProjectList() { async function getProjectList(workspaceId?: string) {
let projectList: ProjectListType; let projectList: ProjectListType;
if (isEE() && api['workspaceProject']) { if (isEE() && api['workspaceProject']) {
const ws = await api['workspace'].list(); projectList = await api['workspaceProject'].list(workspaceId);
projectList = await api['workspaceProject'].list(ws.list[1].id);
} else { } else {
projectList = await api.project.list(); projectList = await api.project.list();
} }
return projectList; return projectList;
} }
async function deleteIfExists(name: string) {
try {
const projectList = await getProjectList();
const project = projectList.list.find((p: any) => p.title === name);
if (project) {
await api.project.delete(project.id);
console.log('deleted project: ', project.id);
}
} catch (e) {
console.log('Error: ', e);
}
}
async function createTestProjectWithData(testProjectName: string) { async function createTestProjectWithData(testProjectName: string) {
await dashboard.leftSidebar.createProject({ title: testProjectName }); await dashboard.leftSidebar.createProject({ title: testProjectName, context });
await dashboard.treeView.openProject({ title: testProjectName }); await dashboard.treeView.openProject({ title: testProjectName, context });
await dashboard.treeView.quickImport({ title: 'Airtable', projectTitle: testProjectName }); await dashboard.treeView.quickImport({ title: 'Airtable', projectTitle: testProjectName, context });
await dashboard.importAirtable.import({ await dashboard.importAirtable.import({
key: airtableApiKey, key: airtableApiKey,
baseId: airtableApiBase, baseId: airtableApiBase,
@ -49,8 +36,8 @@ test.describe('Project operations', () => {
} }
async function cleanupTestData(dupeProjectName: string, testProjectName: string) { async function cleanupTestData(dupeProjectName: string, testProjectName: string) {
await dashboard.treeView.deleteProject({ title: dupeProjectName }); await dashboard.treeView.deleteProject({ title: dupeProjectName, context });
await dashboard.treeView.deleteProject({ title: testProjectName }); await dashboard.treeView.deleteProject({ title: testProjectName, context });
} }
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
@ -71,34 +58,33 @@ test.describe('Project operations', () => {
}); });
test('rename, delete', async () => { test('rename, delete', async () => {
// if project already exists, delete it await dashboard.leftSidebar.createProject({ title: 'project-firstName', context });
await deleteIfExists('project-firstName'); await dashboard.treeView.renameProject({ title: 'project-firstName', newTitle: 'project-rename', context });
await dashboard.treeView.openProject({ title: 'project-rename', context });
await dashboard.leftSidebar.createProject({ title: 'project-firstName' }); await dashboard.treeView.deleteProject({ title: 'project-rename', context });
await dashboard.treeView.renameProject({ title: 'project-firstName', newTitle: 'project-rename' });
await dashboard.treeView.openProject({ title: 'project-rename' });
await dashboard.treeView.deleteProject({ title: 'project-rename' });
}); });
test('project_duplicate', async () => { test('project_duplicate', async () => {
// if project already exists, delete it to avoid test failures due to residual data // if project already exists, delete it to avoid test failures due to residual data
const testProjectName = 'Project-To-Import-Export'; const random = Math.floor(Math.random() * 1000000);
const dupeProjectName: string = testProjectName + ' copy'; const testProjectName = `Project-To-Import-Export-${random}`;
await deleteIfExists(testProjectName); const scopedProjectName = dashboard.treeView.scopedProjectTitle({
await deleteIfExists(dupeProjectName); title: testProjectName,
context,
});
// // data creation for original test project // // data creation for original test project
await createTestProjectWithData(testProjectName); await createTestProjectWithData(testProjectName);
// duplicate duplicate // duplicate duplicate
await dashboard.treeView.duplicateProject({ title: testProjectName }); await dashboard.treeView.duplicateProject({ title: testProjectName, context });
await dashboard.treeView.openProject({ title: testProjectName }); await dashboard.treeView.openProject({ title: testProjectName, context });
// compare // compare
const projectList = await getProjectList(); const projectList = await getProjectList(context.workspace?.id);
const testProjectId = projectList.list.find((p: any) => p.title === testProjectName); const testProjectId = projectList.list.find((p: any) => p.title === scopedProjectName);
const dupeProjectId = projectList.list.find((p: any) => p.title.startsWith(testProjectName + ' copy')); const dupeProjectId = projectList.list.find((p: any) => p.title.startsWith(scopedProjectName + ' copy'));
const projectInfoOp: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token); const projectInfoOp: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token);
const original: Promise<ProjectInfo> = projectInfoOp.extractProjectInfo(testProjectId.id); const original: Promise<ProjectInfo> = projectInfoOp.extractProjectInfo(testProjectId.id);
const duplicate: Promise<ProjectInfo> = projectInfoOp.extractProjectInfo(dupeProjectId.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()) { if (!isEE()) {
// Audit logs in clickhouse; locally wont be accessible // 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.tab_dataSources.click();
await dashboard.projectView.dataSources.openAudit({ rowIndex: 0 }); 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.leftSidebar.openWorkspace({ title: context.workspace.title });
await dashboard.rootPage.waitForTimeout(500); 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.rootPage.waitForTimeout(500);
await dashboard.treeView.openTable({ title: 'Country' }); await dashboard.treeView.openTable({ title: 'Country' });

Loading…
Cancel
Save