penpot/frontend/playwright/ui/specs/inspect-layout.spec.js
Andrés Moya 3cd9bfa9de
Add sync with design tokens in external libraries (#10293)
*  Auto link tokens when adding external libraries (provisional)

* 🔧 Refactor tokens-lib initialization

* 🔧 Add separated TokenStatus to store status apart of TokensLib

* 🔧 Make all status operations use the new data structure

* 🔧 Normalize status helper functions and access token sets by id

* 🔧 Rename :tokens-file to :tokens-source

* 🎉 Allow the user to choose the tokens-source of a file

* 🎉 Make tokens library readonly when it's in an external file

* 🎉 Show tokens in library summaries

* 🎉 Show source info in sidebar

* 🔧 Fix integration tests

* 🐛 Propagate changes of token values in external library

* 🎉 Layout updates

* 🔧 Refactor tokens source calculations

* 🔧 Add harder checks for nil or empty values in everything

* 🐛 Fix some integration tests

* 🔧 Add integration tests for tokens in external libs

* 🔧 Validate and repair missing tokens status

* 🎉 Make ui changes optional with config flag

* 🐛 Propagate tokens after synchronizing components in ext library

* 🐛 Propagate tokens after creating new instances

* 🐛 Propagate tokens after synchronizing tokens in ext library

* 🐛 Add a tokens source icon to libraries section (#11439)

* 🐛 Add a tokens source icon to libraries section

* 🐛 Fix ellipsis on library names

* ♻️ Remove code under flag on legacy component

* 🐛 Fix token theme name on inspect tab

* 🎉 Add changes notification (#11476)

* 🎉 Add changes notification

* ♻️ Change fn names

* 🐛 Fix tokens source label truncation and missing translations (#11533)

* 🐛 Fix tokens source label truncation and missing translations

The tokens source file name always showed, even for the current file,
and long names wrapped onto a second line instead of truncating
because the header used flex-wrap and overflow-wrap: break-word
instead of single-line ellipsis.

Show the source row unconditionally (it now displays "This file" when
the source is the current file, matching the connected-library case),
truncate the file name to one line with an ellipsis, and only attach a
tooltip with the full name when the text is actually truncated.

Replace the hardcoded UI strings with translated ones and add their
English and Spanish entries.

AI-assisted-by: claude-sonnet-5

* 🐛 Remove redundant effect dependency in tokens source

file-name-truncated? was listed as a dependency of the with-effect
that checks and observes label truncation, even though it isn't
read inside the effect body. Since the effect itself flips that
state via check-file-name-truncated, including it as a dependency
caused the ResizeObserver to be needlessly disconnected and
reconnected on every truncation change.

AI-assisted-by: claude-sonnet-5

* 🐛 Fix small visual error

* 🐛 Fix problem with plugins

* 🐛 Fix playwright tests

---------

Co-authored-by: Eva Marco <evamarcod@gmail.com>
Co-authored-by: Eva Marco <eva.marco@kaleidos.net>
Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
2026-09-21 15:37:45 +02:00

192 lines
6.6 KiB
JavaScript

import { test, expect } from "@playwright/test";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WasmWorkspacePage.init(page);
});
// Fix for https://tree.taiga.io/project/penpot/issue/8593
test("Bug 8593 - Grid layout three dots button visible on hover in grid editor", async ({
page,
}) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-9042.json");
await workspacePage.mockRPC(
"get-file-fragment?file-id=*&fragment-id=*",
"workspace/get-file-fragment-9042.json",
);
await workspacePage.goToWorkspace({
fileId: "af2494d0-39ba-8184-8005-230696f6df5c",
pageId: "af2494d0-39ba-8184-8005-230696f6df5d",
});
await workspacePage.clickLeafLayer("Board");
await workspacePage.expectSelectedLayer("Board");
// Zoom in so tracks are wide enough (>= 110px) for the three-dots button to render.
// Board is 200x200 with 2 columns (100px each); zoom 2x makes them 200px.
await workspacePage.page.keyboard.press("Control+=");
await workspacePage.page.keyboard.press("Control+=");
await workspacePage.page.waitForTimeout(200);
// Enter grid editing mode
const layoutContainer = workspacePage.page.getByTestId("inspect-layout");
await layoutContainer.getByRole("button", { name: "Edit grid" }).click();
await workspacePage.page.waitForTimeout(500);
// The three-dots button should always exist in the DOM when track is large enough.
// Previously it was only rendered when JS hover state was true (broken in WebKit/Safari).
// Now it is always rendered and shown/hidden via CSS :hover.
const gridEditorButton = workspacePage.page.getByTestId("grid-track-options-btn").first();
await expect(gridEditorButton).toBeAttached();
// Hover over the track wrapper; CSS :hover should make the button visible.
// This approach works in all browsers including WebKit/Safari.
const gridEditorWrapper = workspacePage.page.getByTestId("grid-track-editor-wrapper").first();
await gridEditorWrapper.hover();
await expect(gridEditorButton).toBeVisible();
});
// Fix for https://tree.taiga.io/project/penpot/issue/9042
test("Bug 9042 - Measurement unit dropdowns for columns are cut off in grid layout edit mode", async ({
page,
}) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-9042.json");
await workspacePage.mockRPC(
"get-file-fragment?file-id=*&fragment-id=*",
"workspace/get-file-fragment-9042.json",
);
await workspacePage.goToWorkspace({
fileId: "af2494d0-39ba-8184-8005-230696f6df5c",
pageId: "af2494d0-39ba-8184-8005-230696f6df5d",
});
await workspacePage.clickLeafLayer("Board");
await workspacePage.expectSelectedLayer("Board");
const layoutContainer = workspacePage.page.getByTestId("inspect-layout");
await layoutContainer.getByRole("button", { name: "Edit grid" }).click();
const rowsContainer = workspacePage.page.getByTestId("inspect-layout-rows");
await rowsContainer.click();
await rowsContainer.getByText("FR").nth(2).click();
await expect(rowsContainer.getByText("%")).toBeInViewport();
});
test("[Taiga #9116] Copy CSS background color in the selected format in the INSPECT tab", async ({
page,
context,
}) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();
await workspacePage.rectShapeButton.click();
await workspacePage.clickWithDragViewportAt(128, 128, 200, 100);
await workspacePage.clickLeafLayer("Rectangle");
const inspectButton = workspacePage.page.getByRole("tab", {
name: "Inspect",
});
await inspectButton.click();
// Open color space selector combobox and change to RGBA format
const colorDropdown = workspacePage.page
.getByRole("combobox")
.getByText("HEX");
await colorDropdown.click();
const rgbaFormatButton = workspacePage.page.getByRole("option", {
name: "RGBA",
});
await rgbaFormatButton.click();
// Open info tab selector and select the computed tab
const infoTabSelector = workspacePage.page
.getByRole("combobox")
.getByText("Styles");
await infoTabSelector.click();
const infoTabSelectorButton = workspacePage.page.getByRole("option", {
name: "Computed",
});
await infoTabSelectorButton.click();
const copyColorButton = workspacePage.page.getByRole("button", {
name: "Copy color",
});
await copyColorButton.click();
const rgbaColorText = await page.evaluate(() =>
navigator.clipboard.readText(),
);
expect(rgbaColorText).toContain("background: rgba(");
});
test("[Taiga #10630] [INSPECT] Style assets not being displayed on info tab", async ({
page,
context,
}) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();
await workspacePage.mockRPC(
"link-file-to-library",
"workspace/link-file-to-library.json",
);
await workspacePage.mockRPC(
"unlink-file-from-library",
"workspace/unlink-file-from-library.json",
);
await workspacePage.mockRPC(
"get-team-shared-files?team-id=*",
"workspace/get-team-shared-libraries-non-empty.json",
);
await workspacePage.clickColorPalette();
await workspacePage.clickAssets();
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-library.json");
await workspacePage.openLibrariesModal();
await workspacePage.librariesModal.getByRole("tab", { name: "Libraries" }).click();
await workspacePage.clickLibrary("Testing library 1");
await workspacePage.closeLibrariesModal();
await expect(
workspacePage.palette.getByRole("button", { name: "test-color-187cd5" }),
).toBeVisible();
await workspacePage.clickLayers();
await workspacePage.rectShapeButton.click();
await workspacePage.clickWithDragViewportAt(128, 128, 200, 100);
await workspacePage.clickLeafLayer("Rectangle");
await workspacePage.palette
.getByRole("button", { name: "test-color-187cd5" })
.click();
const inspectButton = workspacePage.page.getByRole("tab", {
name: "Inspect",
});
await inspectButton.click();
// Open info tab selector and select the computed tab
const infoTabSelector = workspacePage.page
.getByRole("combobox")
.getByText("Styles");
await infoTabSelector.click();
const infoTabSelectorButton = workspacePage.page.getByRole("option", {
name: "Computed",
});
await infoTabSelectorButton.click();
const colorLibraryName = workspacePage.page.getByTestId("color-library-name");
await expect(colorLibraryName).toHaveText("test-color-187cd5");
});