feat: retain seed on shift-paste (#6509)

thanks for the review 👍
This commit is contained in:
David Luzar 2023-04-24 10:26:21 +02:00 committed by GitHub
parent 9d5cfbbfb7
commit d35386755f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 120 additions and 57 deletions

View file

@ -1,5 +1,10 @@
import ReactDOM from "react-dom";
import { render, waitFor, GlobalTestState } from "./test-utils";
import {
render,
waitFor,
GlobalTestState,
createPasteEvent,
} from "./test-utils";
import { Pointer, Keyboard } from "./helpers/ui";
import ExcalidrawApp from "../excalidraw-app";
import { KEYS } from "../keys";
@ -9,6 +14,8 @@ import {
} from "../element/textElement";
import { getElementBounds } from "../element";
import { NormalizedZoomValue } from "../types";
import { API } from "./helpers/api";
import { copyToClipboard } from "../clipboard";
const { h } = window;
@ -35,38 +42,28 @@ const setClipboardText = (text: string) => {
});
};
const sendPasteEvent = () => {
const clipboardEvent = new Event("paste", {
bubbles: true,
cancelable: true,
composed: true,
});
// set `clipboardData` properties.
// @ts-ignore
clipboardEvent.clipboardData = {
getData: () => window.navigator.clipboard.readText(),
files: [],
};
const sendPasteEvent = (text?: string) => {
const clipboardEvent = createPasteEvent(
text || (() => window.navigator.clipboard.readText()),
);
document.dispatchEvent(clipboardEvent);
};
const pasteWithCtrlCmdShiftV = () => {
const pasteWithCtrlCmdShiftV = (text?: string) => {
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
//triggering keydown with an empty clipboard
Keyboard.keyPress(KEYS.V);
//triggering paste event with faked clipboard
sendPasteEvent();
sendPasteEvent(text);
});
};
const pasteWithCtrlCmdV = () => {
const pasteWithCtrlCmdV = (text?: string) => {
Keyboard.withModifierKeys({ ctrl: true }, () => {
//triggering keydown with an empty clipboard
Keyboard.keyPress(KEYS.V);
//triggering paste event with faked clipboard
sendPasteEvent();
sendPasteEvent(text);
});
};
@ -89,6 +86,32 @@ beforeEach(async () => {
});
});
describe("general paste behavior", () => {
it("should randomize seed on paste", async () => {
const rectangle = API.createElement({ type: "rectangle" });
const clipboardJSON = (await copyToClipboard([rectangle], null))!;
pasteWithCtrlCmdV(clipboardJSON);
await waitFor(() => {
expect(h.elements.length).toBe(1);
expect(h.elements[0].seed).not.toBe(rectangle.seed);
});
});
it("should retain seed on shift-paste", async () => {
const rectangle = API.createElement({ type: "rectangle" });
const clipboardJSON = (await copyToClipboard([rectangle], null))!;
// assert we don't randomize seed on shift-paste
pasteWithCtrlCmdShiftV(clipboardJSON);
await waitFor(() => {
expect(h.elements.length).toBe(1);
expect(h.elements[0].seed).toBe(rectangle.seed);
});
});
});
describe("paste text as single lines", () => {
it("should create an element for each line when copying with Ctrl/Cmd+V", async () => {
const text = "sajgfakfn\naaksfnknas\nakefnkasf";

View file

@ -1,5 +1,10 @@
import ReactDOM from "react-dom";
import { GlobalTestState, render, waitFor } from "./test-utils";
import {
createPasteEvent,
GlobalTestState,
render,
waitFor,
} from "./test-utils";
import { UI, Pointer } from "./helpers/ui";
import { API } from "./helpers/api";
import { actionFlipHorizontal, actionFlipVertical } from "../actions";
@ -680,19 +685,7 @@ describe("freedraw", () => {
describe("image", () => {
const createImage = async () => {
const sendPasteEvent = (file?: File) => {
const clipboardEvent = new Event("paste", {
bubbles: true,
cancelable: true,
composed: true,
});
// set `clipboardData` properties.
// @ts-ignore
clipboardEvent.clipboardData = {
getData: () => window.navigator.clipboard.readText(),
files: [file],
};
const clipboardEvent = createPasteEvent("", file ? [file] : []);
document.dispatchEvent(clipboardEvent);
};

View file

@ -190,3 +190,24 @@ export const toggleMenu = (container: HTMLElement) => {
// open menu
fireEvent.click(container.querySelector(".dropdown-menu-button")!);
};
export const createPasteEvent = (
text:
| string
| /* getData function */ ((type: string) => string | Promise<string>),
files?: File[],
) => {
return Object.assign(
new Event("paste", {
bubbles: true,
cancelable: true,
composed: true,
}),
{
clipboardData: {
getData: typeof text === "string" ? () => text : text,
files: files || [],
},
},
);
};