diff --git a/packages/nc-gui/composables/useApi/index.ts b/packages/nc-gui/composables/useApi/index.ts index 7aa794f63c..57f86042b9 100644 --- a/packages/nc-gui/composables/useApi/index.ts +++ b/packages/nc-gui/composables/useApi/index.ts @@ -41,8 +41,6 @@ export function useApi({ */ const { count, inc, dec } = useCounter(0) - watchEffect(() => console.log('useApi: count', count.value)) - /** is request loading */ const isLoading = ref(false) diff --git a/packages/nc-gui/layouts/base.vue b/packages/nc-gui/layouts/base.vue index cdd6ada9c3..215106dbb2 100644 --- a/packages/nc-gui/layouts/base.vue +++ b/packages/nc-gui/layouts/base.vue @@ -57,7 +57,7 @@ hooks.hook('page:finish', () => {
-
+
{{ $t('general.loading') }} diff --git a/packages/nc-gui/layouts/shared-view.vue b/packages/nc-gui/layouts/shared-view.vue index 9c9b026669..4f5ffa0544 100644 --- a/packages/nc-gui/layouts/shared-view.vue +++ b/packages/nc-gui/layouts/shared-view.vue @@ -53,7 +53,7 @@ export default {
diff --git a/scripts/playwright/pages/Dashboard/ExpandedForm/index.ts b/scripts/playwright/pages/Dashboard/ExpandedForm/index.ts index a16d5c9a08..9915bbfaa4 100644 --- a/scripts/playwright/pages/Dashboard/ExpandedForm/index.ts +++ b/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() { diff --git a/scripts/playwright/pages/Dashboard/Grid/index.ts b/scripts/playwright/pages/Dashboard/Grid/index.ts index 2e5e39915a..6221704f48 100644 --- a/scripts/playwright/pages/Dashboard/Grid/index.ts +++ b/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 }) { diff --git a/scripts/playwright/pages/Dashboard/Import/ImportTemplate.ts b/scripts/playwright/pages/Dashboard/Import/ImportTemplate.ts index 19fa72a61e..fb1aa6837e 100644 --- a/scripts/playwright/pages/Dashboard/Import/ImportTemplate.ts +++ b/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 }) { diff --git a/scripts/playwright/pages/Dashboard/common/ProjectMenu/index.ts b/scripts/playwright/pages/Dashboard/common/ProjectMenu/index.ts index 65d50f6e9e..1756808cbb 100644 --- a/scripts/playwright/pages/Dashboard/common/ProjectMenu/index.ts +++ b/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); } } } diff --git a/scripts/playwright/pages/Dashboard/common/Toolbar/Fields.ts b/scripts/playwright/pages/Dashboard/common/Toolbar/Fields.ts index be25cf22d9..d5da79099d 100644 --- a/scripts/playwright/pages/Dashboard/common/Toolbar/Fields.ts +++ b/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(); } } diff --git a/scripts/playwright/pages/Dashboard/common/Toolbar/Filter.ts b/scripts/playwright/pages/Dashboard/common/Toolbar/Filter.ts index 8c7ba9bb2e..3d20909579 100644 --- a/scripts/playwright/pages/Dashboard/common/Toolbar/Filter.ts +++ b/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({ diff --git a/scripts/playwright/pages/Dashboard/common/Toolbar/Sort.ts b/scripts/playwright/pages/Dashboard/common/Toolbar/Sort.ts index 31845a6e84..6783b8842a 100644 --- a/scripts/playwright/pages/Dashboard/common/Toolbar/Sort.ts +++ b/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(); diff --git a/scripts/playwright/pages/Dashboard/index.ts b/scripts/playwright/pages/Dashboard/index.ts index 05a51d2087..3831274314 100644 --- a/scripts/playwright/pages/Dashboard/index.ts +++ b/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" }); + } } diff --git a/scripts/playwright/pages/LoginPage/index.ts b/scripts/playwright/pages/LoginPage/index.ts index 25da7e8e7f..60259acace 100644 --- a/scripts/playwright/pages/LoginPage/index.ts +++ b/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(); diff --git a/scripts/playwright/playwright.config.ts b/scripts/playwright/playwright.config.ts index a0f23d5df1..786d234acd 100644 --- a/scripts/playwright/playwright.config.ts +++ b/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. diff --git a/scripts/playwright/tests/import.spec.ts b/scripts/playwright/tests/import.spec.ts index 95bfb63a55..0bd141f403 100644 --- a/scripts/playwright/tests/import.spec.ts +++ b/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); }); diff --git a/scripts/playwright/tests/rolesCreate.spec.ts b/scripts/playwright/tests/rolesCreate.spec.ts index 847bdb1286..16ac05eaa5 100644 --- a/scripts/playwright/tests/rolesCreate.spec.ts +++ b/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(); diff --git a/scripts/playwright/tests/viewGridShare.spec.ts b/scripts/playwright/tests/viewGridShare.spec.ts index e860063c66..1045f7c4bd 100644 --- a/scripts/playwright/tests/viewGridShare.spec.ts +++ b/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