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;
});
const uiActionWithDelay = () => {
const uiActionWithDelay = async () => {
// 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
return delay(100).then(() => uiAction());
await delay(100);
return await uiAction();
};
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
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();
}
@ -55,12 +55,12 @@ export class ExpandedFormPage extends BasePage {
}
async isDisabledDuplicateRow() {
const isDisabled = await this.duplicateRowButton;
const isDisabled = this.duplicateRowButton;
return await isDisabled.count();
}
async isDisabledDeleteRow() {
const isDisabled = await this.deleteRowButton;
const isDisabled = this.deleteRowButton;
return await isDisabled.count();
}
@ -71,7 +71,7 @@ export class ExpandedFormPage extends BasePage {
}
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}`;
await this.rootPage.goto(expandedFormUrl);
await this.dashboard.waitForLoaderToDisappear();
@ -157,7 +157,7 @@ export class ExpandedFormPage extends BasePage {
}
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();
}
@ -172,9 +172,9 @@ export class ExpandedFormPage extends BasePage {
expect(await this.btn_moreActions.count()).toBe(1);
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' });
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++) {
if (role === 'owner' || role === 'editor' || role === 'creator') {
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 }) {
await expect(await this.getFormFields().nth(index).locator('[data-testid="nc-form-input-label"]')).toContainText(
label
);
await expect(this.getFormFields().nth(index).locator('[data-testid="nc-form-input-label"]')).toContainText(label);
}
async verifyFormFieldHelpText({ index, helpText }: { index: number; helpText: string }) {
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);
}
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 }) {
await expect((await this.afterSubmitMsg.inputValue()).includes(msg)).toBeTruthy();
expect((await this.afterSubmitMsg.inputValue()).includes(msg)).toBeTruthy();
}
async verifyFormViewFieldsOrder({ fields }: { fields: string[] }) {
const fieldLabels = await this.get().locator('[data-testid="nc-form-input-label"]');
await expect(await fieldLabels).toHaveCount(fields.length);
const fieldLabels = this.get().locator('[data-testid="nc-form-input-label"]');
await expect(fieldLabels).toHaveCount(fields.length);
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 }) {
await expect(await this.get().locator(`.nc-form-drag-${sourceField}`)).toBeVisible();
await expect(await this.get().locator(`.nc-form-drag-${destinationField}`)).toBeVisible();
const src = await this.get().locator(`.nc-form-drag-${sourceField.replace(' ', '')}`);
const dst = await this.get().locator(`.nc-form-drag-${destinationField.replace(' ', '')}`);
await expect(this.get().locator(`.nc-form-drag-${sourceField}`)).toBeVisible();
await expect(this.get().locator(`.nc-form-drag-${destinationField}`)).toBeVisible();
const src = this.get().locator(`.nc-form-drag-${sourceField.replace(' ', '')}`);
const dst = this.get().locator(`.nc-form-drag-${destinationField.replace(' ', '')}`);
await src.dragTo(dst);
}
async removeField({ field, mode }: { mode: string; field: string }) {
if (mode === 'dragDrop') {
const src = await this.get().locator(`.nc-form-drag-${field.replace(' ', '')}`);
const dst = await this.get().locator(`[data-testid="nc-drag-n-drop-to-hide"]`);
const src = this.get().locator(`.nc-form-drag-${field.replace(' ', '')}`);
const dst = this.get().locator(`[data-testid="nc-drag-n-drop-to-hide"]`);
await src.dragTo(dst);
} 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();
}
}
async addField({ field, mode }: { mode: string; field: string }) {
if (mode === 'dragDrop') {
const src = await 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 src = this.get().locator(`[data-testid="nc-form-hidden-column-${field}"] > div.ant-card-body`);
const dst = this.get().locator(`[data-testid="nc-form-input-Country"]`);
await src.waitFor({ state: 'visible' });
await dst.waitFor({ state: 'visible' });
await src.dragTo(dst, { trial: true });
await src.dragTo(dst);
} 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();
}
}
@ -206,12 +204,12 @@ export class FormPage extends BasePage {
if (required) expectText = label + ' *';
else expectText = label;
const fieldLabel = await this.get()
const fieldLabel = this.get()
.locator(`.nc-form-drag-${field.replace(' ', '')}`)
.locator('div[data-testid="nc-form-input-label"]');
await expect(fieldLabel).toHaveText(expectText);
const fieldHelpText = await this.get()
const fieldHelpText = this.get()
.locator(`.nc-form-drag-${field.replace(' ', '')}`)
.locator('div[data-testid="nc-form-input-help-text-label"]');
await expect(fieldHelpText).toHaveText(helpText);
@ -232,10 +230,10 @@ export class FormPage extends BasePage {
await this.rootPage.waitForTimeout(100 * retryCounter);
retryCounter++;
}
await expect(await this.getFormAfterSubmit()).toContainText(param.message);
await expect(this.getFormAfterSubmit()).toContainText(param.message);
}
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) {
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
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());
}
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());
}
if (fileTypesExcludeList) {
// 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();
const treeList = await this.column.get().locator(`.ant-tree-list`);
const checkboxList = await treeList.locator(`.ant-tree-treenode`);
const treeList = this.column.get().locator(`.ant-tree-list`);
const checkboxList = treeList.locator(`.ant-tree-treenode`);
for (let i = 0; i < fileTypesExcludeList.length; 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'
// icon: reload
await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Child list`);
await 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(`text=/Link to '.*${linkField}'/i`).isVisible()).toBeTruthy();
expect(await this.get().locator(`[data-testid="nc-child-list-reload"]`).isVisible()).toBeTruthy();
// child list body validation (card count, card title)
const cardCount = cardTitle.length;
@ -29,20 +29,16 @@ export class ChildList extends BasePage {
{
const childList = this.get().locator(`.ant-card`);
const childCards = await childList.count();
await expect(childCards).toEqual(cardCount);
expect(childCards).toEqual(cardCount);
for (let i = 0; i < cardCount; i++) {
await childList.nth(i).locator('.name').waitFor({ state: 'visible' });
await childList.nth(i).locator('.name').scrollIntoViewIfNeeded();
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: delete
await expect(
await childList.nth(i).locator(`[data-testid="nc-child-list-icon-unlink"]`).isVisible()
).toBeTruthy();
await expect(
await childList.nth(i).locator(`[data-testid="nc-child-list-icon-delete"]`).isVisible()
).toBeTruthy();
expect(await childList.nth(i).locator(`[data-testid="nc-child-list-icon-unlink"]`).isVisible()).toBeTruthy();
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[]) {
await this.dashboard.get().locator('.nc-modal-link-record').waitFor();
const linkRecord = await this.get();
const linkRecord = this.get();
// DOM element validation
// title: Link Record
// button: Add new record
// icon: reload
await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Link record`);
await 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(`button:has-text("Add new record")`).isVisible()).toBeTruthy();
expect(await linkRecord.locator(`.nc-reload`).isVisible()).toBeTruthy();
// 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 childCards = await childList.count();
await expect(childCards).toEqual(cardTitle.length);
expect(childCards).toEqual(cardTitle.length);
for (let i = 0; i < cardTitle.length; i++) {
await childList.nth(i).locator('.name').scrollIntoViewIfNeeded();
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' }) {
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') {
menuOption = () => this.rootPage.locator('li[role="menuitem"]:has-text("Sort Descending"):visible').click();
} else {
@ -444,7 +444,7 @@ export class ColumnPageObject extends BasePage {
async getWidth(param: { title: string }) {
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);
}
}

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)
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 });
@ -211,13 +211,13 @@ export class GridPage extends BasePage {
async addRowRightClickMenu(index: number, columnHeader = 'Title') {
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({ button: 'right' });
// Click text=Insert New Row
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 }) {
@ -227,7 +227,7 @@ export class GridPage extends BasePage {
}
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.locator('input[type="checkbox"]').check({ force: true });
}
@ -357,24 +357,24 @@ export class GridPage extends BasePage {
index: 0,
columnHeader: columnHeader,
});
await expect(await cell.locator('input')).not.toBeVisible();
await expect(cell.locator('input')).not.toBeVisible();
// right click menu
await this.get().locator(`td[data-testid="cell-${columnHeader}-0"]`).click({
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
await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover();
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();
// expand row
await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover();
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();
}
@ -385,7 +385,7 @@ export class GridPage extends BasePage {
index: 0,
columnHeader: columnHeader,
});
await expect(await cell.locator('input')).toBeVisible();
await expect(cell.locator('input')).toBeVisible();
// press escape to exit edit mode
await cell.press('Escape');
@ -394,13 +394,11 @@ export class GridPage extends BasePage {
await this.get().locator(`td[data-testid="cell-${columnHeader}-0"]`).click({
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
await this.cell.get({ index: 0, columnHeader: 'Cities' }).hover();
await expect(
await this.cell.get({ index: 0, columnHeader: 'Cities' }).locator('.nc-action-icon.nc-plus')
).toBeVisible();
await expect(this.cell.get({ index: 0, columnHeader: 'Cities' }).locator('.nc-action-icon.nc-plus')).toBeVisible();
}
async verifyRoleAccess(param: { role: string }) {
@ -411,9 +409,9 @@ export class GridPage extends BasePage {
}
async selectRange({ start, end }: { start: CellProps; end: CellProps }) {
const startCell = await this.cell.get({ index: start.index, columnHeader: start.columnHeader });
const endCell = await this.cell.get({ index: end.index, columnHeader: end.columnHeader });
const page = await this.dashboard.get().page();
const startCell = this.cell.get({ index: start.index, columnHeader: start.columnHeader });
const endCell = this.cell.get({ index: end.index, columnHeader: end.columnHeader });
const page = this.dashboard.get().page();
await startCell.hover();
await page.mouse.down();
await endCell.hover();

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

@ -19,7 +19,7 @@ export class ImportTemplatePage extends BasePage {
async getImportTableList() {
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 tableList: string[] = [];
for (let i = 0; i < rowCount; i++) {
@ -32,7 +32,7 @@ export class ImportTemplatePage extends BasePage {
async getImportColumnList() {
// return an array
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();
for (let i = 0; i < rowCount; i++) {
// replace \n and \t from innerText
@ -51,9 +51,9 @@ export class ImportTemplatePage extends BasePage {
const tblList = await this.getImportTableList();
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();
await expect(columnList).toEqual(result[i].columns);
expect(columnList).toEqual(result[i].columns);
if (i < result.length - 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 } }) {
const { from, to } = param;
const srcStack = await this.get().locator(`.nc-kanban-stack`).nth(from.stack);
const dstStack = await this.get().locator(`.nc-kanban-stack`).nth(to.stack);
const fromCard = await srcStack.locator(`.nc-kanban-item`).nth(from.card);
const toCard = await dstStack.locator(`.nc-kanban-item`).nth(to.card);
const srcStack = this.get().locator(`.nc-kanban-stack`).nth(from.stack);
const dstStack = this.get().locator(`.nc-kanban-stack`).nth(to.stack);
const fromCard = srcStack.locator(`.nc-kanban-item`).nth(from.card);
const toCard = dstStack.locator(`.nc-kanban-item`).nth(to.card);
console.log(await fromCard.allTextContents());
console.log(await toCard.allTextContents());
@ -68,10 +68,10 @@ export class KanbanPage extends BasePage {
const { order } = param;
const stacks = await this.get().locator(`.nc-kanban-stack`).count();
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();
// 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 });
}
}
@ -80,10 +80,10 @@ export class KanbanPage extends BasePage {
const { count } = param;
const stacks = await this.get().locator(`.nc-kanban-stack`).count();
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();
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 stacks = await this.get().locator(`.nc-kanban-stack`).count();
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();
const stackCards = stack.locator(`.nc-kanban-item`);
await expect(stackCards).toHaveCount(count[i]);
@ -100,11 +100,11 @@ export class KanbanPage extends BasePage {
async verifyCardOrder(param: { order: string[]; stackIndex: number }) {
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++) {
const card = await stack.locator(`.nc-kanban-item`).nth(i);
const card = stack.locator(`.nc-kanban-item`).nth(i);
await card.scrollIntoViewIfNeeded();
const cardTitle = await card.locator(`.nc-cell`);
const cardTitle = card.locator(`.nc-cell`);
await expect(cardTitle).toHaveText(order[i]);
}
}
@ -121,7 +121,7 @@ export class KanbanPage extends BasePage {
async collapseStack(param: { index: number }) {
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();
}
@ -135,15 +135,15 @@ export class KanbanPage extends BasePage {
async addCard(param: { stackIndex: number }) {
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();
}
async deleteStack(param: { index: number }) {
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();
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();
}
}

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

@ -22,7 +22,7 @@ export class MapPage extends BasePage {
async marker(lat: string, long: string) {
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;
}
@ -35,12 +35,12 @@ export class MapPage extends BasePage {
}
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);
}
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++) {
await zoomOutButton.click();
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' });
const userCount = await this.get().locator('.nc-collaborators-list-row').count();
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];
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();

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

@ -24,7 +24,7 @@ export class DataSourcePage extends BasePage {
async getDatabaseTypeList() {
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 = [];
for (let i = 0; i < (await nodes.count()); 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;
created?: string;
}) {
const table = await this.get();
const table = this.get();
const row = table.locator(`tr.ant-table-row`).nth(index);
if (opType) {
@ -37,7 +37,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`)
.nth(0)
.textContent()
.then(async text => await expect(text).toContain(opType));
.then(async text => expect(text).toContain(opType));
}
if (opSubtype) {
@ -45,7 +45,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`)
.nth(1)
.textContent()
.then(async text => await expect(text).toContain(opSubtype));
.then(async text => expect(text).toContain(opSubtype));
}
if (description) {
@ -53,7 +53,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`)
.nth(2)
.textContent()
.then(async text => await expect(text).toContain(description));
.then(async text => expect(text).toContain(description));
}
if (user) {
@ -61,7 +61,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`)
.nth(3)
.textContent()
.then(async text => await expect(text).toContain(user));
.then(async text => expect(text).toContain(user));
}
if (created) {
@ -69,7 +69,7 @@ export class AuditSettingsPage extends BasePage {
.locator(`td.ant-table-cell`)
.nth(4)
.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('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 this.inviteTeamModal.getByTestId('docs-share-btn').click();
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 share base was disabled && request was to enable
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();
}
} else {
if (!toggle) {
// if share base was enabled && request was to disable
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();
}
}
@ -106,7 +106,7 @@ export class TeamsPage extends BasePage {
// .locator(`.nc-shared-base-role`)
// .waitFor();
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();
}
}

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 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 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, ' ');
fieldText = fieldText.replace(/\u00A0/g, ' ');
await expect(fieldText).toBe(fieldLabel);
expect(fieldText).toBe(fieldLabel);
// parse footer text ("1 / 3") to identify if last slide
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');
} else if (param.type === 'DateTime') {
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 modal.locator('.ant-picker-now-btn').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.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 expect(
this.get()

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

@ -68,17 +68,17 @@ export class WebhookFormPage extends BasePage {
save: boolean;
}) {
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('.nc-filter-field-select').waitFor({ state: 'visible', timeout: 4000 });
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 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();
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 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.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() {
await this.projectMenuLink.click();
const teamAndSettingsLink = await this.getProjectMenuLink({ title: ' Team & Settings' });
const teamAndSettingsLink = this.getProjectMenuLink({ title: ' Team & Settings' });
await expect(teamAndSettingsLink).toBeVisible();
await this.projectMenuLink.click();
}
async verifyTeamAndSettingsLinkIsNotVisible() {
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 this.projectMenuLink.click();
}
@ -243,7 +243,7 @@ export class DashboardPage extends BasePage {
}*/
async closeAllTabs() {
const tab = await this.tabBar.locator(`.ant-tabs-tab`);
const tab = this.tabBar.locator(`.ant-tabs-tab`);
const tabCount = await tab.count();
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';
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();
// 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
if ((await includeDataCheckbox.isChecked()) && !includeData) {
await includeDataCheckbox.click(); // click the checkbox to check it
}
// 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
if ((await includeViewsCheckbox.isChecked()) && !includeViews) {
await includeViewsCheckbox.click(); // click the checkbox to check it
@ -112,7 +112,7 @@ export class ProjectsPage extends BasePage {
await this.get().waitFor({
state: 'visible',
});
(await this.get().elementHandle())?.waitForElementState('stable');
await (await this.get().elementHandle())?.waitForElementState('stable');
// Wait till the ant table is rendered
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);
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}")`),
});
await projRow.locator('.nc-action-btn').nth(0).click();
@ -223,7 +223,7 @@ export class ProjectsPage extends BasePage {
}
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();
}
@ -250,23 +250,23 @@ export class ProjectsPage extends BasePage {
async validateRoleAccess(param: { role: string }) {
// 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
switch (param.role) {
case 'creator':
await expect(await this.buttonColorSelector).toBeVisible();
await expect(await this.buttonEditProject).toBeVisible();
await expect(await this.buttonDeleteProject).toBeVisible();
await expect(await this.buttonMoreActions).toBeVisible();
await expect(this.buttonColorSelector).toBeVisible();
await expect(this.buttonEditProject).toBeVisible();
await expect(this.buttonDeleteProject).toBeVisible();
await expect(this.buttonMoreActions).toBeVisible();
break;
case 'editor':
case 'commenter':
case 'viewer':
await expect(await this.buttonColorSelector).toBeVisible({ visible: false });
await expect(await this.buttonEditProject).toBeVisible({ visible: false });
await expect(await this.buttonDeleteProject).toBeVisible({ visible: false });
await expect(await this.buttonMoreActions).toBeVisible({ visible: false });
await expect(this.buttonColorSelector).toBeVisible({ visible: false });
await expect(this.buttonEditProject).toBeVisible({ visible: false });
await expect(this.buttonDeleteProject).toBeVisible({ visible: false });
await expect(this.buttonMoreActions).toBeVisible({ visible: false });
break;
}
}

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

@ -24,7 +24,7 @@ export class SharedFormPage extends BasePage {
async verifySuccessMessage() {
await expect(
await this.get().locator('.ant-alert-success', {
this.get().locator('.ant-alert-success', {
hasText: 'Successfully submitted form data',
})
).toBeVisible();
@ -36,7 +36,7 @@ export class SharedFormPage extends BasePage {
async verifyChildList(cardTitle?: string[]) {
await this.get().locator('.nc-modal-link-record').waitFor();
const linkRecord = await this.get();
const linkRecord = this.get();
// DOM element validation
// title: Link Record
@ -45,18 +45,18 @@ export class SharedFormPage extends BasePage {
await expect(this.get().locator(`.ant-modal-title`)).toHaveText(`Link record`);
// 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
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 childCards = await childList.count();
await expect(childCards).toEqual(cardTitle.length);
expect(childCards).toEqual(cardTitle.length);
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
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({

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

@ -61,7 +61,7 @@ export class LeftSideBarPage extends BasePage {
}
async getWorkspaceCount() {
return (await this.workspaceItems).count();
return this.workspaceItems.count();
}
async verifyStaticElements() {
@ -88,7 +88,7 @@ export class LeftSideBarPage extends BasePage {
async workspaceGetLocator(title: string) {
// get workspace id
// 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++) {
const ws = list.nth(i);
const wsTitle = (await ws.innerText()).split('\n')[1];
@ -100,7 +100,7 @@ export class LeftSideBarPage extends BasePage {
}
async workspaceList() {
const wsList = await this.workspaceItems;
const wsList = this.workspaceItems;
// for each, extract title and add to array
const titles = [];
for (let i = 0; i < (await wsList.count()); i++) {
@ -155,11 +155,12 @@ export class LeftSideBarPage extends BasePage {
// GET will be triggered after DELETE
await this.waitForResponse({
uiAction: () => {
uiAction: async () => {
// 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
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(),
httpMethodsToMatch: ['GET'],

2
tests/playwright/quickTests/commonTest.ts

@ -1,8 +1,6 @@
import { DashboardPage } from '../pages/Dashboard';
import { ProjectsPage } from '../pages/ProjectsPage';
import { NcContext } from '../setup';
import { isMysql, isPg } from '../setup/db';
import { WorkspacePage } from '../pages/WorkspacePage';
// normal fields
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 cells = rows[10].split(',');
await expect(columns).toBe('Country,Cities,testAttach');
await expect(cells[0]).toBe('Bahrain');
expect(columns).toBe('Country,Cities,testAttach');
expect(cells[0]).toBe('Bahrain');
// PR8504
// await expect(cells[1]).toBe('al-Manama');
await expect(cells[1]).toBe('1');
await expect(cells[2].includes('5.json(http://localhost:8080/download/')).toBe(true);
expect(cells[1]).toBe('1');
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 { UITypes } from 'nocodb-sdk';
import { Api } from 'nocodb-sdk';
import { isPg } from '../../../setup/db';
let api: Api<any>;
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 () => {
await dashboard.treeView.openTable({ title: 'Table0' });
const src = await dashboard.rootPage.locator(`[data-testid="tree-view-table-draggable-handle-Table1"]`);
const dst = await dashboard.rootPage.locator(`[data-testid="grid-row-0"]`);
const src = dashboard.rootPage.locator(`[data-testid="tree-view-table-draggable-handle-Table1"]`);
const dst = dashboard.rootPage.locator(`[data-testid="grid-row-0"]`);
// drag drop for LTAR column creation
//
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 linkTable = await getTextExcludeIconText(
await columnAddModal.locator(`.ant-form-item-control-input`).nth(3)
);
const columnType = await getTextExcludeIconText(columnAddModal.locator(`.nc-column-type-input`));
const linkTable = await getTextExcludeIconText(columnAddModal.locator(`.ant-form-item-control-input`).nth(3));
expect(columnType).toContain('Links');
expect(linkTable).toContain('Table1');
@ -97,13 +95,9 @@ test.describe('Links', () => {
await src.dragTo(dst);
{
// const columnAddModal = await dashboard.rootPage.locator(`.nc-dropdown-grid-add-column`);
const columnType = await getTextExcludeIconText(await columnAddModal.locator(`.nc-column-type-input`));
const linkField = await getTextExcludeIconText(
await columnAddModal.locator(`.ant-form-item-control-input`).nth(2)
);
const childColumn = await getTextExcludeIconText(
await columnAddModal.locator(`.ant-form-item-control-input`).nth(3)
);
const columnType = await getTextExcludeIconText(columnAddModal.locator(`.nc-column-type-input`));
const linkField = await getTextExcludeIconText(columnAddModal.locator(`.ant-form-item-control-input`).nth(2));
const childColumn = await getTextExcludeIconText(columnAddModal.locator(`.ant-form-item-control-input`).nth(3));
// validate
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 { ToolbarPage } from '../../../pages/Dashboard/common/Toolbar';
import { LoginPage } from '../../../pages/LoginPage';
import { ProjectsPage } from '../../../pages/ProjectsPage';
import { getDefaultPwd } from '../../../tests/utils/general';
// To be enabled after shared base is implemented
@ -12,7 +11,6 @@ test.describe('Shared base', () => {
let toolbar: ToolbarPage;
let context: any;
let loginPage: LoginPage;
let projectPage: ProjectsPage;
async function roleTest(role: string) {
// todo: Wait till the page is loaded
@ -52,7 +50,6 @@ test.describe('Shared base', () => {
test.beforeEach(async ({ page }) => {
context = await setup({ page, isEmptyProject: false });
dashboard = new DashboardPage(page, context.project);
projectPage = new ProjectsPage(page);
toolbar = dashboard.grid.toolbar;
loginPage = new LoginPage(page);
});

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

@ -1,6 +1,5 @@
import { test } from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard';
import { SettingsPage, SettingTab } from '../../../pages/Dashboard/Settings';
import setup, { NcContext, unsetup } from '../../../setup';
import { isMysql, isPg, isSqlite, mysqlExec, pgExec, sqliteExec } from '../../../setup/db';
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
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 }) {
let response;
let response: { json: () => any };
// kludge- add delay to allow server to process webhook
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 expect(await response.json()).toBe(count);
expect(await response.json()).toBe(count);
response = await request.get(hookPath + '/all');
return await response.json();
@ -41,7 +41,7 @@ async function getWebhookResponses({ request, count = 1 }) {
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
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
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();
expect(rspJson?.data?.rows[0]?.Title).toBe(value);
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.verifyTable({ title: dupTableName });
// 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');
const api: Api<any> = new Api({
baseURL: `http://localhost:8080/`,
@ -83,11 +83,11 @@ test.describe('Table Operations', () => {
},
});
const tables: TableListType = await api.dbTable.list(context.project.id);
const orginalTable: TableType = await tables.list.filter(t => t.title === orginalTableName)[0];
const duplicateTable: TableType = await tables.list.filter(t => t.title === dupTableName)[0];
const originalTable: TableType = tables.list.filter(t => t.title === orginalTableName)[0];
const duplicateTable: TableType = tables.list.filter(t => t.title === dupTableName)[0];
expect(
deepCompare(
orginalTable,
originalTable,
duplicateTable,
undefined,
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 () => {
const orginalTableName = 'Actor';
const originalTableName = 'Actor';
const dupTableName = 'Actor copy';
// verify table icon customization
await dashboard.treeView.duplicateTable(orginalTableName, false, false);
await dashboard.treeView.duplicateTable(originalTableName, false, false);
await dashboard.treeView.verifyTable({ title: dupTableName });
// 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');
const api: Api<any> = new Api({
baseURL: `http://localhost:8080/`,
@ -112,14 +112,14 @@ test.describe('Table Operations', () => {
},
});
const tables: TableListType = await api.dbTable.list(context.project.id);
const orginalTable: TableType = await tables.list.filter(t => t.title === orginalTableName)[0];
const duplicateTable: TableType = await tables.list.filter(t => t.title === dupTableName)[0];
const originalTable: TableType = tables.list.filter(t => t.title === originalTableName)[0];
const duplicateTable: TableType = tables.list.filter(t => t.title === dupTableName)[0];
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);
expect(
deepCompare(
orginalTableInfo,
originalTableInfo,
duplicateTableInfo,
new Set(['created_at']),
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 { ToolbarPage } from '../../../pages/Dashboard/common/Toolbar';
import setup, { unsetup } from '../../../setup';

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

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

2
tests/playwright/tests/db/usersAccounts/rolesCreate.spec.ts

@ -1,7 +1,7 @@
import { test } from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard';
import setup, { unsetup } from '../../../setup';
import { SettingsPage, SettingTab } from '../../../pages/Dashboard/Settings';
import { SettingsPage } from '../../../pages/Dashboard/Settings';
import { SignupPage } from '../../../pages/SignupPage';
import { ProjectsPage } from '../../../pages/ProjectsPage';
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
await card.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="Webhook URL"]').fill('http://test2.com');
await slackModal.locator('button:has-text("Save")').click();
@ -47,7 +47,7 @@ test.describe.skip('Super user', () => {
// Uninstall
await card.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 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 { FormPage } from '../../../pages/Dashboard/Form';
import { SharedFormPage } from '../../../pages/SharedForm';
import { AccountPage } from '../../../pages/Account';
import { AccountAppStorePage } from '../../../pages/Account/AppStore';
import { Api, UITypes } from 'nocodb-sdk';
import { LoginPage } from '../../../pages/LoginPage';
import { getDefaultPwd } from '../../../tests/utils/general';
@ -15,16 +13,12 @@ import { isEE } from '../../../setup/db';
test.describe('Form view', () => {
let dashboard: DashboardPage;
let form: FormPage;
let accountAppStorePage: AccountAppStorePage;
let accountPage: AccountPage;
let context: any;
test.beforeEach(async ({ page }) => {
context = await setup({ page, isEmptyProject: false });
dashboard = new DashboardPage(page, context.project);
form = dashboard.form;
accountPage = new AccountPage(page);
accountAppStorePage = accountPage.appStore;
});
test.afterEach(async () => {

Loading…
Cancel
Save