diff --git a/scripts/playwright/pages/Dashboard/Import/Airtable.ts b/scripts/playwright/pages/Dashboard/Import/Airtable.ts new file mode 100644 index 0000000000..ca9e76a6e8 --- /dev/null +++ b/scripts/playwright/pages/Dashboard/Import/Airtable.ts @@ -0,0 +1,29 @@ +// playwright-dev-page.ts +import { expect, Locator } from "@playwright/test"; +import BasePage from "../../Base"; +import { DashboardPage } from ".."; + +export class ImportAirtablePage extends BasePage { + readonly dashboard: DashboardPage; + readonly importButton: Locator; + + constructor(dashboard: DashboardPage) { + super(dashboard.rootPage); + this.dashboard = dashboard; + this.importButton = dashboard.get().locator(".nc-btn-airtable-import"); + } + + get() { + return this.dashboard.get().locator(`.nc-modal-airtable-import`); + } + + async import({ key, baseId }: { key: string; baseId: string }) { + console.log(key, baseId); + await this.get().locator(`.nc-input-api-key >> input`).fill(key); + await this.get().locator(`.nc-input-shared-base`).fill(baseId); + await this.importButton.click(); + + await this.get().locator(`button:has-text("Go to Dashboard")`).waitFor(); + await this.get().locator(`button:has-text("Go to Dashboard")`).click(); + } +} diff --git a/scripts/playwright/pages/Dashboard/TreeView.ts b/scripts/playwright/pages/Dashboard/TreeView.ts index 73d7629fae..85dd338067 100644 --- a/scripts/playwright/pages/Dashboard/TreeView.ts +++ b/scripts/playwright/pages/Dashboard/TreeView.ts @@ -1,15 +1,17 @@ -import { expect } from "@playwright/test"; +import { Locator, expect } from "@playwright/test"; import { DashboardPage } from "."; import BasePage from "../Base"; export class TreeViewPage extends BasePage { readonly dashboard: DashboardPage; readonly project: any; + readonly quickImportButton: Locator; constructor(dashboard: DashboardPage, project: any) { super(dashboard.rootPage); this.dashboard = dashboard; this.project = project; + this.quickImportButton = dashboard.get().locator(".nc-import-menu"); } get() { @@ -23,8 +25,12 @@ export class TreeViewPage extends BasePage { // assumption: first view rendered is always GRID // async openTable({ title }: { title: string }) { - if(await this.get().locator('.active.nc-project-tree-tbl').count() > 0) { - if(await this.get().locator('.active.nc-project-tree-tbl').innerText() === title) { + if ((await this.get().locator(".active.nc-project-tree-tbl").count()) > 0) { + if ( + (await this.get() + .locator(".active.nc-project-tree-tbl") + .innerText()) === title + ) { // table already open return; } @@ -42,7 +48,11 @@ export class TreeViewPage extends BasePage { async createTable({ title }: { title: string }) { await this.get().locator(".nc-add-new-table").click(); - await this.dashboard.get().locator('.nc-modal-table-create').locator(".ant-modal-body").waitFor(); + await this.dashboard + .get() + .locator(".nc-modal-table-create") + .locator(".ant-modal-body") + .waitFor(); await this.dashboard .get() @@ -50,12 +60,15 @@ export class TreeViewPage extends BasePage { .fill(title); await this.waitForResponse({ - uiAction: this.dashboard.get().locator('button:has-text("Submit")').click(), + uiAction: this.dashboard + .get() + .locator('button:has-text("Submit")') + .click(), httpMethodsToMatch: ["POST"], requestUrlPathToMatch: `/api/v1/db/meta/projects/`, - responseJsonMatcher: (json) => json.title === title && json.type === 'table', + responseJsonMatcher: (json) => + json.title === title && json.type === "table", }); - await this.dashboard.waitForTabRender({ title }); } @@ -93,13 +106,20 @@ export class TreeViewPage extends BasePage { requestUrlPathToMatch: `/api/v1/db/meta/tables/`, }); - await expect.poll(async () => - await this.dashboard.tabBar.locator('.ant-tabs-tab', { - hasText: title - }).isVisible() - ).toBe(false); - - (await this.rootPage.locator('.nc-container').last().elementHandle())?.waitForElementState('stable'); + await expect + .poll( + async () => + await this.dashboard.tabBar + .locator(".ant-tabs-tab", { + hasText: title, + }) + .isVisible() + ) + .toBe(false); + + ( + await this.rootPage.locator(".nc-container").last().elementHandle() + )?.waitForElementState("stable"); } async renameTable({ title, newTitle }: { title: string; newTitle: string }) { @@ -132,4 +152,13 @@ export class TreeViewPage extends BasePage { this.get().locator(`[pw-data="tree-view-table-${destinationTable}"]`) ); } + + async quickImport({ title }: { title: string }) { + await this.get().locator(".nc-add-new-table").hover(); + await this.quickImportButton.click(); + const importMenu = this.dashboard.get().locator(".nc-dropdown-import-menu"); + await importMenu + .locator(`.ant-dropdown-menu-title-content:has-text("${title}")`) + .click(); + } } diff --git a/scripts/playwright/pages/Dashboard/index.ts b/scripts/playwright/pages/Dashboard/index.ts index dab2f18164..52fe3212ec 100644 --- a/scripts/playwright/pages/Dashboard/index.ts +++ b/scripts/playwright/pages/Dashboard/index.ts @@ -12,6 +12,7 @@ import { ViewSidebarPage } from "./ViewSidebar"; import { GalleryPage } from "./Gallery"; import { KanbanPage } from "./Kanban"; import { ToolbarPage } from "./common/Toolbar"; +import { ImportAirtablePage } from "./Import/Airtable"; export class DashboardPage extends BasePage { readonly project: any; @@ -27,6 +28,7 @@ export class DashboardPage extends BasePage { readonly linkRecord: LinkRecord; readonly settings: SettingsPage; readonly viewSidebar: ViewSidebarPage; + readonly importAirtable: ImportAirtablePage; constructor(rootPage: Page, project: any) { super(rootPage); @@ -43,6 +45,7 @@ export class DashboardPage extends BasePage { this.linkRecord = new LinkRecord(this); this.settings = new SettingsPage(this); this.viewSidebar = new ViewSidebarPage(this); + this.importAirtable = new ImportAirtablePage(this); } get() { @@ -130,4 +133,36 @@ export class DashboardPage extends BasePage { .locator(`[placeholder="${param.json.activity.searchProject}"]`) .waitFor(); } + + // create project + async createProject({ + name = "sample", + type = "xcdb", + }: { + name?: string; + type?: string; + }) { + // fix me! wait for page to be rendered completely + await this.rootPage.waitForTimeout(1000); + await this.rootPage.locator(".nc-new-project-menu").click(); + + const createProjectMenu = await this.rootPage.locator( + ".nc-dropdown-create-project" + ); + if (type === "xcdb") { + await createProjectMenu + .locator(`.ant-dropdown-menu-title-content`) + .nth(0) + .click(); + } else { + await createProjectMenu + .locator(`.ant-dropdown-menu-title-content`) + .nth(1) + .click(); + } + + await this.rootPage.locator(`.nc-metadb-project-name`).waitFor(); + await this.rootPage.locator(`input.nc-metadb-project-name`).fill(name); + await this.rootPage.locator(`input.nc-metadb-project-name`).press("Enter"); + } } diff --git a/scripts/playwright/tests/import.spec.ts b/scripts/playwright/tests/import.spec.ts new file mode 100644 index 0000000000..c9bd74baa5 --- /dev/null +++ b/scripts/playwright/tests/import.spec.ts @@ -0,0 +1,53 @@ +import { test } from "@playwright/test"; +import { DashboardPage } from "../pages/Dashboard"; +import setup from "../setup"; + +const apiKey = process.env.E2E_AIRTABLE_API_KEY; +const apiBase = process.env.E2E_AIRTABLE_BASE_ID; + +test.describe("Import", () => { + let dashboard: DashboardPage; + let context: any; + + test.beforeEach(async ({ page }) => { + context = await setup({ page }); + dashboard = new DashboardPage(page, context.project); + }); + + test("Airtable", async () => { + // create empty project + await dashboard.clickHome(); + await dashboard.createProject({ name: "airtable", type: "xcdb" }); + + await dashboard.treeView.quickImport({ title: "Airtable" }); + await dashboard.importAirtable.import({ + key: apiKey, + baseId: apiBase, + }); + await dashboard.rootPage.waitForTimeout(1000); + }); + + test("Excel", async () => { + // create empty project + await dashboard.clickHome(); + await dashboard.createProject({ name: "excel", type: "xcdb" }); + + await dashboard.treeView.quickImport({ title: "Microsoft Excel" }); + }); + + test("CSV", async () => { + // create empty project + await dashboard.clickHome(); + await dashboard.createProject({ name: "CSV", type: "xcdb" }); + + await dashboard.treeView.quickImport({ title: "CSV file" }); + }); + + test("JSON", async () => { + // create empty project + await dashboard.clickHome(); + await dashboard.createProject({ name: "JSON", type: "xcdb" }); + + await dashboard.treeView.quickImport({ title: "JSON file" }); + }); +});