Browse Source

test: playwright test

pull/9314/head
Pranav C 3 months ago
parent
commit
a0758a7ec4
  1. 2
      packages/nc-gui/components/account/setup/Config.vue
  2. 10
      packages/nc-gui/components/account/setup/List.vue
  3. 2
      packages/nc-gui/components/nc/form-builder/index.vue
  4. 2
      packages/nc-gui/pages/account/index/setup/[[nestedPage]].vue
  5. 36
      tests/playwright/pages/Account/Setup.ts
  6. 14
      tests/playwright/pages/Account/SetupConfig.ts
  7. 6
      tests/playwright/pages/Account/SetupList.ts
  8. 3
      tests/playwright/pages/Account/index.ts
  9. 21
      tests/playwright/setup/index.ts
  10. 88
      tests/playwright/tests/db/usersAccounts/accounSetup.spec.ts

2
packages/nc-gui/components/account/setup/Config.vue

@ -84,7 +84,7 @@ const isValid = computed(() => {
</script>
<template>
<div class="flex flex-col h-full h-[calc(100vh_-_40px)]" data-test-id="nc-setup-config">
<div class="flex flex-col h-full h-[calc(100vh_-_40px)]" data-testid="nc-setup-config">
<NcPageHeader>
<template #title>
<div class="flex gap-3 items-center">

10
packages/nc-gui/components/account/setup/List.vue

@ -43,7 +43,7 @@ const closeResetModal = () => {
</script>
<template>
<div class="flex flex-col" data-test-id="nc-setup-list">
<div class="flex flex-col" data-testid="nc-setup-list">
<NcPageHeader>
<template #title>
<span data-rec="true">
@ -55,7 +55,7 @@ const closeResetModal = () => {
<div class="w-full">
<div class="w-950px px-4 mt-3 mx-auto text-lg font-weight-bold">{{ category }} Services</div>
<div class="container">
<div v-for="app in apps" :key="app.title" class="item group" @click="selectApp(app)">
<div v-for="app in apps" :key="app.title" class="item group" @click="selectApp(app)" :data-testid="`nc-setup-list-item-${app.title}`">
<AccountSetupAppIcon :app="app" class="icon" />
<span class="title">{{ app.title }}</span>
<div class="flex-grow" />
@ -72,7 +72,7 @@ const closeResetModal = () => {
<template #overlay>
<NcMenu class="min-w-20">
<NcMenuItem data-test-id="nc-config-reset" @click.stop="showResetPluginModal(app)">
<NcMenuItem data-testid="nc-config-reset" @click.stop="showResetPluginModal(app)">
<span> {{ $t('general.reset') }} </span>
</NcMenuItem>
</NcMenu>
@ -89,7 +89,7 @@ const closeResetModal = () => {
width="448px"
centered
:footer="null"
wrap-class-name="nc-modal-plugin-uninstall"
wrap-class-name="nc-modal-plugin-reset-conform"
>
<div class="flex flex-col h-full">
<div v-if="showResetActiveAppMsg" class="text-base font-weight-bold">
@ -105,7 +105,7 @@ const closeResetModal = () => {
</div>
<div class="flex mt-6 justify-end space-x-2">
<NcButton size="small" type="secondary" @click="closeResetModal"> {{ $t('general.cancel') }}</NcButton>
<NcButton size="small" type="danger" @click="resetPlugin">
<NcButton size="small" type="danger" @click="resetPlugin" data-testid="nc-reset-confirm-btn">
{{ showResetActiveAppMsg ? `${$t('general.reset')} & ${$t('general.switch')}` : $t('general.reset') }}
</NcButton>
</div>

2
packages/nc-gui/components/nc/form-builder/index.vue

@ -42,7 +42,7 @@ const setFormState = (path: string, value: any) => {
class="nc-form-item"
:style="`width:${+field.width || 100}%`"
:required="false"
:data-test-id="`nc-form-input-${field.model}`"
:data-testid="`nc-form-input-${field.model}`"
>
<template v-if="![FormBuilderInputType.Switch].includes(field.type)" #label>
<div class="flex items-center gap-1">

2
packages/nc-gui/pages/account/index/setup/[[nestedPage]].vue

@ -15,7 +15,7 @@ const activeAppId = computed(
</script>
<template>
<div class="h-full" data-test-id="nc-setup">
<div class="h-full" data-testid="nc-setup">
<template v-if="$route.params.app">
<LazyAccountSetupConfig v-if="activeAppId" :id="activeAppId" />
</template>

36
tests/playwright/pages/Account/Setup.ts

@ -2,6 +2,7 @@ import BasePage from '../Base';
import { AccountPage } from './index';
import { AccountSetupConfigPage } from './SetupConfig';
import { AccountSetupListPage } from './SetupList';
import { expect } from '@playwright/test';
export class AccountSetupPage extends BasePage {
private accountPage: AccountPage;
@ -17,24 +18,43 @@ export class AccountSetupPage extends BasePage {
async goto() {
await this.rootPage.goto('/#/account/setup');
await this.rootPage.locator(`[data-test-id="nc-setup"]`).waitForElementState('visible');
await this.rootPage.locator(`[data-test-id="nc-setup"]`).isVisible();
}
get() {
return this.accountPage.get().locator(`[data-test-id="nc-setup"]`);
return this.accountPage.get().getByTestId('nc-setup');
}
openEmailSettings() {}
getCategoryCard(key: 'email' | 'storage' = 'email') {
return this.get().getByTestId(`nc-setup-${key}`);
}
async isConfigured(key: 'email' | 'storage' = 'email') {
return await this.getCategoryCard(key).locator('.nc-configured').isVisible();
async isConfigured(key: 'email' | 'storage' = 'email', isConfigured = true) {
return await expect(this.getCategoryCard(key).locator('.nc-configured')).toHaveCount(isConfigured ? 1 : 0);
}
async configure({
key = 'email',
plugin,
config,
}: {
key: 'email' | 'storage';
plugin: string;
config: Record<string, any>;
}) {
await this.getCategoryCard(key).click();
await this.setupListPage.getPluginItem(plugin).click();
await this.setupConfigPage.fillForm(config);
await this.setupConfigPage.save();
}
async confirmReset() {
return this.rootPage.locator('.nc-modal-plugin-reset-conform').getByTestId('nc-reset-confirm-btn').click();
}
async configure(key: 'email' | 'storage' = 'email') {
await this.getCategoryCard(key).locator('.nc-setup-btn').click();
async resetConfig({ plugin, key }: { plugin: string; key: string }) {
await this.getCategoryCard(key).click();
await this.setupListPage.reset(plugin);
await this.confirmReset();
}
}

14
tests/playwright/pages/Account/SetupConfig.ts

@ -14,24 +14,20 @@ export class AccountSetupConfigPage extends BasePage {
}
get() {
return this.setupPage.get().locator(`[data-test-id="nc-setup-config"]`);
return this.setupPage.get().getByTestId('nc-setup-config');
}
async fillForm(data: any) {
for (const key in data) {
const fieldWrapper = this.get().locator(`[data-test-id="nc-form-input-${key}"]`);
const fieldWrapper = this.get().getByTestId(`nc-form-input-${key}`);
// if switch then toggle
if (await fieldWrapper.locator('.ant-switch').isVisible()) {
if (data[key]) {
await fieldWrapper.locator('.ant-switch').click();
}
} else if (await fieldWrapper.locator('.ant-select').isVisible()) {
await fieldWrapper.locator('.ant-select').click();
await this.rootPage
.locator(`[data-test-id="nc-form-input-${key}"] .ant-select-item:has-text("${data[key]}")`)
.click();
} else {
await fieldWrapper.locator('input').fill(data[key]);
await fieldWrapper.locator('input').focus();
await fieldWrapper.locator('input').fill(data[key]?.toString?.());
}
}
}
@ -39,7 +35,7 @@ export class AccountSetupConfigPage extends BasePage {
await this.get().getByTestId('nc-setup-config-action-test').click();
}
async Save() {
async save() {
await this.get().getByTestId('nc-setup-config-action-save').click();
}
}

6
tests/playwright/pages/Account/SetupList.ts

@ -14,11 +14,11 @@ export class AccountSetupListPage extends BasePage {
}
get() {
return this.setupPage.get().locator(`[data-test-id="nc-setup-list"]`);
return this.setupPage.get().locator(`[data-testid="nc-setup-list"]`);
}
getPluginItem(plugin: string) {
return this.get().locator(`[data-test-id="nc-setup-list-item-${plugin}"]`);
return this.get().locator(`[data-testid="nc-setup-list-item-${plugin}"]`);
}
async isConfigured(plugin: string) {
@ -27,6 +27,6 @@ export class AccountSetupListPage extends BasePage {
async reset(plugin: string) {
await this.getPluginItem(plugin).locator('.nc-setup-plugin-menu').click();
await this.rootPage.locator('.ant-dropdown').locator('[data-test-id="nc-config-reset"].nc-menu-item').click();
await this.rootPage.locator('.ant-dropdown').getByTestId('nc-config-reset').click();
}
}

3
tests/playwright/pages/Account/index.ts

@ -6,9 +6,11 @@ import { AccountUsersPage } from './Users';
import { AccountAppStorePage } from './AppStore';
import { AccountLicensePage } from './License';
import { AccountAuthenticationPage } from './Authentication';
import { AccountSetupPage } from './Setup';
export class AccountPage extends BasePage {
readonly settings: AccountSettingsPage;
readonly setup: AccountSetupPage;
readonly token: AccountTokenPage;
readonly users: AccountUsersPage;
readonly appStore: AccountAppStorePage;
@ -23,6 +25,7 @@ export class AccountPage extends BasePage {
this.appStore = new AccountAppStorePage(this);
this.license = new AccountLicensePage(this);
this.authentication = new AccountAuthenticationPage(this);
this.setup = new AccountSetupPage(this);
}
get() {

21
tests/playwright/setup/index.ts

@ -171,6 +171,7 @@ async function localInit({
isSuperUser = false,
dbType,
resetSsoClients = false,
resetPlugins,
}: {
workerId: string;
isEmptyProject?: boolean;
@ -178,6 +179,7 @@ async function localInit({
isSuperUser?: boolean;
dbType?: string;
resetSsoClients?: boolean;
resetPlugins?: boolean;
}) {
const parallelId = process.env.TEST_PARALLEL_INDEX;
@ -224,6 +226,22 @@ async function localInit({
}
}
// if oss reset the plugins
if (!isEE() && resetPlugins) {
const plugins = (await api.plugin.list()).list ?? [];
for (const plugin of plugins) {
if (!plugin.input) continue;
try {
await api.plugin.update(plugin.id, {
input: null,
active: false,
});
} catch (e) {
console.log(`Error deleting plugin: ${plugin.id}`);
}
}
}
if (isEE() && api['workspace']) {
// Delete associated workspace
// Note that: on worker error, entire thread is reset & worker ID numbering is reset too
@ -359,6 +377,7 @@ const setup = async ({
isSuperUser = false,
url,
resetSsoClients = false,
resetPlugins,
}: {
baseType?: ProjectTypes;
page: Page;
@ -366,6 +385,7 @@ const setup = async ({
isSuperUser?: boolean;
url?: string;
resetSsoClients?: boolean;
resetPlugins?: boolean;
}): Promise<NcContext> => {
console.time('Setup');
@ -390,6 +410,7 @@ const setup = async ({
isSuperUser,
dbType,
resetSsoClients,
resetPlugins,
});
} catch (e) {
console.error(`Error resetting base: ${process.env.TEST_PARALLEL_INDEX}`, e);

88
tests/playwright/tests/db/usersAccounts/accounSetup.spec.ts

@ -1,65 +1,69 @@
import { test } from '@playwright/test';
import { AccountPage } from '../../../pages/Account';
import { AccountSettingsPage } from '../../../pages/Account/Settings';
import { SignupPage } from '../../../pages/SignupPage';
import setup, { unsetup } from '../../../setup';
import { getDefaultPwd } from '../../../tests/utils/general';
import { isEE } from '../../../setup/db';
import { AccountSetupPage } from '../../../pages/Account/Setup';
test.describe('App setup', () => {
// Org level roles are not available in EE
if (isEE()) {
test.skip();
}
test.describe.only('App setup', () => {
// hub will not have this feature
let accountSettingsPage: AccountSettingsPage;
let accountSetupPage: AccountSetupPage;
let accountPage: AccountPage;
// @ts-ignore
let context: any;
test.beforeEach(async ({ page }) => {
context = await setup({ page, isEmptyProject: true });
context = await setup({ page, isEmptyProject: true, isSuperUser: true, resetPlugins: true });
accountPage = new AccountPage(page);
accountSettingsPage = accountPage.settings;
accountSetupPage = accountPage.setup;
});
test.afterEach(async () => {
await unsetup(context);
});
test('Toggle invite only signup', async () => {
test.slow();
await accountSettingsPage.goto({ networkValidation: false });
// enable invite only signup
if (!(await accountSettingsPage.getInviteOnlyCheckboxValue())) {
await accountSettingsPage.toggleInviteOnlyCheckbox();
await accountSettingsPage.checkInviteOnlySignupCheckbox(true);
}
await accountPage.signOut();
const signupPage = new SignupPage(accountPage.rootPage);
await signupPage.goto();
await signupPage.signUp({
email: 'test-user-1@nocodb.com',
password: getDefaultPwd(),
expectedError: 'Not allowed to signup, contact super admin.',
test('Configure email settings', async () => {
await accountSetupPage.goto();
await accountSetupPage.isConfigured('email', false);
await accountSetupPage.configure({
key: 'email',
plugin: 'SMTP',
config: {
host: 'smtp.gmail.com',
port: 587,
username: 'test',
password: 'test',
name: 'gmail.com',
from: 'test@gmail.com',
},
});
await accountSetupPage.goto();
await accountSetupPage.isConfigured('email', true);
await accountSetupPage.resetConfig({
key: 'email',
plugin: 'SMTP',
});
});
await signupPage.rootPage.reload({ waitUntil: 'load' });
await accountSettingsPage.goto({ networkValidation: false });
await accountSettingsPage.checkInviteOnlySignupCheckbox(true);
await accountSettingsPage.toggleInviteOnlyCheckbox();
await accountSettingsPage.checkInviteOnlySignupCheckbox(false);
await accountPage.signOut();
await signupPage.goto();
await signupPage.signUp({
email: 'test-user-1@nocodb.com',
password: getDefaultPwd(),
test('Configure storage settings', async () => {
await accountSetupPage.goto();
await accountSetupPage.isConfigured('storage', false);
await accountSetupPage.configure({
key: 'storage',
plugin: 'S3',
config: {
bucket: 'test',
region: 'us-east-1',
access_key: 'test',
access_secret: 'test',
},
});
await accountSetupPage.goto();
await accountSetupPage.isConfigured('storage', true);
});
});

Loading…
Cancel
Save