Browse Source

Merge pull request #6284 from nocodb/test/warnings-cleanup

test: remove unintended awaits
pull/6288/head
Raju Udava 1 year ago committed by GitHub
parent
commit
5313c9c264
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      tests/playwright/pages/Base.ts
  2. 14
      tests/playwright/pages/Dashboard/ExpandedForm/index.ts
  3. 44
      tests/playwright/pages/Dashboard/Form/index.ts
  4. 10
      tests/playwright/pages/Dashboard/Grid/Column/Attachment.ts
  5. 16
      tests/playwright/pages/Dashboard/Grid/Column/LTAR/ChildList.ts
  6. 12
      tests/playwright/pages/Dashboard/Grid/Column/LTAR/LinkRecord.ts
  7. 4
      tests/playwright/pages/Dashboard/Grid/Column/index.ts
  8. 30
      tests/playwright/pages/Dashboard/Grid/index.ts
  9. 8
      tests/playwright/pages/Dashboard/Import/ImportTemplate.ts
  10. 32
      tests/playwright/pages/Dashboard/Kanban/index.ts
  11. 6
      tests/playwright/pages/Dashboard/Map/index.ts
  12. 4
      tests/playwright/pages/Dashboard/ProjectView/AccessSettingsPage.ts
  13. 2
      tests/playwright/pages/Dashboard/ProjectView/DataSourcePage.ts
  14. 12
      tests/playwright/pages/Dashboard/Settings/Audit.ts
  15. 8
      tests/playwright/pages/Dashboard/Settings/Teams.ts
  16. 2
      tests/playwright/pages/Dashboard/ShareProjectButton/index.ts
  17. 2
      tests/playwright/pages/Dashboard/Sidebar/DocsSidebar.ts
  18. 4
      tests/playwright/pages/Dashboard/SurveyForm/index.ts
  19. 2
      tests/playwright/pages/Dashboard/ViewSidebar/index.ts
  20. 8
      tests/playwright/pages/Dashboard/WebhookForm/index.ts
  21. 6
      tests/playwright/pages/Dashboard/index.ts
  22. 2
      tests/playwright/pages/LoginPage/index.ts
  23. 28
      tests/playwright/pages/ProjectsPage/index.ts
  24. 14
      tests/playwright/pages/SharedForm/index.ts
  25. 2
      tests/playwright/pages/WorkspacePage/HeaderPage.ts
  26. 13
      tests/playwright/pages/WorkspacePage/LeftSideBarPage.ts
  27. 2
      tests/playwright/quickTests/commonTest.ts
  28. 8
      tests/playwright/tests/db/columns/columnAttachments.spec.ts
  29. 1
      tests/playwright/tests/db/columns/columnCheckbox.spec.ts
  30. 22
      tests/playwright/tests/db/columns/columnLtarDragdrop.spec.ts
  31. 3
      tests/playwright/tests/db/features/baseShare.spec.ts
  32. 1
      tests/playwright/tests/db/features/metaSync.spec.ts
  33. 10
      tests/playwright/tests/db/features/webhook.spec.ts
  34. 22
      tests/playwright/tests/db/general/tableOperations.spec.ts
  35. 2
      tests/playwright/tests/db/general/views.spec.ts
  36. 3
      tests/playwright/tests/db/usersAccounts/accountUserManagement.spec.ts
  37. 6
      tests/playwright/tests/db/usersAccounts/authChangePassword.spec.ts
  38. 2
      tests/playwright/tests/db/usersAccounts/rolesCreate.spec.ts
  39. 4
      tests/playwright/tests/db/usersAccounts/rolesSuperUser.spec.ts
  40. 6
      tests/playwright/tests/db/views/viewForm.spec.ts

7
tests/playwright/pages/Base.ts

@ -63,11 +63,12 @@ export default abstract class BasePage {
return found; return found;
}); });
const uiActionWithDelay = () => { const uiActionWithDelay = async () => {
// Create a promise that resolves after a delay // Create a promise that resolves after a delay
const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
// Returning a promise that resolves with the result after the a delay // Returning a promise that resolves with the result after the a delay
return delay(100).then(() => uiAction()); await delay(100);
return await uiAction();
}; };
await Promise.all([waitForResponsePromise, uiActionWithDelay()]); await Promise.all([waitForResponsePromise, uiActionWithDelay()]);
} }

14
tests/playwright/pages/Dashboard/ExpandedForm/index.ts

