From 6ec259a0e71174651bae95d4628138bf6fd68742 Mon Sep 17 00:00:00 2001
From: kj_sh604
Date: Sun, 15 Mar 2026 16:19:35 -0400
Subject: refactor: packages/

---
 packages/excalidraw/tests/actionStyles.test.tsx | 84 +++++++++++++++++++++++++
 1 file changed, 84 insertions(+)
 create mode 100644 packages/excalidraw/tests/actionStyles.test.tsx

(limited to 'packages/excalidraw/tests/actionStyles.test.tsx')

diff --git a/packages/excalidraw/tests/actionStyles.test.tsx b/packages/excalidraw/tests/actionStyles.test.tsx
new file mode 100644
index 0000000..abe4a7c
--- /dev/null
+++ b/packages/excalidraw/tests/actionStyles.test.tsx
@@ -0,0 +1,84 @@
+import React from "react";
+import { Excalidraw } from "../index";
+import { CODES } from "../keys";
+import { API } from "../tests/helpers/api";
+import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
+import {
+  act,
+  fireEvent,
+  render,
+  screen,
+  togglePopover,
+} from "../tests/test-utils";
+import { copiedStyles } from "../actions/actionStyles";
+
+const { h } = window;
+
+const mouse = new Pointer("mouse");
+
+describe("actionStyles", () => {
+  beforeEach(async () => {
+    await render(<Excalidraw handleKeyboardGlobally={true} />);
+  });
+
+  afterEach(async () => {
+    // https://github.com/floating-ui/floating-ui/issues/1908#issuecomment-1301553793
+    // affects node v16+
+    await act(async () => {});
+  });
+
+  it("should copy & paste styles via keyboard", async () => {
+    UI.clickTool("rectangle");
+    mouse.down(10, 10);
+    mouse.up(20, 20);
+
+    UI.clickTool("rectangle");
+    mouse.down(10, 10);
+    mouse.up(20, 20);
+
+    // Change some styles of second rectangle
+    togglePopover("Stroke");
+    UI.clickOnTestId("color-red");
+    togglePopover("Background");
+    UI.clickOnTestId("color-blue");
+    // Fill style
+    fireEvent.click(screen.getByTitle("Cross-hatch"));
+    // Stroke width
+    fireEvent.click(screen.getByTitle("Bold"));
+    // Stroke style
+    fireEvent.click(screen.getByTitle("Dotted"));
+    // Roughness
+    fireEvent.click(screen.getByTitle("Cartoonist"));
+    // Opacity
+    fireEvent.change(screen.getByTestId("opacity"), {
+      target: { value: "60" },
+    });
+
+    mouse.reset();
+
+    API.setSelectedElements([h.elements[1]]);
+
+    Keyboard.withModifierKeys({ ctrl: true, alt: true }, () => {
+      Keyboard.codeDown(CODES.C);
+    });
+    const secondRect = JSON.parse(copiedStyles)[0];
+    expect(secondRect.id).toBe(h.elements[1].id);
+
+    mouse.reset();
+    // Paste styles to first rectangle
+    API.setSelectedElements([h.elements[0]]);
+    Keyboard.withModifierKeys({ ctrl: true, alt: true }, () => {
+      Keyboard.codeDown(CODES.V);
+    });
+
+    const firstRect = API.getSelectedElement();
+    expect(firstRect.id).toBe(h.elements[0].id);
+    expect(firstRect.strokeColor).toBe("#e03131");
+    expect(firstRect.backgroundColor).toBe("#a5d8ff");
+    expect(firstRect.fillStyle).toBe("cross-hatch");
+    expect(firstRect.strokeWidth).toBe(2); // Bold: 2
+    expect(firstRect.strokeStyle).toBe("dotted");
+    expect(firstRect.roughness).toBe(2); // Cartoonist: 2
+    expect(firstRect.opacity).toBe(60);
+  });
+});
-- 
cgit v1.2.3

