Browse Source

feat(testing): Stability

pull/3848/head
Muhammed Mustafa 2 years ago
parent
commit
f476c3d927
  1. 2
      packages/nc-gui/composables/useApi/index.ts
  2. 2
      packages/nc-gui/layouts/base.vue
  3. 2
      packages/nc-gui/layouts/shared-view.vue
  4. 6
      scripts/playwright/pages/Dashboard/ExpandedForm/index.ts
  5. 7
      scripts/playwright/pages/Dashboard/Grid/index.ts
  6. 9
      scripts/playwright/pages/Dashboard/Import/ImportTemplate.ts
  7. 2
      scripts/playwright/pages/Dashboard/common/ProjectMenu/index.ts
  8. 53
      scripts/playwright/pages/Dashboard/common/Toolbar/Fields.ts
  9. 48
      scripts/playwright/pages/Dashboard/common/Toolbar/Filter.ts
  10. 19
      scripts/playwright/pages/Dashboard/common/Toolbar/Sort.ts
  11. 6
      scripts/playwright/pages/Dashboard/index.ts
  12. 4
      scripts/playwright/pages/LoginPage/index.ts
  13. 2
      scripts/playwright/playwright.config.ts
  14. 2
      scripts/playwright/tests/import.spec.ts
  15. 2
      scripts/playwright/tests/rolesCreate.spec.ts
  16. 2
      scripts/playwright/tests/viewGridShare.spec.ts

2
packages/nc-gui/composables/useApi/index.ts

