Merge pull request #8198 from penpot/ladybenko-13176-playwright-wasm

🔧 Migrate workspace tests to user the wasm viewport
This commit is contained in:
Alejandro Alonso 2026-02-03 13:00:10 +01:00 committed by GitHub
commit bc16b8ddc3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 170 additions and 109 deletions

View File

@ -1,4 +1,5 @@
import { defineConfig, devices } from "@playwright/test"; import { defineConfig, devices } from "@playwright/test";
import { platform } from "os";
/** /**
* Read environment variables from file. * Read environment variables from file.
@ -6,6 +7,10 @@ import { defineConfig, devices } from "@playwright/test";
*/ */
// require('dotenv').config(); // require('dotenv').config();
const userAgent = platform === 'darwin' ?
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" :
undefined;
/** /**
* @see https://playwright.dev/docs/test-configuration * @see https://playwright.dev/docs/test-configuration
*/ */
@ -43,12 +48,20 @@ export default defineConfig({
projects: [ projects: [
{ {
name: "default", name: "default",
use: { ...devices["Desktop Chrome"] },
testDir: "./playwright/ui/specs", testDir: "./playwright/ui/specs",
use: { use: {
...devices["Desktop Chrome"],
viewport: { width: 1920, height: 1080 }, // Add custom viewport size
video: 'retain-on-failure', video: 'retain-on-failure',
trace: 'retain-on-failure', trace: 'retain-on-failure',
} userAgent,
},
snapshotPathTemplate: "{testDir}/{testFilePath}-snapshots/{arg}.png",
expect: {
toHaveScreenshot: {
maxDiffPixelRatio: 0.001,
},
},
}, },
{ {
name: "ds", name: "ds",

View File

@ -0,0 +1,7 @@
{
"~:file-id": "~u8d38942d-b01f-800e-8007-79ee6a9bac45",
"~:tag": "component",
"~:object-id": "8d38942d-b01f-800e-8007-79ee6a9bac45/8d38942d-b01f-800e-8007-79ee6a9bac46/6b68aedd-4c5b-80b9-8007-7b38c1d34ce4/component",
"~:media-id": "~ube2dc82e-615b-486b-a193-8768bdb51d7a",
"~:created-at": "~m1769523563389"
}

View File

@ -253,7 +253,7 @@ export class WorkspacePage extends BaseWebSocketPage {
async #waitForWebSocketReadiness() { async #waitForWebSocketReadiness() {
// TODO: find a better event to settle whether the app is ready to receive notifications via ws // TODO: find a better event to settle whether the app is ready to receive notifications via ws
await expect(this.pageName).toHaveText("Page 1"); await expect(this.pageName).toHaveText("Page 1", { timeout: 30000 })
} }
async sendPresenceMessage(fixture) { async sendPresenceMessage(fixture) {
@ -383,19 +383,46 @@ export class WorkspacePage extends BaseWebSocketPage {
await this.page.keyboard.press("T"); await this.page.keyboard.press("T");
await this.page.waitForTimeout(timeToWait); await this.page.waitForTimeout(timeToWait);
await this.clickAndMove(x1, y1, x2, y2); await this.clickAndMove(x1, y1, x2, y2);
await this.page.waitForTimeout(timeToWait); await expect(this.page.getByTestId("text-editor")).toBeVisible();
if (initialText) { if (initialText) {
await this.page.keyboard.type(initialText); await this.page.keyboard.type(initialText);
} }
} }
/** /**
* Copies the selected element into the clipboard. * Copies the selected element into the clipboard, or copy the
* content of the locator into the clipboard.
* *
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async copy() { async copy(kind = "keyboard", locator = undefined) {
return this.page.keyboard.press("Control+C"); if (kind === "context-menu" && locator) {
await locator.click({ button: "right" });
await this.page.getByText("Copy", { exact: true }).click();
} else {
await this.page.keyboard.press("ControlOrMeta+C");
}
// wait for the clipboard to be updated
await this.page.waitForFunction(async () => {
const content = await navigator.clipboard.readText()
return content !== "";
}, { timeout: 1000 });
}
async cut(kind = "keyboard", locator = undefined) {
if (kind === "context-menu" && locator) {
await locator.click({ button: "right" });
await this.page.getByText("Cut", { exact: true }).click();
} else {
await this.page.keyboard.press("ControlOrMeta+X");
}
// wait for the clipboard to be updated
await this.page.waitForFunction(async () => {
const content = await navigator.clipboard.readText()
return content !== "";
}, { timeout: 1000 });
} }
/** /**
@ -407,9 +434,9 @@ export class WorkspacePage extends BaseWebSocketPage {
async paste(kind = "keyboard") { async paste(kind = "keyboard") {
if (kind === "context-menu") { if (kind === "context-menu") {
await this.viewport.click({ button: "right" }); await this.viewport.click({ button: "right" });
return this.page.getByText("PasteCtrlV").click(); return this.page.getByText("Paste", { exact: true }).click();
} }
return this.page.keyboard.press("Control+V"); return this.page.keyboard.press("ControlOrMeta+V");
} }
async panOnViewportAt(x, y, width, height) { async panOnViewportAt(x, y, width, height) {
@ -448,11 +475,11 @@ export class WorkspacePage extends BaseWebSocketPage {
const layer = this.layers const layer = this.layers
.getByTestId("layer-row") .getByTestId("layer-row")
.filter({ hasText: name }); .filter({ hasText: name });
const button = layer.getByRole("button"); const button = layer.getByTestId("toggle-content");
await button.waitFor(); await expect(button).toBeVisible();
await button.click(clickOptions); await button.click(clickOptions);
await this.page.waitForTimeout(500); await button.waitFor({ ariaExpanded: true });
} }
async expectSelectedLayer(name) { async expectSelectedLayer(name) {
@ -495,13 +522,7 @@ export class WorkspacePage extends BaseWebSocketPage {
async clickColorPalette(clickOptions = {}) { async clickColorPalette(clickOptions = {}) {
await this.palette await this.palette
.getByRole("button", { name: "Color Palette (Alt+P)" }) .getByRole("button", { name: /Color Palette/ })
.click(clickOptions);
}
async clickColorPalette(clickOptions = {}) {
await this.palette
.getByRole("button", { name: "Color Palette (Alt+P)" })
.click(clickOptions); .click(clickOptions);
} }

View File

@ -15,6 +15,8 @@ test("User can complete the onboarding", async ({ page }) => {
const dashboardPage = new DashboardPage(page); const dashboardPage = new DashboardPage(page);
const onboardingPage = new OnboardingPage(page); const onboardingPage = new OnboardingPage(page);
await dashboardPage.mockConfigFlags(["enable-onboarding"]);
await dashboardPage.goToDashboard(); await dashboardPage.goToDashboard();
await expect( await expect(
page.getByRole("heading", { name: "Help us get to know you" }), page.getByRole("heading", { name: "Help us get to know you" }),

View File

@ -1,5 +1,5 @@
import { test, expect } from "@playwright/test"; import { test, expect } from "@playwright/test";
import { WasmWorkspacePage, WASM_FLAGS } from "../pages/WasmWorkspacePage"; import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
await WasmWorkspacePage.init(page); await WasmWorkspacePage.init(page);

View File

@ -5,7 +5,7 @@ import { WorkspacePage } from "../pages/WorkspacePage";
const timeToWait = 100; const timeToWait = 100;
test.beforeEach(async ({ page, context }) => { test.beforeEach(async ({ page, context }) => {
await Clipboard.enable(context, Clipboard.Permission.ONLY_WRITE); await Clipboard.enable(context, Clipboard.Permission.ALL);
await WorkspacePage.init(page); await WorkspacePage.init(page);
await WorkspacePage.mockConfigFlags(page, ["enable-feature-text-editor-v2"]); await WorkspacePage.mockConfigFlags(page, ["enable-feature-text-editor-v2"]);

View File

@ -1,12 +1,19 @@
import { test, expect } from "@playwright/test"; import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage"; import { WorkspacePage } from "../pages/WorkspacePage";
import { BaseWebSocketPage } from "../pages/BaseWebSocketPage"; import { BaseWebSocketPage } from "../pages/BaseWebSocketPage";
import { Clipboard } from "../../helpers/Clipboard";
test.beforeEach(async ({ page, context }) => {
await Clipboard.enable(context, Clipboard.Permission.ALL);
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page); await WorkspacePage.init(page);
await BaseWebSocketPage.mockRPC(page, "get-teams", "get-teams-variants.json"); await BaseWebSocketPage.mockRPC(page, "get-teams", "get-teams-variants.json");
}); });
test.afterEach(async ({ context }) => {
context.clearPermissions();
});
const setupVariantsFile = async (workspacePage) => { const setupVariantsFile = async (workspacePage) => {
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.mockRPC( await workspacePage.mockRPC(
@ -34,9 +41,9 @@ const setupVariantsFileWithVariant = async (workspacePage) => {
await setupVariantsFile(workspacePage); await setupVariantsFile(workspacePage);
await workspacePage.clickLeafLayer("Rectangle"); await workspacePage.clickLeafLayer("Rectangle");
await workspacePage.page.keyboard.press("Control+k"); await workspacePage.page.keyboard.press("ControlOrMeta+k");
await workspacePage.page.waitForTimeout(500); await workspacePage.page.waitForTimeout(500);
await workspacePage.page.keyboard.press("Control+k"); await workspacePage.page.keyboard.press("ControlOrMeta+k");
await workspacePage.page.waitForTimeout(500); await workspacePage.page.waitForTimeout(500);
// We wait until layer-row starts looking like it an component // We wait until layer-row starts looking like it an component
@ -156,7 +163,7 @@ test("User duplicates a variant container", async ({ page }) => {
await variant.container.click(); await variant.container.click();
//Duplicate the variant container //Duplicate the variant container
await workspacePage.page.keyboard.press("Control+d"); await workspacePage.page.keyboard.press("ControlOrMeta+d");
const variant_original = await findVariant(workspacePage, 1); // On duplicate, the new item is the first const variant_original = await findVariant(workspacePage, 1); // On duplicate, the new item is the first
const variant_duplicate = await findVariant(workspacePage, 0); const variant_duplicate = await findVariant(workspacePage, 0);
@ -169,25 +176,27 @@ test("User duplicates a variant container", async ({ page }) => {
await validateVariant(variant_duplicate); await validateVariant(variant_duplicate);
}); });
test("User copy paste a variant container", async ({ page }) => { test("User copy paste a variant container", async ({ page, context }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WorkspacePage(page);
// Access to the read/write clipboard necesary for this functionality
await setupVariantsFileWithVariant(workspacePage); await setupVariantsFileWithVariant(workspacePage);
await workspacePage.mockRPC(
/create-file-object-thumbnail.*/,
"workspace/create-file-object-thumbnail.json",
);
const variant = findVariantNoWait(workspacePage, 0); const variant = findVariantNoWait(workspacePage, 0);
// await variant.container.waitFor();
// Select the variant container
await variant.container.click();
await workspacePage.page.waitForTimeout(1000);
// Copy the variant container // Copy the variant container
await workspacePage.page.keyboard.press("Control+c"); await workspacePage.clickLeafLayer("Rectangle");
await workspacePage.copy("keyboard");
// Paste the variant container // Paste the variant container
await workspacePage.clickAt(400, 400); await workspacePage.clickAt(400, 400);
await workspacePage.page.keyboard.press("Control+v"); await workspacePage.paste("keyboard");
const variants = workspacePage.layers.getByText("Rectangle");
await expect(variants).toHaveCount(2);
const variantDuplicate = findVariantNoWait(workspacePage, 0); const variantDuplicate = findVariantNoWait(workspacePage, 0);
const variantOriginal = findVariantNoWait(workspacePage, 1); const variantOriginal = findVariantNoWait(workspacePage, 1);
@ -212,18 +221,17 @@ test("User cut paste a variant container", async ({ page }) => {
await variant.container.click(); await variant.container.click();
//Cut the variant container //Cut the variant container
await workspacePage.page.keyboard.press("Control+x"); await workspacePage.cut("keyboard");
await workspacePage.page.waitForTimeout(500);
//Paste the variant container //Paste the variant container
await workspacePage.clickAt(500, 500); await workspacePage.clickAt(500, 500);
await workspacePage.page.keyboard.press("Control+v"); await workspacePage.paste("keyboard");
await workspacePage.page.waitForTimeout(500); await workspacePage.page.waitForTimeout(500);
const variantPasted = await findVariant(workspacePage, 0); const variantPasted = await findVariant(workspacePage, 0);
// Expand the layers // Expand the layers
await variantPasted.container.locator("button").first().click(); await workspacePage.clickToggableLayer("Rectangle");
// The variants are valid // The variants are valid
await validateVariant(variantPasted); await validateVariant(variantPasted);
@ -239,27 +247,34 @@ test("User cut paste a variant container into a board, and undo twice", async ({
//Create a board //Create a board
await workspacePage.boardButton.click(); await workspacePage.boardButton.click();
await workspacePage.clickWithDragViewportAt(500, 500, 100, 100); // NOTE: this board should not intersect the existing variants, otherwise
// this test is flaky
await workspacePage.clickWithDragViewportAt(200, 200, 100, 100);
await workspacePage.clickAt(495, 495); await workspacePage.clickAt(495, 495);
const board = await workspacePage.rootShape.locator("Board"); const board = await workspacePage.rootShape.locator("Board");
// Select the variant container // Select the variant container
await variant.container.click(); // await variant.container.click();
await workspacePage.clickLeafLayer("Rectangle");
//Cut the variant container //Cut the variant container
await workspacePage.page.keyboard.press("Control+x"); await workspacePage.cut("keyboard");
await workspacePage.page.waitForTimeout(500); await expect(variant.container).not.toBeVisible();
//Select the board //Select the board
await workspacePage.clickLeafLayer("Board"); await workspacePage.clickLeafLayer("Board");
//Paste the variant container inside the board //Paste the variant container inside the board
await workspacePage.page.keyboard.press("Control+v"); await workspacePage.paste("keyboard");
await expect(variant.container).toBeVisible();
//Undo twice //Undo twice
await workspacePage.page.keyboard.press("Control+z"); await workspacePage.page.keyboard.press("ControlOrMeta+z");
await workspacePage.page.keyboard.press("Control+z");
await workspacePage.page.waitForTimeout(500); await expect(variant.container).not.toBeVisible();
await workspacePage.page.keyboard.press("ControlOrMeta+z");
await expect(variant.container).toBeVisible();
const variantAfterUndo = await findVariant(workspacePage, 0); const variantAfterUndo = await findVariant(workspacePage, 0);
@ -276,12 +291,12 @@ test("User copy paste a variant", async ({ page }) => {
// Select the variant1 // Select the variant1
await variant.variant1.click(); await variant.variant1.click();
//Cut the variant // Copy the variant
await workspacePage.page.keyboard.press("Control+c"); await workspacePage.copy("keyboard");
//Paste the variant // Paste the variant
await workspacePage.clickAt(500, 500); await workspacePage.clickAt(500, 500);
await workspacePage.page.keyboard.press("Control+v"); await workspacePage.paste("keyboard");
const copy = await workspacePage.layers const copy = await workspacePage.layers
.getByTestId("layer-row") .getByTestId("layer-row")
@ -302,11 +317,11 @@ test("User cut paste a variant outside the container", async ({ page }) => {
await variant.variant1.click(); await variant.variant1.click();
//Cut the variant //Cut the variant
await workspacePage.page.keyboard.press("Control+x"); await workspacePage.cut("keyboard");
//Paste the variant //Paste the variant
await workspacePage.clickAt(500, 500); await workspacePage.clickAt(500, 500);
await workspacePage.page.keyboard.press("Control+v"); await workspacePage.paste("keyboard");
const component = await workspacePage.layers const component = await workspacePage.layers
.getByTestId("layer-row") .getByTestId("layer-row")
@ -324,15 +339,11 @@ test("User drag and drop a variant outside the container", async ({ page }) => {
const variant = await findVariant(workspacePage, 0); const variant = await findVariant(workspacePage, 0);
// Drag and drop the variant // Drag and drop the variant
await workspacePage.clickWithDragViewportAt(350, 400, 0, 200); // FIXME: to make this test more resilient, we should get the bounding box of the Value 1 variant
// and use it to calculate the target position
await workspacePage.clickWithDragViewportAt(600, 500, 0, 300);
const component = await workspacePage.layers await expect(workspacePage.layers.getByText("Rectangle / Value 1")).toBeVisible();
.getByTestId("layer-row")
.filter({ has: workspacePage.page.getByText("Rectangle / Value 1") })
.filter({ has: workspacePage.page.getByTestId("icon-component") });
//The component exists and is visible
await expect(component).toBeVisible();
}); });
test("User cut paste a component inside a variant", async ({ page }) => { test("User cut paste a component inside a variant", async ({ page }) => {
@ -345,14 +356,14 @@ test("User cut paste a component inside a variant", async ({ page }) => {
await workspacePage.ellipseShapeButton.click(); await workspacePage.ellipseShapeButton.click();
await workspacePage.clickWithDragViewportAt(500, 500, 20, 20); await workspacePage.clickWithDragViewportAt(500, 500, 20, 20);
await workspacePage.clickLeafLayer("Ellipse"); await workspacePage.clickLeafLayer("Ellipse");
await workspacePage.page.keyboard.press("Control+k"); await workspacePage.page.keyboard.press("ControlOrMeta+k");
//Cut the component //Cut the component
await workspacePage.page.keyboard.press("Control+x"); await workspacePage.cut("keyboard");
//Paste the component inside the variant //Paste the component inside the variant
await variant.container.click(); await variant.container.click();
await workspacePage.page.keyboard.press("Control+v"); await workspacePage.paste("keyboard");
const variant3 = await workspacePage.layers const variant3 = await workspacePage.layers
.getByTestId("layer-row") .getByTestId("layer-row")
@ -376,7 +387,7 @@ test("User cut paste a component with path inside a variant", async ({
await workspacePage.ellipseShapeButton.click(); await workspacePage.ellipseShapeButton.click();
await workspacePage.clickWithDragViewportAt(500, 500, 20, 20); await workspacePage.clickWithDragViewportAt(500, 500, 20, 20);
await workspacePage.clickLeafLayer("Ellipse"); await workspacePage.clickLeafLayer("Ellipse");
await workspacePage.page.keyboard.press("Control+k"); await workspacePage.page.keyboard.press("ControlOrMeta+k");
//Rename the component //Rename the component
await workspacePage.layers.getByText("Ellipse").dblclick(); await workspacePage.layers.getByText("Ellipse").dblclick();
@ -387,11 +398,11 @@ test("User cut paste a component with path inside a variant", async ({
await workspacePage.page.keyboard.press("Enter"); await workspacePage.page.keyboard.press("Enter");
//Cut the component //Cut the component
await workspacePage.page.keyboard.press("Control+x"); await workspacePage.cut("keyboard");
//Paste the component inside the variant //Paste the component inside the variant
await variant.container.click(); await variant.container.click();
await workspacePage.page.keyboard.press("Control+v"); await workspacePage.paste("keyboard");
const variant3 = await workspacePage.layers const variant3 = await workspacePage.layers
.getByTestId("layer-row") .getByTestId("layer-row")
@ -415,7 +426,7 @@ test("User drag and drop a component with path inside a variant", async ({
await workspacePage.ellipseShapeButton.click(); await workspacePage.ellipseShapeButton.click();
await workspacePage.clickWithDragViewportAt(500, 500, 20, 20); await workspacePage.clickWithDragViewportAt(500, 500, 20, 20);
await workspacePage.clickLeafLayer("Ellipse"); await workspacePage.clickLeafLayer("Ellipse");
await workspacePage.page.keyboard.press("Control+k"); await workspacePage.page.keyboard.press("ControlOrMeta+k");
//Rename the component //Rename the component
await workspacePage.layers.getByText("Ellipse").dblclick(); await workspacePage.layers.getByText("Ellipse").dblclick();
@ -426,7 +437,7 @@ test("User drag and drop a component with path inside a variant", async ({
await workspacePage.page.keyboard.press("Enter"); await workspacePage.page.keyboard.press("Enter");
//Drag and drop the component the component //Drag and drop the component the component
await workspacePage.clickWithDragViewportAt(510, 510, 0, -200); await workspacePage.clickWithDragViewportAt(510, 510, 200, 0);
const variant3 = await workspacePage.layers const variant3 = await workspacePage.layers
.getByTestId("layer-row") .getByTestId("layer-row")
@ -446,8 +457,8 @@ test("User cut paste a variant into another container", async ({ page }) => {
await workspacePage.ellipseShapeButton.click(); await workspacePage.ellipseShapeButton.click();
await workspacePage.clickWithDragViewportAt(500, 500, 20, 20); await workspacePage.clickWithDragViewportAt(500, 500, 20, 20);
await workspacePage.clickLeafLayer("Ellipse"); await workspacePage.clickLeafLayer("Ellipse");
await workspacePage.page.keyboard.press("Control+k"); await workspacePage.page.keyboard.press("ControlOrMeta+k");
await workspacePage.page.keyboard.press("Control+k"); await workspacePage.page.keyboard.press("ControlOrMeta+k");
const variantOrigin = await findVariantNoWait(workspacePage, 1); const variantOrigin = await findVariantNoWait(workspacePage, 1);
@ -457,11 +468,11 @@ test("User cut paste a variant into another container", async ({ page }) => {
await variantOrigin.variant1.click(); await variantOrigin.variant1.click();
//Cut the variant //Cut the variant
await workspacePage.page.keyboard.press("Control+x"); await workspacePage.cut("keyboard");
//Paste the variant //Paste the variant
await workspacePage.layers.getByText("Ellipse").first().click(); await workspacePage.layers.getByText("Ellipse").first().click();
await workspacePage.page.keyboard.press("Control+v"); await workspacePage.paste("keyboard");
const variant3 = workspacePage.layers const variant3 = workspacePage.layers
.getByTestId("layer-row") .getByTestId("layer-row")

View File

@ -1,13 +1,13 @@
import { test, expect } from "@playwright/test"; import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage"; import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
import { presenceFixture } from "../../data/workspace/ws-notifications"; import { presenceFixture } from "../../data/workspace/ws-notifications";
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page); await WasmWorkspacePage.init(page);
}); });
test("User loads worskpace with empty file", async ({ page }) => { test("User loads worskpace with empty file", async ({ page }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
@ -16,7 +16,7 @@ test("User loads worskpace with empty file", async ({ page }) => {
}); });
test("User opens a file with a bad page id", async ({ page }) => { test("User opens a file with a bad page id", async ({ page }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace({ await workspacePage.goToWorkspace({
@ -29,7 +29,7 @@ test("User opens a file with a bad page id", async ({ page }) => {
test("User receives presence notifications updates in the workspace", async ({ test("User receives presence notifications updates in the workspace", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
@ -41,7 +41,7 @@ test("User receives presence notifications updates in the workspace", async ({
}); });
test("User draws a rect", async ({ page }) => { test("User draws a rect", async ({ page }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.mockRPC( await workspacePage.mockRPC(
"update-file?id=*", "update-file?id=*",
@ -52,13 +52,12 @@ test("User draws a rect", async ({ page }) => {
await workspacePage.rectShapeButton.click(); await workspacePage.rectShapeButton.click();
await workspacePage.clickWithDragViewportAt(128, 128, 200, 100); await workspacePage.clickWithDragViewportAt(128, 128, 200, 100);
const shape = await workspacePage.rootShape.locator("rect"); await workspacePage.hideUI();
await expect(shape).toHaveAttribute("width", "200"); await expect(workspacePage.canvas).toHaveScreenshot();
await expect(shape).toHaveAttribute("height", "100");
}); });
test("User makes a group", async ({ page }) => { test("User makes a group", async ({ page }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.mockRPC( await workspacePage.mockRPC(
/get\-file\?/, /get\-file\?/,
@ -74,14 +73,14 @@ test("User makes a group", async ({ page }) => {
pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375", pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375",
}); });
await workspacePage.clickLeafLayer("Rectangle"); await workspacePage.clickLeafLayer("Rectangle");
await workspacePage.page.keyboard.press("Control+g"); await workspacePage.page.keyboard.press("ControlOrMeta+g");
await workspacePage.expectSelectedLayer("Group"); await workspacePage.expectSelectedLayer("Group");
}); });
test("Bug 7654 - Toolbar keeps toggling on and off on spacebar press", async ({ test("Bug 7654 - Toolbar keeps toggling on and off on spacebar press", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
@ -91,10 +90,10 @@ test("Bug 7654 - Toolbar keeps toggling on and off on spacebar press", async ({
await workspacePage.expectHiddenToolbarOptions(); await workspacePage.expectHiddenToolbarOptions();
}); });
test("Bug 7525 - User moves a scrollbar and no selciont rectangle appears", async ({ test("Bug 7525 - User moves a scrollbar and no selection rectangle appears", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.mockRPC( await workspacePage.mockRPC(
/get\-file\?/, /get\-file\?/,
@ -110,8 +109,8 @@ test("Bug 7525 - User moves a scrollbar and no selciont rectangle appears", asyn
pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375", pageId: "6191cd35-bb1f-81f7-8004-7cc63d087375",
}); });
// Move created rect to a corner, in orther to get scrollbars // Move created rect to a corner, in order to get scrollbars
await workspacePage.panOnViewportAt(128, 128, 300, 300); await workspacePage.panOnViewportAt(128, 128, 600, 600);
// Check scrollbars appear // Check scrollbars appear
const horizontalScrollbar = workspacePage.horizontalScrollbar; const horizontalScrollbar = workspacePage.horizontalScrollbar;
@ -130,7 +129,7 @@ test("Bug 7525 - User moves a scrollbar and no selciont rectangle appears", asyn
test("User adds a library and its automatically selected in the color palette", async ({ test("User adds a library and its automatically selected in the color palette", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.mockRPC( await workspacePage.mockRPC(
"link-file-to-library", "link-file-to-library",
@ -175,7 +174,7 @@ test("User adds a library and its automatically selected in the color palette",
test("Bug 10179 - Drag & drop doesn't add colors to the Recent Colors palette", async ({ test("Bug 10179 - Drag & drop doesn't add colors to the Recent Colors palette", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
await workspacePage.moveButton.click(); await workspacePage.moveButton.click();
@ -218,7 +217,7 @@ test("Bug 10179 - Drag & drop doesn't add colors to the Recent Colors palette",
test("Bug 7489 - Workspace-palette items stay hidden when opening with keyboard-shortcut", async ({ test("Bug 7489 - Workspace-palette items stay hidden when opening with keyboard-shortcut", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
@ -235,7 +234,7 @@ test("Bug 7489 - Workspace-palette items stay hidden when opening with keyboard-
test("Bug 8784 - Use keyboard arrow to move inside a text input does not change tabs", async ({ test("Bug 8784 - Use keyboard arrow to move inside a text input does not change tabs", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(); await workspacePage.setupEmptyFile();
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
await workspacePage.pageName.click(); await workspacePage.pageName.click();
@ -245,7 +244,7 @@ test("Bug 8784 - Use keyboard arrow to move inside a text input does not change
}); });
test("Bug 9066 - Problem with grid layout", async ({ page }) => { test("Bug 9066 - Problem with grid layout", async ({ page }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-9066.json"); await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-9066.json");
@ -273,7 +272,7 @@ test("Bug 9066 - Problem with grid layout", async ({ page }) => {
}); });
test("User have toolbar", async ({ page }) => { test("User have toolbar", async ({ page }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
@ -282,7 +281,7 @@ test("User have toolbar", async ({ page }) => {
}); });
test("User have edition menu entries", async ({ page }) => { test("User have edition menu entries", async ({ page }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
@ -298,7 +297,7 @@ test("User have edition menu entries", async ({ page }) => {
}); });
test("Copy/paste properties", async ({ page, context }) => { test("Copy/paste properties", async ({ page, context }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.mockRPC( await workspacePage.mockRPC(
/get\-file\?/, /get\-file\?/,
@ -355,23 +354,23 @@ test("Copy/paste properties", async ({ page, context }) => {
}); });
test("[Taiga #9929] Paste text in workspace", async ({ page, context }) => { test("[Taiga #9929] Paste text in workspace", async ({ page, context }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
await context.grantPermissions(["clipboard-read", "clipboard-write"]); await context.grantPermissions(["clipboard-read", "clipboard-write"]);
await page.evaluate(() => navigator.clipboard.writeText("Lorem ipsum dolor")); await page.evaluate(() => navigator.clipboard.writeText("Lorem ipsum dolor"));
await workspacePage.viewport.click({ button: "right" }); await workspacePage.viewport.click({ button: "right" });
await page.getByText("PasteCtrlV").click(); await page.getByText(/^Paste/i).click();
await workspacePage.viewport await workspacePage.viewport
.getByRole("textbox") .getByRole("textbox")
.getByText("Lorem ipsum dolor"); .getByText("Lorem ipsum dolor");
}); });
test("[Taiga #9930] Zoom fit all doesn't fits all", async ({ test("[Taiga #9930] Zoom fit all doesn't fit all shapes", async ({
page, page,
context, context,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-9930.json"); await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-9930.json");
await workspacePage.goToWorkspace({ await workspacePage.goToWorkspace({
@ -379,16 +378,18 @@ test("[Taiga #9930] Zoom fit all doesn't fits all", async ({
pageId: "fb9798e7-a547-80ae-8005-9ffda4a13e2c", pageId: "fb9798e7-a547-80ae-8005-9ffda4a13e2c",
}); });
const zoom = await page.getByTitle("Zoom"); const zoom = page.getByTitle("Zoom");
await zoom.click(); await zoom.click();
const zoomIn = await page.getByRole("button", { name: "Zoom in" }); const zoomIn = page.getByRole("button", { name: "Zoom in" });
await zoomIn.click(); await zoomIn.click();
await zoomIn.click(); await zoomIn.click();
await zoomIn.click(); await zoomIn.click();
// Zoom fit all // Zoom fit all
await page.keyboard.press("Shift+1"); await page.keyboard.press("Shift+1");
// Select all shapes to display selrect
await workspacePage.page.keyboard.press("ControlOrMeta+a");
const ids = [ const ids = [
"shape-165d1e5a-5873-8010-8005-9ffdbeaeec59", "shape-165d1e5a-5873-8010-8005-9ffdbeaeec59",
@ -410,7 +411,7 @@ test("[Taiga #9930] Zoom fit all doesn't fits all", async ({
const viewportBoundingBox = await workspacePage.viewport.boundingBox(); const viewportBoundingBox = await workspacePage.viewport.boundingBox();
for (const id of ids) { for (const id of ids) {
const shape = await page.locator(`.ws-shape-wrapper > g#${id}`); const shape = page.locator(`.viewport-selrect`);
const shapeBoundingBox = await shape.boundingBox(); const shapeBoundingBox = await shape.boundingBox();
expect(contains(viewportBoundingBox, shapeBoundingBox)).toBeTruthy(); expect(contains(viewportBoundingBox, shapeBoundingBox)).toBeTruthy();
} }
@ -419,7 +420,7 @@ test("[Taiga #9930] Zoom fit all doesn't fits all", async ({
test("Bug 9877, user navigation to dashboard from header goes to blank page", async ({ test("Bug 9877, user navigation to dashboard from header goes to blank page", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace(); await workspacePage.goToWorkspace();
@ -436,7 +437,7 @@ test("Bug 9877, user navigation to dashboard from header goes to blank page", as
test("Bug 8371 - Flatten option is not visible in context menu", async ({ test("Bug 8371 - Flatten option is not visible in context menu", async ({
page, page,
}) => { }) => {
const workspacePage = new WorkspacePage(page); const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page); await workspacePage.setupEmptyFile(page);
await workspacePage.mockGetFile("workspace/get-file-8371.json"); await workspacePage.mockGetFile("workspace/get-file-8371.json");
await workspacePage.goToWorkspace({ await workspacePage.goToWorkspace({

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -21,7 +21,7 @@
(def ^:private schema:properties-row (def ^:private schema:properties-row
[:map [:map
[:term :string] [:term :string]
[:detail :string] [:detail {:optional true} [:maybe :string]]
[:property {:optional true} :string] ;; CSS valid property [:property {:optional true} :string] ;; CSS valid property
[:token {:optional true} :any] ;; resolved token object [:token {:optional true} :any] ;; resolved token object
[:copiable {:optional true} :boolean]]) [:copiable {:optional true} :boolean]])

View File

@ -401,7 +401,8 @@
(dm/fmt "scale(%)" maybe-zoom))}))] (dm/fmt "scale(%)" maybe-zoom))}))]
[:g.text-editor {:clip-path (dm/fmt "url(#%)" clip-id) [:g.text-editor {:clip-path (dm/fmt "url(#%)" clip-id)
:transform (dm/str transform)} :transform (dm/str transform)
:data-testid "text-editor"}
[:defs [:defs
[:clipPath {:id clip-id} [:clipPath {:id clip-id}
[:rect {:x x :y y :width width :height height}]]] [:rect {:x x :y y :width width :height height}]]]

View File

@ -119,6 +119,9 @@
[:button {:class (stl/css-case [:button {:class (stl/css-case
:toggle-content true :toggle-content true
:inverse expanded?) :inverse expanded?)
:data-testid "toggle-content"
:aria-expanded expanded?
:aria-labelledby (dm/str "layer-name-" id)
:on-click on-toggle-collapse} :on-click on-toggle-collapse}
deprecated-icon/arrow]) deprecated-icon/arrow])

View File

@ -108,6 +108,7 @@
:on-blur accept-edit :on-blur accept-edit
:on-key-down on-key-down :on-key-down on-key-down
:auto-focus true :auto-focus true
:id (dm/str "layer-name-" shape-id)
:default-value (d/nilv default-value "")}] :default-value (d/nilv default-value "")}]
[:* [:*
[:span [:span
@ -118,6 +119,7 @@
:hidden is-hidden :hidden is-hidden
:type-comp type-comp :type-comp type-comp
:type-frame type-frame) :type-frame type-frame)
:id (dm/str "layer-name-" shape-id)
:style {"--depth" depth "--parent-size" parent-size} :style {"--depth" depth "--parent-size" parent-size}
:ref ref :ref ref
:on-double-click start-edit} :on-double-click start-edit}