Browse Source

fix(test): Integrated multiple sources changes with playwright

pull/3573/head
Muhammed Mustafa 2 years ago committed by mertmit
parent
commit
fbefe104e4
  1. 38
      packages/nocodb/src/lib/models/Base.ts
  2. 6
      packages/nocodb/src/lib/services/test/TestResetService/index.ts
  3. 4
      tests/playwright/constants/index.ts
  4. 13
      tests/playwright/pages/Dashboard/Settings/Acl.ts
  5. 40
      tests/playwright/pages/Dashboard/Settings/DataSources.ts
  6. 12
      tests/playwright/pages/Dashboard/Settings/Erd.ts
  7. 12
      tests/playwright/pages/Dashboard/Settings/Metadata.ts
  8. 8
      tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts
  9. 17
      tests/playwright/pages/Dashboard/Settings/index.ts
  10. 7
      tests/playwright/pages/Dashboard/TreeView.ts
  11. 9
      tests/playwright/tests/baseShare.spec.ts
  12. 34
      tests/playwright/tests/erd.spec.ts
  13. 83
      tests/playwright/tests/metaSync.spec.ts
  14. 20
      tests/playwright/tests/rolesCreate.spec.ts
  15. 20
      tests/playwright/tests/rolesPreview.spec.ts

38
packages/nocodb/src/lib/models/Base.ts

