Browse Source

feat(testing): Reduced flakyness

pull/3848/head
Muhammed Mustafa 2 years ago
parent
commit
323868c0d5
  1. 2
      packages/nc-gui/pages/[projectType]/[projectId]/index/index.vue
  2. 2
      scripts/playwright/pages/Dashboard/ExpandedForm/index.ts
  3. 5
      scripts/playwright/pages/Dashboard/Grid/Column/index.ts
  4. 37
      scripts/playwright/pages/Dashboard/Grid/index.ts
  5. 29
      scripts/playwright/pages/Dashboard/TreeView.ts
  6. 22
      scripts/playwright/pages/Dashboard/index.ts
  7. 4
      scripts/playwright/tests/multiSelect.spec.ts
  8. 2
      scripts/playwright/tests/singleSelect.spec.ts

2
packages/nc-gui/pages/[projectType]/[projectId]/index/index.vue

@ -68,7 +68,7 @@ function onEdit(targetKey: number, action: 'add' | 'remove' | string) {
<span class="flex-1" /> <span class="flex-1" />
<div class="flex justify-center self-center mr-2 min-w-[115px]"> <div class="flex justify-center self-center mr-2 min-w-[115px]">
<div v-show="isLoading" class="flex items-center gap-2 ml-3 text-gray-200"> <div v-show="isLoading" class="flex items-center gap-2 ml-3 text-gray-200" pw-data="nc-loading">
{{ $t('general.loading') }} {{ $t('general.loading') }}
<MdiLoading class="animate-infinite animate-spin" /> <MdiLoading class="animate-infinite animate-spin" />

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

@ -35,7 +35,7 @@ export class ExpandedFormPage extends BasePage {
await this.get().press("Escape"); await this.get().press("Escape");
await this.get().waitFor({ state: "hidden" }); await this.get().waitFor({ state: "hidden" });
await this.toastWait({ message: `updated successfully.` }); await this.toastWait({ message: `updated successfully.` });
await this.get() await this.rootPage
.locator('[pw-data="grid-load-spinner"]') .locator('[pw-data="grid-load-spinner"]')
.waitFor({ state: "hidden" }); .waitFor({ state: "hidden" });
} }

5
scripts/playwright/pages/Dashboard/Grid/Column/index.ts

