diff --git a/packages/noco-docs/content/en/engineering/playwright.md b/packages/noco-docs/content/en/engineering/playwright.md index f946d8e90c..45d8eea8e8 100644 --- a/packages/noco-docs/content/en/engineering/playwright.md +++ b/packages/noco-docs/content/en/engineering/playwright.md @@ -189,7 +189,7 @@ This a method which will reset/clear all the filters. Since this is an action me ```js async resetFilter() { await this.waitForResponse({ - uiAction: this.get().locator('.nc-filter-item-remove-btn').click(), + uiAction: () => this.get().locator('.nc-filter-item-remove-btn').click(), httpMethodsToMatch: ['DELETE'], requestUrlPathToMatch: '/api/v1/db/meta/filters/', }); @@ -221,4 +221,4 @@ async verifyFilter({ title }: { title: string }) { - Open `Summary` tab in the CI workflow in github actions. - Scroll down to `Artifacts` section. - Access reports which suffixed with the db type and shard number(corresponding to the CI workerflow name). i.e `playwright-report-mysql-2` is for `playwright-mysql-2` workflow. -- Download it and run `npm install -D @playwright/test && npx playwright show-report ./` inside the downloaded folder. \ No newline at end of file +- Download it and run `npm install -D @playwright/test && npx playwright show-report ./` inside the downloaded folder. diff --git a/packages/nocodb/package-lock.json b/packages/nocodb/package-lock.json index 54ff491a54..1b7dacd810 100644 --- a/packages/nocodb/package-lock.json +++ b/packages/nocodb/package-lock.json @@ -58,7 +58,7 @@ "lru-cache": "^6.0.0", "mailersend": "^1.1.0", "minio": "^7.0.18", - "mkdirp": "^0.5.5", + "mkdirp": "^2.1.3", "morgan": "^1.10.0", "mssql": "^6.2.0", "multer": "^1.4.2", @@ -4259,6 +4259,18 @@ "run-queue": "^1.0.0" } }, + "node_modules/copy-concurrently/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -10321,6 +10333,17 @@ "node": ">8 <=18" } }, + "node_modules/minio/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/minio/node_modules/through2": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", @@ -10510,14 +10533,17 @@ } }, "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz", + "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==", "bin": { - "mkdirp": "bin/cmd.js" + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mocha": { @@ -10874,6 +10900,18 @@ "run-queue": "^1.0.3" } }, + "node_modules/move-concurrently/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/move-file": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/move-file/-/move-file-1.2.0.tgz", @@ -11021,6 +11059,17 @@ "node": ">= 0.10.0" } }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/multi-stage-sourcemap": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/multi-stage-sourcemap/-/multi-stage-sourcemap-0.3.1.tgz", @@ -17153,6 +17202,17 @@ "node": ">= 0.12.0" } }, + "node_modules/utility/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -18318,6 +18378,18 @@ "node": ">=0.10.0" } }, + "node_modules/webpack/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/webpack/node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -22371,6 +22443,17 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } } }, "copy-descriptor": { @@ -27047,6 +27130,14 @@ "xml2js": "^0.4.15" }, "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, "through2": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", @@ -27213,12 +27304,9 @@ } }, "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" - } + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz", + "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==" }, "mocha": { "version": "10.1.0", @@ -27489,6 +27577,17 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } } }, "move-file": { @@ -27612,6 +27711,16 @@ "on-finished": "^2.3.0", "type-is": "^1.6.4", "xtend": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + } } }, "multi-stage-sourcemap": { @@ -32428,6 +32537,16 @@ "mkdirp": "^0.5.1", "mz": "^2.7.0", "unescape": "^1.0.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + } } }, "utils-merge": { @@ -33032,6 +33151,15 @@ "to-regex": "^3.0.2" } }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", diff --git a/packages/nocodb/package.json b/packages/nocodb/package.json index 3d6be49ca5..ffc724b29b 100644 --- a/packages/nocodb/package.json +++ b/packages/nocodb/package.json @@ -98,7 +98,7 @@ "lru-cache": "^6.0.0", "mailersend": "^1.1.0", "minio": "^7.0.18", - "mkdirp": "^0.5.5", + "mkdirp": "^2.1.3", "morgan": "^1.10.0", "mssql": "^6.2.0", "multer": "^1.4.2", diff --git a/tests/playwright/pages/Account/ChangePassword.ts b/tests/playwright/pages/Account/ChangePassword.ts index 00b3b6f2de..9e9795d5a7 100644 --- a/tests/playwright/pages/Account/ChangePassword.ts +++ b/tests/playwright/pages/Account/ChangePassword.ts @@ -29,7 +29,8 @@ export class ChangePasswordPage extends BasePage { await newPassword.fill(newPass); await confirmPassword.fill(repeatPass); - const submitChangePassword = this.get().locator('button[data-testid="nc-user-settings-form__submit"]').click(); + const submitChangePassword = () => + this.get().locator('button[data-testid="nc-user-settings-form__submit"]').click(); if (networkValidation) { await this.waitForResponse({ uiAction: submitChangePassword, @@ -37,7 +38,7 @@ export class ChangePasswordPage extends BasePage { requestUrlPathToMatch: 'api/v1/auth/password/change', }); } else { - await submitChangePassword; + await submitChangePassword(); } } diff --git a/tests/playwright/pages/Base.ts b/tests/playwright/pages/Base.ts index 783f6c51ca..d363c4fd31 100644 --- a/tests/playwright/pages/Base.ts +++ b/tests/playwright/pages/Base.ts @@ -23,30 +23,31 @@ export default abstract class BasePage { // A function that takes the response body and returns true if the response is the one we are looking for responseJsonMatcher, }: { - uiAction: Promise; + uiAction: () => Promise; requestUrlPathToMatch: string; httpMethodsToMatch?: string[]; responseJsonMatcher?: ResponseSelector; }) { - await Promise.all([ - this.rootPage.waitForResponse(async res => { - let isResJsonMatched = true; - if (responseJsonMatcher) { - try { - isResJsonMatched = responseJsonMatcher(await res.json()); - } catch (e) { - return false; - } + const waitForResposePromise = this.rootPage.waitForResponse(async res => { + let isResJsonMatched = true; + if (responseJsonMatcher) { + try { + isResJsonMatched = responseJsonMatcher(await res.json()); + } catch (e) { + return false; } + } - return ( - res.request().url().includes(requestUrlPathToMatch) && - httpMethodsToMatch.includes(res.request().method()) && - isResJsonMatched - ); - }), - uiAction, - ]); + return ( + res.request().url().includes(requestUrlPathToMatch) && + httpMethodsToMatch.includes(res.request().method()) && + isResJsonMatched + ); + }); + + const uiActionPromise = uiAction(); + + await Promise.all([waitForResposePromise, uiActionPromise]); } async attachFile({ filePickUIAction, filePath }: { filePickUIAction: Promise; filePath: string[] }) { diff --git a/tests/playwright/pages/Dashboard/ExpandedForm/index.ts b/tests/playwright/pages/Dashboard/ExpandedForm/index.ts index fa66bebd0c..0f3d8c432e 100644 --- a/tests/playwright/pages/Dashboard/ExpandedForm/index.ts +++ b/tests/playwright/pages/Dashboard/ExpandedForm/index.ts @@ -92,9 +92,10 @@ export class ExpandedFormPage extends BasePage { await dropdownList.locator('.ant-dropdown-menu-item:has-text("Save & Stay")').click(); } - const saveRowAction = saveAndExitMode - ? this.get().locator('button:has-text("Save & Exit")').click() - : this.get().locator('button:has-text("Save & Stay")').click(); + const saveRowAction = () => + saveAndExitMode + ? this.get().locator('button:has-text("Save & Exit")').click() + : this.get().locator('button:has-text("Save & Stay")').click(); if (waitForRowsData) { await this.waitForResponse({ diff --git a/tests/playwright/pages/Dashboard/Grid/Column/LTAR/ChildList.ts b/tests/playwright/pages/Dashboard/Grid/Column/LTAR/ChildList.ts index 22dd01ede9..fb068e61d7 100644 --- a/tests/playwright/pages/Dashboard/Grid/Column/LTAR/ChildList.ts +++ b/tests/playwright/pages/Dashboard/Grid/Column/LTAR/ChildList.ts @@ -50,7 +50,7 @@ export class ChildList extends BasePage { } async openLinkRecord({ linkTableTitle }: { linkTableTitle: string }) { - const openActions = this.get().locator(`text=/Link to '.*${linkTableTitle}'/i`).click(); + const openActions = () => this.get().locator(`text=/Link to '.*${linkTableTitle}'/i`).click(); await this.waitForResponse({ requestUrlPathToMatch: '/exclude', httpMethodsToMatch: ['GET'], diff --git a/tests/playwright/pages/Dashboard/Grid/Column/index.ts b/tests/playwright/pages/Dashboard/Grid/Column/index.ts index 21af2677bc..9c902566bc 100644 --- a/tests/playwright/pages/Dashboard/Grid/Column/index.ts +++ b/tests/playwright/pages/Dashboard/Grid/Column/index.ts @@ -330,7 +330,7 @@ export class ColumnPageObject extends BasePage { } await this.waitForResponse({ - uiAction: this.rootPage.locator('li[role="menuitem"]:has-text("Hide Field"):visible').click(), + uiAction: () => this.rootPage.locator('li[role="menuitem"]:has-text("Hide Field"):visible').click(), requestUrlPathToMatch: 'api/v1/db/meta/views', httpMethodsToMatch: ['PATCH'], }); @@ -340,7 +340,7 @@ export class ColumnPageObject extends BasePage { async save({ isUpdated }: { isUpdated?: boolean } = {}) { await this.waitForResponse({ - uiAction: this.get().locator('button:has-text("Save")').click(), + uiAction: () => this.get().locator('button:has-text("Save")').click(), requestUrlPathToMatch: 'api/v1/db/data/noco/', httpMethodsToMatch: ['GET'], responseJsonMatcher: json => json['pageInfo'], @@ -375,9 +375,9 @@ export class ColumnPageObject extends BasePage { await this.grid.get().locator(`th[data-title="${title}"] .nc-ui-dt-dropdown`).click(); let menuOption; if (direction === 'desc') { - menuOption = this.rootPage.locator('li[role="menuitem"]:has-text("Sort Descending"):visible').click(); + menuOption = () => this.rootPage.locator('li[role="menuitem"]:has-text("Sort Descending"):visible').click(); } else { - menuOption = this.rootPage.locator('li[role="menuitem"]:has-text("Sort Ascending"):visible').click(); + menuOption = () => this.rootPage.locator('li[role="menuitem"]:has-text("Sort Ascending"):visible').click(); } await this.waitForResponse({ diff --git a/tests/playwright/pages/Dashboard/Grid/index.ts b/tests/playwright/pages/Dashboard/Grid/index.ts index 59b04c53ca..93f3a77b93 100644 --- a/tests/playwright/pages/Dashboard/Grid/index.ts +++ b/tests/playwright/pages/Dashboard/Grid/index.ts @@ -79,10 +79,8 @@ export class GridPage extends BasePage { await this._fillRow({ index, columnHeader, value: rowValue }); - const clickOnColumnHeaderToSave = this.get() - .locator(`[data-title="${columnHeader}"]`) - .locator(`span[title="${columnHeader}"]`) - .click(); + const clickOnColumnHeaderToSave = () => + this.get().locator(`[data-title="${columnHeader}"]`).locator(`span[title="${columnHeader}"]`).click(); if (networkValidation) { await this.waitForResponse({ @@ -92,6 +90,7 @@ export class GridPage extends BasePage { responseJsonMatcher: resJson => resJson?.[columnHeader] === rowValue, }); } else { + await clickOnColumnHeaderToSave(); await this.rootPage.waitForTimeout(300); } @@ -111,10 +110,8 @@ export class GridPage extends BasePage { }) { await this._fillRow({ index, columnHeader, value }); - const clickOnColumnHeaderToSave = this.get() - .locator(`[data-title="${columnHeader}"]`) - .locator(`span[title="${columnHeader}"]`) - .click(); + const clickOnColumnHeaderToSave = () => + this.get().locator(`[data-title="${columnHeader}"]`).locator(`span[title="${columnHeader}"]`).click(); if (networkValidation) { await this.waitForResponse({ @@ -128,6 +125,7 @@ export class GridPage extends BasePage { responseJsonMatcher: resJson => resJson?.[columnHeader] === value, }); } else { + await clickOnColumnHeaderToSave(); await this.rootPage.waitForTimeout(300); } @@ -231,7 +229,7 @@ export class GridPage extends BasePage { async clickPagination({ page }: { page: string }) { await this.waitForResponse({ - uiAction: (await this.pagination({ page })).click(), + uiAction: async () => (await this.pagination({ page })).click(), httpMethodsToMatch: ['GET'], requestUrlPathToMatch: '/views/', responseJsonMatcher: resJson => resJson?.pageInfo, diff --git a/tests/playwright/pages/Dashboard/Import/ImportTemplate.ts b/tests/playwright/pages/Dashboard/Import/ImportTemplate.ts index 8021060f46..9db97b3318 100644 --- a/tests/playwright/pages/Dashboard/Import/ImportTemplate.ts +++ b/tests/playwright/pages/Dashboard/Import/ImportTemplate.ts @@ -65,7 +65,7 @@ export class ImportTemplatePage extends BasePage { await this.waitForResponse({ requestUrlPathToMatch: '/api/v1/db/data/noco/', httpMethodsToMatch: ['GET'], - uiAction: this.get().locator('button:has-text("Import"):visible').click(), + uiAction: () => this.get().locator('button:has-text("Import"):visible').click(), }); await this.dashboard.waitForTabRender({ title: tblList[0], diff --git a/tests/playwright/pages/Dashboard/Settings/Acl.ts b/tests/playwright/pages/Dashboard/Settings/Acl.ts index 0e0c2d0e97..93384a1155 100644 --- a/tests/playwright/pages/Dashboard/Settings/Acl.ts +++ b/tests/playwright/pages/Dashboard/Settings/Acl.ts @@ -19,7 +19,7 @@ export class AclPage extends BasePage { async save() { await this.waitForResponse({ - uiAction: this.get().locator(`button:has-text("Save")`).click(), + uiAction: () => this.get().locator(`button:has-text("Save")`).click(), httpMethodsToMatch: ['POST'], requestUrlPathToMatch: '/visibility-rules', }); diff --git a/tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts b/tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts index 75ae679458..04263fae7c 100644 --- a/tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts +++ b/tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts @@ -14,7 +14,7 @@ export class MiscSettingsPage extends BasePage { } async clickShowM2MTables() { - const clickAction = this.get().locator('input[type="checkbox"]').first().click(); + const clickAction = () => this.get().locator('input[type="checkbox"]').first().click(); await this.waitForResponse({ uiAction: clickAction, requestUrlPathToMatch: 'tables?includeM2M', diff --git a/tests/playwright/pages/Dashboard/TreeView.ts b/tests/playwright/pages/Dashboard/TreeView.ts index eb0372c756..384c85c44b 100644 --- a/tests/playwright/pages/Dashboard/TreeView.ts +++ b/tests/playwright/pages/Dashboard/TreeView.ts @@ -54,7 +54,7 @@ export class TreeViewPage extends BasePage { if (networkResponse === true) { await this.waitForResponse({ - uiAction: this.get().locator(`.nc-project-tree-tbl-${title}`).click(), + uiAction: () => this.get().locator(`.nc-project-tree-tbl-${title}`).click(), httpMethodsToMatch: ['GET'], requestUrlPathToMatch: `/api/v1/db/data/noco/`, responseJsonMatcher: json => json.pageInfo, @@ -74,7 +74,7 @@ export class TreeViewPage extends BasePage { await this.dashboard.get().getByPlaceholder('Enter table name').fill(title); await this.waitForResponse({ - uiAction: this.dashboard.get().locator('button:has-text("Submit")').click(), + uiAction: () => this.dashboard.get().locator('button:has-text("Submit")').click(), httpMethodsToMatch: ['POST'], requestUrlPathToMatch: `/api/v1/db/meta/projects/`, responseJsonMatcher: json => json.title === title && json.type === 'table', @@ -101,7 +101,7 @@ export class TreeViewPage extends BasePage { await this.dashboard.get().locator('div.nc-project-menu-item:has-text("Delete")').click(); await this.waitForResponse({ - uiAction: this.dashboard.get().locator('button:has-text("Yes")').click(), + uiAction: () => this.dashboard.get().locator('button:has-text("Yes")').click(), httpMethodsToMatch: ['DELETE'], requestUrlPathToMatch: `/api/v1/db/meta/tables/`, }); diff --git a/tests/playwright/pages/Dashboard/ViewSidebar/index.ts b/tests/playwright/pages/Dashboard/ViewSidebar/index.ts index 6260f9d5b6..5f9f45b55a 100644 --- a/tests/playwright/pages/Dashboard/ViewSidebar/index.ts +++ b/tests/playwright/pages/Dashboard/ViewSidebar/index.ts @@ -38,10 +38,8 @@ export class ViewSidebarPage extends BasePage { private async createView({ title, locator }: { title: string; locator: Locator }) { await locator.click(); await this.rootPage.locator('input[id="form_item_title"]:visible').fill(title); - const submitAction = this.rootPage - .locator('.ant-modal-content') - .locator('button:has-text("Submit"):visible') - .click(); + const submitAction = () => + this.rootPage.locator('.ant-modal-content').locator('button:has-text("Submit"):visible').click(); await this.waitForResponse({ httpMethodsToMatch: ['POST'], requestUrlPathToMatch: '/api/v1/db/meta/tables/', @@ -128,10 +126,8 @@ export class ViewSidebarPage extends BasePage { .locator(`[data-testid="view-sidebar-view-actions-${title}"]`) .locator('.nc-view-copy-icon') .click(); - const submitAction = this.rootPage - .locator('.ant-modal-content') - .locator('button:has-text("Submit"):visible') - .click(); + const submitAction = () => + this.rootPage.locator('.ant-modal-content').locator('button:has-text("Submit"):visible').click(); await this.waitForResponse({ httpMethodsToMatch: ['POST'], requestUrlPathToMatch: '/api/v1/db/meta/tables/', diff --git a/tests/playwright/pages/Dashboard/WebhookForm/index.ts b/tests/playwright/pages/Dashboard/WebhookForm/index.ts index 6fdc6e0602..47205471c5 100644 --- a/tests/playwright/pages/Dashboard/WebhookForm/index.ts +++ b/tests/playwright/pages/Dashboard/WebhookForm/index.ts @@ -105,7 +105,7 @@ export class WebhookFormPage extends BasePage { } async save() { - const saveAction = this.saveButton.click(); + const saveAction = () => this.saveButton.click(); await this.waitForResponse({ uiAction: saveAction, requestUrlPathToMatch: '/hooks', diff --git a/tests/playwright/pages/Dashboard/common/Cell/RatingCell.ts b/tests/playwright/pages/Dashboard/common/Cell/RatingCell.ts index da8b44d9f7..8514e4ea21 100644 --- a/tests/playwright/pages/Dashboard/common/Cell/RatingCell.ts +++ b/tests/playwright/pages/Dashboard/common/Cell/RatingCell.ts @@ -16,7 +16,7 @@ export class RatingCellPageObject extends BasePage { async select({ index, columnHeader, rating }: { index?: number; columnHeader: string; rating: number }) { await this.waitForResponse({ - uiAction: this.get({ index, columnHeader }).locator('.ant-rate-star > div').nth(rating).click(), + uiAction: () => this.get({ index, columnHeader }).locator('.ant-rate-star > div').nth(rating).click(), httpMethodsToMatch: ['POST', 'PATCH'], requestUrlPathToMatch: 'api/v1/db/data/noco/', }); diff --git a/tests/playwright/pages/Dashboard/common/Cell/index.ts b/tests/playwright/pages/Dashboard/common/Cell/index.ts index 6dea2446a7..71b4856b16 100644 --- a/tests/playwright/pages/Dashboard/common/Cell/index.ts +++ b/tests/playwright/pages/Dashboard/common/Cell/index.ts @@ -75,7 +75,7 @@ export class CellPageObject extends BasePage { async inCellExpand({ index, columnHeader }: CellProps) { await this.get({ index, columnHeader }).hover(); await this.waitForResponse({ - uiAction: this.get({ index, columnHeader }).locator('.nc-action-icon >> nth=0').click(), + uiAction: () => this.get({ index, columnHeader }).locator('.nc-action-icon >> nth=0').click(), requestUrlPathToMatch: '/api/v1/db/data/noco/', httpMethodsToMatch: ['GET'], }); diff --git a/tests/playwright/pages/Dashboard/common/Toolbar/Fields.ts b/tests/playwright/pages/Dashboard/common/Toolbar/Fields.ts index 08c8bfc1ed..1aaddc4581 100644 --- a/tests/playwright/pages/Dashboard/common/Toolbar/Fields.ts +++ b/tests/playwright/pages/Dashboard/common/Toolbar/Fields.ts @@ -17,10 +17,8 @@ export class ToolbarFieldsPage extends BasePage { // todo: Click and toggle are similar method. Remove one of them async toggle({ title, isLocallySaved }: { title: string; isLocallySaved?: boolean }) { await this.toolbar.clickFields(); - const toggleColumn = this.get() - .locator(`[data-testid="nc-fields-menu-${title}"]`) - .locator('input[type="checkbox"]') - .click(); + const toggleColumn = () => + this.get().locator(`[data-testid="nc-fields-menu-${title}"]`).locator('input[type="checkbox"]').click(); await this.waitForResponse({ uiAction: toggleColumn, @@ -43,7 +41,8 @@ export class ToolbarFieldsPage extends BasePage { async click({ title, isLocallySaved }: { title: string; isLocallySaved?: boolean }) { await this.waitForResponse({ - uiAction: this.get().locator(`[data-testid="nc-fields-menu-${title}"]`).locator('input[type="checkbox"]').click(), + uiAction: () => + this.get().locator(`[data-testid="nc-fields-menu-${title}"]`).locator('input[type="checkbox"]').click(), requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/', httpMethodsToMatch: ['GET'], }); @@ -53,7 +52,7 @@ export class ToolbarFieldsPage extends BasePage { async hideAll({ isLocallySaved }: { isLocallySaved?: boolean } = {}) { await this.toolbar.clickFields(); await this.waitForResponse({ - uiAction: this.get().locator(`button:has-text("Hide all")`).click(), + uiAction: () => this.get().locator(`button:has-text("Hide all")`).click(), requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/', httpMethodsToMatch: ['GET'], }); @@ -63,7 +62,7 @@ export class ToolbarFieldsPage extends BasePage { async showAll({ isLocallySaved }: { isLocallySaved?: boolean } = {}) { await this.toolbar.clickFields(); await this.waitForResponse({ - uiAction: this.get().locator(`button:has-text("Show all")`).click(), + uiAction: () => this.get().locator(`button:has-text("Show all")`).click(), requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/', httpMethodsToMatch: ['GET'], }); @@ -73,7 +72,7 @@ export class ToolbarFieldsPage extends BasePage { async toggleShowSystemFields({ isLocallySaved }: { isLocallySaved?: boolean } = {}) { await this.toolbar.clickFields(); await this.waitForResponse({ - uiAction: this.get().locator(`.nc-fields-show-system-fields`).click(), + uiAction: () => this.get().locator(`.nc-fields-show-system-fields`).click(), requestUrlPathToMatch: isLocallySaved ? '/api/v1/db/public/' : '/api/v1/db/data/noco/', httpMethodsToMatch: ['GET'], }); diff --git a/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts b/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts index 9e48388e57..8b8420f00a 100644 --- a/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts +++ b/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts @@ -137,7 +137,7 @@ export class ToolbarFilterPage extends BasePage { } break; default: - fillFilter = this.rootPage.locator('.nc-filter-value-select > input').last().fill(value); + fillFilter = () => this.rootPage.locator('.nc-filter-value-select > input').last().fill(value); await this.waitForResponse({ uiAction: fillFilter, httpMethodsToMatch: ['GET'], @@ -154,7 +154,7 @@ export class ToolbarFilterPage extends BasePage { await this.toolbar.clickFilter(); if (networkValidation) { await this.waitForResponse({ - uiAction: this.get().locator('.nc-filter-item-remove-btn').click(), + uiAction: () => this.get().locator('.nc-filter-item-remove-btn').click(), httpMethodsToMatch: ['DELETE'], requestUrlPathToMatch: '/api/v1/db/meta/filters/', }); diff --git a/tests/playwright/pages/Dashboard/common/Toolbar/Sort.ts b/tests/playwright/pages/Dashboard/common/Toolbar/Sort.ts index 3256c771d5..7da27ba7fe 100644 --- a/tests/playwright/pages/Dashboard/common/Toolbar/Sort.ts +++ b/tests/playwright/pages/Dashboard/common/Toolbar/Sort.ts @@ -61,11 +61,12 @@ export class ToolbarSortPage extends BasePage { // await this.toolbar.parent.dashboard.waitForLoaderToDisappear(); await this.rootPage.locator('.nc-sort-dir-select').last().click(); - const selectSortDirection = this.rootPage - .locator('.nc-dropdown-sort-dir') - .locator('.ant-select-item') - .nth(isAscending ? 0 : 1) - .click(); + const selectSortDirection = () => + this.rootPage + .locator('.nc-dropdown-sort-dir') + .locator('.ant-select-item') + .nth(isAscending ? 0 : 1) + .click(); await this.waitForResponse({ uiAction: selectSortDirection, diff --git a/tests/playwright/pages/Dashboard/common/Toolbar/index.ts b/tests/playwright/pages/Dashboard/common/Toolbar/index.ts index c741273225..6eb70c9dd5 100644 --- a/tests/playwright/pages/Dashboard/common/Toolbar/index.ts +++ b/tests/playwright/pages/Dashboard/common/Toolbar/index.ts @@ -82,10 +82,10 @@ export class ToolbarPage extends BasePage { }: { networkValidation?: boolean } = {}) { const menuOpen = await this.filter.get().isVisible(); - const clickFilterAction = this.get().locator(`button.nc-filter-menu-btn`).click(); + const clickFilterAction = () => this.get().locator(`button.nc-filter-menu-btn`).click(); // Wait for the menu to close if (menuOpen) { - await clickFilterAction; + await clickFilterAction(); await this.filter.get().waitFor({ state: 'hidden' }); } else { if (networkValidation) { @@ -96,7 +96,7 @@ export class ToolbarPage extends BasePage { httpMethodsToMatch: ['GET'], }); } else { - await clickFilterAction; + await clickFilterAction(); } } } diff --git a/tests/playwright/pages/ProjectsPage/index.ts b/tests/playwright/pages/ProjectsPage/index.ts index 0edbb06fa7..224f75cd28 100644 --- a/tests/playwright/pages/ProjectsPage/index.ts +++ b/tests/playwright/pages/ProjectsPage/index.ts @@ -26,7 +26,7 @@ export class ProjectsPage extends BasePage { await this.rootPage.locator(`.nc-metadb-project-name`).waitFor(); await this.rootPage.locator(`input.nc-metadb-project-name`).fill(name); - const createProjectSubmitAction = this.rootPage.locator(`button:has-text("Create")`).click(); + const createProjectSubmitAction = () => this.rootPage.locator(`button:has-text("Create")`).click(); await this.waitForResponse({ uiAction: createProjectSubmitAction, httpMethodsToMatch: ['POST'], @@ -42,7 +42,7 @@ export class ProjectsPage extends BasePage { } async reloadProjects() { - const reloadUiAction = this.get().locator('[data-testid="projects-reload-button"]').click(); + const reloadUiAction = () => this.get().locator('[data-testid="projects-reload-button"]').click(); await this.waitForResponse({ uiAction: reloadUiAction, requestUrlPathToMatch: '/api/v1/db/meta/projects', @@ -119,7 +119,7 @@ export class ProjectsPage extends BasePage { await this.get().locator(`[data-testid="delete-project-${title}"]`).click(); - const deleteProjectAction = this.rootPage.locator(`button:has-text("Yes")`).click(); + const deleteProjectAction = () => this.rootPage.locator(`button:has-text("Yes")`).click(); await this.waitForResponse({ uiAction: deleteProjectAction, httpMethodsToMatch: ['DELETE'], @@ -149,7 +149,7 @@ export class ProjectsPage extends BasePage { await project.locator('input.nc-metadb-project-name').fill(newTitle); // press enter to save - const submitAction = project.locator('input.nc-metadb-project-name').press('Enter'); + const submitAction = () => project.locator('input.nc-metadb-project-name').press('Enter'); await this.waitForResponse({ uiAction: submitAction, requestUrlPathToMatch: 'api/v1/db/meta/projects/', diff --git a/tests/playwright/pages/SharedForm/index.ts b/tests/playwright/pages/SharedForm/index.ts index 0079bde67d..2e27d08c94 100644 --- a/tests/playwright/pages/SharedForm/index.ts +++ b/tests/playwright/pages/SharedForm/index.ts @@ -16,7 +16,7 @@ export class SharedFormPage extends BasePage { async submit() { await this.waitForResponse({ - uiAction: this.get().getByTestId('shared-form-submit-button').click(), + uiAction: () => this.get().getByTestId('shared-form-submit-button').click(), httpMethodsToMatch: ['POST'], requestUrlPathToMatch: '/rows', });