diff --git a/packages/excalidraw/element/duplicate.test.ts b/packages/excalidraw/element/duplicate.test.tsx similarity index 65% rename from packages/excalidraw/element/duplicate.test.ts rename to packages/excalidraw/element/duplicate.test.tsx index e330ef95e..bb3478f6e 100644 --- a/packages/excalidraw/element/duplicate.test.ts +++ b/packages/excalidraw/element/duplicate.test.tsx @@ -1,17 +1,27 @@ +import React from "react"; import { pointFrom } from "@excalidraw/math"; import type { LocalPoint } from "@excalidraw/math"; -import { FONT_FAMILY, ROUNDNESS } from "../constants"; +import { FONT_FAMILY, ORIG_ID, ROUNDNESS } from "../constants"; import { API } from "../tests/helpers/api"; import { isPrimitive } from "../utils"; +import { act, assertElements, render } from "../tests/test-utils"; +import { Excalidraw } from ".."; +import { actionDuplicateSelection } from "../actions"; + +import { Keyboard, Pointer } from "../tests/helpers/ui"; + import { mutateElement } from "./mutateElement"; import { duplicateElement, duplicateElements } from "./duplicate"; import type { ExcalidrawLinearElement } from "./types"; +const { h } = window; +const mouse = new Pointer("mouse"); + const assertCloneObjects = (source: any, clone: any) => { for (const key in clone) { if (clone.hasOwnProperty(key) && !isPrimitive(clone[key])) { @@ -381,3 +391,210 @@ describe("duplicating multiple elements", () => { }); }); }); + +describe("duplication z-order", () => { + beforeEach(async () => { + await render(); + }); + + it("duplication z order with Cmd+D for the lowest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + API.setSelectedElements([rectangle1]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rectangle1.id }, + { [ORIG_ID]: rectangle1.id, selected: true }, + { id: rectangle2.id }, + { id: rectangle3.id }, + ]); + }); + + it("duplication z order with Cmd+D for the highest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + API.setSelectedElements([rectangle3]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rectangle1.id }, + { id: rectangle2.id }, + { id: rectangle3.id }, + { [ORIG_ID]: rectangle3.id, selected: true }, + ]); + }); + + it("duplication z order with alt+drag for the lowest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + + mouse.select(rectangle1); + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle1.x + 5, rectangle1.y + 5); + mouse.up(rectangle1.x + 5, rectangle1.y + 5); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: rectangle1.id }, + { id: rectangle1.id, selected: true }, + { id: rectangle2.id }, + { id: rectangle3.id }, + ]); + }); + + it("duplication z order with alt+drag for the highest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + + mouse.select(rectangle3); + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle3.x + 5, rectangle3.y + 5); + mouse.up(rectangle3.x + 5, rectangle3.y + 5); + }); + + assertElements(h.elements, [ + { id: rectangle1.id }, + { id: rectangle2.id }, + { [ORIG_ID]: rectangle3.id }, + { id: rectangle3.id, selected: true }, + ]); + }); + + it("duplication z order with alt+drag for the lowest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + + mouse.select(rectangle1); + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle1.x + 5, rectangle1.y + 5); + mouse.up(rectangle1.x + 5, rectangle1.y + 5); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: rectangle1.id }, + { id: rectangle1.id, selected: true }, + { id: rectangle2.id }, + { id: rectangle3.id }, + ]); + }); + + it("duplication z order with alt+drag with grouped elements should consider the group together when determining z-index", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + groupIds: ["group1"], + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + groupIds: ["group1"], + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + groupIds: ["group1"], + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + + mouse.select(rectangle1); + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle1.x + 5, rectangle1.y + 5); + mouse.up(rectangle1.x + 15, rectangle1.y + 15); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: rectangle1.id }, + { [ORIG_ID]: rectangle2.id }, + { [ORIG_ID]: rectangle3.id }, + { id: rectangle1.id, selected: true }, + { id: rectangle2.id, selected: true }, + { id: rectangle3.id, selected: true }, + ]); + }); +}); diff --git a/packages/excalidraw/tests/regressionTests.test.tsx b/packages/excalidraw/tests/regressionTests.test.tsx index b34706afd..42d726f1d 100644 --- a/packages/excalidraw/tests/regressionTests.test.tsx +++ b/packages/excalidraw/tests/regressionTests.test.tsx @@ -1,20 +1,16 @@ import React from "react"; import { vi } from "vitest"; -import { FONT_FAMILY, ORIG_ID } from "../constants"; +import { FONT_FAMILY } from "../constants"; import { Excalidraw } from "../index"; import { CODES, KEYS } from "../keys"; import { reseed } from "../random"; import * as StaticScene from "../renderer/staticScene"; import { setDateTimeForTests } from "../utils"; -import { actionDuplicateSelection } from "../actions"; - import { API } from "./helpers/api"; import { Keyboard, Pointer, UI } from "./helpers/ui"; import { - act, - assertElements, assertSelectedElements, fireEvent, render, @@ -1189,209 +1185,6 @@ it( }, ); -describe("duplication z-order", () => { - beforeEach(async () => { - await render(); - }); - - it("duplication z order with Cmd+D for the lowest z-ordered element should be +1 for the clone", () => { - const rectangle1 = API.createElement({ - type: "rectangle", - x: 0, - y: 0, - }); - const rectangle2 = API.createElement({ - type: "rectangle", - x: 10, - y: 10, - }); - const rectangle3 = API.createElement({ - type: "rectangle", - x: 20, - y: 20, - }); - - API.setElements([rectangle1, rectangle2, rectangle3]); - API.setSelectedElements([rectangle1]); - - act(() => { - h.app.actionManager.executeAction(actionDuplicateSelection); - }); - - assertElements(h.elements, [ - { id: rectangle1.id }, - { [ORIG_ID]: rectangle1.id, selected: true }, - { id: rectangle2.id }, - { id: rectangle3.id }, - ]); - }); - - it("duplication z order with Cmd+D for the highest z-ordered element should be +1 for the clone", () => { - const rectangle1 = API.createElement({ - type: "rectangle", - x: 0, - y: 0, - }); - const rectangle2 = API.createElement({ - type: "rectangle", - x: 10, - y: 10, - }); - const rectangle3 = API.createElement({ - type: "rectangle", - x: 20, - y: 20, - }); - - API.setElements([rectangle1, rectangle2, rectangle3]); - API.setSelectedElements([rectangle3]); - - act(() => { - h.app.actionManager.executeAction(actionDuplicateSelection); - }); - - assertElements(h.elements, [ - { id: rectangle1.id }, - { id: rectangle2.id }, - { id: rectangle3.id }, - { [ORIG_ID]: rectangle3.id, selected: true }, - ]); - }); - - it("duplication z order with alt+drag for the lowest z-ordered element should be +1 for the clone", () => { - const rectangle1 = API.createElement({ - type: "rectangle", - x: 0, - y: 0, - }); - const rectangle2 = API.createElement({ - type: "rectangle", - x: 10, - y: 10, - }); - const rectangle3 = API.createElement({ - type: "rectangle", - x: 20, - y: 20, - }); - - API.setElements([rectangle1, rectangle2, rectangle3]); - - mouse.select(rectangle1); - Keyboard.withModifierKeys({ alt: true }, () => { - mouse.down(rectangle1.x + 5, rectangle1.y + 5); - mouse.up(rectangle1.x + 5, rectangle1.y + 5); - }); - - assertElements(h.elements, [ - { [ORIG_ID]: rectangle1.id }, - { id: rectangle1.id, selected: true }, - { id: rectangle2.id }, - { id: rectangle3.id }, - ]); - }); - - it("duplication z order with alt+drag for the highest z-ordered element should be +1 for the clone", () => { - const rectangle1 = API.createElement({ - type: "rectangle", - x: 0, - y: 0, - }); - const rectangle2 = API.createElement({ - type: "rectangle", - x: 10, - y: 10, - }); - const rectangle3 = API.createElement({ - type: "rectangle", - x: 20, - y: 20, - }); - - API.setElements([rectangle1, rectangle2, rectangle3]); - - mouse.select(rectangle3); - Keyboard.withModifierKeys({ alt: true }, () => { - mouse.down(rectangle3.x + 5, rectangle3.y + 5); - mouse.up(rectangle3.x + 5, rectangle3.y + 5); - }); - - assertElements(h.elements, [ - { id: rectangle1.id }, - { id: rectangle2.id }, - { [ORIG_ID]: rectangle3.id }, - { id: rectangle3.id, selected: true }, - ]); - }); - - it("duplication z order with alt+drag for the lowest z-ordered element should be +1 for the clone", () => { - const rectangle1 = API.createElement({ - type: "rectangle", - x: 0, - y: 0, - }); - const rectangle2 = API.createElement({ - type: "rectangle", - x: 10, - y: 10, - }); - const rectangle3 = API.createElement({ - type: "rectangle", - x: 20, - y: 20, - }); - - API.setElements([rectangle1, rectangle2, rectangle3]); - - mouse.select(rectangle1); - Keyboard.withModifierKeys({ alt: true }, () => { - mouse.down(rectangle1.x + 5, rectangle1.y + 5); - mouse.up(rectangle1.x + 5, rectangle1.y + 5); - }); - - assertElements(h.elements, [ - { [ORIG_ID]: rectangle1.id }, - { id: rectangle1.id, selected: true }, - { id: rectangle2.id }, - { id: rectangle3.id }, - ]); - }); - - it("duplication z order with alt+drag with grouped elements should consider the group together when determining z-index", () => { - const rectangle1 = API.createElement({ - type: "rectangle", - x: 0, - y: 0, - groupIds: ["group1"], - }); - const rectangle2 = API.createElement({ - type: "rectangle", - x: 10, - y: 10, - groupIds: ["group1"], - }); - const rectangle3 = API.createElement({ - type: "rectangle", - x: 20, - y: 20, - groupIds: ["group1"], - }); - - API.setElements([rectangle1, rectangle2, rectangle3]); - - mouse.select(rectangle1); - Keyboard.withModifierKeys({ alt: true }, () => { - mouse.down(rectangle1.x + 5, rectangle1.y + 5); - mouse.up(rectangle1.x + 15, rectangle1.y + 15); - }); - - assertElements(h.elements, [ - { [ORIG_ID]: rectangle1.id }, - { [ORIG_ID]: rectangle2.id }, - { [ORIG_ID]: rectangle3.id }, - { id: rectangle1.id, selected: true }, - { id: rectangle2.id, selected: true }, - { id: rectangle3.id, selected: true }, - ]); - }); -}); +// +// DEPRECATED: DO NOT ADD TESTS HERE +//