@ -155,11 +155,6 @@ export class ColumnPageObject extends BasePage {
await this.get().waitFor({ state: "visible" }); await this.get().waitFor({ state: "visible" });
// todo: Hack to wait for the modal to be fully loaded
await this.fillTitle({ title: "dummy" });
await this.fillTitle({ title });
await this.get().locator('label[title="Column Name"]').click();
switch (type) { switch (type) {
case "Formula": case "Formula":
await this.get().locator(".nc-formula-input").fill(formula); await this.get().locator(".nc-formula-input").fill(formula);

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

@ -32,7 +32,7 @@ export class GridPage extends BasePage {
} }
async rowCount() { async rowCount() {
await this.get().locator(".nc-grid-row").count(); return await this.get().locator(".nc-grid-row").count();
} }
async verifyRowCount({ count }: { count: number }) { async verifyRowCount({ count }: { count: number }) {
@ -41,9 +41,9 @@ export class GridPage extends BasePage {
async addNewRow({ async addNewRow({
index = 0, index = 0,
title = "Title", columnHeader = "Title",
value, value,
}: { index?: number; title?: string; value?: string } = {}) { }: { index?: number; columnHeader?: string; value?: string } = {}) {
const rowCount = await this.get().locator(".nc-grid-row").count(); const rowCount = await this.get().locator(".nc-grid-row").count();
await this.get().locator(".nc-grid-add-new-cell").click(); await this.get().locator(".nc-grid-add-new-cell").click();
@ -51,22 +51,24 @@ export class GridPage extends BasePage {
.poll(async () => await this.get().locator(".nc-grid-row").count()) .poll(async () => await this.get().locator(".nc-grid-row").count())
.toBe(rowCount + 1); .toBe(rowCount + 1);
const cell = this.cell.get({ index, columnHeader: title }); const cell = this.cell.get({ index, columnHeader });
await this.cell.dblclick({ await this.cell.dblclick({
index, index,
columnHeader: title, columnHeader,
}); });
if (value) {
await cell.locator("input").fill(value); await cell.locator("input").fill(value ?? `Row ${index}`);
} else {
await cell.locator("input").fill(title ?? `Row ${index}`);
}
await this.cell.grid await this.cell.grid
.get() .get()
.locator(`[data-title="${title}"]`) .locator(`[data-title="${columnHeader}"]`)
.locator(`span[title="${title}"]`) .locator(`span[title="${columnHeader}"]`)
.click(); .click();
await this.rootPage.waitForResponse(async (res) => {
return (await res.json())[columnHeader] === value;
});
} }
async verifyRow({ index }: { index: number }) { async verifyRow({ index }: { index: number }) {
@ -114,6 +116,7 @@ export class GridPage extends BasePage {
async openExpandedRow({ index }: { index: number }) { async openExpandedRow({ index }: { index: number }) {
await this.row(index).locator(`td[pw-data="cell-id-${index}"]`).hover(); await this.row(index).locator(`td[pw-data="cell-id-${index}"]`).hover();
await this.row(index).locator(`div[pw-data="nc-expand-${index}"]`).click(); await this.row(index).locator(`div[pw-data="nc-expand-${index}"]`).click();
await (await this.rootPage.locator('.ant-drawer-body').elementHandle())?.waitForElementState('stable');
} }
async selectAll() { async selectAll() {
@ -125,7 +128,15 @@ export class GridPage extends BasePage {
await this.get() await this.get()
.locator('[pw-data="nc-check-all"]') .locator('[pw-data="nc-check-all"]')
.locator('input[type="checkbox"]') .locator('input[type="checkbox"]')
.click(); .check({
force: true,
});
const rowCount = await this.rowCount();
for(let i = 0; i < rowCount; i++) {
await expect.poll(async () => await this.row(i).locator(`[pw-data="cell-id-${i}"]`).locator('span.ant-checkbox-checked').count()).toBe(1);
}
await this.rootPage.waitForTimeout(300);
} }
async deleteAll() { async deleteAll() {

29
scripts/playwright/pages/Dashboard/TreeView.ts

@ -24,26 +24,7 @@ export class TreeViewPage extends BasePage {
// //
async openTable({ title }: { title: string }) { async openTable({ title }: { title: string }) {
await this.get().locator(`.nc-project-tree-tbl-${title}`).click(); await this.get().locator(`.nc-project-tree-tbl-${title}`).click();
await this.dashboard.waitForTabRender({ title });
// wait for the column, active tab animation will be started
await this.dashboard.get().locator('[pw-data="grid-id-column"]').waitFor();
await this.dashboard.tabBar.locator(`.ant-tabs-tab-active:has-text("${title}")`).waitFor();
// wait active tab animation to finish
await expect.poll(async () => {
return await this.dashboard.tabBar.locator(`[data-pw="nc-root-tabs-${title}"]`).evaluate((el) => {
return window.getComputedStyle(el).getPropertyValue("color")
})
}).toBe("rgb(67, 81, 232)"); // active tab text color
await this.dashboard
.get()
.locator('[pw-data="grid-load-spinner"]')
.waitFor({ state: "hidden" });
await expect(this.rootPage).toHaveURL(
`/#/nc/${this.project.id}/table/${title}`
);
} }
async createTable({ title }: { title: string }) { async createTable({ title }: { title: string }) {
@ -54,13 +35,7 @@ export class TreeViewPage extends BasePage {
await this.dashboard.get().locator('[placeholder="Enter table name"]').fill(title); await this.dashboard.get().locator('[placeholder="Enter table name"]').fill(title);
await this.dashboard.get().locator('button:has-text("Submit")').click(); await this.dashboard.get().locator('button:has-text("Submit")').click();
await expect(this.rootPage).toHaveURL( await this.dashboard.waitForTabRender({ title });
`/#/nc/${this.project.id}/table/${title}`
);
await this.dashboard.get()
.locator('[pw-data="grid-load-spinner"]')
.waitFor({ state: "hidden" });
await this.dashboard.get().locator('.nc-grid-add-new-cell').waitFor();
} }
async verifyTable({ title, index }: { title: string; index?: number }) { async verifyTable({ title, index }: { title: string; index?: number }) {

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

@ -64,4 +64,26 @@ export class DashboardPage extends BasePage {
// await tab.waitFor({ state: "detached" }); // await tab.waitFor({ state: "detached" });
await this.rootPage.waitForTimeout(2000); await this.rootPage.waitForTimeout(2000);
} }
async waitForTabRender({ title }: { title: string }) {
// wait for the column, active tab animation will be started
await this.get().locator('[pw-data="grid-id-column"]').waitFor();
await this.tabBar.locator(`.ant-tabs-tab-active:has-text("${title}")`).waitFor();
// wait active tab animation to finish
await expect.poll(async () => {
return await this.tabBar.locator(`[data-pw="nc-root-tabs-${title}"]`).evaluate((el) => {
return window.getComputedStyle(el).getPropertyValue("color")
})
}).toBe("rgb(67, 81, 232)"); // active tab text color
await this
.get()
.locator('[pw-data="grid-load-spinner"]')
.waitFor({ state: "hidden" });
await expect(this.rootPage).toHaveURL(
`/#/nc/${this.project.id}/table/${title}`
);
}
} }

4
scripts/playwright/tests/multiSelect.spec.ts

@ -16,7 +16,7 @@ test.describe('Multi select', () => {
await dashboard.treeView.createTable({ title: 'sheet1' }); await dashboard.treeView.createTable({ title: 'sheet1' });
await grid.column.create({ title: 'MultiSelect', type: 'MultiSelect' }); await grid.column.create({ title: 'MultiSelect', type: 'MultiSelect' });
await grid.addNewRow({index: 0, title: "Row 0"}); await grid.addNewRow({index: 0, value: "Row 0"});
}) })
test('Select and clear options and rename options', async () => { test('Select and clear options and rename options', async () => {
@ -26,7 +26,7 @@ test.describe('Multi select', () => {
await grid.cell.selectOption.select({index: 0, columnHeader: 'MultiSelect', option: 'Option 2', multiSelect: true}); await grid.cell.selectOption.select({index: 0, columnHeader: 'MultiSelect', option: 'Option 2', multiSelect: true});
await grid.cell.selectOption.verify({index: 0, columnHeader: 'MultiSelect', option: 'Option 2', multiSelect: true}); await grid.cell.selectOption.verify({index: 0, columnHeader: 'MultiSelect', option: 'Option 2', multiSelect: true});
await grid.addNewRow({index: 1, title: "Row 1"}); await grid.addNewRow({index: 1, value: "Row 1"});
await grid.cell.selectOption.select({index: 1, columnHeader: 'MultiSelect', option: 'Option 1', multiSelect: true}); await grid.cell.selectOption.select({index: 1, columnHeader: 'MultiSelect', option: 'Option 1', multiSelect: true});
await grid.cell.selectOption.clear({index: 0, columnHeader: 'MultiSelect', multiSelect: true}); await grid.cell.selectOption.clear({index: 0, columnHeader: 'MultiSelect', multiSelect: true});

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

@ -16,7 +16,7 @@ test.describe('Single select', () => {
await dashboard.treeView.createTable({ title: 'sheet1' }); await dashboard.treeView.createTable({ title: 'sheet1' });
await grid.column.create({ title: 'SingleSelect', type: 'SingleSelect' }); await grid.column.create({ title: 'SingleSelect', type: 'SingleSelect' });
await grid.addNewRow({index: 0, title: "Row 0"}); await grid.addNewRow({index: 0, value: "Row 0"});
}) })
test('Select and clear options and rename options', async () => { test('Select and clear options and rename options', async () => {

Loading…
Cancel
Save