From 439ca4b52c75effc3e95052c6a48a7b3fff5b853 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Tue, 12 Nov 2024 17:26:11 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20Add=20token=20creation=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/workspace/get-team-tokens.json | 24 +++++ frontend/playwright/ui/pages/WorkspacePage.js | 3 + frontend/playwright/ui/specs/tokens.spec.js | 87 +++++++++++++++++++ .../app/main/ui/workspace/tokens/form.cljs | 4 +- .../app/main/ui/workspace/tokens/modals.cljs | 3 +- .../app/main/ui/workspace/tokens/sidebar.cljs | 3 +- 6 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 frontend/playwright/data/workspace/get-team-tokens.json create mode 100644 frontend/playwright/ui/specs/tokens.spec.js diff --git a/frontend/playwright/data/workspace/get-team-tokens.json b/frontend/playwright/data/workspace/get-team-tokens.json new file mode 100644 index 0000000000..855b1506ac --- /dev/null +++ b/frontend/playwright/data/workspace/get-team-tokens.json @@ -0,0 +1,24 @@ +{ + "~:features": { + "~#set": [ + "design-tokens/v1", + "layout/grid", + "styles/v2", + "fdata/pointer-map", + "fdata/objects-map", + "components/v2", + "fdata/shape-data-type" + ] + }, + "~:permissions": { + "~:type": "~:membership", + "~:is-owner": true, + "~:is-admin": true, + "~:can-edit": true + }, + "~:name": "Default", + "~:modified-at": "~m1713533116375", + "~:id": "~uc7ce0794-0992-8105-8004-38e630f40f6d", + "~:created-at": "~m1713533116375", + "~:is-default": true +} diff --git a/frontend/playwright/ui/pages/WorkspacePage.js b/frontend/playwright/ui/pages/WorkspacePage.js index 71c20b639f..1b66cc34c6 100644 --- a/frontend/playwright/ui/pages/WorkspacePage.js +++ b/frontend/playwright/ui/pages/WorkspacePage.js @@ -76,6 +76,9 @@ export class WorkspacePage extends BaseWebSocketPage { this.togglePalettesVisibility = page.getByTestId( "toggle-palettes-visibility", ); + this.tokensUpdateCreateModal = page.getByTestId( + "token-update-create-modal", + ); } async goToWorkspace({ diff --git a/frontend/playwright/ui/specs/tokens.spec.js b/frontend/playwright/ui/specs/tokens.spec.js new file mode 100644 index 0000000000..7ea79ce74a --- /dev/null +++ b/frontend/playwright/ui/specs/tokens.spec.js @@ -0,0 +1,87 @@ +import { test, expect } from "@playwright/test"; +import { WorkspacePage } from "../pages/WorkspacePage"; + +test.beforeEach(async ({ page }) => { + await WorkspacePage.init(page); +}); + +test.describe("Tokens: Tab", () => { + test("Clicking tokens tab button opens tokens sidebar tab", async ({ + page, + }) => { + const workspacePage = new WorkspacePage(page); + await workspacePage.setupEmptyFile(); + await workspacePage.mockRPC( + "get-team?id=*", + "workspace/get-team-tokens.json", + ); + + await workspacePage.goToWorkspace(); + + const tokensTabButton = page.getByRole("tab", { name: "Tokens" }); + await tokensTabButton.click(); + + const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" }); + + await expect(tokensTabPanel).toHaveText(/TOKENS/); + await expect(tokensTabPanel).toHaveText(/Themes/); + }); + + test("Created color token shows up in the sidebar", async ({ page }) => { + const workspacePage = new WorkspacePage(page); + await workspacePage.setupEmptyFile(); + await workspacePage.mockRPC( + "get-team?id=*", + "workspace/get-team-tokens.json", + ); + + await workspacePage.goToWorkspace(); + + const tokensTabButton = page.getByRole("tab", { name: "Tokens" }); + await tokensTabButton.click(); + + const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" }); + await tokensTabPanel.getByTitle("Add token: Color").click(); + + // Create color token with mouse + + await expect(workspacePage.tokensUpdateCreateModal).toBeVisible(); + + const nameField = workspacePage.tokensUpdateCreateModal.getByLabel("Name"); + const valueField = + workspacePage.tokensUpdateCreateModal.getByLabel("Value"); + + await nameField.click(); + await nameField.fill("color.primary"); + + await valueField.click(); + await valueField.fill("red"); + + const submitButtonSelector = `button[type="submit"]:enabled`; + await page.waitForSelector(submitButtonSelector); + await page.locator(submitButtonSelector).click(); + + await expect(tokensTabPanel.getByText("color.primary")).toBeEnabled(); + + // Create token referencing the previous one with keyboard + + await tokensTabPanel.getByTitle("Add token: Color").click(); + await expect(workspacePage.tokensUpdateCreateModal).toBeVisible(); + + await nameField.click(); + await nameField.fill("color.secondary"); + await nameField.press("Tab"); + + await valueField.click(); + await valueField.fill("{color.primary}"); + + await page.waitForSelector(submitButtonSelector); + await nameField.press("Enter"); + + const referenceToken = tokensTabPanel.getByText("color.secondary"); + await expect(referenceToken).toBeEnabled(); + + // Tokens tab panel should have two tokens with the color red / #ff0000 + await expect(tokensTabPanel.getByTitle("#ff0000")).toHaveCount(2); + }); +}); diff --git a/frontend/src/app/main/ui/workspace/tokens/form.cljs b/frontend/src/app/main/ui/workspace/tokens/form.cljs index de24713031..a23ea972c2 100644 --- a/frontend/src/app/main/ui/workspace/tokens/form.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/form.cljs @@ -360,8 +360,8 @@ Token names should only contain letters and digits separated by . characters.")} (dom/prevent-default e) (modal/hide!)))] - [:form {:class (stl/css :form-wrapper) - :on-submit on-submit} + [:form {:class (stl/css :form-wrapper) + :on-submit on-submit} [:div {:class (stl/css :token-rows)} [:> heading* {:level 2 :typography "headline-medium" :class (stl/css :form-modal-title)} (if (= action "edit") diff --git a/frontend/src/app/main/ui/workspace/tokens/modals.cljs b/frontend/src/app/main/ui/workspace/tokens/modals.cljs index a34ccfe618..56a77ccd72 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals.cljs @@ -48,7 +48,8 @@ (fn [] (modal/hide!)))] [:div {:class (stl/css :token-modal-wrapper) - :style wrapper-style} + :style wrapper-style + :data-testid "token-update-create-modal"} [:> icon-button* {:on-click close-modal :class (stl/css :close-btn) :icon i/close diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index b496a2d974..20f4b7c0af 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -148,7 +148,8 @@ :open? open?} [:& cmm/asset-section-block {:role :title-button} [:button {:class (stl/css :action-button) - :on-click on-popover-open-click} + :on-click on-popover-open-click + :title (str "Add token: " title)} i/add]] (when open? [:& cmm/asset-section-block {:role :content} From 85fa635f6646f1e27baeeabc6a63333a6eef4c6c Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Mon, 25 Nov 2024 11:10:17 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9C=A8=20Check=20for=20auto-created=20se?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/playwright/ui/pages/WorkspacePage.js | 1 + frontend/playwright/ui/specs/tokens.spec.js | 16 +++++++++++++++- .../src/app/main/ui/workspace/tokens/sets.cljs | 5 +++-- .../app/main/ui/workspace/tokens/sidebar.cljs | 3 ++- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/frontend/playwright/ui/pages/WorkspacePage.js b/frontend/playwright/ui/pages/WorkspacePage.js index 1b66cc34c6..42326e4841 100644 --- a/frontend/playwright/ui/pages/WorkspacePage.js +++ b/frontend/playwright/ui/pages/WorkspacePage.js @@ -79,6 +79,7 @@ export class WorkspacePage extends BaseWebSocketPage { this.tokensUpdateCreateModal = page.getByTestId( "token-update-create-modal", ); + this.tokenThemesSetsSidebar = page.getByTestId("token-themes-sets-sidebar"); } async goToWorkspace({ diff --git a/frontend/playwright/ui/specs/tokens.spec.js b/frontend/playwright/ui/specs/tokens.spec.js index 7ea79ce74a..1d1959c671 100644 --- a/frontend/playwright/ui/specs/tokens.spec.js +++ b/frontend/playwright/ui/specs/tokens.spec.js @@ -27,7 +27,9 @@ test.describe("Tokens: Tab", () => { await expect(tokensTabPanel).toHaveText(/Themes/); }); - test("Created color token shows up in the sidebar", async ({ page }) => { + test("User creates color token and auto created set show up in the sidebar", async ({ + page, + }) => { const workspacePage = new WorkspacePage(page); await workspacePage.setupEmptyFile(); await workspacePage.mockRPC( @@ -83,5 +85,17 @@ test.describe("Tokens: Tab", () => { // Tokens tab panel should have two tokens with the color red / #ff0000 await expect(tokensTabPanel.getByTitle("#ff0000")).toHaveCount(2); + + // Global set has been auto created and is active + await expect( + workspacePage.tokenThemesSetsSidebar.getByRole("button", { + name: "Global", + }), + ).toHaveCount(1); + await expect( + workspacePage.tokenThemesSetsSidebar.getByRole("button", { + name: "Global", + }), + ).toHaveAttribute("aria-checked", "true"); }); }); diff --git a/frontend/src/app/main/ui/workspace/tokens/sets.cljs b/frontend/src/app/main/ui/workspace/tokens/sets.cljs index 127f13c3fa..49c41b0610 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sets.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sets.cljs @@ -111,7 +111,7 @@ [{:keys [set label tree-depth tree-path selected? on-select active? on-toggle editing? on-edit on-edit-reset on-edit-submit]}] (let [set-name (.-name set) editing?' (editing? tree-path) - active?' (active? set-name) + active?' (some? (active? set-name)) on-click (mf/use-fn (mf/deps editing?' tree-path) @@ -138,7 +138,8 @@ :selected-set selected?) :on-click on-click :on-double-click #(on-edit tree-path) - :on-context-menu on-context-menu} + :on-context-menu on-context-menu + :aria-checked active?'} [:> icon* {:id "document" :class (stl/css-case :icon true diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index 20f4b7c0af..a6b28ecb6e 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -239,7 +239,8 @@ on-open (mf/use-fn #(reset! open? true))] [:& sets-context/provider {} [:& sets-context-menu] - [:article {:class (stl/css :sets-section-wrapper) + [:article {:data-testid "token-themes-sets-sidebar" + :class (stl/css :sets-section-wrapper) :style {"--resize-height" (str resize-height "px")}} [:div {:class (stl/css :sets-sidebar)} [:& themes-header] From e4460acfae4cb68c41f885f2c4bea59c79dc3c2d Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Mon, 25 Nov 2024 16:41:02 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=E2=99=BB=20Extract=20common=20token=20setu?= =?UTF-8?q?p=20logic,=20fix=20selector?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/playwright/ui/specs/tokens.spec.js | 53 +++++++++++---------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/frontend/playwright/ui/specs/tokens.spec.js b/frontend/playwright/ui/specs/tokens.spec.js index 1d1959c671..2f920c275d 100644 --- a/frontend/playwright/ui/specs/tokens.spec.js +++ b/frontend/playwright/ui/specs/tokens.spec.js @@ -5,21 +5,27 @@ test.beforeEach(async ({ page }) => { await WorkspacePage.init(page); }); +const setupFileWithTokens = async (page) => { + const workspacePage = new WorkspacePage(page); + await workspacePage.setupEmptyFile(); + await workspacePage.mockRPC( + "get-team?id=*", + "workspace/get-team-tokens.json", + ); + + await workspacePage.goToWorkspace(); + + const tokensTabButton = page.getByRole("tab", { name: "Tokens" }); + await tokensTabButton.click(); + + return { workspacePage }; +}; + test.describe("Tokens: Tab", () => { test("Clicking tokens tab button opens tokens sidebar tab", async ({ page, }) => { - const workspacePage = new WorkspacePage(page); - await workspacePage.setupEmptyFile(); - await workspacePage.mockRPC( - "get-team?id=*", - "workspace/get-team-tokens.json", - ); - - await workspacePage.goToWorkspace(); - - const tokensTabButton = page.getByRole("tab", { name: "Tokens" }); - await tokensTabButton.click(); + const { workspacePage } = await setupFileWithTokens(page); const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" }); @@ -30,17 +36,7 @@ test.describe("Tokens: Tab", () => { test("User creates color token and auto created set show up in the sidebar", async ({ page, }) => { - const workspacePage = new WorkspacePage(page); - await workspacePage.setupEmptyFile(); - await workspacePage.mockRPC( - "get-team?id=*", - "workspace/get-team-tokens.json", - ); - - await workspacePage.goToWorkspace(); - - const tokensTabButton = page.getByRole("tab", { name: "Tokens" }); - await tokensTabButton.click(); + const { workspacePage } = await setupFileWithTokens(page); const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" }); await tokensTabPanel.getByTitle("Add token: Color").click(); @@ -59,9 +55,14 @@ test.describe("Tokens: Tab", () => { await valueField.click(); await valueField.fill("red"); - const submitButtonSelector = `button[type="submit"]:enabled`; - await page.waitForSelector(submitButtonSelector); - await page.locator(submitButtonSelector).click(); + const submitButton = workspacePage.tokensUpdateCreateModal.getByRole( + "button", + { + name: "Save", + }, + ); + await expect(submitButton).toBeEnabled(); + await submitButton.click(); await expect(tokensTabPanel.getByText("color.primary")).toBeEnabled(); @@ -77,7 +78,7 @@ test.describe("Tokens: Tab", () => { await valueField.click(); await valueField.fill("{color.primary}"); - await page.waitForSelector(submitButtonSelector); + await expect(submitButton).toBeEnabled(); await nameField.press("Enter"); const referenceToken = tokensTabPanel.getByText("color.secondary");