diff --git a/packages/nc-gui/components/cell/attachment/index.vue b/packages/nc-gui/components/cell/attachment/index.vue index a5cc81f54c..afc6a21636 100644 --- a/packages/nc-gui/components/cell/attachment/index.vue +++ b/packages/nc-gui/components/cell/attachment/index.vue @@ -160,6 +160,7 @@ watch( v-if="!isReadonly" :class="{ 'mx-auto px-4': !visibleItems.length }" class="group cursor-pointer flex gap-1 items-center active:(ring ring-accent ring-opacity-100) rounded border-1 p-1 shadow-sm hover:(bg-primary bg-opacity-10) dark:(!bg-slate-500)" + pw-data="attachment-cell-file-picker-button" @click.stop="open" > diff --git a/packages/nc-gui/pages/[projectType]/form/[viewId]/index/index.vue b/packages/nc-gui/pages/[projectType]/form/[viewId]/index/index.vue index 75648f7b65..51ba76d207 100644 --- a/packages/nc-gui/pages/[projectType]/form/[viewId]/index/index.vue +++ b/packages/nc-gui/pages/[projectType]/form/[viewId]/index/index.vue @@ -85,6 +85,7 @@ function isRequired(_columnObj: Record, required = false) { @@ -93,6 +94,7 @@ function isRequired(_columnObj: Record, required = false) { v-else v-model="formState[field.title]" class="nc-input" + :pw-data="`nc-form-input-cell-${field.label || field.title}`" :class="`nc-form-input-${field.title.replaceAll(' ', '')}`" :column="field" :edit-enabled="true" @@ -110,7 +112,12 @@ function isRequired(_columnObj: Record, required = false) {
-
diff --git a/scripts/playwright/fixtures/sampleFiles/1.json b/scripts/playwright/fixtures/sampleFiles/1.json new file mode 100644 index 0000000000..0afeb21411 --- /dev/null +++ b/scripts/playwright/fixtures/sampleFiles/1.json @@ -0,0 +1,5 @@ +{ + "country": "Afghanistan", + "city": ["Kabul"] +} + diff --git a/scripts/playwright/fixtures/sampleFiles/2.json b/scripts/playwright/fixtures/sampleFiles/2.json new file mode 100644 index 0000000000..9b9168c2e7 --- /dev/null +++ b/scripts/playwright/fixtures/sampleFiles/2.json @@ -0,0 +1,4 @@ +{ + "country": "Algeria", + "city": ["Batna", "Bchar", "Skikda"] +} diff --git a/scripts/playwright/fixtures/sampleFiles/3.json b/scripts/playwright/fixtures/sampleFiles/3.json new file mode 100644 index 0000000000..02770a7a6b --- /dev/null +++ b/scripts/playwright/fixtures/sampleFiles/3.json @@ -0,0 +1,4 @@ +{ + "country": "Americal Samoa", + "city": ["Tafuna"] +} diff --git a/scripts/playwright/fixtures/sampleFiles/4.json b/scripts/playwright/fixtures/sampleFiles/4.json new file mode 100644 index 0000000000..92fe507084 --- /dev/null +++ b/scripts/playwright/fixtures/sampleFiles/4.json @@ -0,0 +1,4 @@ +{ + "country": "Angola", + "city": ["Benguela", "Namibe"] +} diff --git a/scripts/playwright/fixtures/sampleFiles/5.json b/scripts/playwright/fixtures/sampleFiles/5.json new file mode 100644 index 0000000000..14bf2e4299 --- /dev/null +++ b/scripts/playwright/fixtures/sampleFiles/5.json @@ -0,0 +1,4 @@ +{ + "country": "Anguilla", + "city": ["South Hill"] +} diff --git a/scripts/playwright/fixtures/sampleFiles/6.json b/scripts/playwright/fixtures/sampleFiles/6.json new file mode 100644 index 0000000000..f3e4c3427b --- /dev/null +++ b/scripts/playwright/fixtures/sampleFiles/6.json @@ -0,0 +1,4 @@ +{ + "country": "Argentina", + "city": ["Almirante Brown", "Avellaneda", "Beha Blanca", "Crdoba"] +} \ No newline at end of file diff --git a/scripts/playwright/pages/Base.ts b/scripts/playwright/pages/Base.ts index 27a3c6eef0..54a8eeef61 100644 --- a/scripts/playwright/pages/Base.ts +++ b/scripts/playwright/pages/Base.ts @@ -56,4 +56,14 @@ export default abstract class BasePage { uiAction, ]); } + + async attachFile({filePickUIAction, filePath}:{ filePickUIAction: Promise, filePath: string}) { + const [fileChooser] = await Promise.all([ + // It is important to call waitForEvent before click to set up waiting. + this.rootPage.waitForEvent('filechooser'), + // Opens the file chooser. + filePickUIAction, + ]); + await fileChooser.setFiles(filePath); + } } diff --git a/scripts/playwright/pages/Dashboard/Form/index.ts b/scripts/playwright/pages/Dashboard/Form/index.ts index a72c76c78c..f903d2375b 100644 --- a/scripts/playwright/pages/Dashboard/Form/index.ts +++ b/scripts/playwright/pages/Dashboard/Form/index.ts @@ -249,6 +249,7 @@ export class FormPage extends BasePage { ); } + // todo: Wait for render to complete async waitLoading() { await this.rootPage.waitForTimeout(1000); } diff --git a/scripts/playwright/pages/Dashboard/Gallery/index.ts b/scripts/playwright/pages/Dashboard/Gallery/index.ts index a0bc99bb41..fff4fdc79d 100644 --- a/scripts/playwright/pages/Dashboard/Gallery/index.ts +++ b/scripts/playwright/pages/Dashboard/Gallery/index.ts @@ -45,6 +45,7 @@ export class GalleryPage extends BasePage { await this.rootPage.locator(`.nc-fields-menu-btn`).click(); } + // todo: Wait for render to complete async waitLoading() { await this.rootPage.waitForTimeout(1000); } diff --git a/scripts/playwright/pages/Dashboard/Grid/index.ts b/scripts/playwright/pages/Dashboard/Grid/index.ts index 9fdfb89bd7..4b4cd5a743 100644 --- a/scripts/playwright/pages/Dashboard/Grid/index.ts +++ b/scripts/playwright/pages/Dashboard/Grid/index.ts @@ -2,7 +2,7 @@ import { Locator, expect } from "@playwright/test"; import { DashboardPage } from ".."; import BasePage from "../../Base"; -import { CellPageObject } from "./Cell"; +import { CellPageObject } from "../common/Cell"; import { ColumnPageObject } from "./Column"; import { ToolbarPage } from "../common/Toolbar"; @@ -72,7 +72,7 @@ export class GridPage extends BasePage { await this._fillRow({ index, columnHeader, value: rowValue }); - const clickOnColumnHeaderToSave = this.cell.grid + const clickOnColumnHeaderToSave = this .get() .locator(`[data-title="${columnHeader}"]`) .locator(`span[title="${columnHeader}"]`) @@ -94,7 +94,7 @@ export class GridPage extends BasePage { }: { index?: number; columnHeader?: string; value: string }) { await this._fillRow({ index, columnHeader, value }); - const clickOnColumnHeaderToSave = this.cell.grid + const clickOnColumnHeaderToSave = this .get() .locator(`[data-title="${columnHeader}"]`) .locator(`span[title="${columnHeader}"]`) diff --git a/scripts/playwright/pages/Dashboard/Kanban/index.ts b/scripts/playwright/pages/Dashboard/Kanban/index.ts index d880306aed..0ee342454a 100644 --- a/scripts/playwright/pages/Dashboard/Kanban/index.ts +++ b/scripts/playwright/pages/Dashboard/Kanban/index.ts @@ -106,6 +106,7 @@ export class KanbanPage extends BasePage { } } + // todo: Wait for render to complete async waitLoading() { await this.rootPage.waitForTimeout(1000); } diff --git a/scripts/playwright/pages/Dashboard/common/Cell/AttachmentCell.ts b/scripts/playwright/pages/Dashboard/common/Cell/AttachmentCell.ts new file mode 100644 index 0000000000..e5435dd027 --- /dev/null +++ b/scripts/playwright/pages/Dashboard/common/Cell/AttachmentCell.ts @@ -0,0 +1,29 @@ +import { expect } from "@playwright/test"; +import { CellPageObject } from "."; +import BasePage from "../../../Base"; + +export class AttachmentCellPageObject extends BasePage { + readonly cell: CellPageObject; + + constructor(cell: CellPageObject) { + super(cell.rootPage); + this.cell = cell; + } + + get({index, columnHeader}: {index?: number, columnHeader: string}) { + return this.cell.get({index, columnHeader}); + } + + clickFilePicker({ index, columnHeader }: { index?: number, columnHeader: string }) { + return this.get({index, columnHeader}).locator('[pw-data="attachment-cell-file-picker-button"]').click(); + } + + async addFile({ index, columnHeader, filePath }: { index?: number, columnHeader: string, filePath: string; }) { + const attachFileAction = this.get({index, columnHeader}).locator('[pw-data="attachment-cell-file-picker-button"]').click(); + return this.attachFile({ filePickUIAction: attachFileAction, filePath }); + } + + async verifyFile({ index, columnHeader }: { index: number, columnHeader: string }) { + expect(await this.get({index, columnHeader}).locator('.nc-attachment')).toBeVisible(); + } +} \ No newline at end of file diff --git a/scripts/playwright/pages/Dashboard/Grid/Cell/SelectOptionCell.ts b/scripts/playwright/pages/Dashboard/common/Cell/SelectOptionCell.ts similarity index 100% rename from scripts/playwright/pages/Dashboard/Grid/Cell/SelectOptionCell.ts rename to scripts/playwright/pages/Dashboard/common/Cell/SelectOptionCell.ts diff --git a/scripts/playwright/pages/Dashboard/Grid/Cell/index.ts b/scripts/playwright/pages/Dashboard/common/Cell/index.ts similarity index 82% rename from scripts/playwright/pages/Dashboard/Grid/Cell/index.ts rename to scripts/playwright/pages/Dashboard/common/Cell/index.ts index 66bd616b7a..659aaec7ae 100644 --- a/scripts/playwright/pages/Dashboard/Grid/Cell/index.ts +++ b/scripts/playwright/pages/Dashboard/common/Cell/index.ts @@ -1,28 +1,38 @@ import { expect, Locator } from "@playwright/test"; -import { GridPage } from ".."; +import { GridPage } from "../../Grid"; import BasePage from "../../../Base"; +import { AttachmentCellPageObject } from "./AttachmentCell"; import { SelectOptionCellPageObject } from "./SelectOptionCell"; +import { SharedFormPage } from "../../../SharedForm"; export class CellPageObject extends BasePage { - readonly grid: GridPage; + readonly parent: GridPage | SharedFormPage; readonly selectOption: SelectOptionCellPageObject; + readonly attachment: AttachmentCellPageObject; - constructor(grid: GridPage) { - super(grid.rootPage); - this.grid = grid; + constructor(parent: GridPage | SharedFormPage) { + super(parent.rootPage); + this.parent = parent; this.selectOption = new SelectOptionCellPageObject(this); + this.attachment = new AttachmentCellPageObject(this); } get({ index, columnHeader, }: { - index: number; + index?: number; columnHeader: string; }): Locator { - return this.grid + if(this.parent instanceof SharedFormPage) { + return this.parent + .get() + .locator(`[pw-data="nc-form-input-cell-${columnHeader}"]`); + } else { + return this.parent .get() .locator(`td[data-pw="cell-${columnHeader}-${index}"]`); + } } async click({ diff --git a/scripts/playwright/pages/SharedForm/index.ts b/scripts/playwright/pages/SharedForm/index.ts new file mode 100644 index 0000000000..898026ee2c --- /dev/null +++ b/scripts/playwright/pages/SharedForm/index.ts @@ -0,0 +1,21 @@ +// playwright-dev-page.ts +import { Locator, Page, expect } from "@playwright/test"; +import BasePage from "../Base"; +import { CellPageObject } from "../Dashboard/common/Cell"; + +export class SharedFormPage extends BasePage { + readonly cell: CellPageObject; + + constructor(rootPage: Page) { + super(rootPage); + this.cell = new CellPageObject(this); + } + + get() { + return this.rootPage.locator("html"); + } + + async submit() { + await this.get().locator('[pw-data="shared-form-submit-button"]').click(); + } +} diff --git a/scripts/playwright/tests/attachments.spec.ts b/scripts/playwright/tests/attachments.spec.ts new file mode 100644 index 0000000000..3810e3efc0 --- /dev/null +++ b/scripts/playwright/tests/attachments.spec.ts @@ -0,0 +1,39 @@ +import { test } from "@playwright/test"; +import { DashboardPage } from "../pages/Dashboard"; +import { SharedFormPage } from "../pages/SharedForm"; +import setup from "../setup"; + +test.describe("Attachment column", () => { + let dashboard: DashboardPage; + let context: any; + + test.beforeEach(async ({ page }) => { + context = await setup({ page }); + dashboard = new DashboardPage(page, context.project); + }); + + test("Create duration column", async ({page, context}) => { + await dashboard.treeView.openTable({title: "Country"}); + await dashboard.grid.column.create({ + title: "testAttach", + type: "Attachment", + }) + for (let i = 4; i <= 6; i++) { + const filepath = `${process.cwd()}/fixtures/sampleFiles/${i}.json`; + await dashboard.grid.cell.attachment.addFile({index: i, columnHeader: "testAttach", filePath: filepath}); + await dashboard.grid.cell.attachment.verifyFile({index: i, columnHeader: "testAttach"}); + } + + await dashboard.viewSidebar.createFormView({ + title: "Form 1", + }); + await dashboard.form.toolbar.clickShareView(); + const sharedFormUrl = await dashboard.form.toolbar.shareView.getShareLink(); + const newPage = await context.newPage() + await newPage.goto(sharedFormUrl); + + const sharedForm = new SharedFormPage(newPage); + await sharedForm.cell.attachment.addFile({columnHeader: 'testAttach', filePath: `${process.cwd()}/fixtures/sampleFiles/1.json`}); + await sharedForm.submit(); + }); +});