@ -38,7 +38,7 @@ export class ExpandedFormPage extends BasePage {
// add delay; wait for the menu to appear // add delay; wait for the menu to appear
await this.rootPage.waitForTimeout(500); await this.rootPage.waitForTimeout(500);
const popUpMenu = await this.rootPage.locator('.ant-dropdown'); const popUpMenu = this.rootPage.locator('.ant-dropdown');
await popUpMenu.locator(`.ant-dropdown-menu-item:has-text("${menuItem}")`).click(); await popUpMenu.locator(`.ant-dropdown-menu-item:has-text("${menuItem}")`).click();
} }
@ -55,12 +55,12 @@ export class ExpandedFormPage extends BasePage {
} }
async isDisabledDuplicateRow() { async isDisabledDuplicateRow() {
const isDisabled = await this.duplicateRowButton; const isDisabled = this.duplicateRowButton;
return await isDisabled.count(); return await isDisabled.count();
} }
async isDisabledDeleteRow() { async isDisabledDeleteRow() {
const isDisabled = await this.deleteRowButton; const isDisabled = this.deleteRowButton;
return await isDisabled.count(); return await isDisabled.count();
} }
@ -71,7 +71,7 @@ export class ExpandedFormPage extends BasePage {
} }
async gotoUsingUrlAndRowId({ rowId }: { rowId: string }) { async gotoUsingUrlAndRowId({ rowId }: { rowId: string }) {
const url = await this.dashboard.rootPage.url(); const url = this.dashboard.rootPage.url();
const expandedFormUrl = '/' + url.split('/').slice(3).join('/').split('?')[0] + `?rowId=${rowId}`; const expandedFormUrl = '/' + url.split('/').slice(3).join('/').split('?')[0] + `?rowId=${rowId}`;
await this.rootPage.goto(expandedFormUrl); await this.rootPage.goto(expandedFormUrl);
await this.dashboard.waitForLoaderToDisappear(); await this.dashboard.waitForLoaderToDisappear();
@ -157,7 +157,7 @@ export class ExpandedFormPage extends BasePage {
} }
async openChildCard(param: { column: string; title: string }) { async openChildCard(param: { column: string; title: string }) {
const childList = await this.get().locator(`[data-testid="nc-expand-col-${param.column}"]`); const childList = this.get().locator(`[data-testid="nc-expand-col-${param.column}"]`);
await childList.locator(`.ant-card:has-text("${param.title}")`).click(); await childList.locator(`.ant-card:has-text("${param.title}")`).click();
} }
@ -172,9 +172,9 @@ export class ExpandedFormPage extends BasePage {
expect(await this.btn_moreActions.count()).toBe(1); expect(await this.btn_moreActions.count()).toBe(1);
await this.btn_moreActions.click(); await this.btn_moreActions.click();
const menu = await this.rootPage.locator('.ant-dropdown:visible'); const menu = this.rootPage.locator('.ant-dropdown:visible');
await menu.waitFor({ state: 'visible' }); await menu.waitFor({ state: 'visible' });
const menuItems = await menu.locator('.ant-dropdown-menu-item'); const menuItems = menu.locator('.ant-dropdown-menu-item');
for (let i = 0; i < (await menuItems.count()); i++) { for (let i = 0; i < (await menuItems.count()); i++) {
if (role === 'owner' || role === 'editor' || role === 'creator') { if (role === 'owner' || role === 'editor' || role === 'creator') {
const menuText = ['Reload', 'Duplicate row', 'Delete row', 'Close']; const menuText = ['Reload', 'Duplicate row', 'Delete row', 'Close'];

44
tests/playwright/pages/Dashboard/Form/index.ts

@ -79,62 +79,60 @@ export class FormPage extends BasePage {
} }
async verifyFormFieldLabel({ index, label }: { index: number; label: string }) { async verifyFormFieldLabel({ index, label }: { index: number; label: string }) {
await expect(await this.getFormFields().nth(index).locator('[data-testid="nc-form-input-label"]')).toContainText( await expect(this.getFormFields().nth(index).locator('[data-testid="nc-form-input-label"]')).toContainText(label);
label
);
} }
async verifyFormFieldHelpText({ index, helpText }: { index: number; helpText: string }) { async verifyFormFieldHelpText({ index, helpText }: { index: number; helpText: string }) {
await expect( await expect(
await this.getFormFields().nth(index).locator('[data-testid="nc-form-input-help-text-label"]') this.getFormFields().nth(index).locator('[data-testid="nc-form-input-help-text-label"]')
).toContainText(helpText); ).toContainText(helpText);
} }
async verifyFieldsIsEditable({ index }: { index: number }) { async verifyFieldsIsEditable({ index }: { index: number }) {
await expect(await this.getFormFields().nth(index)).toHaveClass(/nc-editable/); await expect(this.getFormFields().nth(index)).toHaveClass(/nc-editable/);
} }
async verifyAfterSubmitMsg({ msg }: { msg: string }) { async verifyAfterSubmitMsg({ msg }: { msg: string }) {
await expect((await this.afterSubmitMsg.inputValue()).includes(msg)).toBeTruthy(); expect((await this.afterSubmitMsg.inputValue()).includes(msg)).toBeTruthy();
} }
async verifyFormViewFieldsOrder({ fields }: { fields: string[] }) { async verifyFormViewFieldsOrder({ fields }: { fields: string[] }) {
const fieldLabels = await this.get().locator('[data-testid="nc-form-input-label"]'); const fieldLabels = this.get().locator('[data-testid="nc-form-input-label"]');
await expect(await fieldLabels).toHaveCount(fields.length); await expect(fieldLabels).toHaveCount(fields.length);
for (let i = 0; i < fields.length; i++) { for (let i = 0; i < fields.length; i++) {
await expect(await fieldLabels.nth(i)).toContainText(fields[i]); await expect(fieldLabels.nth(i)).toContainText(fields[i]);
} }
} }
async reorderFields({ sourceField, destinationField }: { sourceField: string; destinationField: string }) { async reorderFields({ sourceField, destinationField }: { sourceField: string; destinationField: string }) {
await expect(await this.get().locator(`.nc-form-drag-${sourceField}`)).toBeVisible(); await expect(this.get().locator(`.nc-form-drag-${sourceField}`)).toBeVisible();
await expect(await this.get().locator(`.nc-form-drag-${destinationField}`)).toBeVisible(); await expect(this.get().locator(`.nc-form-drag-${destinationField}`)).toBeVisible();
const src = await this.get().locator(`.nc-form-drag-${sourceField.replace(' ', '')}`); const src = this.get().locator(`.nc-form-drag-${sourceField.replace(' ', '')}`);
const dst = await this.get().locator(`.nc-form-drag-${destinationField.replace(' ', '')}`); const dst = this.get().locator(`.nc-form-drag-${destinationField.replace(' ', '')}`);
await src.dragTo(dst); await src.dragTo(dst);
} }
async removeField({ field, mode }: { mode: string; field: string }) { async removeField({ field, mode }: { mode: string; field: string }) {
if (mode === 'dragDrop') { if (mode === 'dragDrop') {
const src = await this.get().locator(`.nc-form-drag-${field.replace(' ', '')}`); const src = this.get().locator(`.nc-form-drag-${field.replace(' ', '')}`);
const dst = await this.get().locator(`[data-testid="nc-drag-n-drop-to-hide"]`); const dst = this.get().locator(`[data-testid="nc-drag-n-drop-to-hide"]`);
await src.dragTo(dst); await src.dragTo(dst);
} else if (mode === 'hideField') { } else if (mode === 'hideField') {
const src = await this.get().locator(`.nc-form-drag-${field.replace(' ', '')}`); const src = this.get().locator(`.nc-form-drag-${field.replace(' ', '')}`);
await src.locator(`[data-testid="nc-field-remove-icon"]`).click(); await src.locator(`[data-testid="nc-field-remove-icon"]`).click();
} }
} }
async addField({ field, mode }: { mode: string; field: string }) { async addField({ field, mode }: { mode: string; field: string }) {
if (mode === 'dragDrop') { if (mode === 'dragDrop') {
const src = await this.get().locator(`[data-testid="nc-form-hidden-column-${field}"] > div.ant-card-body`); const src = this.get().locator(`[data-testid="nc-form-hidden-column-${field}"] > div.ant-card-body`);
const dst = await this.get().locator(`[data-testid="nc-form-input-Country"]`); const dst = this.get().locator(`[data-testid="nc-form-input-Country"]`);
await src.waitFor({ state: 'visible' }); await src.waitFor({ state: 'visible' });
await dst.waitFor({ state: 'visible' }); await dst.waitFor({ state: 'visible' });
await src.dragTo(dst, { trial: true }); await src.dragTo(dst, { trial: true });
await src.dragTo(dst); await src.dragTo(dst);
} else if (mode === 'clickField') { } else if (mode === 'clickField') {
const src = await this.get().locator(`[data-testid="nc-form-hidden-column-${field}"]`); const src = this.get().locator(`[data-testid="nc-form-hidden-column-${field}"]`);
await src.click(); await src.click();
} }
} }
@ -206,12 +204,12 @@ export class FormPage extends BasePage {
if (required) expectText = label + ' *'; if (required) expectText = label + ' *';
else expectText = label; else expectText = label;
const fieldLabel = await this.get() const fieldLabel = this.get()
.locator(`.nc-form-drag-${field.replace(' ', '')}`) .locator(`.nc-form-drag-${field.replace(' ', '')}`)
.locator('div[data-testid="nc-form-input-label"]'); .locator('div[data-testid="nc-form-input-label"]');
await expect(fieldLabel).toHaveText(expectText); await expect(fieldLabel).toHaveText(expectText);
const fieldHelpText = await this.get() const fieldHelpText = this.get()
.locator(`.nc-form-drag-${field.replace(' ', '')}`) .locator(`.nc-form-drag-${field.replace(' ', '')}`)
.locator('div[data-testid="nc-form-input-help-text-label"]'); .locator('div[data-testid="nc-form-input-help-text-label"]');
await expect(fieldHelpText).toHaveText(helpText); await expect(fieldHelpText).toHaveText(helpText);
@ -232,10 +230,10 @@ export class FormPage extends BasePage {
await this.rootPage.waitForTimeout(100 * retryCounter); await this.rootPage.waitForTimeout(100 * retryCounter);
retryCounter++; retryCounter++;
} }
await expect(await this.getFormAfterSubmit()).toContainText(param.message); await expect(this.getFormAfterSubmit()).toContainText(param.message);
} }
if (true === param.submitAnotherForm) { if (true === param.submitAnotherForm) {
await expect(await this.getFormAfterSubmit().locator('button:has-text("Submit Another Form")')).toBeVisible(); await expect(this.getFormAfterSubmit().locator('button:has-text("Submit Another Form")')).toBeVisible();
} }
if (true === param.showBlankForm) { if (true === param.showBlankForm) {
await this.get().waitFor(); await this.get().waitFor();

10
tests/playwright/pages/Dashboard/Grid/Column/Attachment.ts

@ -34,22 +34,22 @@ export class AttachmentColumnPageObject extends BasePage {
// Checkbox order: Application, Audio, Image, Video, Misc // Checkbox order: Application, Audio, Image, Video, Misc
if (fileCount) { if (fileCount) {
const inputMaxCount = await this.column.get().locator(`.nc-attachment-max-count`); const inputMaxCount = this.column.get().locator(`.nc-attachment-max-count`);
await inputMaxCount.locator(`input`).fill(fileCount.toString()); await inputMaxCount.locator(`input`).fill(fileCount.toString());
} }
if (fileSize) { if (fileSize) {
const inputMaxSize = await this.column.get().locator(`.nc-attachment-max-size`); const inputMaxSize = this.column.get().locator(`.nc-attachment-max-size`);
await inputMaxSize.locator(`input`).fill(fileSize.toString()); await inputMaxSize.locator(`input`).fill(fileSize.toString());
} }
if (fileTypesExcludeList) { if (fileTypesExcludeList) {
// click on nc-allow-all-mime-type-checkbox // click on nc-allow-all-mime-type-checkbox
const allowAllMimeCheckbox = await this.column.get().locator(`.nc-allow-all-mime-type-checkbox`); const allowAllMimeCheckbox = this.column.get().locator(`.nc-allow-all-mime-type-checkbox`);
await allowAllMimeCheckbox.click(); await allowAllMimeCheckbox.click();
const treeList = await this.column.get().locator(`.ant-tree-list`); const treeList = this.column.get().locator(`.ant-tree-list`);
const checkboxList = await treeList.locator(`.ant-tree-treenode`); const checkboxList = treeList.locator(`.ant-tree-treenode`);
for (let i = 0; i < fileTypesExcludeList.length; i++) { for (let i = 0; i < fileTypesExcludeList.length; i++) {
const fileType = fileTypesExcludeList[i]; const fileType = fileTypesExcludeList[i];

16
tests/playwright/pages/Dashboard/Grid/Column/LTAR/ChildList.ts

@ -20,8 +20,8 @@ export class ChildList extends BasePage {
// button: Link to 'City' // button: Link to 'City'
// icon: reload // icon: reload
await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Child list`); await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Child list`);
await expect(await this.get().locator(`text=/Link to '.*${linkField}'/i`).isVisible()).toBeTruthy(); expect(await this.get().locator(`text=/Link to '.*${linkField}'/i`).isVisible()).toBeTruthy();
await expect(await this.get().locator(`[data-testid="nc-child-list-reload"]`).isVisible()).toBeTruthy(); expect(await this.get().locator(`[data-testid="nc-child-list-reload"]`).isVisible()).toBeTruthy();
// child list body validation (card count, card title) // child list body validation (card count, card title)
const cardCount = cardTitle.length; const cardCount = cardTitle.length;
@ -29,20 +29,16 @@ export class ChildList extends BasePage {
{ {
const childList = this.get().locator(`.ant-card`); const childList = this.get().locator(`.ant-card`);
const childCards = await childList.count(); const childCards = await childList.count();
await expect(childCards).toEqual(cardCount); expect(childCards).toEqual(cardCount);
for (let i = 0; i < cardCount; i++) { for (let i = 0; i < cardCount; i++) {
await childList.nth(i).locator('.name').waitFor({ state: 'visible' }); await childList.nth(i).locator('.name').waitFor({ state: 'visible' });
await childList.nth(i).locator('.name').scrollIntoViewIfNeeded(); await childList.nth(i).locator('.name').scrollIntoViewIfNeeded();
await this.rootPage.waitForTimeout(100); await this.rootPage.waitForTimeout(100);
await expect(await childList.nth(i).locator('.name').textContent()).toContain(cardTitle[i]); expect(await childList.nth(i).locator('.name').textContent()).toContain(cardTitle[i]);
// icon: unlink // icon: unlink
// icon: delete // icon: delete
await expect( expect(await childList.nth(i).locator(`[data-testid="nc-child-list-icon-unlink"]`).isVisible()).toBeTruthy();
await childList.nth(i).locator(`[data-testid="nc-child-list-icon-unlink"]`).isVisible() expect(await childList.nth(i).locator(`[data-testid="nc-child-list-icon-delete"]`).isVisible()).toBeTruthy();
).toBeTruthy();
await expect(
await childList.nth(i).locator(`[data-testid="nc-child-list-icon-delete"]`).isVisible()
).toBeTruthy();
} }
} }
} }

12
tests/playwright/pages/Dashboard/Grid/Column/LTAR/LinkRecord.ts

@ -12,26 +12,26 @@ export class LinkRecord extends BasePage {
async verify(cardTitle?: string[]) { async verify(cardTitle?: string[]) {
await this.dashboard.get().locator('.nc-modal-link-record').waitFor(); await this.dashboard.get().locator('.nc-modal-link-record').waitFor();
const linkRecord = await this.get(); const linkRecord = this.get();
// DOM element validation // DOM element validation
// title: Link Record // title: Link Record
// button: Add new record // button: Add new record
// icon: reload // icon: reload
await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Link record`); await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Link record`);
await expect(await linkRecord.locator(`button:has-text("Add new record")`).isVisible()).toBeTruthy(); expect(await linkRecord.locator(`button:has-text("Add new record")`).isVisible()).toBeTruthy();
await expect(await linkRecord.locator(`.nc-reload`).isVisible()).toBeTruthy(); expect(await linkRecord.locator(`.nc-reload`).isVisible()).toBeTruthy();
// placeholder: Filter query // placeholder: Filter query
await expect(await linkRecord.locator(`[placeholder="Filter query"]`).isVisible()).toBeTruthy(); expect(await linkRecord.locator(`[placeholder="Filter query"]`).isVisible()).toBeTruthy();
{ {
const childList = linkRecord.locator(`.ant-card`); const childList = linkRecord.locator(`.ant-card`);
const childCards = await childList.count(); const childCards = await childList.count();
await expect(childCards).toEqual(cardTitle.length); expect(childCards).toEqual(cardTitle.length);
for (let i = 0; i < cardTitle.length; i++) { for (let i = 0; i < cardTitle.length; i++) {
await childList.nth(i).locator('.name').scrollIntoViewIfNeeded(); await childList.nth(i).locator('.name').scrollIntoViewIfNeeded();
await childList.nth(i).locator('.name').waitFor({ state: 'visible' }); await childList.nth(i).locator('.name').waitFor({ state: 'visible' });
await expect(await childList.nth(i).locator('.name').textContent()).toContain(cardTitle[i]); expect(await childList.nth(i).locator('.name').textContent()).toContain(cardTitle[i]);
} }
} }
} }

4
tests/playwright/pages/Dashboard/Grid/Column/index.ts

@ -401,7 +401,7 @@ export class ColumnPageObject extends BasePage {
async sortColumn({ title, direction = 'asc' }: { title: string; direction: 'asc' | 'desc' }) { async sortColumn({ title, direction = 'asc' }: { title: string; direction: 'asc' | 'desc' }) {
await this.grid.get().locator(`th[data-title="${title}"] .nc-ui-dt-dropdown`).click(); await this.grid.get().locator(`th[data-title="${title}"] .nc-ui-dt-dropdown`).click();
let menuOption; let menuOption: { (): Promise<void>; (): Promise<void> };
if (direction === 'desc') { 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 { } else {
@ -444,7 +444,7 @@ export class ColumnPageObject extends BasePage {
async getWidth(param: { title: string }) { async getWidth(param: { title: string }) {
const { title } = param; const { title } = param;
const cell = await this.rootPage.locator(`th[data-title="${title}"]`); const cell = this.rootPage.locator(`th[data-title="${title}"]`);
return await cell.evaluate(el => el.getBoundingClientRect().width); return await cell.evaluate(el => el.getBoundingClientRect().width);
} }
} }

30
tests/playwright/pages/Dashboard/Grid/index.ts

@ -122,7 +122,7 @@ export class GridPage extends BasePage {
// add delay for UI to render (can wait for count to stabilize by reading it multiple times) // add delay for UI to render (can wait for count to stabilize by reading it multiple times)
await this.rootPage.waitForTimeout(100); await this.rootPage.waitForTimeout(100);
await expect(await this.get().locator('.nc-grid-row').count()).toBe(rowCount + 1); expect(await this.get().locator('.nc-grid-row').count()).toBe(rowCount + 1);
await this._fillRow({ index, columnHeader, value: rowValue }); await this._fillRow({ index, columnHeader, value: rowValue });
@ -211,13 +211,13 @@ export class GridPage extends BasePage {
async addRowRightClickMenu(index: number, columnHeader = 'Title') { async addRowRightClickMenu(index: number, columnHeader = 'Title') {
const rowCount = await this.get().locator('.nc-grid-row').count(); const rowCount = await this.get().locator('.nc-grid-row').count();
const cell = await this.get().locator(`td[data-testid="cell-${columnHeader}-${index}"]`).last(); const cell = this.get().locator(`td[data-testid="cell-${columnHeader}-${index}"]`).last();
await cell.click(); await cell.click();
await cell.click({ button: 'right' }); await cell.click({ button: 'right' });
// Click text=Insert New Row // Click text=Insert New Row
await this.rootPage.locator('text=Insert New Row').click(); await this.rootPage.locator('text=Insert New Row').click();
await expect(await this.get().locator('.nc-grid-row')).toHaveCount(rowCount + 1); await expect(this.get().locator('.nc-grid-row')).toHaveCount(rowCount + 1);
} }
async openExpandedRow({ index }: { index: number }) { async openExpandedRow({ index }: { index: number }) {
@ -227,7 +227,7 @@ export class GridPage extends BasePage {
} }
async selectRow(index: number) { async selectRow(index: number) {
const cell: Locator = await this.get().locator(`td[data-testid="cell-Id-${index}"]`); const cell: Locator = this.get().locator(`td[data-testid="cell-Id-${index}"]`);
await cell.hover(); await cell.hover();
await cell.locator('input[type="checkbox"]').check({ force: true }); await cell.locator('input[type="checkbox"]').check({ force: true });
} }
@ -357,24 +357,24 @@ export class GridPage extends BasePage {
index: 0, index: 0,
columnHeader: columnHeader, columnHeader: columnHeader,
}); });
await expect(await cell.locator('input')).not.toBeVisible(); await expect(cell.locator('input')).not.toBeVisible();
// right click menu // right click menu
await this.get().locator(`td[data-testid="cell-${columnHeader}-0"]`).click({ await this.get().locator(`td[data-testid="cell-${columnHeader}-0"]`).click({
button: 'right', button: 'right',
}); });
await expect(await this.rootPage.locator('text=Insert New Row')).not.toBeVisible(); await expect(this.rootPage.locator('text=Insert New Row')).not.toBeVisible();
// in cell-add // in cell-add
await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover(); await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover();
await expect( await expect(
await this.cell.get({ index: 0, columnHeader: 'Cities' }).locator('.nc-action-icon.nc-plus') this.cell.get({ index: 0, columnHeader: 'Cities' }).locator('.nc-action-icon.nc-plus')
).not.toBeVisible(); ).not.toBeVisible();
// expand row // expand row
await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover(); await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover();
await expect( await expect(
await this.cell.get({ index: 0, columnHeader: 'Cities' }).locator('.nc-action-icon >> nth=0') this.cell.get({ index: 0, columnHeader: 'Cities' }).locator('.nc-action-icon >> nth=0')
).not.toBeVisible(); ).not.toBeVisible();
} }
@ -385,7 +385,7 @@ export class GridPage extends BasePage {
index: 0, index: 0,
columnHeader: columnHeader, columnHeader: columnHeader,
}); });
await expect(await cell.locator('input')).toBeVisible(); await expect(cell.locator('input')).toBeVisible();
// press escape to exit edit mode // press escape to exit edit mode
await cell.press('Escape'); await cell.press('Escape');
@ -394,13 +394,11 @@ export class GridPage extends BasePage {
await this.get().locator(`td[data-testid="cell-${columnHeader}-0"]`).click({ await this.get().locator(`td[data-testid="cell-${columnHeader}-0"]`).click({
button: 'right', button: 'right',
}); });
await expect(await this.rootPage.locator('text=Insert New Row')).toBeVisible(); await expect(this.rootPage.locator('text=Insert New Row')).toBeVisible();
// in cell-add // in cell-add
await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover(); await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover();
await expect( await expect(this.cell.get({ index: 0, columnHeader: 'Cities' }).locator('.nc-action-icon.nc-plus')).toBeVisible();
await this.cell.get({ index: 0, columnHeader: 'Cities' }).locator('.nc-action-icon.nc-plus')
).toBeVisible();
} }
async verifyRoleAccess(param: { role: string }) { async verifyRoleAccess(param: { role: string }) {
@ -411,9 +409,9 @@ export class GridPage extends BasePage {
} }
async selectRange({ start, end }: { start: CellProps; end: CellProps }) { async selectRange({ start, end }: { start: CellProps; end: CellProps }) {
const startCell = await this.cell.get({ index: start.index, columnHeader: start.columnHeader }); const startCell = this.cell.get({ index: start.index, columnHeader: start.columnHeader });
const endCell = await this.cell.get({ index: end.index, columnHeader: end.columnHeader }); const endCell = this.cell.get({ index: end.index, columnHeader: end.columnHeader });
const page = await this.dashboard.get().page(); const page = this.dashboard.get().page();
await startCell.hover(); await startCell.hover();
await page.mouse.down(); await page.mouse.down();
await endCell.hover(); await endCell.hover();

8
tests/playwright/pages/Dashboard/Import/ImportTemplate.ts

@ -19,7 +19,7 @@ export class ImportTemplatePage extends BasePage {
async getImportTableList() { async getImportTableList() {
await this.get().locator(`.ant-collapse-header`).nth(0).waitFor(); await this.get().locator(`.ant-collapse-header`).nth(0).waitFor();
const tr = await this.get().locator(`.ant-collapse-header`); const tr = this.get().locator(`.ant-collapse-header`);
const rowCount = await tr.count(); const rowCount = await tr.count();
const tableList: string[] = []; const tableList: string[] = [];
for (let i = 0; i < rowCount; i++) { for (let i = 0; i < rowCount; i++) {
@ -32,7 +32,7 @@ export class ImportTemplatePage extends BasePage {
async getImportColumnList() { async getImportColumnList() {
// return an array // return an array
const columnList: { type: string; name: string }[] = []; const columnList: { type: string; name: string }[] = [];
const tr = await this.get().locator(`tr.ant-table-row-level-0:visible`); const tr = this.get().locator(`tr.ant-table-row-level-0:visible`);
const rowCount = await tr.count(); const rowCount = await tr.count();
for (let i = 0; i < rowCount; i++) { for (let i = 0; i < rowCount; i++) {
// replace \n and \t from innerText // replace \n and \t from innerText
@ -51,9 +51,9 @@ export class ImportTemplatePage extends BasePage {
const tblList = await this.getImportTableList(); const tblList = await this.getImportTableList();
for (let i = 0; i < result.length; i++) { for (let i = 0; i < result.length; i++) {
await expect(tblList[i]).toBe(result[i].name); expect(tblList[i]).toBe(result[i].name);
const columnList = await this.getImportColumnList(); const columnList = await this.getImportColumnList();
await expect(columnList).toEqual(result[i].columns); expect(columnList).toEqual(result[i].columns);
if (i < result.length - 1) { if (i < result.length - 1) {
await this.expandTableList({ index: i + 1 }); await this.expandTableList({ index: i + 1 });
} }

32
tests/playwright/pages/Dashboard/Kanban/index.ts

@ -34,10 +34,10 @@ export class KanbanPage extends BasePage {
async dragDropCard(param: { from: { stack: number; card: number }; to: { stack: number; card: number } }) { async dragDropCard(param: { from: { stack: number; card: number }; to: { stack: number; card: number } }) {
const { from, to } = param; const { from, to } = param;
const srcStack = await this.get().locator(`.nc-kanban-stack`).nth(from.stack); const srcStack = this.get().locator(`.nc-kanban-stack`).nth(from.stack);
const dstStack = await this.get().locator(`.nc-kanban-stack`).nth(to.stack); const dstStack = this.get().locator(`.nc-kanban-stack`).nth(to.stack);
const fromCard = await srcStack.locator(`.nc-kanban-item`).nth(from.card); const fromCard = srcStack.locator(`.nc-kanban-item`).nth(from.card);
const toCard = await dstStack.locator(`.nc-kanban-item`).nth(to.card); const toCard = dstStack.locator(`.nc-kanban-item`).nth(to.card);
console.log(await fromCard.allTextContents()); console.log(await fromCard.allTextContents());
console.log(await toCard.allTextContents()); console.log(await toCard.allTextContents());
@ -68,10 +68,10 @@ export class KanbanPage extends BasePage {
const { order } = param; const { order } = param;
const stacks = await this.get().locator(`.nc-kanban-stack`).count(); const stacks = await this.get().locator(`.nc-kanban-stack`).count();
for (let i = 0; i < stacks; i++) { for (let i = 0; i < stacks; i++) {
const stack = await this.get().locator(`.nc-kanban-stack`).nth(i); const stack = this.get().locator(`.nc-kanban-stack`).nth(i);
await stack.scrollIntoViewIfNeeded(); await stack.scrollIntoViewIfNeeded();
// Since otherwise stack title will be repeated as title is in two divs, with one having hidden class // Since otherwise stack title will be repeated as title is in two divs, with one having hidden class
const stackTitle = await stack.locator(`.nc-kanban-stack-head >> [data-testid="truncate-label"]`); const stackTitle = stack.locator(`.nc-kanban-stack-head >> [data-testid="truncate-label"]`);
await expect(stackTitle).toHaveText(order[i], { ignoreCase: true }); await expect(stackTitle).toHaveText(order[i], { ignoreCase: true });
} }
} }
@ -80,10 +80,10 @@ export class KanbanPage extends BasePage {
const { count } = param; const { count } = param;
const stacks = await this.get().locator(`.nc-kanban-stack`).count(); const stacks = await this.get().locator(`.nc-kanban-stack`).count();
for (let i = 0; i < stacks; i++) { for (let i = 0; i < stacks; i++) {
const stack = await this.get().locator(`.nc-kanban-stack`).nth(i); const stack = this.get().locator(`.nc-kanban-stack`).nth(i);
await stack.scrollIntoViewIfNeeded(); await stack.scrollIntoViewIfNeeded();
const stackFooter = await stack.locator(`.nc-kanban-data-count`).innerText(); const stackFooter = await stack.locator(`.nc-kanban-data-count`).innerText();
await expect(stackFooter).toContain(`${count[i]} record${count[i] !== 1 ? 's' : ''}`); expect(stackFooter).toContain(`${count[i]} record${count[i] !== 1 ? 's' : ''}`);
} }
} }
@ -91,7 +91,7 @@ export class KanbanPage extends BasePage {
const { count } = param; const { count } = param;
const stacks = await this.get().locator(`.nc-kanban-stack`).count(); const stacks = await this.get().locator(`.nc-kanban-stack`).count();
for (let i = 0; i < stacks; i++) { for (let i = 0; i < stacks; i++) {
const stack = await this.get().locator(`.nc-kanban-stack`).nth(i); const stack = this.get().locator(`.nc-kanban-stack`).nth(i);
await stack.scrollIntoViewIfNeeded(); await stack.scrollIntoViewIfNeeded();
const stackCards = stack.locator(`.nc-kanban-item`); const stackCards = stack.locator(`.nc-kanban-item`);
await expect(stackCards).toHaveCount(count[i]); await expect(stackCards).toHaveCount(count[i]);
@ -100,11 +100,11 @@ export class KanbanPage extends BasePage {
async verifyCardOrder(param: { order: string[]; stackIndex: number }) { async verifyCardOrder(param: { order: string[]; stackIndex: number }) {
const { order, stackIndex } = param; const { order, stackIndex } = param;
const stack = await this.get().locator(`.nc-kanban-stack`).nth(stackIndex); const stack = this.get().locator(`.nc-kanban-stack`).nth(stackIndex);
for (let i = 0; i < order.length; i++) { for (let i = 0; i < order.length; i++) {
const card = await stack.locator(`.nc-kanban-item`).nth(i); const card = stack.locator(`.nc-kanban-item`).nth(i);
await card.scrollIntoViewIfNeeded(); await card.scrollIntoViewIfNeeded();
const cardTitle = await card.locator(`.nc-cell`); const cardTitle = card.locator(`.nc-cell`);
await expect(cardTitle).toHaveText(order[i]); await expect(cardTitle).toHaveText(order[i]);
} }
} }
@ -121,7 +121,7 @@ export class KanbanPage extends BasePage {
async collapseStack(param: { index: number }) { async collapseStack(param: { index: number }) {
await this.get().locator(`.nc-kanban-stack-head`).nth(param.index).click(); await this.get().locator(`.nc-kanban-stack-head`).nth(param.index).click();
const modal = await this.rootPage.locator(`.nc-dropdown-kanban-stack-context-menu`); const modal = this.rootPage.locator(`.nc-dropdown-kanban-stack-context-menu`);
await modal.locator('.ant-dropdown-menu-item:has-text("Collapse Stack")').click(); await modal.locator('.ant-dropdown-menu-item:has-text("Collapse Stack")').click();
} }
@ -135,15 +135,15 @@ export class KanbanPage extends BasePage {
async addCard(param: { stackIndex: number }) { async addCard(param: { stackIndex: number }) {
await this.get().locator(`.nc-kanban-stack-head`).nth(param.stackIndex).click(); await this.get().locator(`.nc-kanban-stack-head`).nth(param.stackIndex).click();
const modal = await this.rootPage.locator(`.nc-dropdown-kanban-stack-context-menu`); const modal = this.rootPage.locator(`.nc-dropdown-kanban-stack-context-menu`);
await modal.locator('.ant-dropdown-menu-item:has-text("Add new record")').click(); await modal.locator('.ant-dropdown-menu-item:has-text("Add new record")').click();
} }
async deleteStack(param: { index: number }) { async deleteStack(param: { index: number }) {
await this.get().locator(`.nc-kanban-stack-head`).nth(param.index).click(); await this.get().locator(`.nc-kanban-stack-head`).nth(param.index).click();
const modal = await this.rootPage.locator(`.nc-dropdown-kanban-stack-context-menu`); const modal = this.rootPage.locator(`.nc-dropdown-kanban-stack-context-menu`);
await modal.locator('.ant-dropdown-menu-item:has-text("Delete Stack")').click(); await modal.locator('.ant-dropdown-menu-item:has-text("Delete Stack")').click();
const confirmationModal = await this.rootPage.locator(`div.ant-modal-content`); const confirmationModal = this.rootPage.locator(`div.ant-modal-content`);
await confirmationModal.locator(`button:has-text("Delete Stack")`).click(); await confirmationModal.locator(`button:has-text("Delete Stack")`).click();
} }
} }

6
tests/playwright/pages/Dashboard/Map/index.ts

@ -22,7 +22,7 @@ export class MapPage extends BasePage {
async marker(lat: string, long: string) { async marker(lat: string, long: string) {
const latLongStr = `${lat}, ${long}`; const latLongStr = `${lat}, ${long}`;
const marker = await this.get().locator(`.leaflet-marker-pane img[alt="${latLongStr}"]`); const marker = this.get().locator(`.leaflet-marker-pane img[alt="${latLongStr}"]`);
return marker; return marker;
} }
@ -35,12 +35,12 @@ export class MapPage extends BasePage {
} }
async verifyMarkerCount(count: number) { async verifyMarkerCount(count: number) {
const markers = await this.get().locator('.leaflet-marker-pane img'); const markers = this.get().locator('.leaflet-marker-pane img');
await expect(markers).toHaveCount(count); await expect(markers).toHaveCount(count);
} }
async zoomOut(times = 10) { async zoomOut(times = 10) {
const zoomOutButton = await this.get().locator('.leaflet-control-zoom-out'); const zoomOutButton = this.get().locator('.leaflet-control-zoom-out');
for (let i = 0; i < times; i++) { for (let i = 0; i < times; i++) {
await zoomOutButton.click(); await zoomOutButton.click();
await this.rootPage.waitForTimeout(400); await this.rootPage.waitForTimeout(400);

4
tests/playwright/pages/Dashboard/ProjectView/AccessSettingsPage.ts

@ -17,10 +17,10 @@ export class AccessSettingsPage extends BasePage {
await this.get().locator('.nc-collaborators-list-row').nth(0).waitFor({ state: 'visible' }); await this.get().locator('.nc-collaborators-list-row').nth(0).waitFor({ state: 'visible' });
const userCount = await this.get().locator('.nc-collaborators-list-row').count(); const userCount = await this.get().locator('.nc-collaborators-list-row').count();
for (let i = 0; i < userCount; i++) { for (let i = 0; i < userCount; i++) {
const user = await this.get().locator('.nc-collaborators-list-row').nth(i); const user = this.get().locator('.nc-collaborators-list-row').nth(i);
const userEmail = (await user.locator('.email').innerText()).split('\n')[1]; const userEmail = (await user.locator('.email').innerText()).split('\n')[1];
if (userEmail === email) { if (userEmail === email) {
const roleDropdown = await user.locator('.nc-collaborator-role-select'); const roleDropdown = user.locator('.nc-collaborator-role-select');
const selectedRole = await user.locator('.nc-collaborator-role-select').innerText(); const selectedRole = await user.locator('.nc-collaborator-role-select').innerText();

2
tests/playwright/pages/Dashboard/ProjectView/DataSourcePage.ts

@ -24,7 +24,7 @@ export class DataSourcePage extends BasePage {
async getDatabaseTypeList() { async getDatabaseTypeList() {
await this.databaseType.click(); await this.databaseType.click();
const nodes = await this.rootPage.locator('.nc-dropdown-ext-db-type').locator('.ant-select-item'); const nodes = this.rootPage.locator('.nc-dropdown-ext-db-type').locator('.ant-select-item');
const list = []; const list = [];
for (let i = 0; i < (await nodes.count()); i++) { for (let i = 0; i < (await nodes.count()); i++) {
const node = nodes.nth(i); const node = nodes.nth(i);

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

@ -29,7 +29,7 @@ export class AuditSettingsPage extends BasePage {
user?: string; user?: string;
created?: string; created?: string;
}) { }) {
const table = await this.get(); const table = this.get();
const row = table.locator(`tr.ant-table-row`).nth(index); const row = table.locator(`tr.ant-table-row`).nth(index);
if (opType) { if (opType) {
@ -37,7 +37,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`) .locator(`td.ant-table-cell`)
.nth(0) .nth(0)
.textContent() .textContent()
.then(async text => await expect(text).toContain(opType)); .then(async text => expect(text).toContain(opType));
} }
if (opSubtype) { if (opSubtype) {
@ -45,7 +45,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`) .locator(`td.ant-table-cell`)
.nth(1) .nth(1)
.textContent() .textContent()
.then(async text => await expect(text).toContain(opSubtype)); .then(async text => expect(text).toContain(opSubtype));
} }
if (description) { if (description) {
@ -53,7 +53,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`) .locator(`td.ant-table-cell`)
.nth(2) .nth(2)
.textContent() .textContent()
.then(async text => await expect(text).toContain(description)); .then(async text => expect(text).toContain(description));
} }
if (user) { if (user) {
@ -61,7 +61,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`) .locator(`td.ant-table-cell`)
.nth(3) .nth(3)
.textContent() .textContent()
.then(async text => await expect(text).toContain(user)); .then(async text => expect(text).toContain(user));
} }
if (created) { if (created) {
@ -69,7 +69,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`) .locator(`td.ant-table-cell`)
.nth(4) .nth(4)
.textContent() .textContent()
.then(async text => await expect(text).toContain(created)); .then(async text => expect(text).toContain(created));
} }
} }
} }

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

@ -38,7 +38,7 @@ export class TeamsPage extends BasePage {
await this.inviteTeamModal.getByTestId('docs-share-dlg-share-project-collaborate-emails').fill(email); await this.inviteTeamModal.getByTestId('docs-share-dlg-share-project-collaborate-emails').fill(email);
await this.inviteTeamModal.getByTestId('nc-share-invite-user-role-option-viewer').click(); await this.inviteTeamModal.getByTestId('nc-share-invite-user-role-option-viewer').click();
const dropdown = await this.rootPage.locator('.nc-dropdown-user-role'); const dropdown = this.rootPage.locator('.nc-dropdown-user-role');
await dropdown.locator(`.nc-role-option:has-text("${role}")`).click(); await dropdown.locator(`.nc-role-option:has-text("${role}")`).click();
await this.inviteTeamModal.getByTestId('docs-share-btn').click(); await this.inviteTeamModal.getByTestId('docs-share-btn').click();
await this.inviteTeamModal.getByTestId('docs-share-invitation-copy').waitFor({ state: 'visible', timeout: 2000 }); await this.inviteTeamModal.getByTestId('docs-share-invitation-copy').waitFor({ state: 'visible', timeout: 2000 });
@ -72,14 +72,14 @@ export class TeamsPage extends BasePage {
if (toggle) { if (toggle) {
// if share base was disabled && request was to enable // if share base was disabled && request was to enable
await toggleBtn.click(); await toggleBtn.click();
const modal = await this.rootPage.locator(`.nc-dropdown-shared-base-toggle`); const modal = this.rootPage.locator(`.nc-dropdown-shared-base-toggle`);
await modal.locator(`.ant-dropdown-menu-title-content`).click(); await modal.locator(`.ant-dropdown-menu-title-content`).click();
} }
} else { } else {
if (!toggle) { if (!toggle) {
// if share base was enabled && request was to disable // if share base was enabled && request was to disable
await toggleBtn.click(); await toggleBtn.click();
const modal = await this.rootPage.locator(`.nc-dropdown-shared-base-toggle`); const modal = this.rootPage.locator(`.nc-dropdown-shared-base-toggle`);
await modal.locator(`.ant-dropdown-menu-title-content`).click(); await modal.locator(`.ant-dropdown-menu-title-content`).click();
} }
} }
@ -106,7 +106,7 @@ export class TeamsPage extends BasePage {
// .locator(`.nc-shared-base-role`) // .locator(`.nc-shared-base-role`)
// .waitFor(); // .waitFor();
await this.getSharedBaseSubModal().locator(`.nc-shared-base-role:visible`).click(); await this.getSharedBaseSubModal().locator(`.nc-shared-base-role:visible`).click();
const userRoleModal = await this.rootPage.locator(`.nc-dropdown-share-base-role:visible`); const userRoleModal = this.rootPage.locator(`.nc-dropdown-share-base-role:visible`);
await userRoleModal.locator(`.ant-select-item-option-content:has-text("${role}"):visible`).click(); await userRoleModal.locator(`.ant-select-item-option-content:has-text("${role}"):visible`).click();
} }
} }

2
tests/playwright/pages/Dashboard/ShareProjectButton/index.ts

@ -1,4 +1,4 @@
import { expect, Locator } from '@playwright/test'; import { expect } from '@playwright/test';
import { DashboardPage } from '..'; import { DashboardPage } from '..';
import BasePage from '../../Base'; import BasePage from '../../Base';

2
tests/playwright/pages/Dashboard/Sidebar/DocsSidebar.ts

@ -1,4 +1,4 @@
import { expect, Locator } from '@playwright/test'; import { expect } from '@playwright/test';
import { SidebarPage } from '.'; import { SidebarPage } from '.';
import BasePage from '../../Base'; import BasePage from '../../Base';

4
tests/playwright/pages/Dashboard/SurveyForm/index.ts

@ -51,7 +51,7 @@ export class SurveyFormPage extends BasePage {
fieldLabel = fieldLabel.replace(/\u00A0/g, ' '); fieldLabel = fieldLabel.replace(/\u00A0/g, ' ');
fieldText = fieldText.replace(/\u00A0/g, ' '); fieldText = fieldText.replace(/\u00A0/g, ' ');
await expect(fieldText).toBe(fieldLabel); expect(fieldText).toBe(fieldLabel);
// parse footer text ("1 / 3") to identify if last slide // parse footer text ("1 / 3") to identify if last slide
let isLastSlide = false; let isLastSlide = false;
@ -76,7 +76,7 @@ export class SurveyFormPage extends BasePage {
await this.get().locator(`[data-testid="nc-survey-form__input-${param.fieldLabel}"] >> input`).press('Enter'); await this.get().locator(`[data-testid="nc-survey-form__input-${param.fieldLabel}"] >> input`).press('Enter');
} else if (param.type === 'DateTime') { } else if (param.type === 'DateTime') {
await this.get().locator(`[data-testid="nc-survey-form__input-${param.fieldLabel}"] >> input`).click(); await this.get().locator(`[data-testid="nc-survey-form__input-${param.fieldLabel}"] >> input`).click();
const modal = await this.rootPage.locator('.nc-picker-datetime'); const modal = this.rootPage.locator('.nc-picker-datetime');
await expect(modal).toBeVisible(); await expect(modal).toBeVisible();
await modal.locator('.ant-picker-now-btn').click(); await modal.locator('.ant-picker-now-btn').click();
await modal.locator('.ant-picker-ok').click(); await modal.locator('.ant-picker-ok').click();

2
tests/playwright/pages/Dashboard/ViewSidebar/index.ts

@ -177,7 +177,7 @@ export class ViewSidebarPage extends BasePage {
await this.get().locator(`[data-testid="view-sidebar-view-${title}"] .nc-view-icon`).click(); await this.get().locator(`[data-testid="view-sidebar-view-${title}"] .nc-view-icon`).click();
await this.rootPage.locator('.emoji-mart-search').type(icon); await this.rootPage.locator('.emoji-mart-search').type(icon);
const emojiList = await this.rootPage.locator('[id="emoji-mart-list"]'); const emojiList = this.rootPage.locator('[id="emoji-mart-list"]');
await emojiList.locator('button').first().click(); await emojiList.locator('button').first().click();
await expect( await expect(
this.get() this.get()

8
tests/playwright/pages/Dashboard/WebhookForm/index.ts

@ -68,17 +68,17 @@ export class WebhookFormPage extends BasePage {
save: boolean; save: boolean;
}) { }) {
await this.get().locator(`.nc-check-box-hook-condition`).click(); await this.get().locator(`.nc-check-box-hook-condition`).click();
const modal = await this.get().locator(`.menu-filter-dropdown`).last(); const modal = this.get().locator(`.menu-filter-dropdown`).last();
await modal.locator(`button:has-text("Add Filter")`).click(); await modal.locator(`button:has-text("Add Filter")`).click();
await modal.locator('.nc-filter-field-select').waitFor({ state: 'visible', timeout: 4000 }); await modal.locator('.nc-filter-field-select').waitFor({ state: 'visible', timeout: 4000 });
await modal.locator('.nc-filter-field-select').click(); await modal.locator('.nc-filter-field-select').click();
const modalField = await this.dashboard.rootPage.locator('.nc-dropdown-toolbar-field-list:visible'); const modalField = this.dashboard.rootPage.locator('.nc-dropdown-toolbar-field-list:visible');
await modalField.locator(`.ant-select-item:has-text("${column}")`).click(); await modalField.locator(`.ant-select-item:has-text("${column}")`).click();
await modal.locator('.nc-filter-operation-select').click(); await modal.locator('.nc-filter-operation-select').click();
const modalOp = await this.dashboard.rootPage.locator('.nc-dropdown-filter-comp-op:visible'); const modalOp = this.dashboard.rootPage.locator('.nc-dropdown-filter-comp-op:visible');
await modalOp.locator(`.ant-select-item:has-text("${operator}")`).click(); await modalOp.locator(`.ant-select-item:has-text("${operator}")`).click();
if (operator != 'is null' && operator != 'is not null') { if (operator != 'is null' && operator != 'is not null') {
@ -201,7 +201,7 @@ export class WebhookFormPage extends BasePage {
const locator = this.get().locator('.nc-select-hook-notification-type >> .ant-select-selection-item'); const locator = this.get().locator('.nc-select-hook-notification-type >> .ant-select-selection-item');
const text = await getTextExcludeIconText(locator); const text = await getTextExcludeIconText(locator);
await expect(text).toBe(notificationType); expect(text).toBe(notificationType);
await expect(this.get().locator('.nc-select-hook-url-method >> .ant-select-selection-item')).toHaveText(urlMethod); await expect(this.get().locator('.nc-select-hook-url-method >> .ant-select-selection-item')).toHaveText(urlMethod);
await expect.poll(async () => await this.get().locator('input.nc-text-field-hook-url-path').inputValue()).toBe(url); await expect.poll(async () => await this.get().locator('input.nc-text-field-hook-url-path').inputValue()).toBe(url);

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

@ -98,14 +98,14 @@ export class DashboardPage extends BasePage {
async verifyTeamAndSettingsLinkIsVisible() { async verifyTeamAndSettingsLinkIsVisible() {
await this.projectMenuLink.click(); await this.projectMenuLink.click();
const teamAndSettingsLink = await this.getProjectMenuLink({ title: ' Team & Settings' }); const teamAndSettingsLink = this.getProjectMenuLink({ title: ' Team & Settings' });
await expect(teamAndSettingsLink).toBeVisible(); await expect(teamAndSettingsLink).toBeVisible();
await this.projectMenuLink.click(); await this.projectMenuLink.click();
} }
async verifyTeamAndSettingsLinkIsNotVisible() { async verifyTeamAndSettingsLinkIsNotVisible() {
await this.projectMenuLink.click(); await this.projectMenuLink.click();
const teamAndSettingsLink = await this.getProjectMenuLink({ title: ' Team & Settings' }); const teamAndSettingsLink = this.getProjectMenuLink({ title: ' Team & Settings' });
await expect(teamAndSettingsLink).not.toBeVisible(); await expect(teamAndSettingsLink).not.toBeVisible();
await this.projectMenuLink.click(); await this.projectMenuLink.click();
} }
@ -243,7 +243,7 @@ export class DashboardPage extends BasePage {
}*/ }*/
async closeAllTabs() { async closeAllTabs() {
const tab = await this.tabBar.locator(`.ant-tabs-tab`); const tab = this.tabBar.locator(`.ant-tabs-tab`);
const tabCount = await tab.count(); const tabCount = await tab.count();
for (let i = 0; i < tabCount; i++) { for (let i = 0; i < tabCount; i++) {

2
tests/playwright/pages/LoginPage/index.ts

@ -1,4 +1,4 @@
import { expect, Page } from '@playwright/test'; import { Page } from '@playwright/test';
import BasePage from '../Base'; import BasePage from '../Base';
export class LoginPage extends BasePage { export class LoginPage extends BasePage {

28
tests/playwright/pages/ProjectsPage/index.ts

@ -70,14 +70,14 @@ export class ProjectsPage extends BasePage {
await this.rootPage.getByTestId('dupe-project-' + name).click(); await this.rootPage.getByTestId('dupe-project-' + name).click();
// Find the checkbox element with the label "Include data" // Find the checkbox element with the label "Include data"
const includeDataCheckbox = await this.rootPage.getByText('Include data', { exact: true }); const includeDataCheckbox = this.rootPage.getByText('Include data', { exact: true });
// Check the checkbox if it is not already checked // Check the checkbox if it is not already checked
if ((await includeDataCheckbox.isChecked()) && !includeData) { if ((await includeDataCheckbox.isChecked()) && !includeData) {
await includeDataCheckbox.click(); // click the checkbox to check it await includeDataCheckbox.click(); // click the checkbox to check it
} }
// Find the checkbox element with the label "Include data" // Find the checkbox element with the label "Include data"
const includeViewsCheckbox = await this.rootPage.getByText('Include views', { exact: true }); const includeViewsCheckbox = this.rootPage.getByText('Include views', { exact: true });
// Check the checkbox if it is not already checked // Check the checkbox if it is not already checked
if ((await includeViewsCheckbox.isChecked()) && !includeViews) { if ((await includeViewsCheckbox.isChecked()) && !includeViews) {
await includeViewsCheckbox.click(); // click the checkbox to check it await includeViewsCheckbox.click(); // click the checkbox to check it
@ -112,7 +112,7 @@ export class ProjectsPage extends BasePage {
await this.get().waitFor({ await this.get().waitFor({
state: 'visible', state: 'visible',
}); });
(await this.get().elementHandle())?.waitForElementState('stable'); await (await this.get().elementHandle())?.waitForElementState('stable');
// Wait till the ant table is rendered // Wait till the ant table is rendered
await this.get().locator('thead.ant-table-thead >> th').nth(0).waitFor({ state: 'visible' }); await this.get().locator('thead.ant-table-thead >> th').nth(0).waitFor({ state: 'visible' });
@ -200,7 +200,7 @@ export class ProjectsPage extends BasePage {
if (!withoutPrefix) newTitle = this.prefixTitle(newTitle); if (!withoutPrefix) newTitle = this.prefixTitle(newTitle);
const project = this.rootPage; const project = this.rootPage;
const projRow = await project.locator(`tr`, { const projRow = project.locator(`tr`, {
has: project.locator(`td.ant-table-cell:has-text("${title}")`), has: project.locator(`td.ant-table-cell:has-text("${title}")`),
}); });
await projRow.locator('.nc-action-btn').nth(0).click(); await projRow.locator('.nc-action-btn').nth(0).click();
@ -223,7 +223,7 @@ export class ProjectsPage extends BasePage {
} }
async selectLanguage({ index }: { index: number }) { async selectLanguage({ index }: { index: number }) {
const modal = await this.rootPage.locator('.nc-dropdown-menu-translate'); const modal = this.rootPage.locator('.nc-dropdown-menu-translate');
await modal.locator(`.ant-dropdown-menu-item`).nth(index).click(); await modal.locator(`.ant-dropdown-menu-item`).nth(index).click();
} }
@ -250,23 +250,23 @@ export class ProjectsPage extends BasePage {
async validateRoleAccess(param: { role: string }) { async validateRoleAccess(param: { role: string }) {
// new user; by default org level permission is to viewer (can't create project) // new user; by default org level permission is to viewer (can't create project)
await expect(await this.buttonNewProject).toBeVisible({ visible: false }); await expect(this.buttonNewProject).toBeVisible({ visible: false });
// role specific permissions // role specific permissions
switch (param.role) { switch (param.role) {
case 'creator': case 'creator':
await expect(await this.buttonColorSelector).toBeVisible(); await expect(this.buttonColorSelector).toBeVisible();
await expect(await this.buttonEditProject).toBeVisible(); await expect(this.buttonEditProject).toBeVisible();
await expect(await this.buttonDeleteProject).toBeVisible(); await expect(this.buttonDeleteProject).toBeVisible();
await expect(await this.buttonMoreActions).toBeVisible(); await expect(this.buttonMoreActions).toBeVisible();
break; break;
case 'editor': case 'editor':
case 'commenter': case 'commenter':
case 'viewer': case 'viewer':
await expect(await this.buttonColorSelector).toBeVisible({ visible: false }); await expect(this.buttonColorSelector).toBeVisible({ visible: false });
await expect(await this.buttonEditProject).toBeVisible({ visible: false }); await expect(this.buttonEditProject).toBeVisible({ visible: false });
await expect(await this.buttonDeleteProject).toBeVisible({ visible: false }); await expect(this.buttonDeleteProject).toBeVisible({ visible: false });
await expect(await this.buttonMoreActions).toBeVisible({ visible: false }); await expect(this.buttonMoreActions).toBeVisible({ visible: false });
break; break;
} }
} }

14
tests/playwright/pages/SharedForm/index.ts

@ -24,7 +24,7 @@ export class SharedFormPage extends BasePage {
async verifySuccessMessage() { async verifySuccessMessage() {
await expect( await expect(
await this.get().locator('.ant-alert-success', { this.get().locator('.ant-alert-success', {
hasText: 'Successfully submitted form data', hasText: 'Successfully submitted form data',
}) })
).toBeVisible(); ).toBeVisible();
@ -36,7 +36,7 @@ export class SharedFormPage extends BasePage {
async verifyChildList(cardTitle?: string[]) { async verifyChildList(cardTitle?: string[]) {
await this.get().locator('.nc-modal-link-record').waitFor(); await this.get().locator('.nc-modal-link-record').waitFor();
const linkRecord = await this.get(); const linkRecord = this.get();
// DOM element validation // DOM element validation
// title: Link Record // title: Link Record
@ -45,18 +45,18 @@ export class SharedFormPage extends BasePage {
await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Link record`); await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Link record`);
// add new record option is not available for shared form // add new record option is not available for shared form
await expect(await linkRecord.locator(`button:has-text("Add new record")`).isVisible()).toBeFalsy(); expect(await linkRecord.locator(`button:has-text("Add new record")`).isVisible()).toBeFalsy();
await expect(await linkRecord.locator(`.nc-reload`).isVisible()).toBeTruthy(); expect(await linkRecord.locator(`.nc-reload`).isVisible()).toBeTruthy();
// placeholder: Filter query // placeholder: Filter query
await expect(await linkRecord.locator(`[placeholder="Filter query"]`).isVisible()).toBeTruthy(); expect(await linkRecord.locator(`[placeholder="Filter query"]`).isVisible()).toBeTruthy();
{ {
const childList = linkRecord.locator(`.ant-card`); const childList = linkRecord.locator(`.ant-card`);
const childCards = await childList.count(); const childCards = await childList.count();
await expect(childCards).toEqual(cardTitle.length); expect(childCards).toEqual(cardTitle.length);
for (let i = 0; i < cardTitle.length; i++) { for (let i = 0; i < cardTitle.length; i++) {
await expect(await childList.nth(i).textContent()).toContain(cardTitle[i]); expect(await childList.nth(i).textContent()).toContain(cardTitle[i]);
} }
} }
} }

2
tests/playwright/pages/WorkspacePage/HeaderPage.ts

@ -55,7 +55,7 @@ export class HeaderPage extends BasePage {
// Menu : Workspaces, Explore, Help, Community // Menu : Workspaces, Explore, Help, Community
async openMenu(param: { title: string }) { async openMenu(param: { title: string }) {
await this.get().locator(`[data-testid="nc-dash-nav-${param.title.toLowerCase()}"]`); this.get().locator(`[data-testid="nc-dash-nav-${param.title.toLowerCase()}"]`);
} }
async navigateUsingCmdK({ async navigateUsingCmdK({

13
tests/playwright/pages/WorkspacePage/LeftSideBarPage.ts

@ -61,7 +61,7 @@ export class LeftSideBarPage extends BasePage {
} }
async getWorkspaceCount() { async getWorkspaceCount() {
return (await this.workspaceItems).count(); return this.workspaceItems.count();
} }
async verifyStaticElements() { async verifyStaticElements() {
@ -88,7 +88,7 @@ export class LeftSideBarPage extends BasePage {
async workspaceGetLocator(title: string) { async workspaceGetLocator(title: string) {
// get workspace id // get workspace id
// return this.get().locator('[data-id="' + wsId + '"]'); // return this.get().locator('[data-id="' + wsId + '"]');
const list = await this.get().locator(`.nc-workspace-list-item`); const list = this.get().locator(`.nc-workspace-list-item`);
for (let i = 0; i < (await list.count()); i++) { for (let i = 0; i < (await list.count()); i++) {
const ws = list.nth(i); const ws = list.nth(i);
const wsTitle = (await ws.innerText()).split('\n')[1]; const wsTitle = (await ws.innerText()).split('\n')[1];
@ -100,7 +100,7 @@ export class LeftSideBarPage extends BasePage {
} }
async workspaceList() { async workspaceList() {
const wsList = await this.workspaceItems; const wsList = this.workspaceItems;
// for each, extract title and add to array // for each, extract title and add to array
const titles = []; const titles = [];
for (let i = 0; i < (await wsList.count()); i++) { for (let i = 0; i < (await wsList.count()); i++) {
@ -155,11 +155,12 @@ export class LeftSideBarPage extends BasePage {
// GET will be triggered after DELETE // GET will be triggered after DELETE
await this.waitForResponse({ await this.waitForResponse({
uiAction: () => { uiAction: async () => {
// Create a promise that resolves after 1 second // Create a promise that resolves after 1 second
const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
// Returning a promise that resolves with the result after the 1-second delay // Returning a promise that resolves with the result after the 1-second delay
return delay(500).then(() => this.rootPage.locator('button:has-text("Delete Workspace")').click()); await delay(500);
return await this.rootPage.locator('button:has-text("Delete Workspace")').click();
}, },
// uiAction: () => this.rootPage.locator('button:has-text("Delete Workspace")').click(), // uiAction: () => this.rootPage.locator('button:has-text("Delete Workspace")').click(),
httpMethodsToMatch: ['GET'], httpMethodsToMatch: ['GET'],

2
tests/playwright/quickTests/commonTest.ts

@ -1,8 +1,6 @@
import { DashboardPage } from '../pages/Dashboard'; import { DashboardPage } from '../pages/Dashboard';
import { ProjectsPage } from '../pages/ProjectsPage';
import { NcContext } from '../setup'; import { NcContext } from '../setup';
import { isMysql, isPg } from '../setup/db'; import { isMysql, isPg } from '../setup/db';
import { WorkspacePage } from '../pages/WorkspacePage';
// normal fields // normal fields
const recordCells = { const recordCells = {

8
tests/playwright/tests/db/columns/columnAttachments.spec.ts

@ -88,11 +88,11 @@ test.describe('Attachment column', () => {
const rows = csvArray.slice(1); const rows = csvArray.slice(1);
const cells = rows[10].split(','); const cells = rows[10].split(',');
await expect(columns).toBe('Country,Cities,testAttach'); expect(columns).toBe('Country,Cities,testAttach');
await expect(cells[0]).toBe('Bahrain'); expect(cells[0]).toBe('Bahrain');
// PR8504 // PR8504
// await expect(cells[1]).toBe('al-Manama'); // await expect(cells[1]).toBe('al-Manama');
await expect(cells[1]).toBe('1'); expect(cells[1]).toBe('1');
await expect(cells[2].includes('5.json(http://localhost:8080/download/')).toBe(true); expect(cells[2].includes('5.json(http://localhost:8080/download/')).toBe(true);
}); });
}); });

1
tests/playwright/tests/db/columns/columnCheckbox.spec.ts

@ -4,7 +4,6 @@ import setup, { unsetup } from '../../../setup';
import { ToolbarPage } from '../../../pages/Dashboard/common/Toolbar'; import { ToolbarPage } from '../../../pages/Dashboard/common/Toolbar';
import { UITypes } from 'nocodb-sdk'; import { UITypes } from 'nocodb-sdk';
import { Api } from 'nocodb-sdk'; import { Api } from 'nocodb-sdk';
import { isPg } from '../../../setup/db';
let api: Api<any>; let api: Api<any>;
test.describe('Checkbox - cell, filter, sort', () => { test.describe('Checkbox - cell, filter, sort', () => {

22
tests/playwright/tests/db/columns/columnLtarDragdrop.spec.ts

@ -70,18 +70,16 @@ test.describe('Links', () => {
test('drag drop for Link, lookup creation', async () => { test('drag drop for Link, lookup creation', async () => {
await dashboard.treeView.openTable({ title: 'Table0' }); await dashboard.treeView.openTable({ title: 'Table0' });
const src = await dashboard.rootPage.locator(`[data-testid="tree-view-table-draggable-handle-Table1"]`); const src = dashboard.rootPage.locator(`[data-testid="tree-view-table-draggable-handle-Table1"]`);
const dst = await dashboard.rootPage.locator(`[data-testid="grid-row-0"]`); const dst = dashboard.rootPage.locator(`[data-testid="grid-row-0"]`);
// drag drop for LTAR column creation // drag drop for LTAR column creation
// //
await src.dragTo(dst); await src.dragTo(dst);
const columnAddModal = await dashboard.rootPage.locator(`.nc-dropdown-grid-add-column`); const columnAddModal = dashboard.rootPage.locator(`.nc-dropdown-grid-add-column`);
{ {
const columnType = await getTextExcludeIconText(await columnAddModal.locator(`.nc-column-type-input`)); const columnType = await getTextExcludeIconText(columnAddModal.locator(`.nc-column-type-input`));
const linkTable = await getTextExcludeIconText( const linkTable = await getTextExcludeIconText(columnAddModal.locator(`.ant-form-item-control-input`).nth(3));
await columnAddModal.locator(`.ant-form-item-control-input`).nth(3)
);
expect(columnType).toContain('Links'); expect(columnType).toContain('Links');
expect(linkTable).toContain('Table1'); expect(linkTable).toContain('Table1');
@ -97,13 +95,9 @@ test.describe('Links', () => {
await src.dragTo(dst); await src.dragTo(dst);
{ {
// const columnAddModal = await dashboard.rootPage.locator(`.nc-dropdown-grid-add-column`); // const columnAddModal = await dashboard.rootPage.locator(`.nc-dropdown-grid-add-column`);
const columnType = await getTextExcludeIconText(await columnAddModal.locator(`.nc-column-type-input`)); const columnType = await getTextExcludeIconText(columnAddModal.locator(`.nc-column-type-input`));
const linkField = await getTextExcludeIconText( const linkField = await getTextExcludeIconText(columnAddModal.locator(`.ant-form-item-control-input`).nth(2));
await columnAddModal.locator(`.ant-form-item-control-input`).nth(2) const childColumn = await getTextExcludeIconText(columnAddModal.locator(`.ant-form-item-control-input`).nth(3));
);
const childColumn = await getTextExcludeIconText(
await columnAddModal.locator(`.ant-form-item-control-input`).nth(3)
);
// validate // validate
expect(columnType).toContain('Lookup'); expect(columnType).toContain('Lookup');

3
tests/playwright/tests/db/features/baseShare.spec.ts

@ -3,7 +3,6 @@ import { DashboardPage } from '../../../pages/Dashboard';
import setup, { unsetup } from '../../../setup'; import setup, { unsetup } from '../../../setup';
import { ToolbarPage } from '../../../pages/Dashboard/common/Toolbar'; import { ToolbarPage } from '../../../pages/Dashboard/common/Toolbar';
import { LoginPage } from '../../../pages/LoginPage'; import { LoginPage } from '../../../pages/LoginPage';
import { ProjectsPage } from '../../../pages/ProjectsPage';
import { getDefaultPwd } from '../../../tests/utils/general'; import { getDefaultPwd } from '../../../tests/utils/general';
// To be enabled after shared base is implemented // To be enabled after shared base is implemented
@ -12,7 +11,6 @@ test.describe('Shared base', () => {
let toolbar: ToolbarPage; let toolbar: ToolbarPage;
let context: any; let context: any;
let loginPage: LoginPage; let loginPage: LoginPage;
let projectPage: ProjectsPage;
async function roleTest(role: string) { async function roleTest(role: string) {
// todo: Wait till the page is loaded // todo: Wait till the page is loaded
@ -52,7 +50,6 @@ test.describe('Shared base', () => {
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
context = await setup({ page, isEmptyProject: false }); context = await setup({ page, isEmptyProject: false });
dashboard = new DashboardPage(page, context.project); dashboard = new DashboardPage(page, context.project);
projectPage = new ProjectsPage(page);
toolbar = dashboard.grid.toolbar; toolbar = dashboard.grid.toolbar;
loginPage = new LoginPage(page); loginPage = new LoginPage(page);
}); });

1
tests/playwright/tests/db/features/metaSync.spec.ts

@ -1,6 +1,5 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard'; import { DashboardPage } from '../../../pages/Dashboard';
import { SettingsPage, SettingTab } from '../../../pages/Dashboard/Settings';
import setup, { NcContext, unsetup } from '../../../setup'; import setup, { NcContext, unsetup } from '../../../setup';
import { isMysql, isPg, isSqlite, mysqlExec, pgExec, sqliteExec } from '../../../setup/db'; import { isMysql, isPg, isSqlite, mysqlExec, pgExec, sqliteExec } from '../../../setup/db';
import { MetaDataPage } from '../../../pages/Dashboard/ProjectView/Metadata'; import { MetaDataPage } from '../../../pages/Dashboard/ProjectView/Metadata';

10
tests/playwright/tests/db/features/webhook.spec.ts

@ -16,11 +16,11 @@ async function clearServerData({ request }) {
// ensure stored message count is 0 // ensure stored message count is 0
const response = await request.get(hookPath + '/count'); const response = await request.get(hookPath + '/count');
await expect(await response.json()).toBe(0); expect(await response.json()).toBe(0);
} }
async function getWebhookResponses({ request, count = 1 }) { async function getWebhookResponses({ request, count = 1 }) {
let response; let response: { json: () => any };
// kludge- add delay to allow server to process webhook // kludge- add delay to allow server to process webhook
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
@ -33,7 +33,7 @@ async function getWebhookResponses({ request, count = 1 }) {
} }
await new Promise(resolve => setTimeout(resolve, 100)); await new Promise(resolve => setTimeout(resolve, 100));
} }
await expect(await response.json()).toBe(count); expect(await response.json()).toBe(count);
response = await request.get(hookPath + '/all'); response = await request.get(hookPath + '/all');
return await response.json(); return await response.json();
@ -41,7 +41,7 @@ async function getWebhookResponses({ request, count = 1 }) {
async function verifyHookTrigger(count: number, value: string, request, expectedData?: any) { async function verifyHookTrigger(count: number, value: string, request, expectedData?: any) {
// Retry since there can be lag between the time the hook is triggered and the time the server receives the request // Retry since there can be lag between the time the hook is triggered and the time the server receives the request
let response; let response: { json: () => any };
// retry since there can be lag between the time the hook is triggered and the time the server receives the request // retry since there can be lag between the time the hook is triggered and the time the server receives the request
for (let i = 0; i < 20; i++) { for (let i = 0; i < 20; i++) {
@ -70,7 +70,7 @@ async function verifyHookTrigger(count: number, value: string, request, expected
const rspJson = await response.json(); const rspJson = await response.json();
expect(rspJson?.data?.rows[0]?.Title).toBe(value); expect(rspJson?.data?.rows[0]?.Title).toBe(value);
if (expectedData) { if (expectedData) {
await expect(isSubset(rspJson, expectedData)).toBe(true); expect(isSubset(rspJson, expectedData)).toBe(true);
} }
} }
} }

22
tests/playwright/tests/db/general/tableOperations.spec.ts

@ -74,7 +74,7 @@ test.describe('Table Operations', () => {
await dashboard.treeView.duplicateTable(orginalTableName, true, true); await dashboard.treeView.duplicateTable(orginalTableName, true, true);
await dashboard.treeView.verifyTable({ title: dupTableName }); await dashboard.treeView.verifyTable({ title: dupTableName });
// let projectInfoApiUtil: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token); // let projectInfoApiUtil: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token);
// let orginalTable: Promise<TableInfo> = projectInfoApiUtil.extractTableInfo(context.project_id, 'Address'); // let originalTable: Promise<TableInfo> = projectInfoApiUtil.extractTableInfo(context.project_id, 'Address');
// let duplicateTable: Promise<TableInfo> = await this.api.dbTable.list(projectId);.extractTableInfo(context.project_id, 'Address copy'); // let duplicateTable: Promise<TableInfo> = await this.api.dbTable.list(projectId);.extractTableInfo(context.project_id, 'Address copy');
const api: Api<any> = new Api({ const api: Api<any> = new Api({
baseURL: `http://localhost:8080/`, baseURL: `http://localhost:8080/`,
@ -83,11 +83,11 @@ test.describe('Table Operations', () => {
}, },
}); });
const tables: TableListType = await api.dbTable.list(context.project.id); const tables: TableListType = await api.dbTable.list(context.project.id);
const orginalTable: TableType = await tables.list.filter(t => t.title === orginalTableName)[0]; const originalTable: TableType = tables.list.filter(t => t.title === orginalTableName)[0];
const duplicateTable: TableType = await tables.list.filter(t => t.title === dupTableName)[0]; const duplicateTable: TableType = tables.list.filter(t => t.title === dupTableName)[0];
expect( expect(
deepCompare( deepCompare(
orginalTable, originalTable,
duplicateTable, duplicateTable,
undefined, undefined,
new Set(['.id', '.table_name', '.title', '.order', '.created_at', '.updated_at']) new Set(['.id', '.table_name', '.title', '.order', '.created_at', '.updated_at'])
@ -97,13 +97,13 @@ test.describe('Table Operations', () => {
}); });
test.skip('duplicate_table_with_no_data_views', async () => { test.skip('duplicate_table_with_no_data_views', async () => {
const orginalTableName = 'Actor'; const originalTableName = 'Actor';
const dupTableName = 'Actor copy'; const dupTableName = 'Actor copy';
// verify table icon customization // verify table icon customization
await dashboard.treeView.duplicateTable(orginalTableName, false, false); await dashboard.treeView.duplicateTable(originalTableName, false, false);
await dashboard.treeView.verifyTable({ title: dupTableName }); await dashboard.treeView.verifyTable({ title: dupTableName });
// let projectInfoApiUtil: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token); // let projectInfoApiUtil: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token);
// let orginalTable: Promise<TableInfo> = projectInfoApiUtil.extractTableInfo(context.project_id, 'Address'); // let originalTable: Promise<TableInfo> = projectInfoApiUtil.extractTableInfo(context.project_id, 'Address');
// let duplicateTable: Promise<TableInfo> = await this.api.dbTable.list(projectId);.extractTableInfo(context.project_id, 'Address copy'); // let duplicateTable: Promise<TableInfo> = await this.api.dbTable.list(projectId);.extractTableInfo(context.project_id, 'Address copy');
const api: Api<any> = new Api({ const api: Api<any> = new Api({
baseURL: `http://localhost:8080/`, baseURL: `http://localhost:8080/`,
@ -112,14 +112,14 @@ test.describe('Table Operations', () => {
}, },
}); });
const tables: TableListType = await api.dbTable.list(context.project.id); const tables: TableListType = await api.dbTable.list(context.project.id);
const orginalTable: TableType = await tables.list.filter(t => t.title === orginalTableName)[0]; const originalTable: TableType = tables.list.filter(t => t.title === originalTableName)[0];
const duplicateTable: TableType = await tables.list.filter(t => t.title === dupTableName)[0]; const duplicateTable: TableType = tables.list.filter(t => t.title === dupTableName)[0];
const p: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token); const p: ProjectInfoApiUtil = new ProjectInfoApiUtil(context.token);
const orginalTableInfo: TableInfo = await p.extractTableInfo(orginalTable, context.project.id); const originalTableInfo: TableInfo = await p.extractTableInfo(originalTable, context.project.id);
const duplicateTableInfo: TableInfo = await p.extractTableInfo(duplicateTable, context.project.id); const duplicateTableInfo: TableInfo = await p.extractTableInfo(duplicateTable, context.project.id);
expect( expect(
deepCompare( deepCompare(
orginalTableInfo, originalTableInfo,
duplicateTableInfo, duplicateTableInfo,
new Set(['created_at']), new Set(['created_at']),
new Set([ new Set([

2
tests/playwright/tests/db/general/views.spec.ts

@ -1,4 +1,4 @@
import { expect, test } from '@playwright/test'; import { test } from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard'; import { DashboardPage } from '../../../pages/Dashboard';
import { ToolbarPage } from '../../../pages/Dashboard/common/Toolbar'; import { ToolbarPage } from '../../../pages/Dashboard/common/Toolbar';
import setup, { unsetup } from '../../../setup'; import setup, { unsetup } from '../../../setup';

3
tests/playwright/tests/db/usersAccounts/accountUserManagement.spec.ts

@ -1,7 +1,6 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import { AccountPage } from '../../../pages/Account'; import { AccountPage } from '../../../pages/Account';
import { AccountUsersPage } from '../../../pages/Account/Users'; import { AccountUsersPage } from '../../../pages/Account/Users';
import { ProjectsPage } from '../../../pages/ProjectsPage';
import { SignupPage } from '../../../pages/SignupPage'; import { SignupPage } from '../../../pages/SignupPage';
import setup, { unsetup } from '../../../setup'; import setup, { unsetup } from '../../../setup';
import { WorkspacePage } from '../../../pages/WorkspacePage'; import { WorkspacePage } from '../../../pages/WorkspacePage';
@ -16,7 +15,6 @@ test.describe.skip('User roles', () => {
let accountUsersPage: AccountUsersPage; let accountUsersPage: AccountUsersPage;
let accountPage: AccountPage; let accountPage: AccountPage;
let signupPage: SignupPage; let signupPage: SignupPage;
let projectsPage: ProjectsPage;
let workspacePage: WorkspacePage; let workspacePage: WorkspacePage;
// @ts-ignore // @ts-ignore
let context: any; let context: any;
@ -27,7 +25,6 @@ test.describe.skip('User roles', () => {
accountUsersPage = new AccountUsersPage(accountPage); accountUsersPage = new AccountUsersPage(accountPage);
signupPage = new SignupPage(accountPage.rootPage); signupPage = new SignupPage(accountPage.rootPage);
projectsPage = new ProjectsPage(accountPage.rootPage);
workspacePage = new WorkspacePage(accountPage.rootPage); workspacePage = new WorkspacePage(accountPage.rootPage);
}); });

6
tests/playwright/tests/db/usersAccounts/authChangePassword.spec.ts

@ -2,7 +2,6 @@ import { test } from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard'; import { DashboardPage } from '../../../pages/Dashboard';
import setup, { unsetup } from '../../../setup'; import setup, { unsetup } from '../../../setup';
import { LoginPage } from '../../../pages/LoginPage'; import { LoginPage } from '../../../pages/LoginPage';
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';
import { AccountPage } from '../../../pages/Account'; import { AccountPage } from '../../../pages/Account';
@ -13,9 +12,7 @@ import { WorkspacePage } from '../../../pages/WorkspacePage';
test.describe.skip('Auth', () => { test.describe.skip('Auth', () => {
let context: any; let context: any;
let dashboard: DashboardPage; let dashboard: DashboardPage;
let settings: SettingsPage;
let signupPage: SignupPage; let signupPage: SignupPage;
let projectsPage: ProjectsPage;
let accountPage: AccountPage; let accountPage: AccountPage;
let workspacePage: WorkspacePage; let workspacePage: WorkspacePage;
@ -23,11 +20,8 @@ test.describe.skip('Auth', () => {
context = await setup({ page, isEmptyProject: false }); context = await setup({ page, isEmptyProject: false });
dashboard = new DashboardPage(page, context.project); dashboard = new DashboardPage(page, context.project);
signupPage = new SignupPage(page); signupPage = new SignupPage(page);
projectsPage = new ProjectsPage(page);
accountPage = new AccountPage(page); accountPage = new AccountPage(page);
workspacePage = new WorkspacePage(page); workspacePage = new WorkspacePage(page);
settings = dashboard.settings;
}); });
test.afterEach(async () => { test.afterEach(async () => {

2
tests/playwright/tests/db/usersAccounts/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, { unsetup } from '../../../setup'; import setup, { unsetup } from '../../../setup';
import { SettingsPage, SettingTab } from '../../../pages/Dashboard/Settings'; import { SettingsPage } from '../../../pages/Dashboard/Settings';
import { SignupPage } from '../../../pages/SignupPage'; import { SignupPage } from '../../../pages/SignupPage';
import { ProjectsPage } from '../../../pages/ProjectsPage'; import { ProjectsPage } from '../../../pages/ProjectsPage';
import { getDefaultPwd } from '../../../tests/utils/general'; import { getDefaultPwd } from '../../../tests/utils/general';

4
tests/playwright/tests/db/usersAccounts/rolesSuperUser.spec.ts

@ -38,7 +38,7 @@ test.describe.skip('Super user', () => {
// Modify configuration // Modify configuration
await card.click(); await card.click();
await card.locator('.nc-app-store-card-edit').click(); await card.locator('.nc-app-store-card-edit').click();
slackModal = await appPage.locator('.nc-modal-plugin-install'); slackModal = appPage.locator('.nc-modal-plugin-install');
await slackModal.locator('[placeholder="Channel Name"]').fill('Test Channel 2'); await slackModal.locator('[placeholder="Channel Name"]').fill('Test Channel 2');
await slackModal.locator('[placeholder="Webhook URL"]').fill('http://test2.com'); await slackModal.locator('[placeholder="Webhook URL"]').fill('http://test2.com');
await slackModal.locator('button:has-text("Save")').click(); await slackModal.locator('button:has-text("Save")').click();
@ -47,7 +47,7 @@ test.describe.skip('Super user', () => {
// Uninstall // Uninstall
await card.click(); await card.click();
await card.locator('.nc-app-store-card-reset').click(); await card.locator('.nc-app-store-card-reset').click();
slackModal = await appPage.locator('.nc-modal-plugin-uninstall'); slackModal = appPage.locator('.nc-modal-plugin-uninstall');
await slackModal.locator('button:has-text("Confirm")').click(); await slackModal.locator('button:has-text("Confirm")').click();
await dashboard.verifyToast({ message: 'Plugin uninstalled successfully' }); await dashboard.verifyToast({ message: 'Plugin uninstalled successfully' });
}); });

6
tests/playwright/tests/db/views/viewForm.spec.ts

@ -3,8 +3,6 @@ import { DashboardPage } from '../../../pages/Dashboard';
import setup, { unsetup } from '../../../setup'; import setup, { unsetup } from '../../../setup';
import { FormPage } from '../../../pages/Dashboard/Form'; import { FormPage } from '../../../pages/Dashboard/Form';
import { SharedFormPage } from '../../../pages/SharedForm'; import { SharedFormPage } from '../../../pages/SharedForm';
import { AccountPage } from '../../../pages/Account';
import { AccountAppStorePage } from '../../../pages/Account/AppStore';
import { Api, UITypes } from 'nocodb-sdk'; import { Api, UITypes } from 'nocodb-sdk';
import { LoginPage } from '../../../pages/LoginPage'; import { LoginPage } from '../../../pages/LoginPage';
import { getDefaultPwd } from '../../../tests/utils/general'; import { getDefaultPwd } from '../../../tests/utils/general';
@ -15,16 +13,12 @@ import { isEE } from '../../../setup/db';
test.describe('Form view', () => { test.describe('Form view', () => {
let dashboard: DashboardPage; let dashboard: DashboardPage;
let form: FormPage; let form: FormPage;
let accountAppStorePage: AccountAppStorePage;
let accountPage: AccountPage;
let context: any; let context: any;
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
context = await setup({ page, isEmptyProject: false }); context = await setup({ page, isEmptyProject: false });
dashboard = new DashboardPage(page, context.project); dashboard = new DashboardPage(page, context.project);
form = dashboard.form; form = dashboard.form;
accountPage = new AccountPage(page);
accountAppStorePage = accountPage.appStore;
}); });
test.afterEach(async () => { test.afterEach(async () => {

Loading…
Cancel
Save