@ -41,8 +41,6 @@ export function useApi<Data = any, RequestConfig = any>({
*/
const { count, inc, dec } = useCounter(0)
watchEffect(() => console.log('useApi: count', count.value))
/** is request loading */
const isLoading = ref(false)

2
packages/nc-gui/layouts/base.vue

@ -57,7 +57,7 @@ hooks.hook('page:finish', () => {
</div>
<div class="!text-white flex justify-center">
<div v-show="isLoading" class="flex items-center gap-2 ml-3">
<div class="flex items-center gap-2 ml-3" pw-data="nc-loading">
{{ $t('general.loading') }}
<MdiReload :class="{ 'animate-infinite animate-spin': isLoading }" />

2
packages/nc-gui/layouts/shared-view.vue

@ -53,7 +53,7 @@ export default {
<div class="flex justify-center items-center">
<div class="flex items-center gap-2 ml-3 text-white">
<template v-if="isLoading">
<span class="text-white">{{ $t('general.loading') }}</span>
<span class="text-white" pw-data="nc-loading">{{ $t('general.loading') }}</span>
<MdiReload :class="{ 'animate-infinite animate-spin ': isLoading }" />
</template>

6
scripts/playwright/pages/Dashboard/ExpandedForm/index.ts

@ -85,10 +85,8 @@ export class ExpandedFormPage extends BasePage {
}
async verify({ header, url }: { header: string; url: string }) {
await expect(
await this.get().locator(`.nc-expanded-form-header`).last().innerText()
).toContain(header);
await expect(await this.rootPage.url()).toContain(url);
await expect(this.get().locator(`.nc-expanded-form-header`).last()).toContainText(header);
await expect.poll(() => this.rootPage.url()).toContain(url);
}
async close() {

7
scripts/playwright/pages/Dashboard/Grid/index.ts

@ -94,6 +94,8 @@ export class GridPage extends BasePage {
} else {
await this.rootPage.waitForTimeout(300);
}
await this.dashboard.waitForLoaderToDisappear();
}
async editRow({
@ -124,6 +126,8 @@ export class GridPage extends BasePage {
} else {
await this.rootPage.waitForTimeout(300);
}
await this.dashboard.waitForLoaderToDisappear();
}
async verifyRow({ index }: { index: number }) {
@ -151,7 +155,9 @@ export class GridPage extends BasePage {
await this.rootPage
.locator("span.ant-dropdown-menu-title-content > nc-project-menu-item")
.waitFor({ state: "hidden" });
await this.rootPage.waitForTimeout(300);
await this.dashboard.waitForLoaderToDisappear();
}
async addRowRightClickMenu(index: number) {
@ -197,6 +203,7 @@ export class GridPage extends BasePage {
button: "right",
});
await this.rootPage.locator("text=Delete Selected Rows").click();
await this.dashboard.waitForLoaderToDisappear();
}
private async pagination({ page }: { page: string }) {

9
scripts/playwright/pages/Dashboard/Import/ImportTemplate.ts

@ -66,7 +66,14 @@ export class ImportTemplatePage extends BasePage {
}
await this.get().locator('button:has-text("Back"):visible').waitFor();
await this.get().locator('button:has-text("Import"):visible').click();
await this.waitForResponse({
requestUrlPathToMatch: '/api/v1/db/data/noco/',
httpMethodsToMatch: ['GET'],
uiAction: this.get().locator('button:has-text("Import"):visible').click()
});
await this.dashboard.waitForTabRender({
title: tblList[0],
})
}
private async expandTableList(param: { index: number }) {

2
scripts/playwright/pages/Dashboard/common/ProjectMenu/index.ts

@ -30,7 +30,7 @@ export class ProjectMenuObject extends BasePage {
await this.rootPage
.locator(`div.nc-project-menu-item:has-text("${subMenu}"):visible`)
.click();
await this.rootPage.waitForTimeout(10000);
await this.rootPage.waitForTimeout(1000);
}
}
}

53
scripts/playwright/pages/Dashboard/common/Toolbar/Fields.ts

@ -14,12 +14,17 @@ export class ToolbarFieldsPage extends BasePage {
return this.rootPage.locator(`[pw-data="nc-fields-menu"]`);
}
async toggle({ title }: { title: string }) {
// todo: Click and toggle are similar method. Remove one of them
async toggle({ title, isLocallySaved }: { title: string; isLocallySaved?: boolean }) {
await this.toolbar.clickFields();
await this.get()
.locator(`[pw-data="nc-fields-menu-${title}"]`)
.locator('input[type="checkbox"]')
.click();
await this.waitForResponse({
uiAction: this.get()
.locator(`[pw-data="nc-fields-menu-${title}"]`)
.locator('input[type="checkbox"]')
.click(),
requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/',
httpMethodsToMatch: ['GET'],
});
await this.toolbar.clickFields();
}
@ -35,29 +40,45 @@ export class ToolbarFieldsPage extends BasePage {
}
}
async click({ title }: { title: string }) {
await this.get()
.locator(`[pw-data="nc-fields-menu-${title}"]`)
.locator('input[type="checkbox"]')
.click();
async click({ title, isLocallySaved }: { title: string; isLocallySaved?: boolean }) {
await this.waitForResponse({
uiAction: this.get()
.locator(`[pw-data="nc-fields-menu-${title}"]`)
.locator('input[type="checkbox"]')
.click(),
requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/',
httpMethodsToMatch: ['GET'],
});
await this.toolbar.parent.waitLoading();
}
async hideAll() {
async hideAll({ isLocallySaved }: { isLocallySaved?: boolean } = {}) {
await this.toolbar.clickFields();
await this.get().locator(`button:has-text("Hide all")`).click();
await this.waitForResponse({
uiAction: this.get().locator(`button:has-text("Hide all")`).click(),
requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/',
httpMethodsToMatch: ['GET'],
});
await this.toolbar.clickFields();
}
async showAll() {
async showAll({ isLocallySaved }: { isLocallySaved? : boolean } = {}) {
await this.toolbar.clickFields();
await this.get().locator(`button:has-text("Show all")`).click();
await this.waitForResponse({
uiAction: this.get().locator(`button:has-text("Show all")`).click(),
requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/',
httpMethodsToMatch: ['GET'],
});
await this.toolbar.clickFields();
}
async toggleShowSystemFields() {
async toggleShowSystemFields({ isLocallySaved }: { isLocallySaved?: boolean } = {}) {
await this.toolbar.clickFields();
await this.get().locator(`.nc-fields-show-system-fields`).click();
await this.waitForResponse({
uiAction: this.get().locator(`.nc-fields-show-system-fields`).click(),
requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/',
httpMethodsToMatch: ['GET'],
});
await this.toolbar.clickFields();
}
}

48
scripts/playwright/pages/Dashboard/common/Toolbar/Filter.ts

@ -52,48 +52,50 @@ export class ToolbarFilterPage extends BasePage {
await this.get().locator(`button:has-text("Add Filter")`).first().click();
const selectedColumnTitle = await this.rootPage.locator('.nc-filter-field-select').textContent();
await this.rootPage.locator(".nc-filter-field-select").last().click();
await this.rootPage
if(selectedColumnTitle !== columnTitle) {
const selectColumn = this.rootPage
.locator("div.ant-select-dropdown.nc-dropdown-toolbar-field-list")
.locator(`div[label="${columnTitle}"][aria-selected="false"]:visible`)
.click();
await this.waitForResponse({
uiAction: selectColumn,
httpMethodsToMatch: isLocallySaved ? [ "GET" ] : ["POST", "PATCH" ],
requestUrlPathToMatch: isLocallySaved ? `/api/v1/db/public/` : `/filters`,
});
}
await this.rootPage.locator(".nc-filter-operation-select").last().click();
await this.rootPage
const selectedOpType = await this.rootPage.locator('.nc-filter-operation-select').textContent();
if(selectedOpType !== opType) {
await this.rootPage.locator(".nc-filter-operation-select").last().click();
const selectOpType = this.rootPage
.locator(".nc-dropdown-filter-comp-op")
.locator(`.ant-select-item:has-text("${opType}")`)
.click();
await this.waitForResponse({
uiAction: selectOpType,
httpMethodsToMatch: isLocallySaved ? [ "GET" ] : ["POST", "PATCH"],
requestUrlPathToMatch: isLocallySaved ? `/api/v1/db/public/` : `/filters`,
});
}
const fillFilter = this.rootPage
.locator(".nc-filter-value-select")
.last()
.fill(value);
await this.waitForResponse({
uiAction: fillFilter,
httpMethodsToMatch: ["GET"],
requestUrlPathToMatch: isLocallySaved ? `/api/v1/db/public/` : `/api/v1/db/data/noco/`,
});
if (isLocallySaved) {
await this.waitForResponse({
uiAction: fillFilter,
httpMethodsToMatch: ["GET"],
requestUrlPathToMatch: `${value.replace(" ", "+")}`,
});
} else {
await this.waitForResponse({
uiAction: fillFilter,
httpMethodsToMatch: ["POST", "PATCH"],
requestUrlPathToMatch: "/filters",
});
}
await this.toolbar.clickFilter();
await this.toolbar.parent.waitLoading()
}
click({ title }: { title: string }) {
return this.get()
.locator(`[pw-data="nc-fields-menu-${title}"]`)
.locator('input[type="checkbox"]')
.click();
}
async resetFilter() {
await this.toolbar.clickFilter();
await this.waitForResponse({

19
scripts/playwright/pages/Dashboard/common/Toolbar/Sort.ts

@ -55,20 +55,11 @@ export class ToolbarSortPage extends BasePage {
.nth(isAscending ? 0 : 1)
.click();
if(isLocallySaved) {
await this.waitForResponse({
uiAction: selectSortDirection,
httpMethodsToMatch: ["GET"],
requestUrlPathToMatch: `${isAscending ? "asc" : "desc"}`,
})
} else {
await this.waitForResponse({
uiAction: selectSortDirection,
httpMethodsToMatch: ["POST", "PATCH"],
requestUrlPathToMatch: "/sorts",
})
}
await this.waitForResponse({
uiAction: selectSortDirection,
httpMethodsToMatch: ["GET"],
requestUrlPathToMatch: isLocallySaved ? `/api/v1/db/public/`: `/api/v1/db/data/noco/`,
});
// close sort menu
await this.toolbar.clickSort();

6
scripts/playwright/pages/Dashboard/index.ts

@ -234,4 +234,10 @@ export class DashboardPage extends BasePage {
}
await this.rootPage.locator('[pw-data="nc-project-menu"]').click();
}
async waitForLoaderToDisappear() {
await this.rootPage
.locator('[pw-data="nc-loading"]')
.waitFor({ state: "hidden" });
}
}

4
scripts/playwright/pages/LoginPage/index.ts

@ -35,11 +35,15 @@ export class LoginPage extends BasePage {
async submit() {
await this.get().locator(`[pw-data="nc-form-signin__submit"]`).click();
await expect(this.rootPage).toHaveURL("http://localhost:3000/#/");
}
async signIn({ email, password, withoutPrefix }: { email: string; password: string, withoutPrefix?: boolean }) {
await this.goto();
// todo: Login page is sometimes not loaded. Probably because of lazy loading
await this.rootPage.waitForTimeout(1500);
await this.fillEmail({email, withoutPrefix});
await this.fillPassword(password);
await this.submit();

2
scripts/playwright/playwright.config.ts

@ -13,7 +13,7 @@ require('dotenv').config();
const config: PlaywrightTestConfig = {
testDir: process.env.PW_QUICK_TEST ? './quickTests' : './tests',
/* Maximum time one test can run for. */
timeout: process.env.CI ? 80 * 1000 : 65 * 1000,
timeout: process.env.CI ? 140 * 1000 : 100 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.

2
scripts/playwright/tests/import.spec.ts

@ -11,7 +11,7 @@ test.describe("Import", () => {
test.setTimeout(150000);
test.beforeEach(async ({ page }) => {
page.setDefaultTimeout(50000);
page.setDefaultTimeout(70000);
context = await setup({ page, isEmptyProject: true });
dashboard = new DashboardPage(page, context.project);
});

2
scripts/playwright/tests/rolesCreate.spec.ts

@ -32,6 +32,8 @@ test.describe("User roles", () => {
});
test("Create role", async () => {
test.setTimeout(150000);
// close 'Team & Auth' tab
await dashboard.closeTab({ title: "Team & Auth" });
await dashboard.gotoSettings();

2
scripts/playwright/tests/viewGridShare.spec.ts

@ -133,7 +133,7 @@ test.describe("Shared view", () => {
opType: "is like",
isLocallySaved: true,
});
await sharedPage.grid.toolbar.fields.toggle({ title: "LastUpdate" });
await sharedPage.grid.toolbar.fields.toggle({ title: "LastUpdate", isLocallySaved: true });
expectedColumns[6].isVisible = false;
// verify new sort & filter criteria

Loading…
Cancel
Save