@ -66,7 +66,7 @@ export default class Base implements BaseType {
[base.projectId], [base.projectId],
`${CacheScope.BASE}:${id}` `${CacheScope.BASE}:${id}`
); );
// call before reorder to update cache // call before reorder to update cache
const returnBase = await this.get(id, ncMeta); const returnBase = await this.get(id, ncMeta);
@ -77,7 +77,12 @@ export default class Base implements BaseType {
public static async updateBase( public static async updateBase(
baseId: string, baseId: string,
base: BaseType & { id: string; projectId: string; created_at?; updated_at? }, base: BaseType & {
id: string;
projectId: string;
created_at?;
updated_at?;
},
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const oldBase = await Base.get(baseId, ncMeta); const oldBase = await Base.get(baseId, ncMeta);
@ -107,7 +112,7 @@ export default class Base implements BaseType {
'order', 'order',
'enabled', 'enabled',
]); ]);
if (insertObj.config) { if (insertObj.config) {
insertObj.config = CryptoJS.AES.encrypt( insertObj.config = CryptoJS.AES.encrypt(
JSON.stringify(base.config), JSON.stringify(base.config),
@ -178,7 +183,7 @@ export default class Base implements BaseType {
return new Base(baseData); return new Base(baseData);
}); });
} }
static async get(id: string, ncMeta = Noco.ncMeta): Promise<Base> { static async get(id: string, ncMeta = Noco.ncMeta): Promise<Base> {
let baseData = let baseData =
id && id &&
@ -193,11 +198,18 @@ export default class Base implements BaseType {
return baseData && new Base(baseData); return baseData && new Base(baseData);
} }
static async reorderBases(projectId: string, keepBase?: string, ncMeta = Noco.ncMeta) { static async reorderBases(
projectId: string,
keepBase?: string,
ncMeta = Noco.ncMeta
) {
const bases = await this.list({ projectId: projectId }, ncMeta); const bases = await this.list({ projectId: projectId }, ncMeta);
if (keepBase) { if (keepBase) {
const kpBase = bases.splice(bases.indexOf(bases.find((base) => base.id === keepBase)), 1); const kpBase = bases.splice(
bases.indexOf(bases.find((base) => base.id === keepBase)),
1
);
if (kpBase.length) { if (kpBase.length) {
bases.splice(kpBase[0].order - 1, 0, kpBase[0]); bases.splice(kpBase[0].order - 1, 0, kpBase[0]);
} }
@ -208,15 +220,15 @@ export default class Base implements BaseType {
await ncMeta.metaDelete(null, null, MetaTable.BASES, { await ncMeta.metaDelete(null, null, MetaTable.BASES, {
id: b.id, id: b.id,
}); });
await NocoCache.deepDel( await NocoCache.deepDel(
CacheScope.BASE, CacheScope.BASE,
`${CacheScope.BASE}:${b.id}`, `${CacheScope.BASE}:${b.id}`,
CacheDelDirection.CHILD_TO_PARENT CacheDelDirection.CHILD_TO_PARENT
); );
b.order = parseInt(i) + 1; b.order = parseInt(i) + 1;
const { id } = await ncMeta.metaInsert2( const { id } = await ncMeta.metaInsert2(
b.project_id, b.project_id,
null, null,
@ -265,10 +277,12 @@ export default class Base implements BaseType {
return Project.get(this.project_id, ncMeta); return Project.get(this.project_id, ncMeta);
} }
async delete(ncMeta = Noco.ncMeta) { async delete(ncMeta = Noco.ncMeta, { force }: { force?: boolean } = {}) {
const bases = await Base.list({ projectId: this.project_id }, ncMeta); const bases = await Base.list({ projectId: this.project_id }, ncMeta);
if (bases[0].id === this.id) NcError.badRequest('Cannot delete first base'); if (bases[0].id === this.id && !force) {
NcError.badRequest('Cannot delete first base');
}
const models = await Model.list( const models = await Model.list(
{ {

6
packages/nocodb/src/lib/services/test/TestResetService/index.ts

@ -1,6 +1,7 @@
import axios from 'axios'; import axios from 'axios';
import Project from '../../../models/Project'; import Project from '../../../models/Project';
import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2';
import Noco from '../../../Noco';
import resetMetaSakilaSqliteProject from './resetMetaSakilaSqliteProject'; import resetMetaSakilaSqliteProject from './resetMetaSakilaSqliteProject';
import resetMysqlSakilaProject from './resetMysqlSakilaProject'; import resetMysqlSakilaProject from './resetMysqlSakilaProject';
import resetPgSakilaProject from './resetPgSakilaProject'; import resetPgSakilaProject from './resetPgSakilaProject';
@ -111,8 +112,9 @@ export class TestResetService {
const bases = await project.getBases(); const bases = await project.getBases();
if (bases.length > 0) { for (const base of bases) {
await NcConnectionMgrv2.deleteAwait(bases[0]); await NcConnectionMgrv2.deleteAwait(base);
await base.delete(Noco.ncMeta, { force: true });
} }
await Project.delete(project.id); await Project.delete(project.id);

4
tests/playwright/constants/index.ts

@ -1,4 +1,6 @@
const airtableApiKey = 'keyn1MR87qgyUsYg4'; const airtableApiKey = 'keyn1MR87qgyUsYg4';
const airtableApiBase = 'https://airtable.com/shr4z0qmh6dg5s3eB'; const airtableApiBase = 'https://airtable.com/shr4z0qmh6dg5s3eB';
export { airtableApiKey, airtableApiBase }; const defaultBaseName = 'Base';
export { airtableApiKey, airtableApiBase, defaultBaseName };

13
tests/playwright/pages/Dashboard/Settings/Acl.ts

@ -1,17 +1,16 @@
import { expect, Locator } from '@playwright/test';
import { SettingsPage } from '.';
import BasePage from '../../Base'; import BasePage from '../../Base';
import { DataSourcesPage } from './DataSources';
export class AclPage extends BasePage { export class AclPage extends BasePage {
private readonly settings: SettingsPage; readonly dataSources: DataSourcesPage;
constructor(settings: SettingsPage) { constructor(dataSources: DataSourcesPage) {
super(settings.rootPage); super(dataSources.rootPage);
this.settings = settings; this.dataSources = dataSources;
} }
get() { get() {
return this.settings.get().locator(`[data-testid="nc-settings-subtab-UI Access Control"]`); return this.dataSources.get();
} }
async toggle({ table, role }: { table: string; role: string }) { async toggle({ table, role }: { table: string; role: string }) {

40
tests/playwright/pages/Dashboard/Settings/DataSources.ts

@ -0,0 +1,40 @@
import { SettingsPage } from '.';
import { defaultBaseName } from '../../../constants';
import BasePage from '../../Base';
import { AclPage } from './Acl';
import { SettingsErdPage } from './Erd';
import { MetaDataPage } from './Metadata';
export class DataSourcesPage extends BasePage {
private readonly settings: SettingsPage;
readonly erd: SettingsErdPage;
readonly acl: AclPage;
readonly metaData: MetaDataPage;
constructor(settings: SettingsPage) {
super(settings.rootPage);
this.settings = settings;
this.erd = new SettingsErdPage(this);
this.acl = new AclPage(this);
this.metaData = new MetaDataPage(this);
}
get() {
return this.settings.get().locator(`[data-nc="nc-settings-subtab-Data Sources"]`);
}
async openErd({ dataSourceName }: { dataSourceName: string }) {
await this.get().locator('.ds-table-row', { hasText: dataSourceName }).locator('button:has-text("ERD")').click();
}
async openAcl({ dataSourceName = defaultBaseName }: { dataSourceName?: string } = {}) {
await this.get().locator('.ds-table-row', { hasText: dataSourceName }).locator('button:has-text("UI ACL")').click();
}
async openMetaSync({ dataSourceName = defaultBaseName }: { dataSourceName?: string } = {}) {
await this.get()
.locator('.ds-table-row', { hasText: dataSourceName })
.locator('button:has-text("Sync Metadata")')
.click();
}
}

12
tests/playwright/pages/Dashboard/Settings/Erd.ts

@ -1,15 +1,15 @@
import { SettingsPage } from '.';
import { ErdBasePage } from '../commonBase/Erd'; import { ErdBasePage } from '../commonBase/Erd';
import { DataSourcesPage } from './DataSources';
export class SettingsErdPage extends ErdBasePage { export class SettingsErdPage extends ErdBasePage {
readonly settings: SettingsPage; readonly dataSources: DataSourcesPage;
constructor(settings: SettingsPage) { constructor(dataSources: DataSourcesPage) {
super(settings.rootPage); super(dataSources.rootPage);
this.settings = settings; this.dataSources = dataSources;
} }
get() { get() {
return this.rootPage.locator(`[data-testid="nc-settings-subtab-ERD View"]`); return this.dataSources.get();
} }
} }

12
tests/playwright/pages/Dashboard/Settings/Metadata.ts

@ -1,17 +1,17 @@
import { expect } from '@playwright/test'; import { expect } from '@playwright/test';
import { SettingsPage } from '.';
import BasePage from '../../Base'; import BasePage from '../../Base';
import { DataSourcesPage } from './DataSources';
export class MetaDataPage extends BasePage { export class MetaDataPage extends BasePage {
private readonly settings: SettingsPage; private readonly dataSources: DataSourcesPage;
constructor(settings: SettingsPage) { constructor(dataSources: DataSourcesPage) {
super(settings.rootPage); super(dataSources.rootPage);
this.settings = settings; this.dataSources = dataSources;
} }
get() { get() {
return this.settings.get().locator(`[data-testid="nc-settings-subtab-Metadata"]`); return this.dataSources.get();
} }
async clickReload() { async clickReload() {

8
tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts

@ -1,4 +1,3 @@
import { expect } from '@playwright/test';
import { SettingsPage } from '.'; import { SettingsPage } from '.';
import BasePage from '../../Base'; import BasePage from '../../Base';
@ -15,6 +14,11 @@ export class MiscSettingsPage extends BasePage {
} }
async clickShowM2MTables() { async clickShowM2MTables() {
await this.get().locator('input[type="checkbox"]').click(); const clickAction = this.get().locator('input[type="checkbox"]').click();
await this.waitForResponse({
uiAction: clickAction,
requestUrlPathToMatch: 'tables?includeM2M',
httpMethodsToMatch: ['GET'],
});
} }
} }

17
tests/playwright/pages/Dashboard/Settings/index.ts

@ -1,18 +1,17 @@
import { DashboardPage } from '..'; import { DashboardPage } from '..';
import BasePage from '../../Base'; import BasePage from '../../Base';
import { AuditSettingsPage } from './Audit'; import { AuditSettingsPage } from './Audit';
import { SettingsErdPage } from './Erd';
import { MetaDataPage } from './Metadata';
import { AppStoreSettingsPage } from './AppStore'; import { AppStoreSettingsPage } from './AppStore';
import { MiscSettingsPage } from './Miscellaneous'; import { MiscSettingsPage } from './Miscellaneous';
import { TeamsPage } from './Teams'; import { TeamsPage } from './Teams';
import { AclPage } from './Acl'; import { DataSourcesPage } from './DataSources';
export enum SettingTab { export enum SettingTab {
TeamAuth = 'teamAndAuth', TeamAuth = 'teamAndAuth',
AppStore = 'appStore', AppStore = 'appStore',
ProjectMetadata = 'projMetaData', DataSources = 'dataSources',
Audit = 'audit', Audit = 'audit',
ProjectSettings = 'projectSettings',
} }
export enum SettingsSubTab { export enum SettingsSubTab {
@ -22,25 +21,19 @@ export enum SettingsSubTab {
} }
export class SettingsPage extends BasePage { export class SettingsPage extends BasePage {
private readonly dashboard: DashboardPage;
readonly audit: AuditSettingsPage; readonly audit: AuditSettingsPage;
readonly appStore: AppStoreSettingsPage; readonly appStore: AppStoreSettingsPage;
readonly metaData: MetaDataPage;
readonly miscellaneous: MiscSettingsPage; readonly miscellaneous: MiscSettingsPage;
readonly erd: SettingsErdPage; readonly dataSources: DataSourcesPage;
readonly teams: TeamsPage; readonly teams: TeamsPage;
readonly acl: AclPage;
constructor(dashboard: DashboardPage) { constructor(dashboard: DashboardPage) {
super(dashboard.rootPage); super(dashboard.rootPage);
this.dashboard = dashboard;
this.audit = new AuditSettingsPage(this); this.audit = new AuditSettingsPage(this);
this.appStore = new AppStoreSettingsPage(this); this.appStore = new AppStoreSettingsPage(this);
this.metaData = new MetaDataPage(this);
this.miscellaneous = new MiscSettingsPage(this); this.miscellaneous = new MiscSettingsPage(this);
this.erd = new SettingsErdPage(this); this.dataSources = new DataSourcesPage(this);
this.teams = new TeamsPage(this); this.teams = new TeamsPage(this);
this.acl = new AclPage(this);
} }
get() { get() {

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

@ -6,14 +6,12 @@ export class TreeViewPage extends BasePage {
readonly dashboard: DashboardPage; readonly dashboard: DashboardPage;
readonly project: any; readonly project: any;
readonly quickImportButton: Locator; readonly quickImportButton: Locator;
readonly inviteTeamButton: Locator;
constructor(dashboard: DashboardPage, project: any) { constructor(dashboard: DashboardPage, project: any) {
super(dashboard.rootPage); super(dashboard.rootPage);
this.dashboard = dashboard; this.dashboard = dashboard;
this.project = project; this.project = project;
this.quickImportButton = dashboard.get().locator('.nc-import-menu'); this.quickImportButton = dashboard.get().locator('.nc-import-menu');
this.inviteTeamButton = dashboard.get().locator('.nc-share-base');
} }
get() { get() {
@ -131,13 +129,14 @@ export class TreeViewPage extends BasePage {
await importMenu.locator(`.ant-dropdown-menu-title-content:has-text("${title}")`).click(); await importMenu.locator(`.ant-dropdown-menu-title-content:has-text("${title}")`).click();
} }
// todo: Break this into smaller methods
async validateRoleAccess(param: { role: string }) { async validateRoleAccess(param: { role: string }) {
// Add new table button // Add new table button
await expect(this.get().locator(`.nc-add-new-table`)).toHaveCount(param.role === 'creator' ? 1 : 0); await expect(this.get().locator(`.nc-add-new-table`)).toHaveCount(param.role === 'creator' ? 1 : 0);
// Import menu // Import menu
await expect(this.get().locator(`.nc-import-menu`)).toHaveCount(param.role === 'creator' ? 1 : 0); await expect(this.get().locator(`.nc-import-menu`)).toHaveCount(param.role === 'creator' ? 1 : 0);
// Invite Team button // Team and Settings button
await expect(this.get().locator(`.nc-share-base`)).toHaveCount(param.role === 'creator' ? 1 : 0); await expect(this.get().locator(`.nc-new-base`)).toHaveCount(param.role === 'creator' ? 1 : 0);
// Right click context menu // Right click context menu
await this.get().locator(`.nc-project-tree-tbl-Country`).click({ await this.get().locator(`.nc-project-tree-tbl-Country`).click({
button: 'right', button: 'right',

9
tests/playwright/tests/baseShare.spec.ts

@ -58,15 +58,18 @@ test.describe('Shared base', () => {
// close 'Team & Auth' tab // close 'Team & Auth' tab
await dashboard.closeTab({ title: 'Team & Auth' }); await dashboard.closeTab({ title: 'Team & Auth' });
await dashboard.treeView.inviteTeamButton.click(); await dashboard.gotoSettings();
await dashboard.settings.teams.clickInviteTeamBtn();
await dashboard.settings.teams.toggleSharedBase({ toggle: true }); await dashboard.settings.teams.toggleSharedBase({ toggle: true });
await dashboard.settings.teams.sharedBaseRole({ role: 'editor' }); await dashboard.settings.teams.sharedBaseRole({ role: 'editor' });
let url = await dashboard.settings.teams.getSharedBaseUrl(); let url = await dashboard.settings.teams.getSharedBaseUrl();
await dashboard.settings.teams.closeInvite(); await dashboard.settings.teams.closeInvite();
await dashboard.settings.close();
await dashboard.rootPage.waitForTimeout(2000); await dashboard.rootPage.waitForTimeout(2000);
// access shared base link // access shared base link
await dashboard.signOut(); await dashboard.signOut();
await dashboard.rootPage.waitForTimeout(2000);
// todo: Move this to a page object // todo: Move this to a page object
await dashboard.rootPage.goto(url); await dashboard.rootPage.goto(url);
@ -81,11 +84,13 @@ test.describe('Shared base', () => {
await projectPage.openProject({ title: context.project.title, withoutPrefix: true }); await projectPage.openProject({ title: context.project.title, withoutPrefix: true });
await dashboard.closeTab({ title: 'Team & Auth' }); await dashboard.closeTab({ title: 'Team & Auth' });
await dashboard.treeView.inviteTeamButton.click(); await dashboard.gotoSettings();
await dashboard.settings.teams.clickInviteTeamBtn();
await dashboard.settings.teams.toggleSharedBase({ toggle: true }); await dashboard.settings.teams.toggleSharedBase({ toggle: true });
await dashboard.settings.teams.sharedBaseRole({ role: 'viewer' }); await dashboard.settings.teams.sharedBaseRole({ role: 'viewer' });
url = await dashboard.settings.teams.getSharedBaseUrl(); url = await dashboard.settings.teams.getSharedBaseUrl();
await dashboard.settings.teams.closeInvite(); await dashboard.settings.teams.closeInvite();
await dashboard.settings.close();
await dashboard.rootPage.waitForTimeout(2000); await dashboard.rootPage.waitForTimeout(2000);
// access shared base link // access shared base link

34
tests/playwright/tests/erd.spec.ts

@ -11,6 +11,7 @@ import { SettingsSubTab, SettingTab } from '../pages/Dashboard/Settings';
import setup from '../setup'; import setup from '../setup';
import { isMysql, isPg, isSqlite } from '../setup/db'; import { isMysql, isPg, isSqlite } from '../setup/db';
import { SettingsErdPage } from '../pages/Dashboard/Settings/Erd'; import { SettingsErdPage } from '../pages/Dashboard/Settings/Erd';
import { defaultBaseName } from '../constants';
test.describe('Erd', () => { test.describe('Erd', () => {
let dashboard: DashboardPage; let dashboard: DashboardPage;
@ -35,15 +36,21 @@ test.describe('Erd', () => {
} }
}); });
const enableMM = async () => { const toggleMMAndOpenErd = async () => {
await dashboard.settings.selectTab({ tab: SettingTab.ProjectMetadata, subTab: SettingsSubTab.Miscellaneous }); await dashboard.settings.selectTab({ tab: SettingTab.ProjectSettings, subTab: SettingsSubTab.Miscellaneous });
await dashboard.settings.miscellaneous.clickShowM2MTables(); await dashboard.settings.miscellaneous.clickShowM2MTables();
await dashboard.settings.selectSubTab({ subTab: SettingsSubTab.ERD }); await dashboard.settings.selectTab({ tab: SettingTab.DataSources });
await dashboard.settings.dataSources.openErd({
dataSourceName: defaultBaseName,
});
}; };
const openSettingsErd = async () => { const openSettingsErd = async () => {
await dashboard.gotoSettings(); await dashboard.gotoSettings();
await dashboard.settings.selectTab({ tab: SettingTab.ProjectMetadata, subTab: SettingsSubTab.ERD }); await dashboard.settings.selectTab({ tab: SettingTab.DataSources });
await dashboard.settings.dataSources.openErd({
dataSourceName: defaultBaseName,
});
}; };
const openErdOfATable = async (tableName: string) => { const openErdOfATable = async (tableName: string) => {
@ -54,9 +61,9 @@ test.describe('Erd', () => {
test('Verify default config, all columns disabled, only PK and FK disabled, Sql views and MM table option, junction table names', async () => { test('Verify default config, all columns disabled, only PK and FK disabled, Sql views and MM table option, junction table names', async () => {
await openSettingsErd(); await openSettingsErd();
await enableMM(); await toggleMMAndOpenErd();
const erd: SettingsErdPage = dashboard.settings.erd; const erd: SettingsErdPage = dashboard.settings.dataSources.erd;
await erd.dbClickShowColumnNames(); await erd.dbClickShowColumnNames();
@ -219,7 +226,7 @@ test.describe('Erd', () => {
await dashboard.grid.column.create({ title: 'test_column' }); await dashboard.grid.column.create({ title: 'test_column' });
// Verify in Settings ERD and table ERD // Verify in Settings ERD and table ERD
await openSettingsErd(); await openSettingsErd();
await dashboard.settings.erd.verifyNode({ await dashboard.settings.dataSources.erd.verifyNode({
tableName: `country`, tableName: `country`,
columnName: 'test_column', columnName: 'test_column',
}); });
@ -242,7 +249,7 @@ test.describe('Erd', () => {
}); });
// Verify in Settings ERD and table ERD // Verify in Settings ERD and table ERD
await openSettingsErd(); await openSettingsErd();
await dashboard.settings.erd.verifyNode({ await dashboard.settings.dataSources.erd.verifyNode({
tableName: `country`, tableName: `country`,
columnName: 'new_test_column', columnName: 'new_test_column',
}); });
@ -261,7 +268,7 @@ test.describe('Erd', () => {
await dashboard.grid.column.delete({ title: 'new_test_column' }); await dashboard.grid.column.delete({ title: 'new_test_column' });
// Verify in Settings ERD and table ERD // Verify in Settings ERD and table ERD
await openSettingsErd(); await openSettingsErd();
await dashboard.settings.erd.verifyNode({ await dashboard.settings.dataSources.erd.verifyNode({
tableName: `country`, tableName: `country`,
columnNameShouldNotExist: 'new_test_column', columnNameShouldNotExist: 'new_test_column',
}); });
@ -285,7 +292,7 @@ test.describe('Erd', () => {
await dashboard.treeView.createTable({ title: 'Test' }); await dashboard.treeView.createTable({ title: 'Test' });
// Verify in Settings ERD and table ERD // Verify in Settings ERD and table ERD
await openSettingsErd(); await openSettingsErd();
await dashboard.settings.erd.verifyNode({ await dashboard.settings.dataSources.erd.verifyNode({
tableName: `Test`, tableName: `Test`,
}); });
await dashboard.settings.close(); await dashboard.settings.close();
@ -293,14 +300,13 @@ test.describe('Erd', () => {
// Delete table and verify ERD // Delete table and verify ERD
await dashboard.treeView.deleteTable({ title: 'Test' }); await dashboard.treeView.deleteTable({ title: 'Test' });
await openSettingsErd(); await openSettingsErd();
await dashboard.settings.erd.verifyNodeDoesNotExist({ await dashboard.settings.dataSources.erd.verifyNodeDoesNotExist({
tableName: `Test`, tableName: `Test`,
}); });
// Verify that `show mm table` option disabled will not trigger easter in ERD options // Verify that `show mm table` option disabled will not trigger easter in ERD options
await dashboard.settings.selectSubTab({ subTab: SettingsSubTab.Miscellaneous }); await dashboard.settings.dataSources.erd.dbClickShowColumnNames();
await dashboard.settings.miscellaneous.clickShowM2MTables(); // disable await dashboard.settings.dataSources.erd.verifyEasterEggNotShown();
await dashboard.settings.selectSubTab({ subTab: SettingsSubTab.ERD });
await dashboard.settings.close(); await dashboard.settings.close();
}); });
}); });

83
tests/playwright/tests/metaSync.spec.ts

@ -4,7 +4,6 @@ import { SettingsPage, SettingTab } from '../pages/Dashboard/Settings';
import setup, { NcContext } from '../setup'; import setup, { NcContext } from '../setup';
import { isMysql, isPg, isSqlite, mysqlExec, pgExec, sqliteExec } from '../setup/db'; import { isMysql, isPg, isSqlite, mysqlExec, pgExec, sqliteExec } from '../setup/db';
// todo: Enable when view bug is fixed
test.describe('Meta sync', () => { test.describe('Meta sync', () => {
let dashboard: DashboardPage; let dashboard: DashboardPage;
let settings: SettingsPage; let settings: SettingsPage;
@ -33,30 +32,31 @@ test.describe('Meta sync', () => {
test.setTimeout(process.env.CI ? 100000 : 70000); test.setTimeout(process.env.CI ? 100000 : 70000);
await dashboard.gotoSettings(); await dashboard.gotoSettings();
await settings.selectTab({ tab: SettingTab.ProjectMetadata }); await settings.selectTab({ tab: SettingTab.DataSources });
await settings.dataSources.openMetaSync();
await dbExec(`CREATE TABLE table1 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))`); await dbExec(`CREATE TABLE table1 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))`);
await dbExec(`CREATE TABLE table2 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))`); await dbExec(`CREATE TABLE table2 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))`);
await settings.metaData.clickReload(); await settings.dataSources.metaData.clickReload();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: `table1`, model: `table1`,
state: 'New table', state: 'New table',
}); });
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 22 : 17, index: isPg(context) ? 22 : 17,
model: `table2`, model: `table2`,
state: 'New table', state: 'New table',
}); });
await settings.metaData.sync(); await settings.dataSources.metaData.sync();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: 'Table1', model: 'Table1',
state: 'No change identified', state: 'No change identified',
}); });
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 22 : 17, index: isPg(context) ? 22 : 17,
model: 'Table2', model: 'Table2',
state: 'No change identified', state: 'No change identified',
@ -72,16 +72,16 @@ test.describe('Meta sync', () => {
`ALTER TABLE table1 ADD CONSTRAINT fk1 FOREIGN KEY (col1) REFERENCES table2 (id) ON DELETE NO ACTION ON UPDATE NO ACTION` `ALTER TABLE table1 ADD CONSTRAINT fk1 FOREIGN KEY (col1) REFERENCES table2 (id) ON DELETE NO ACTION ON UPDATE NO ACTION`
); );
} }
await settings.metaData.clickReload(); await settings.dataSources.metaData.clickReload();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: 'Table1', model: 'Table1',
state: 'New relation added', state: 'New relation added',
}); });
//verify after sync //verify after sync
await settings.metaData.sync(); await settings.dataSources.metaData.sync();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: 'Table1', model: 'Table1',
state: 'No change identified', state: 'No change identified',
@ -94,16 +94,16 @@ test.describe('Meta sync', () => {
await dbExec(`ALTER TABLE table1 DROP FOREIGN KEY fk1`); await dbExec(`ALTER TABLE table1 DROP FOREIGN KEY fk1`);
await dbExec(`ALTER TABLE table1 DROP INDEX fk1_idx`); await dbExec(`ALTER TABLE table1 DROP INDEX fk1_idx`);
} }
await settings.metaData.clickReload(); await settings.dataSources.metaData.clickReload();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: 'Table1', model: 'Table1',
state: 'Relation removed', state: 'Relation removed',
}); });
//verify after sync //verify after sync
await settings.metaData.sync(); await settings.dataSources.metaData.sync();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: 'Table1', model: 'Table1',
state: 'No change identified', state: 'No change identified',
@ -119,16 +119,16 @@ test.describe('Meta sync', () => {
await dbExec(`ALTER TABLE table1 ADD COLUMN newCol INT`); await dbExec(`ALTER TABLE table1 ADD COLUMN newCol INT`);
} }
await settings.metaData.clickReload(); await settings.dataSources.metaData.clickReload();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: `Table1`, model: `Table1`,
state: 'New column(newCol)', state: 'New column(newCol)',
}); });
//verify after sync //verify after sync
await settings.metaData.sync(); await settings.dataSources.metaData.sync();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: 'Table1', model: 'Table1',
state: 'No change identified', state: 'No change identified',
@ -143,16 +143,16 @@ test.describe('Meta sync', () => {
await dbExec(`ALTER TABLE table1 RENAME COLUMN newCol TO newColName`); await dbExec(`ALTER TABLE table1 RENAME COLUMN newCol TO newColName`);
} }
await settings.metaData.clickReload(); await settings.dataSources.metaData.clickReload();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: `Table1`, model: `Table1`,
state: 'New column(newColName), Column removed(newCol)', state: 'New column(newColName), Column removed(newCol)',
}); });
//verify after sync //verify after sync
await settings.metaData.sync(); await settings.dataSources.metaData.sync();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: 'Table1', model: 'Table1',
state: 'No change identified', state: 'No change identified',
@ -162,16 +162,16 @@ test.describe('Meta sync', () => {
// todo: Add for sqlite // todo: Add for sqlite
if (!isSqlite(context)) { if (!isSqlite(context)) {
await dbExec(`ALTER TABLE table1 DROP COLUMN newColName`); await dbExec(`ALTER TABLE table1 DROP COLUMN newColName`);
await settings.metaData.clickReload(); await settings.dataSources.metaData.clickReload();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: `Table1`, model: `Table1`,
state: 'Column removed(newColName)', state: 'Column removed(newColName)',
}); });
//verify after sync //verify after sync
await settings.metaData.sync(); await settings.dataSources.metaData.sync();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: 'Table1', model: 'Table1',
state: 'No change identified', state: 'No change identified',
@ -181,51 +181,51 @@ test.describe('Meta sync', () => {
// Delete table // Delete table
await dbExec(`DROP TABLE table1`); await dbExec(`DROP TABLE table1`);
await dbExec(`DROP TABLE table2`); await dbExec(`DROP TABLE table2`);
await settings.metaData.clickReload(); await settings.dataSources.metaData.clickReload();
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16, index: isPg(context) ? 21 : 16,
model: `table1`, model: `table1`,
state: 'Table removed', state: 'Table removed',
}); });
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 22 : 17, index: isPg(context) ? 22 : 17,
model: `table2`, model: `table2`,
state: 'Table removed', state: 'Table removed',
}); });
//verify after sync //verify after sync
await settings.metaData.sync(); await settings.dataSources.metaData.sync();
if (isSqlite(context)) { if (isSqlite(context)) {
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: 16, index: 16,
model: 'CustomerList', model: 'CustomerList',
state: 'No change identified', state: 'No change identified',
}); });
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: 17, index: 17,
model: 'FilmList', model: 'FilmList',
state: 'No change identified', state: 'No change identified',
}); });
} }
if (isPg(context)) { if (isPg(context)) {
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: 21, index: 21,
model: 'ActorInfo', model: 'ActorInfo',
state: 'No change identified', state: 'No change identified',
}); });
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: 22, index: 22,
model: 'CustomerList', model: 'CustomerList',
state: 'No change identified', state: 'No change identified',
}); });
} else if (isMysql(context)) { } else if (isMysql(context)) {
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: 16, index: 16,
model: 'ActorInfo', model: 'ActorInfo',
state: 'No change identified', state: 'No change identified',
}); });
await settings.metaData.verifyRow({ await settings.dataSources.metaData.verifyRow({
index: 17, index: 17,
model: 'CustomerList', model: 'CustomerList',
state: 'No change identified', state: 'No change identified',
@ -242,10 +242,11 @@ test.describe('Meta sync', () => {
); );
await dashboard.gotoSettings(); await dashboard.gotoSettings();
await settings.selectTab({ tab: SettingTab.ProjectMetadata }); await settings.selectTab({ tab: SettingTab.DataSources });
await settings.dataSources.openMetaSync();
await settings.metaData.clickReload(); await settings.dataSources.metaData.clickReload();
await settings.metaData.sync(); await settings.dataSources.metaData.sync();
await settings.close(); await settings.close();
await dashboard.treeView.openTable({ title: 'Table1' }); await dashboard.treeView.openTable({ title: 'Table1' });

20
tests/playwright/tests/rolesCreate.spec.ts

@ -1,7 +1,7 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import { DashboardPage } from '../pages/Dashboard'; import { DashboardPage } from '../pages/Dashboard';
import setup from '../setup'; import setup from '../setup';
import { SettingsPage, SettingsSubTab, SettingTab } from '../pages/Dashboard/Settings'; import { SettingsPage, SettingTab } from '../pages/Dashboard/Settings';
import { SignupPage } from '../pages/SignupPage'; import { SignupPage } from '../pages/SignupPage';
import { ProjectsPage } from '../pages/ProjectsPage'; import { ProjectsPage } from '../pages/ProjectsPage';
@ -46,16 +46,16 @@ test.describe('User roles', () => {
// configure access control // configure access control
await dashboard.gotoSettings(); await dashboard.gotoSettings();
await settings.selectTab({ await settings.selectTab({
tab: SettingTab.ProjectMetadata, tab: SettingTab.DataSources,
subTab: SettingsSubTab.ACL,
}); });
await settings.acl.toggle({ table: 'Language', role: 'editor' }); await settings.dataSources.openAcl();
await settings.acl.toggle({ table: 'Language', role: 'commenter' }); await settings.dataSources.acl.toggle({ table: 'Language', role: 'editor' });
await settings.acl.toggle({ table: 'Language', role: 'viewer' }); await settings.dataSources.acl.toggle({ table: 'Language', role: 'commenter' });
await settings.acl.toggle({ table: 'CustomerList', role: 'editor' }); await settings.dataSources.acl.toggle({ table: 'Language', role: 'viewer' });
await settings.acl.toggle({ table: 'CustomerList', role: 'commenter' }); await settings.dataSources.acl.toggle({ table: 'CustomerList', role: 'editor' });
await settings.acl.toggle({ table: 'CustomerList', role: 'viewer' }); await settings.dataSources.acl.toggle({ table: 'CustomerList', role: 'commenter' });
await settings.acl.save(); await settings.dataSources.acl.toggle({ table: 'CustomerList', role: 'viewer' });
await settings.dataSources.acl.save();
await settings.close(); await settings.close();
// Role test // Role test

20
tests/playwright/tests/rolesPreview.spec.ts

@ -2,7 +2,7 @@ import { test } from '@playwright/test';
import { DashboardPage } from '../pages/Dashboard'; import { DashboardPage } from '../pages/Dashboard';
import setup from '../setup'; import setup from '../setup';
import { ToolbarPage } from '../pages/Dashboard/common/Toolbar'; import { ToolbarPage } from '../pages/Dashboard/common/Toolbar';
import { SettingsPage, SettingsSubTab, SettingTab } from '../pages/Dashboard/Settings'; import { SettingsPage, SettingTab } from '../pages/Dashboard/Settings';
const roles = ['Editor', 'Commenter', 'Viewer']; const roles = ['Editor', 'Commenter', 'Viewer'];
@ -30,16 +30,16 @@ test.describe('Preview Mode', () => {
// configure access control // configure access control
await dashboard.gotoSettings(); await dashboard.gotoSettings();
await settings.selectTab({ await settings.selectTab({
tab: SettingTab.ProjectMetadata, tab: SettingTab.DataSources,
subTab: SettingsSubTab.ACL,
}); });
await settings.acl.toggle({ table: 'Language', role: 'editor' }); await settings.dataSources.openAcl();
await settings.acl.toggle({ table: 'Language', role: 'commenter' }); await settings.dataSources.acl.toggle({ table: 'Language', role: 'editor' });
await settings.acl.toggle({ table: 'Language', role: 'viewer' }); await settings.dataSources.acl.toggle({ table: 'Language', role: 'commenter' });
await settings.acl.toggle({ table: 'CustomerList', role: 'editor' }); await settings.dataSources.acl.toggle({ table: 'Language', role: 'viewer' });
await settings.acl.toggle({ table: 'CustomerList', role: 'commenter' }); await settings.dataSources.acl.toggle({ table: 'CustomerList', role: 'editor' });
await settings.acl.toggle({ table: 'CustomerList', role: 'viewer' }); await settings.dataSources.acl.toggle({ table: 'CustomerList', role: 'commenter' });
await settings.acl.save(); await settings.dataSources.acl.toggle({ table: 'CustomerList', role: 'viewer' });
await settings.dataSources.acl.save();
await settings.close(); await settings.close();
// Role test // Role test

Loading…
Cancel
Save