mirror of
https://github.com/penpot/penpot.git
synced 2026-11-01 15:40:41 +00:00
* ♻️ Explain why layout_container.scss keeps the deprecated import The TODO at the top said to remove the refactor/ import once the buttons were replaced, and sat above the DS imports instead of that one. The buttons are now DS buttons (#12428, #12431), but the import is still needed by the numeric inputs (%input-element, %disabled-input) and by the two raw track header buttons, which keep the secondary and tertiary placeholders. Replace the TODO with a comment on the import that says so. AI-assisted-by: claude-opus-5-5 * 📎 Format the workspace visual spec with Prettier Three expectations added in #12423, #12428 and #12431 broke a call chain in a way Prettier rewrites. check-fmt:js did not catch it: its playwright/**/*.js glob is expanded by the shell without globstar, so it does not reach visual-specs/. AI-assisted-by: claude-opus-5-5
587 lines
20 KiB
JavaScript
587 lines
20 KiB
JavaScript
import { test, expect } from "@playwright/test";
|
|
import { WorkspacePage } from "../pages/WorkspacePage";
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await WorkspacePage.init(page);
|
|
});
|
|
|
|
const setupFileWithAssets = async (workspace) => {
|
|
const fileId = "015fda4f-caa6-8103-8004-862a00dd4f31";
|
|
const pageId = "015fda4f-caa6-8103-8004-862a00ddbe94";
|
|
const fragments = {
|
|
"015fda4f-caa6-8103-8004-862a9e4b4d4b":
|
|
"assets/get-file-fragment-with-assets-components.json",
|
|
"015fda4f-caa6-8103-8004-862a9e4ad279":
|
|
"assets/get-file-fragmnet-with-assets-page.json",
|
|
};
|
|
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "assets/get-file-with-assets.json");
|
|
|
|
for (const [id, fixture] of Object.entries(fragments)) {
|
|
await workspace.mockRPC(
|
|
`get-file-fragment?file-id=*&fragment-id=${id}`,
|
|
fixture,
|
|
);
|
|
}
|
|
|
|
return { fileId, pageId };
|
|
};
|
|
|
|
test.describe("Viewport", () => {
|
|
test("Shows the workspace correctly for a blank file", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
|
|
await workspace.goToWorkspace();
|
|
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
});
|
|
|
|
test("User creates a rectangle and locks it", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile(page);
|
|
await workspace.goToWorkspace();
|
|
|
|
await workspace.rectShapeButton.click();
|
|
await workspace.clickWithDragViewportAt(128, 128, 200, 100);
|
|
await workspace.clickLeafLayer("Rectangle");
|
|
|
|
await page.keyboard.press("Shift+Control+L");
|
|
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
});
|
|
});
|
|
|
|
test.describe("Grid layout", () => {
|
|
test("Shows the grid layout options and the grid editor", async ({
|
|
page,
|
|
}) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-9042.json");
|
|
await workspace.mockRPC(
|
|
"get-file-fragment?file-id=*&fragment-id=*",
|
|
"workspace/get-file-fragment-9042.json",
|
|
);
|
|
await workspace.goToWorkspace({
|
|
fileId: "af2494d0-39ba-8184-8005-230696f6df5c",
|
|
pageId: "af2494d0-39ba-8184-8005-230696f6df5d",
|
|
});
|
|
|
|
await workspace.clickLeafLayer("Board");
|
|
const section = page.getByTestId("inspect-layout");
|
|
await expect(
|
|
section.getByRole("button", { name: "Edit grid" }),
|
|
).toBeVisible();
|
|
// The buttons are a small part of the section: compare every pixel.
|
|
await expect(section).toHaveScreenshot("grid-layout-options.png", {
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
|
|
await section.getByRole("button", { name: "Edit grid" }).click();
|
|
await expect(workspace.rightSidebar.getByText("GRID LAYOUT")).toBeVisible();
|
|
// Expand the column tracks so their rows show too.
|
|
await workspace.rightSidebar.getByText(/^Columns? \d/).click();
|
|
await page.mouse.move(0, 0);
|
|
await expect(workspace.rightSidebar).toHaveScreenshot(
|
|
"grid-layout-editor.png",
|
|
{ maxDiffPixelRatio: 0, threshold: 0 },
|
|
);
|
|
});
|
|
});
|
|
|
|
test.describe("Design tab", () => {
|
|
test("Shows the boolean options when selecting two shapes", async ({
|
|
page,
|
|
}) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.goToWorkspace();
|
|
|
|
await workspace.rectShapeButton.click();
|
|
await workspace.clickWithDragViewportAt(128, 128, 200, 100);
|
|
await workspace.clickLeafLayer("Rectangle");
|
|
await page.keyboard.press("Control+D");
|
|
await expect(workspace.layers.getByText("Rectangle")).toHaveCount(2);
|
|
await page.keyboard.press("Control+A");
|
|
|
|
await expect(
|
|
workspace.rightSidebar.getByRole("button", { name: "Flatten" }),
|
|
).toBeVisible();
|
|
// The boolean options are a small part of the sidebar: compare every
|
|
// pixel.
|
|
await expect(workspace.rightSidebar).toHaveScreenshot({
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
|
|
test("Shows the design tab when selecting a shape", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-not-empty.json");
|
|
|
|
await workspace.goToWorkspace({
|
|
fileId: "6191cd35-bb1f-81f7-8004-7cc63d087374",
|
|
pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375",
|
|
});
|
|
|
|
await workspace.clickLeafLayer("Rectangle");
|
|
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
});
|
|
|
|
test("Shows expanded sections of the design tab", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-not-empty.json");
|
|
|
|
await workspace.goToWorkspace({
|
|
fileId: "6191cd35-bb1f-81f7-8004-7cc63d087374",
|
|
pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375",
|
|
});
|
|
|
|
await workspace.clickLeafLayer("Rectangle");
|
|
await workspace.rightSidebar.getByTestId("add-stroke").click();
|
|
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
});
|
|
|
|
test("Shows the wrap and padding modes of a flex layout", async ({
|
|
page,
|
|
}) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-7760.json");
|
|
await workspace.mockRPC(
|
|
"get-file-fragment?file-id=*&fragment-id=*",
|
|
"workspace/get-file-fragment-7760.json",
|
|
);
|
|
await workspace.mockRPC(
|
|
"update-file?id=*",
|
|
"workspace/update-file-create-rect.json",
|
|
);
|
|
await workspace.goToWorkspace({
|
|
fileId: "cd90e028-326a-80b4-8004-7cdec16ffad5",
|
|
pageId: "cd90e028-326a-80b4-8004-7cdec16ffad6",
|
|
});
|
|
|
|
await workspace.clickLeafLayer("Flex Board");
|
|
|
|
const section = workspace.rightSidebar.getByRole("region", {
|
|
name: "Layout container section",
|
|
});
|
|
const wrap = section.getByRole("button", { name: /^(No w|W)rap$/ });
|
|
const padding = section.getByRole("button", {
|
|
name: "Show 4 sided padding options",
|
|
});
|
|
await expect(wrap).toBeVisible();
|
|
// The buttons are a small part of the section: compare every pixel.
|
|
await expect(section).toHaveScreenshot("flex-layout-rest.png", {
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
|
|
await wrap.click();
|
|
await padding.click();
|
|
await padding.blur();
|
|
await page.mouse.move(0, 0);
|
|
await expect(
|
|
section.getByRole("textbox", { name: /top padding/i }),
|
|
).toBeVisible();
|
|
await expect(section).toHaveScreenshot("flex-layout-pressed.png", {
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
|
|
test("Shows the align options when selecting two shapes", async ({
|
|
page,
|
|
}) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.goToWorkspace();
|
|
|
|
await workspace.rectShapeButton.click();
|
|
await workspace.clickWithDragViewportAt(128, 128, 200, 100);
|
|
await workspace.clickLeafLayer("Rectangle");
|
|
await page.keyboard.press("Control+D");
|
|
await expect(workspace.layers.getByText("Rectangle")).toHaveCount(2);
|
|
await page.keyboard.press("Control+A");
|
|
|
|
await expect(
|
|
workspace.rightSidebar.getByRole("button", { name: /^Align left/ }),
|
|
).toBeVisible();
|
|
// The align options are a small part of the sidebar: compare every pixel.
|
|
await expect(workspace.rightSidebar).toHaveScreenshot({
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
|
|
test("Shows the margin modes of a flex layout element", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-7760.json");
|
|
await workspace.mockRPC(
|
|
"get-file-fragment?file-id=*&fragment-id=*",
|
|
"workspace/get-file-fragment-7760.json",
|
|
);
|
|
await workspace.mockRPC(
|
|
"update-file?id=*",
|
|
"workspace/update-file-create-rect.json",
|
|
);
|
|
await workspace.goToWorkspace({
|
|
fileId: "cd90e028-326a-80b4-8004-7cdec16ffad5",
|
|
pageId: "cd90e028-326a-80b4-8004-7cdec16ffad6",
|
|
});
|
|
|
|
await workspace.clickToggableLayer("Flex Board");
|
|
await workspace.clickLeafLayer("Rectangle");
|
|
|
|
const section = workspace.rightSidebar.getByRole("region", {
|
|
name: "Layout item section",
|
|
});
|
|
const marginMode = section.getByRole("button", {
|
|
name: "Margin - multiple",
|
|
});
|
|
await expect(marginMode).toBeVisible();
|
|
// The margin button is a small part of the section: compare every pixel.
|
|
await expect(section).toHaveScreenshot("margin-simple.png", {
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
|
|
await marginMode.click();
|
|
await marginMode.blur();
|
|
await page.mouse.move(0, 0);
|
|
await expect(
|
|
section.getByRole("textbox", { name: "Top margin" }),
|
|
).toBeVisible();
|
|
await expect(section).toHaveScreenshot("margin-multiple.png", {
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe("Component options", () => {
|
|
test("Shows the component pill of a copy", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-9066.json");
|
|
await workspace.goToWorkspace({
|
|
fileId: "e179d9df-de35-80bf-8005-283bbd5516b0",
|
|
pageId: "e179d9df-de35-80bf-8005-283bbd5516b1",
|
|
});
|
|
|
|
await workspace.clickToggableLayer("Board");
|
|
await workspace.clickToggableLayer("Group");
|
|
await workspace.layers.getByText("A", { exact: true }).click();
|
|
|
|
await expect(
|
|
workspace.rightSidebar.getByTestId("component-pill-button"),
|
|
).toBeVisible();
|
|
// The component pill is a small part of the sidebar: compare every
|
|
// pixel.
|
|
await expect(workspace.rightSidebar).toHaveScreenshot({
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
|
|
test("Shows the annotation actions of a main component", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-9066.json");
|
|
await workspace.goToWorkspace({
|
|
fileId: "e179d9df-de35-80bf-8005-283bbd5516b0",
|
|
pageId: "e179d9df-de35-80bf-8005-283bbd5516b1",
|
|
});
|
|
|
|
await workspace.clickToggableLayer("Board");
|
|
await workspace.clickToggableLayer("Group");
|
|
await workspace.layers.getByText("B", { exact: true }).click();
|
|
await workspace.rightSidebar
|
|
.getByRole("button", { name: "Options" })
|
|
.click();
|
|
await workspace.rightSidebar.getByText("Create annotation").click();
|
|
|
|
// Creating: save (disabled while the text is empty) and discard.
|
|
const annotation = workspace.rightSidebar.locator("#annotation-textarea");
|
|
await expect(annotation).toBeFocused();
|
|
await expect(workspace.rightSidebar).toHaveScreenshot(
|
|
"annotation-creating.png",
|
|
{ maxDiffPixelRatio: 0, threshold: 0 },
|
|
);
|
|
|
|
// Saved: edit and delete show when hovering the title.
|
|
await annotation.fill("An annotation");
|
|
await workspace.rightSidebar
|
|
.getByRole("button", { name: "Create", exact: true })
|
|
.click();
|
|
const title = workspace.rightSidebar.getByText("Annotation", {
|
|
exact: true,
|
|
});
|
|
await title.hover();
|
|
await expect(workspace.rightSidebar).toHaveScreenshot(
|
|
"annotation-saved.png",
|
|
{ maxDiffPixelRatio: 0, threshold: 0 },
|
|
);
|
|
});
|
|
});
|
|
|
|
test.describe("Assets tab", () => {
|
|
test("Shows the libraries modal correctly", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(
|
|
"link-file-to-library",
|
|
"workspace/link-file-to-library.json",
|
|
);
|
|
await workspace.mockRPC(
|
|
"get-team-shared-files?team-id=*",
|
|
"workspace/get-team-shared-libraries-non-empty.json",
|
|
);
|
|
|
|
await workspace.mockRPC(
|
|
"push-audit-events",
|
|
"workspace/audit-event-empty.json",
|
|
);
|
|
|
|
await workspace.goToWorkspace();
|
|
await workspace.clickAssets();
|
|
await workspace.openLibrariesModal();
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
|
|
await workspace.librariesModal
|
|
.getByRole("tab", { name: "Libraries" })
|
|
.click();
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
|
|
// Now the get-file call should return a library
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-library.json");
|
|
await workspace.clickLibrary("Testing library 1");
|
|
await expect(workspace.librariesModal.getByText("Added")).toBeVisible();
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
});
|
|
|
|
test("Shows the assets correctly", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
const { fileId, pageId } = await setupFileWithAssets(workspace);
|
|
|
|
await workspace.goToWorkspace({ fileId, pageId });
|
|
|
|
await workspace.clickAssets();
|
|
await workspace.sidebar.getByRole("button", { name: "Components" }).click();
|
|
await workspace.sidebar.getByRole("button", { name: "Colors" }).click();
|
|
await workspace.sidebar
|
|
.getByRole("button", { name: "Typographies" })
|
|
.click();
|
|
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
|
|
await workspace.sidebar.getByTitle("List view").click();
|
|
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
});
|
|
});
|
|
|
|
test.describe("Guides", () => {
|
|
test("Shows the advanced options of a square guide", async ({ page }) => {
|
|
// A taller window keeps the whole Design tab visible: a scrolled
|
|
// sidebar can land on a fractional offset and change the antialiasing.
|
|
await page.setViewportSize({ width: 1280, height: 900 });
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.goToWorkspace();
|
|
|
|
await workspace.boardButton.click();
|
|
await workspace.clickWithDragViewportAt(128, 128, 200, 200);
|
|
await workspace.rightSidebar
|
|
.getByRole("button", { name: "Add guide" })
|
|
.click();
|
|
|
|
// The advanced options toggle has no accessible name yet.
|
|
await workspace.rightSidebar
|
|
.locator("button[class*='frame_grid__show-options']")
|
|
.click();
|
|
await expect(workspace.rightSidebar.getByText("Color")).toBeVisible();
|
|
// The guide options are a small part of the sidebar: compare every
|
|
// pixel. The color rows antialias their rounded corners one color step
|
|
// differently between runs, so allow that much and nothing more.
|
|
await expect(workspace.rightSidebar).toHaveScreenshot({
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0.02,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe("Left header", () => {
|
|
test("Shows the shared badge and the save status", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-library.json");
|
|
await workspace.mockRPC(
|
|
"update-file?id=*",
|
|
"workspace/update-file-create-rect.json",
|
|
);
|
|
await workspace.goToWorkspace({
|
|
fileId: "c1249a66-fce0-8175-8004-7433fe4be8bc",
|
|
pageId: "c1249a66-fce0-8175-8004-7433fe4be8bd",
|
|
});
|
|
|
|
const header = page.locator("header", { hasText: "Testing library 1" });
|
|
await expect(header).toBeVisible();
|
|
// The badge and the status dot are tiny: compare every pixel.
|
|
await expect(header).toHaveScreenshot("left-header-shared.png", {
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
|
|
await workspace.rectShapeButton.click();
|
|
await workspace.clickWithDragViewportAt(128, 128, 200, 100);
|
|
await expect(header.getByTitle("Saved")).toBeVisible();
|
|
await page.mouse.move(640, 600);
|
|
await expect(header).toHaveScreenshot("left-header-saved.png", {
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe("Palette", () => {
|
|
test("Shows the bottom palette expanded and collapsed", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
const { fileId, pageId } = await setupFileWithAssets(workspace);
|
|
|
|
await workspace.goToWorkspace({ fileId, pageId });
|
|
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
|
|
await workspace.palette
|
|
.getByRole("button", { name: "Typographies" })
|
|
.click();
|
|
await expect(
|
|
workspace.palette.getByText("Source Sans Pro Regular"),
|
|
).toBeVisible();
|
|
await expect(workspace.page).toHaveScreenshot();
|
|
|
|
await workspace.palette
|
|
.getByRole("button", { name: "Color Palette" })
|
|
.click();
|
|
await expect(
|
|
workspace.palette.getByText(
|
|
"There are no color styles in your library yet",
|
|
),
|
|
).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe("Nudge modal", () => {
|
|
test("Shows the nudge amount modal", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.goToWorkspace();
|
|
|
|
await page.getByRole("button", { name: "Main menu" }).click();
|
|
await page.locator("#file-menu-preferences").click();
|
|
await page.locator("#file-menu-nudge").click();
|
|
|
|
await expect(page.getByText("Nudge amount")).toBeVisible();
|
|
await page.mouse.move(0, 0);
|
|
await expect(workspace.page).toHaveScreenshot("nudge-modal.png", {
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe("Selected colors", () => {
|
|
test("Shows the more colors button", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-9066.json");
|
|
await workspace.goToWorkspace({
|
|
fileId: "e179d9df-de35-80bf-8005-283bbd5516b0",
|
|
pageId: "e179d9df-de35-80bf-8005-283bbd5516b1",
|
|
});
|
|
|
|
await workspace.clickToggableLayer("Board");
|
|
await page.keyboard.press("Control+A");
|
|
|
|
await expect(
|
|
workspace.rightSidebar.getByRole("button", { name: "More colors" }),
|
|
).toBeVisible();
|
|
// The button is a small part of the sidebar: compare every pixel.
|
|
await expect(workspace.rightSidebar).toHaveScreenshot({
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe("Imported SVG attributes", () => {
|
|
test("Shows the attributes of an imported SVG shape", async ({ page }) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-9930.json");
|
|
await workspace.goToWorkspace({
|
|
fileId: "8f843b59-7fbb-81ce-8005-aa6d47ae3111",
|
|
pageId: "fb9798e7-a547-80ae-8005-9ffda4a13e2c",
|
|
});
|
|
|
|
// The fourth "workspace" board holds the imported SVG groups.
|
|
await workspace.clickToggableLayer("workspace", {}, 3);
|
|
await workspace.clickToggableLayer("Canvas");
|
|
await workspace.clickLeafLayer("Rectangle 760 (Stroke)");
|
|
|
|
const section = workspace.rightSidebar.getByText("Imported SVG Attributes");
|
|
await section.scrollIntoViewIfNeeded();
|
|
await expect(section).toBeVisible();
|
|
// The attributes are a small part of the sidebar: compare every pixel.
|
|
await expect(workspace.rightSidebar).toHaveScreenshot({
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe("Grid cell options", () => {
|
|
test("Shows the grid cell options when selecting a cell", async ({
|
|
page,
|
|
}) => {
|
|
const workspace = new WorkspacePage(page);
|
|
await workspace.setupEmptyFile();
|
|
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-9042.json");
|
|
await workspace.mockRPC(
|
|
"get-file-fragment?file-id=*&fragment-id=*",
|
|
"workspace/get-file-fragment-9042.json",
|
|
);
|
|
await workspace.goToWorkspace({
|
|
fileId: "af2494d0-39ba-8184-8005-230696f6df5c",
|
|
pageId: "af2494d0-39ba-8184-8005-230696f6df5d",
|
|
});
|
|
|
|
await workspace.clickLeafLayer("Board");
|
|
await page
|
|
.getByTestId("inspect-layout")
|
|
.getByRole("button", { name: "Edit grid" })
|
|
.click();
|
|
|
|
// Click the first cell of the grid editor.
|
|
const cell = page.locator("g.cell-editor > rect").first();
|
|
const box = await cell.boundingBox();
|
|
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
|
|
|
|
await expect(workspace.rightSidebar.getByText("Grid cell")).toBeVisible();
|
|
// The cell options are a small part of the sidebar: compare every pixel.
|
|
await expect(workspace.rightSidebar).toHaveScreenshot({
|
|
maxDiffPixelRatio: 0,
|
|
threshold: 0,
|
|
});
|
|
});
|
|
});
|