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/App.test.tsx | 45 +
.../excalidraw/tests/MermaidToExcalidraw.test.tsx | 117 +
.../tests/__snapshots__/App.test.tsx.snap | 50 +
.../MermaidToExcalidraw.test.tsx.snap | 19 +
.../tests/__snapshots__/MobileMenu.test.tsx.snap | 257 +
.../tests/__snapshots__/charts.test.tsx.snap | 20 +
.../tests/__snapshots__/contextmenu.test.tsx.snap | 9977 +++++++++
.../tests/__snapshots__/dragCreate.test.tsx.snap | 210 +
.../tests/__snapshots__/excalidraw.test.tsx.snap | 654 +
.../tests/__snapshots__/export.test.tsx.snap | 11 +
.../tests/__snapshots__/history.test.tsx.snap | 20131 +++++++++++++++++++
.../linearElementEditor.test.tsx.snap | 57 +
.../tests/__snapshots__/move.test.tsx.snap | 239 +
.../__snapshots__/multiPointCreate.test.tsx.snap | 114 +
.../__snapshots__/regressionTests.test.tsx.snap | 14782 ++++++++++++++
.../tests/__snapshots__/selection.test.tsx.snap | 202 +
packages/excalidraw/tests/actionStyles.test.tsx | 84 +
packages/excalidraw/tests/align.test.tsx | 579 +
packages/excalidraw/tests/appState.test.tsx | 81 +
packages/excalidraw/tests/binding.test.tsx | 481 +
packages/excalidraw/tests/charts.test.tsx | 13 +
packages/excalidraw/tests/clients.test.ts | 39 +
packages/excalidraw/tests/clipboard.test.tsx | 521 +
packages/excalidraw/tests/contextmenu.test.tsx | 625 +
packages/excalidraw/tests/cropElement.test.tsx | 342 +
.../tests/data/__snapshots__/restore.test.ts.snap | 397 +
packages/excalidraw/tests/data/reconcile.test.ts | 382 +
packages/excalidraw/tests/data/restore.test.ts | 815 +
packages/excalidraw/tests/dragCreate.test.tsx | 347 +
packages/excalidraw/tests/elementLocking.test.tsx | 388 +
packages/excalidraw/tests/excalidraw.test.tsx | 409 +
packages/excalidraw/tests/export.test.tsx | 197 +
packages/excalidraw/tests/fitToContent.test.tsx | 191 +
packages/excalidraw/tests/fixtures/deer.png | Bin 0 -> 12468 bytes
.../excalidraw/tests/fixtures/diagramFixture.ts | 33 +
.../excalidraw/tests/fixtures/elementFixture.ts | 67 +
.../tests/fixtures/fixture_library.excalidrawlib | 31 +
packages/excalidraw/tests/fixtures/smiley.png | Bin 0 -> 1255 bytes
.../tests/fixtures/smiley_embedded_v2.png | Bin 0 -> 2097 bytes
.../tests/fixtures/smiley_embedded_v2.svg | 16 +
.../fixtures/svg-image-exporting-reference.svg | 16 +
.../excalidraw/tests/fixtures/test_embedded_v1.png | Bin 0 -> 1768 bytes
.../excalidraw/tests/fixtures/test_embedded_v1.svg | 16 +
packages/excalidraw/tests/flip.test.tsx | 895 +
packages/excalidraw/tests/fractionalIndex.test.ts | 807 +
packages/excalidraw/tests/helpers/api.ts | 511 +
packages/excalidraw/tests/helpers/colorize.ts | 2 +
packages/excalidraw/tests/helpers/mocks.ts | 32 +
packages/excalidraw/tests/helpers/polyfills.ts | 95 +
packages/excalidraw/tests/helpers/ui.ts | 647 +
packages/excalidraw/tests/history.test.tsx | 4938 +++++
packages/excalidraw/tests/library.test.tsx | 341 +
.../excalidraw/tests/linearElementEditor.test.tsx | 1380 ++
packages/excalidraw/tests/move.test.tsx | 180 +
.../excalidraw/tests/multiPointCreate.test.tsx | 177 +
.../__snapshots__/excalidraw.test.tsx.snap | 616 +
.../packages/__snapshots__/utils.test.ts.snap | 103 +
packages/excalidraw/tests/packages/events.test.tsx | 65 +
packages/excalidraw/tests/queries/dom.ts | 19 +
packages/excalidraw/tests/queries/toolQueries.ts | 25 +
packages/excalidraw/tests/regressionTests.test.tsx | 1183 ++
packages/excalidraw/tests/resize.test.tsx | 1344 ++
packages/excalidraw/tests/rotate.test.tsx | 81 +
.../tests/scene/__snapshots__/export.test.ts.snap | 251 +
packages/excalidraw/tests/scene/export.test.ts | 521 +
packages/excalidraw/tests/scroll.test.tsx | 112 +
packages/excalidraw/tests/search.test.tsx | 148 +
packages/excalidraw/tests/selection.test.tsx | 536 +
packages/excalidraw/tests/shortcuts.test.tsx | 31 +
packages/excalidraw/tests/test-utils.ts | 425 +
packages/excalidraw/tests/tool.test.tsx | 64 +
packages/excalidraw/tests/utils.test.ts | 13 +
packages/excalidraw/tests/viewMode.test.tsx | 68 +
packages/excalidraw/tests/zindex.test.tsx | 1502 ++
74 files changed, 70067 insertions(+)
create mode 100644 packages/excalidraw/tests/App.test.tsx
create mode 100644 packages/excalidraw/tests/MermaidToExcalidraw.test.tsx
create mode 100644 packages/excalidraw/tests/__snapshots__/App.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/MermaidToExcalidraw.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/MobileMenu.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/charts.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/export.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/history.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/linearElementEditor.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/move.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap
create mode 100644 packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap
create mode 100644 packages/excalidraw/tests/actionStyles.test.tsx
create mode 100644 packages/excalidraw/tests/align.test.tsx
create mode 100644 packages/excalidraw/tests/appState.test.tsx
create mode 100644 packages/excalidraw/tests/binding.test.tsx
create mode 100644 packages/excalidraw/tests/charts.test.tsx
create mode 100644 packages/excalidraw/tests/clients.test.ts
create mode 100644 packages/excalidraw/tests/clipboard.test.tsx
create mode 100644 packages/excalidraw/tests/contextmenu.test.tsx
create mode 100644 packages/excalidraw/tests/cropElement.test.tsx
create mode 100644 packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap
create mode 100644 packages/excalidraw/tests/data/reconcile.test.ts
create mode 100644 packages/excalidraw/tests/data/restore.test.ts
create mode 100644 packages/excalidraw/tests/dragCreate.test.tsx
create mode 100644 packages/excalidraw/tests/elementLocking.test.tsx
create mode 100644 packages/excalidraw/tests/excalidraw.test.tsx
create mode 100644 packages/excalidraw/tests/export.test.tsx
create mode 100644 packages/excalidraw/tests/fitToContent.test.tsx
create mode 100644 packages/excalidraw/tests/fixtures/deer.png
create mode 100644 packages/excalidraw/tests/fixtures/diagramFixture.ts
create mode 100644 packages/excalidraw/tests/fixtures/elementFixture.ts
create mode 100644 packages/excalidraw/tests/fixtures/fixture_library.excalidrawlib
create mode 100644 packages/excalidraw/tests/fixtures/smiley.png
create mode 100644 packages/excalidraw/tests/fixtures/smiley_embedded_v2.png
create mode 100644 packages/excalidraw/tests/fixtures/smiley_embedded_v2.svg
create mode 100644 packages/excalidraw/tests/fixtures/svg-image-exporting-reference.svg
create mode 100644 packages/excalidraw/tests/fixtures/test_embedded_v1.png
create mode 100644 packages/excalidraw/tests/fixtures/test_embedded_v1.svg
create mode 100644 packages/excalidraw/tests/flip.test.tsx
create mode 100644 packages/excalidraw/tests/fractionalIndex.test.ts
create mode 100644 packages/excalidraw/tests/helpers/api.ts
create mode 100644 packages/excalidraw/tests/helpers/colorize.ts
create mode 100644 packages/excalidraw/tests/helpers/mocks.ts
create mode 100644 packages/excalidraw/tests/helpers/polyfills.ts
create mode 100644 packages/excalidraw/tests/helpers/ui.ts
create mode 100644 packages/excalidraw/tests/history.test.tsx
create mode 100644 packages/excalidraw/tests/library.test.tsx
create mode 100644 packages/excalidraw/tests/linearElementEditor.test.tsx
create mode 100644 packages/excalidraw/tests/move.test.tsx
create mode 100644 packages/excalidraw/tests/multiPointCreate.test.tsx
create mode 100644 packages/excalidraw/tests/packages/__snapshots__/excalidraw.test.tsx.snap
create mode 100644 packages/excalidraw/tests/packages/__snapshots__/utils.test.ts.snap
create mode 100644 packages/excalidraw/tests/packages/events.test.tsx
create mode 100644 packages/excalidraw/tests/queries/dom.ts
create mode 100644 packages/excalidraw/tests/queries/toolQueries.ts
create mode 100644 packages/excalidraw/tests/regressionTests.test.tsx
create mode 100644 packages/excalidraw/tests/resize.test.tsx
create mode 100644 packages/excalidraw/tests/rotate.test.tsx
create mode 100644 packages/excalidraw/tests/scene/__snapshots__/export.test.ts.snap
create mode 100644 packages/excalidraw/tests/scene/export.test.ts
create mode 100644 packages/excalidraw/tests/scroll.test.tsx
create mode 100644 packages/excalidraw/tests/search.test.tsx
create mode 100644 packages/excalidraw/tests/selection.test.tsx
create mode 100644 packages/excalidraw/tests/shortcuts.test.tsx
create mode 100644 packages/excalidraw/tests/test-utils.ts
create mode 100644 packages/excalidraw/tests/tool.test.tsx
create mode 100644 packages/excalidraw/tests/utils.test.ts
create mode 100644 packages/excalidraw/tests/viewMode.test.tsx
create mode 100644 packages/excalidraw/tests/zindex.test.tsx
(limited to 'packages/excalidraw/tests')
diff --git a/packages/excalidraw/tests/App.test.tsx b/packages/excalidraw/tests/App.test.tsx
new file mode 100644
index 0000000..ad62706
--- /dev/null
+++ b/packages/excalidraw/tests/App.test.tsx
@@ -0,0 +1,45 @@
+import React from "react";
+import * as StaticScene from "../renderer/staticScene";
+import { reseed } from "../random";
+import { render, queryByTestId, unmountComponent } from "../tests/test-utils";
+
+import { Excalidraw } from "../index";
+import { vi } from "vitest";
+
+const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene");
+
+describe("Test ", () => {
+ beforeEach(async () => {
+ unmountComponent();
+ localStorage.clear();
+ renderStaticScene.mockClear();
+ reseed(7);
+ });
+
+ it("should show error modal when using brave and measureText API is not working", async () => {
+ (global.navigator as any).brave = {
+ isBrave: {
+ name: "isBrave",
+ },
+ };
+
+ const originalContext = global.HTMLCanvasElement.prototype.getContext("2d");
+ //@ts-ignore
+ global.HTMLCanvasElement.prototype.getContext = (contextId) => {
+ return {
+ ...originalContext,
+ measureText: () => ({
+ width: 0,
+ }),
+ };
+ };
+
+ await render();
+ expect(
+ queryByTestId(
+ document.querySelector(".excalidraw-modal-container")!,
+ "brave-measure-text-error",
+ ),
+ ).toMatchSnapshot();
+ });
+});
diff --git a/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx b/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx
new file mode 100644
index 0000000..05727a0
--- /dev/null
+++ b/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx
@@ -0,0 +1,117 @@
+import React from "react";
+import { render, waitFor } from "./test-utils";
+import { Excalidraw } from "../index";
+import { expect } from "vitest";
+import { getTextEditor, updateTextEditor } from "./queries/dom";
+import { mockMermaidToExcalidraw } from "./helpers/mocks";
+
+mockMermaidToExcalidraw({
+ mockRef: true,
+ parseMermaidToExcalidraw: async (definition) => {
+ const firstLine = definition.split("\n")[0];
+ return new Promise((resolve, reject) => {
+ if (firstLine === "flowchart TD") {
+ resolve({
+ elements: [
+ {
+ id: "Start",
+ type: "rectangle",
+ groupIds: [],
+ x: 0,
+ y: 0,
+ width: 69.703125,
+ height: 44,
+ strokeWidth: 2,
+ label: {
+ groupIds: [],
+ text: "Start",
+ fontSize: 20,
+ },
+ link: null,
+ },
+ {
+ id: "Stop",
+ type: "rectangle",
+ groupIds: [],
+ x: 2.7109375,
+ y: 94,
+ width: 64.28125,
+ height: 44,
+ strokeWidth: 2,
+ label: {
+ groupIds: [],
+ text: "Stop",
+ fontSize: 20,
+ },
+ link: null,
+ },
+ {
+ id: "Start_Stop",
+ type: "arrow",
+ groupIds: [],
+ x: 34.852,
+ y: 44,
+ strokeWidth: 2,
+ points: [
+ [0, 0],
+ [0, 50],
+ ],
+ roundness: {
+ type: 2,
+ },
+ start: {
+ id: "Start",
+ },
+ end: {
+ id: "Stop",
+ },
+ },
+ ],
+ });
+ } else {
+ reject(new Error("ERROR"));
+ }
+ });
+ },
+});
+
+describe("Test ", () => {
+ beforeEach(async () => {
+ await render(
+ ,
+ );
+ });
+
+ it("should open mermaid popup when active tool is mermaid", async () => {
+ const dialog = document.querySelector(".ttd-dialog")!;
+ await waitFor(() => expect(dialog.querySelector("canvas")).not.toBeNull());
+ expect(dialog.outerHTML).toMatchSnapshot();
+ });
+
+ it("should show error in preview when mermaid library throws error", async () => {
+ const dialog = document.querySelector(".ttd-dialog")!;
+
+ expect(dialog).not.toBeNull();
+
+ const selector = ".ttd-dialog-input";
+ let editor = await getTextEditor(selector, true);
+
+ expect(dialog.querySelector('[data-testid="mermaid-error"]')).toBeNull();
+
+ expect(editor.textContent).toMatchSnapshot();
+
+ updateTextEditor(editor, "flowchart TD1");
+ editor = await getTextEditor(selector, false);
+
+ expect(editor.textContent).toBe("flowchart TD1");
+ expect(
+ dialog.querySelector('[data-testid="mermaid-error"]'),
+ ).toMatchInlineSnapshot("null");
+ });
+});
diff --git a/packages/excalidraw/tests/__snapshots__/App.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/App.test.tsx.snap
new file mode 100644
index 0000000..49c2fd0
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/App.test.tsx.snap
@@ -0,0 +1,50 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Test > should show error modal when using brave and measureText API is not working 1`] = `
+
+
+ Looks like you are using Brave browser with the
+
+ Aggressively Block Fingerprinting
+
+ setting enabled.
+
+
+ This could result in breaking the
+
+ Text Elements
+
+ in your drawings.
+
+
+ We strongly recommend disabling this setting. You can follow
+
+ these steps
+
+ on how to do so.
+
+
+ If disabling this setting doesn't fix the display of text elements, please open an
+
+ issue
+
+ on our GitHub, or write us on
+
+ Discord
+ .
+
+
+
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/MermaidToExcalidraw.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/MermaidToExcalidraw.test.tsx.snap
new file mode 100644
index 0000000..2943aee
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/MermaidToExcalidraw.test.tsx.snap
@@ -0,0 +1,19 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Test > should open mermaid popup when active tool is mermaid 1`] = `
+"Mermaid to Excalidraw
Currently only
Flowchart,
Sequence, and
Class Diagrams are supported. The other types will be rendered as image in Excalidraw.
"
+`;
+
+exports[`Test > should show error in preview when mermaid library throws error 1`] = `
+"flowchart TD
+ A[Christmas] -->|Get money| B(Go shopping)
+ B --> C{Let me think}
+ C -->|One| D[Laptop]
+ C -->|Two| E[iPhone]
+ C -->|Three| F[Car]"
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/MobileMenu.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/MobileMenu.test.tsx.snap
new file mode 100644
index 0000000..ad0c9f0
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/MobileMenu.test.tsx.snap
@@ -0,0 +1,257 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Test MobileMenu > should initialize with welcome screen and hide once user interacts 1`] = `
+
+
+
+ All your data is saved locally in your browser.
+
+
+
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/charts.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/charts.test.tsx.snap
new file mode 100644
index 0000000..868e27e
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/charts.test.tsx.snap
@@ -0,0 +1,20 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`tryParseSpreadsheet > works for numbers with comma in them 1`] = `
+{
+ "spreadsheet": {
+ "labels": [
+ "Week 1",
+ "Week 2",
+ "Week 3",
+ ],
+ "title": "Users",
+ "values": [
+ 814,
+ 10301,
+ 4264,
+ ],
+ },
+ "type": "VALID_SPREADSHEET",
+}
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap
new file mode 100644
index 0000000..f77eb8d
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap
@@ -0,0 +1,9977 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`contextMenu element > right-clicking on a group should select whole group > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": {
+ "items": [
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.cut",
+ "name": "cut",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": undefined,
+ "label": "labels.copy",
+ "name": "copy",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keyTest": undefined,
+ "label": "labels.paste",
+ "name": "paste",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.selectAllElementsInFrame",
+ "name": "selectAllElementsInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ },
+ },
+ {
+ "label": "labels.removeAllElementsFromFrame",
+ "name": "removeAllElementsFromFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "history",
+ },
+ },
+ {
+ "label": "labels.wrapSelectionInFrame",
+ "name": "wrapSelectionInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keywords": [
+ "image",
+ "crop",
+ ],
+ "label": "helpDialog.cropStart",
+ "name": "cropEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "menu",
+ },
+ "viewMode": true,
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "png",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsPng",
+ "name": "copyAsPng",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keywords": [
+ "svg",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsSvg",
+ "name": "copyAsSvg",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keywords": [
+ "text",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyText",
+ "name": "copyText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.copyStyles",
+ "name": "copyStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.pasteStyles",
+ "name": "pasteStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.group",
+ "name": "group",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": null,
+ "label": "labels.autoResize",
+ "name": "autoResize",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.unbindText",
+ "name": "unbindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.bindText",
+ "name": "bindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.createContainerFromText",
+ "name": "wrapTextInContainer",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.ungroup",
+ "name": "ungroup",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.addToLibrary",
+ "name": "addToLibrary",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendBackward",
+ "name": "sendBackward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringForward",
+ "name": "bringForward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendToBack",
+ "name": "sendToBack",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringToFront",
+ "name": "bringToFront",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipHorizontal",
+ "name": "flipHorizontal",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipVertical",
+ "name": "flipVertical",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "category": "Elements",
+ "keywords": [
+ "line",
+ ],
+ "label": [Function],
+ "name": "toggleLinearEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "hyperlink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "action": "click",
+ "category": "hyperlink",
+ },
+ },
+ {
+ "icon": ,
+ "label": "labels.copyElementLink",
+ "name": "copyElementLink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.duplicateSelection",
+ "name": "duplicateSelection",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "toggleElementLock",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.delete",
+ "name": "deleteSelectedElements",
+ "perform": [Function],
+ "trackEvent": {
+ "action": "delete",
+ "category": "element",
+ },
+ },
+ ],
+ "left": 30,
+ "top": 40,
+ },
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "g1": true,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > right-clicking on a group should select whole group > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "red",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "g1",
+ ],
+ "height": 100,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": 1278240551,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > right-clicking on a group should select whole group > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "red",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "g1",
+ ],
+ "height": 100,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": 449462985,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > right-clicking on a group should select whole group > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [],
+}
+`;
+
+exports[`contextMenu element > right-clicking on a group should select whole group > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > right-clicking on a group should select whole group > [end of test] number of renders 1`] = `5`;
+
+exports[`contextMenu element > selecting 'Add to library' in context menu adds element to library > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": {
+ "message": "Added to library",
+ },
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Add to library' in context menu adds element to library > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1150084233,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Add to library' in context menu adds element to library > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Add to library' in context menu adds element to library > [end of test] number of elements 1`] = `1`;
+
+exports[`contextMenu element > selecting 'Add to library' in context menu adds element to library > [end of test] number of renders 1`] = `5`;
+
+exports[`contextMenu element > selecting 'Bring forward' in context menu brings element forward > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Bring forward' in context menu brings element forward > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1014066025,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1604849351,
+ "width": 20,
+ "x": 20,
+ "y": 30,
+}
+`;
+
+exports[`contextMenu element > selecting 'Bring forward' in context menu brings element forward > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 23633383,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Bring forward' in context menu brings element forward > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 20,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "index": "a2",
+ },
+ "inserted": {
+ "index": "a0",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Bring forward' in context menu brings element forward > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > selecting 'Bring forward' in context menu brings element forward > [end of test] number of renders 1`] = `10`;
+
+exports[`contextMenu element > selecting 'Bring to front' in context menu brings element to front > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Bring to front' in context menu brings element to front > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1014066025,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1604849351,
+ "width": 20,
+ "x": 20,
+ "y": 30,
+}
+`;
+
+exports[`contextMenu element > selecting 'Bring to front' in context menu brings element to front > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 23633383,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Bring to front' in context menu brings element to front > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 20,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "index": "a2",
+ },
+ "inserted": {
+ "index": "a0",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Bring to front' in context menu brings element to front > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > selecting 'Bring to front' in context menu brings element to front > [end of test] number of renders 1`] = `10`;
+
+exports[`contextMenu element > selecting 'Copy styles' in context menu copies styles > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": {
+ "message": "Copied styles.",
+ },
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Copy styles' in context menu copies styles > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1150084233,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Copy styles' in context menu copies styles > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Copy styles' in context menu copies styles > [end of test] number of elements 1`] = `1`;
+
+exports[`contextMenu element > selecting 'Copy styles' in context menu copies styles > [end of test] number of renders 1`] = `5`;
+
+exports[`contextMenu element > selecting 'Delete' in context menu deletes element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Delete' in context menu deletes element > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 1014066025,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Delete' in context menu deletes element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id0" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "isDeleted": false,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Delete' in context menu deletes element > [end of test] number of elements 1`] = `1`;
+
+exports[`contextMenu element > selecting 'Delete' in context menu deletes element > [end of test] number of renders 1`] = `6`;
+
+exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates element > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1150084233,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates element > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1014066025,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 238820263,
+ "width": 20,
+ "x": 0,
+ "y": 10,
+}
+`;
+
+exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 0,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates element > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates element > [end of test] number of renders 1`] = `6`;
+
+exports[`contextMenu element > selecting 'Group selection' in context menu groups selected elements > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id1": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Group selection' in context menu groups selected elements > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id3",
+ ],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 493213705,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Group selection' in context menu groups selected elements > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id3",
+ ],
+ "height": 20,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1014066025,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 915032327,
+ "width": 20,
+ "x": 20,
+ "y": 30,
+}
+`;
+
+exports[`contextMenu element > selecting 'Group selection' in context menu groups selected elements > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 20,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Group selection' in context menu groups selected elements > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > selecting 'Group selection' in context menu groups selected elements > [end of test] number of renders 1`] = `10`;
+
+exports[`contextMenu element > selecting 'Paste styles' in context menu pastes styles > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#a5d8ff",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "cross-hatch",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 60,
+ "currentItemRoughness": 2,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#e03131",
+ "currentItemStrokeStyle": "dotted",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": {
+ "message": "Copied styles.",
+ },
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Paste styles' in context menu pastes styles > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "#a5d8ff",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "cross-hatch",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 60,
+ "roughness": 2,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#e03131",
+ "strokeStyle": "dotted",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 941653321,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Paste styles' in context menu pastes styles > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "#a5d8ff",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "cross-hatch",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 60,
+ "roughness": 2,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 289600103,
+ "strokeColor": "#e03131",
+ "strokeStyle": "dotted",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 9,
+ "versionNonce": 640725609,
+ "width": 20,
+ "x": 20,
+ "y": 30,
+}
+`;
+
+exports[`contextMenu element > selecting 'Paste styles' in context menu pastes styles > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 20,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "strokeColor": "#e03131",
+ },
+ "inserted": {
+ "strokeColor": "#1e1e1e",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "backgroundColor": "#a5d8ff",
+ },
+ "inserted": {
+ "backgroundColor": "transparent",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "fillStyle": "cross-hatch",
+ },
+ "inserted": {
+ "fillStyle": "solid",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "strokeStyle": "dotted",
+ },
+ "inserted": {
+ "strokeStyle": "solid",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "roughness": 2,
+ },
+ "inserted": {
+ "roughness": 1,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "opacity": 60,
+ },
+ "inserted": {
+ "opacity": 100,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "backgroundColor": "#a5d8ff",
+ "fillStyle": "cross-hatch",
+ "opacity": 60,
+ "roughness": 2,
+ "strokeColor": "#e03131",
+ "strokeStyle": "dotted",
+ },
+ "inserted": {
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "opacity": 100,
+ "roughness": 1,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Paste styles' in context menu pastes styles > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > selecting 'Paste styles' in context menu pastes styles > [end of test] number of renders 1`] = `16`;
+
+exports[`contextMenu element > selecting 'Send backward' in context menu sends element backward > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Send backward' in context menu sends element backward > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id1",
+ "index": "Zz",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1014066025,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 23633383,
+ "width": 20,
+ "x": 20,
+ "y": 30,
+}
+`;
+
+exports[`contextMenu element > selecting 'Send backward' in context menu sends element backward > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1150084233,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Send backward' in context menu sends element backward > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 20,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "index": "Zz",
+ },
+ "inserted": {
+ "index": "a1",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Send backward' in context menu sends element backward > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > selecting 'Send backward' in context menu sends element backward > [end of test] number of renders 1`] = `9`;
+
+exports[`contextMenu element > selecting 'Send to back' in context menu sends element to back > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Send to back' in context menu sends element to back > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id1",
+ "index": "Zz",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1014066025,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 23633383,
+ "width": 20,
+ "x": 20,
+ "y": 30,
+}
+`;
+
+exports[`contextMenu element > selecting 'Send to back' in context menu sends element to back > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1150084233,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Send to back' in context menu sends element to back > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 20,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "index": "Zz",
+ },
+ "inserted": {
+ "index": "a1",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Send to back' in context menu sends element to back > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > selecting 'Send to back' in context menu sends element to back > [end of test] number of renders 1`] = `9`;
+
+exports[`contextMenu element > selecting 'Ungroup selection' in context menu ungroups selected group > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id1": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > selecting 'Ungroup selection' in context menu ungroups selected group > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "versionNonce": 1723083209,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > selecting 'Ungroup selection' in context menu ungroups selected group > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 238820263,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "versionNonce": 760410951,
+ "width": 20,
+ "x": 20,
+ "y": 30,
+}
+`;
+
+exports[`contextMenu element > selecting 'Ungroup selection' in context menu ungroups selected group > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 20,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [],
+ },
+ "inserted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [],
+ },
+ "inserted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > selecting 'Ungroup selection' in context menu ungroups selected group > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > selecting 'Ungroup selection' in context menu ungroups selected group > [end of test] number of renders 1`] = `11`;
+
+exports[`contextMenu element > shows 'Group selection' in context menu for multiple selected elements > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": {
+ "items": [
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.cut",
+ "name": "cut",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": undefined,
+ "label": "labels.copy",
+ "name": "copy",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keyTest": undefined,
+ "label": "labels.paste",
+ "name": "paste",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.selectAllElementsInFrame",
+ "name": "selectAllElementsInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ },
+ },
+ {
+ "label": "labels.removeAllElementsFromFrame",
+ "name": "removeAllElementsFromFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "history",
+ },
+ },
+ {
+ "label": "labels.wrapSelectionInFrame",
+ "name": "wrapSelectionInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keywords": [
+ "image",
+ "crop",
+ ],
+ "label": "helpDialog.cropStart",
+ "name": "cropEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "menu",
+ },
+ "viewMode": true,
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "png",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsPng",
+ "name": "copyAsPng",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keywords": [
+ "svg",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsSvg",
+ "name": "copyAsSvg",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keywords": [
+ "text",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyText",
+ "name": "copyText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.copyStyles",
+ "name": "copyStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.pasteStyles",
+ "name": "pasteStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.group",
+ "name": "group",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": null,
+ "label": "labels.autoResize",
+ "name": "autoResize",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.unbindText",
+ "name": "unbindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.bindText",
+ "name": "bindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.createContainerFromText",
+ "name": "wrapTextInContainer",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.ungroup",
+ "name": "ungroup",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.addToLibrary",
+ "name": "addToLibrary",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendBackward",
+ "name": "sendBackward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringForward",
+ "name": "bringForward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendToBack",
+ "name": "sendToBack",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringToFront",
+ "name": "bringToFront",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipHorizontal",
+ "name": "flipHorizontal",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipVertical",
+ "name": "flipVertical",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "category": "Elements",
+ "keywords": [
+ "line",
+ ],
+ "label": [Function],
+ "name": "toggleLinearEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "hyperlink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "action": "click",
+ "category": "hyperlink",
+ },
+ },
+ {
+ "icon": ,
+ "label": "labels.copyElementLink",
+ "name": "copyElementLink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.duplicateSelection",
+ "name": "duplicateSelection",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "toggleElementLock",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.delete",
+ "name": "deleteSelectedElements",
+ "perform": [Function],
+ "trackEvent": {
+ "action": "delete",
+ "category": "element",
+ },
+ },
+ ],
+ "left": -17,
+ "top": -7,
+ },
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > shows 'Group selection' in context menu for multiple selected elements > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 453191,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1014066025,
+ "width": 10,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > shows 'Group selection' in context menu for multiple selected elements > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 400692809,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 23633383,
+ "width": 10,
+ "x": 12,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > shows 'Group selection' in context menu for multiple selected elements > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 12,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > shows 'Group selection' in context menu for multiple selected elements > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > shows 'Group selection' in context menu for multiple selected elements > [end of test] number of renders 1`] = `10`;
+
+exports[`contextMenu element > shows 'Ungroup selection' in context menu for group inside selected elements > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": {
+ "items": [
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.cut",
+ "name": "cut",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": undefined,
+ "label": "labels.copy",
+ "name": "copy",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keyTest": undefined,
+ "label": "labels.paste",
+ "name": "paste",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.selectAllElementsInFrame",
+ "name": "selectAllElementsInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ },
+ },
+ {
+ "label": "labels.removeAllElementsFromFrame",
+ "name": "removeAllElementsFromFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "history",
+ },
+ },
+ {
+ "label": "labels.wrapSelectionInFrame",
+ "name": "wrapSelectionInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keywords": [
+ "image",
+ "crop",
+ ],
+ "label": "helpDialog.cropStart",
+ "name": "cropEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "menu",
+ },
+ "viewMode": true,
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "png",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsPng",
+ "name": "copyAsPng",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keywords": [
+ "svg",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsSvg",
+ "name": "copyAsSvg",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keywords": [
+ "text",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyText",
+ "name": "copyText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.copyStyles",
+ "name": "copyStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.pasteStyles",
+ "name": "pasteStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.group",
+ "name": "group",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": null,
+ "label": "labels.autoResize",
+ "name": "autoResize",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.unbindText",
+ "name": "unbindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.bindText",
+ "name": "bindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.createContainerFromText",
+ "name": "wrapTextInContainer",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.ungroup",
+ "name": "ungroup",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.addToLibrary",
+ "name": "addToLibrary",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendBackward",
+ "name": "sendBackward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringForward",
+ "name": "bringForward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendToBack",
+ "name": "sendToBack",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringToFront",
+ "name": "bringToFront",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipHorizontal",
+ "name": "flipHorizontal",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipVertical",
+ "name": "flipVertical",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "category": "Elements",
+ "keywords": [
+ "line",
+ ],
+ "label": [Function],
+ "name": "toggleLinearEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "hyperlink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "action": "click",
+ "category": "hyperlink",
+ },
+ },
+ {
+ "icon": ,
+ "label": "labels.copyElementLink",
+ "name": "copyElementLink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.duplicateSelection",
+ "name": "duplicateSelection",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "toggleElementLock",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.delete",
+ "name": "deleteSelectedElements",
+ "perform": [Function],
+ "trackEvent": {
+ "action": "delete",
+ "category": "element",
+ },
+ },
+ ],
+ "left": -17,
+ "top": -7,
+ },
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > shows 'Ungroup selection' in context menu for group inside selected elements > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id4",
+ ],
+ "height": 10,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 81784553,
+ "width": 10,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > shows 'Ungroup selection' in context menu for group inside selected elements > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id4",
+ ],
+ "height": 10,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 238820263,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 747212839,
+ "width": 10,
+ "x": 12,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > shows 'Ungroup selection' in context menu for group inside selected elements > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 12,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > shows 'Ungroup selection' in context menu for group inside selected elements > [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element > shows 'Ungroup selection' in context menu for group inside selected elements > [end of test] number of renders 1`] = `11`;
+
+exports[`contextMenu element > shows context menu for canvas > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": {
+ "items": [
+ {
+ "keyTest": undefined,
+ "label": "labels.paste",
+ "name": "paste",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "png",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsPng",
+ "name": "copyAsPng",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keywords": [
+ "svg",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsSvg",
+ "name": "copyAsSvg",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keywords": [
+ "text",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyText",
+ "name": "copyText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.selectAll",
+ "name": "selectAll",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ },
+ "viewMode": false,
+ },
+ {
+ "icon": ,
+ "label": "labels.elementLock.unlockAll",
+ "name": "unlockAllElements",
+ "paletteName": "Unlock all elements",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ },
+ "viewMode": false,
+ },
+ "separator",
+ {
+ "checked": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "snap",
+ ],
+ "label": "labels.toggleGrid",
+ "name": "gridMode",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ "predicate": [Function],
+ },
+ "viewMode": true,
+ },
+ {
+ "checked": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "buttons.objectsSnapMode",
+ "name": "objectsSnapMode",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ "predicate": [Function],
+ },
+ "viewMode": false,
+ },
+ {
+ "checked": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "buttons.zenMode",
+ "name": "zenMode",
+ "paletteName": "Toggle zen mode",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ "predicate": [Function],
+ },
+ "viewMode": true,
+ },
+ {
+ "checked": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.viewMode",
+ "name": "viewMode",
+ "paletteName": "Toggle view mode",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ "predicate": [Function],
+ },
+ "viewMode": true,
+ },
+ {
+ "checked": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "edit",
+ "attributes",
+ "customize",
+ ],
+ "label": "stats.fullTitle",
+ "name": "stats",
+ "paletteName": "Toggle stats",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "menu",
+ },
+ "viewMode": true,
+ },
+ ],
+ "left": -19,
+ "top": -9,
+ },
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > shows context menu for canvas > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [],
+}
+`;
+
+exports[`contextMenu element > shows context menu for canvas > [end of test] number of elements 1`] = `0`;
+
+exports[`contextMenu element > shows context menu for canvas > [end of test] number of renders 1`] = `3`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": {
+ "items": [
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.cut",
+ "name": "cut",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": undefined,
+ "label": "labels.copy",
+ "name": "copy",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keyTest": undefined,
+ "label": "labels.paste",
+ "name": "paste",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.selectAllElementsInFrame",
+ "name": "selectAllElementsInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ },
+ },
+ {
+ "label": "labels.removeAllElementsFromFrame",
+ "name": "removeAllElementsFromFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "history",
+ },
+ },
+ {
+ "label": "labels.wrapSelectionInFrame",
+ "name": "wrapSelectionInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keywords": [
+ "image",
+ "crop",
+ ],
+ "label": "helpDialog.cropStart",
+ "name": "cropEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "menu",
+ },
+ "viewMode": true,
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "png",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsPng",
+ "name": "copyAsPng",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keywords": [
+ "svg",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsSvg",
+ "name": "copyAsSvg",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keywords": [
+ "text",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyText",
+ "name": "copyText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.copyStyles",
+ "name": "copyStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.pasteStyles",
+ "name": "pasteStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.group",
+ "name": "group",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": null,
+ "label": "labels.autoResize",
+ "name": "autoResize",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.unbindText",
+ "name": "unbindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.bindText",
+ "name": "bindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.createContainerFromText",
+ "name": "wrapTextInContainer",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.ungroup",
+ "name": "ungroup",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.addToLibrary",
+ "name": "addToLibrary",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendBackward",
+ "name": "sendBackward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringForward",
+ "name": "bringForward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendToBack",
+ "name": "sendToBack",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringToFront",
+ "name": "bringToFront",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipHorizontal",
+ "name": "flipHorizontal",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipVertical",
+ "name": "flipVertical",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "category": "Elements",
+ "keywords": [
+ "line",
+ ],
+ "label": [Function],
+ "name": "toggleLinearEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "hyperlink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "action": "click",
+ "category": "hyperlink",
+ },
+ },
+ {
+ "icon": ,
+ "label": "labels.copyElementLink",
+ "name": "copyElementLink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.duplicateSelection",
+ "name": "duplicateSelection",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "toggleElementLock",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.delete",
+ "name": "deleteSelectedElements",
+ "perform": [Function],
+ "trackEvent": {
+ "action": "delete",
+ "category": "element",
+ },
+ },
+ ],
+ "left": -17,
+ "top": -7,
+ },
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] appState 2`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": {
+ "items": [
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.cut",
+ "name": "cut",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": undefined,
+ "label": "labels.copy",
+ "name": "copy",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keyTest": undefined,
+ "label": "labels.paste",
+ "name": "paste",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.selectAllElementsInFrame",
+ "name": "selectAllElementsInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "canvas",
+ },
+ },
+ {
+ "label": "labels.removeAllElementsFromFrame",
+ "name": "removeAllElementsFromFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "history",
+ },
+ },
+ {
+ "label": "labels.wrapSelectionInFrame",
+ "name": "wrapSelectionInFrame",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keywords": [
+ "image",
+ "crop",
+ ],
+ "label": "helpDialog.cropStart",
+ "name": "cropEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "menu",
+ },
+ "viewMode": true,
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "png",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsPng",
+ "name": "copyAsPng",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keywords": [
+ "svg",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyAsSvg",
+ "name": "copyAsSvg",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "keywords": [
+ "text",
+ "clipboard",
+ "copy",
+ ],
+ "label": "labels.copyText",
+ "name": "copyText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.copyStyles",
+ "name": "copyStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.pasteStyles",
+ "name": "pasteStyles",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.group",
+ "name": "group",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": null,
+ "label": "labels.autoResize",
+ "name": "autoResize",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.unbindText",
+ "name": "unbindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.bindText",
+ "name": "bindText",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "label": "labels.createContainerFromText",
+ "name": "wrapTextInContainer",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": "labels.ungroup",
+ "name": "ungroup",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "label": "labels.addToLibrary",
+ "name": "addToLibrary",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendBackward",
+ "name": "sendBackward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyPriority": 40,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringForward",
+ "name": "bringForward",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move down",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.sendToBack",
+ "name": "sendToBack",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "keywords": [
+ "move up",
+ "zindex",
+ "layer",
+ ],
+ "label": "labels.bringToFront",
+ "name": "bringToFront",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipHorizontal",
+ "name": "flipHorizontal",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.flipVertical",
+ "name": "flipVertical",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "category": "Elements",
+ "keywords": [
+ "line",
+ ],
+ "label": [Function],
+ "name": "toggleLinearEditor",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "hyperlink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "action": "click",
+ "category": "hyperlink",
+ },
+ },
+ {
+ "icon": ,
+ "label": "labels.copyElementLink",
+ "name": "copyElementLink",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.duplicateSelection",
+ "name": "duplicateSelection",
+ "perform": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ {
+ "icon": [Function],
+ "keyTest": [Function],
+ "label": [Function],
+ "name": "toggleElementLock",
+ "perform": [Function],
+ "predicate": [Function],
+ "trackEvent": {
+ "category": "element",
+ },
+ },
+ "separator",
+ {
+ "PanelComponent": [Function],
+ "icon": ,
+ "keyTest": [Function],
+ "label": "labels.delete",
+ "name": "deleteSelectedElements",
+ "perform": [Function],
+ "trackEvent": {
+ "action": "delete",
+ "category": "element",
+ },
+ },
+ ],
+ "left": 80,
+ "top": 90,
+ },
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 100,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 20,
+ "offsetTop": 10,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 200,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 449462985,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 1150084233,
+ "width": 20,
+ "x": -10,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] element 0 2`] = `
+{
+ "angle": 0,
+ "backgroundColor": "red",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 200,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": 1278240551,
+ "width": 200,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "red",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 200,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": 449462985,
+ "width": 200,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": -10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] history 2`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [],
+}
+`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] number of elements 1`] = `1`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] number of elements 2`] = `2`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] number of renders 1`] = `5`;
+
+exports[`contextMenu element > shows context menu for element > [end of test] number of renders 2`] = `6`;
diff --git a/packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap
new file mode 100644
index 0000000..acc9b79
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/dragCreate.test.tsx.snap
@@ -0,0 +1,210 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > arrow 3`] = `1`;
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > arrow 4`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 30,
+ 50,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 2019559783,
+ "width": 30,
+ "x": 30,
+ "y": 20,
+}
+`;
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > diamond 3`] = `1`;
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > diamond 4`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 401146281,
+ "width": 30,
+ "x": 30,
+ "y": 20,
+}
+`;
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > ellipse 3`] = `1`;
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > ellipse 4`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 401146281,
+ "width": 30,
+ "x": 30,
+ "y": 20,
+}
+`;
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > line 3`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 30,
+ 50,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 2019559783,
+ "width": 30,
+ "x": 30,
+ "y": 20,
+}
+`;
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > rectangle 3`] = `1`;
+
+exports[`Test dragCreate > add element to the scene when pointer dragging long enough > rectangle 4`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 401146281,
+ "width": 30,
+ "x": 30,
+ "y": 20,
+}
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap
new file mode 100644
index 0000000..e5e431d
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/excalidraw.test.tsx.snap
@@ -0,0 +1,654 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[` > > should render main menu with host menu items if passed from host 1`] = `
+
+`;
+
+exports[` > Test UIOptions prop > Test canvasActions > should render menu with default items when "UIOPtions" is "undefined" 1`] = `
+
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/export.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/export.test.tsx.snap
new file mode 100644
index 0000000..7f766e1
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/export.test.tsx.snap
@@ -0,0 +1,11 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`export > export svg-embedded scene > svg-embdedded scene export output 1`] = `
+""
+`;
+
+exports[`export > exporting svg containing transformed images > svg export output 1`] = `
+""
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap
new file mode 100644
index 0000000..165c135
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap
@@ -0,0 +1,20131 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id172": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id172": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id170",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 18,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id171",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 19,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id175",
+ "fixedPoint": [
+ "0.50000",
+ 1,
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": "102.35417",
+ "id": "id172",
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "101.77517",
+ "102.35417",
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 40,
+ "width": "101.77517",
+ "x": "0.70711",
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id172",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id175",
+ "index": "a3",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 6,
+ "width": 50,
+ "x": 100,
+ "y": 100,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id172" => Delta {
+ "deleted": {
+ "endBinding": {
+ "elementId": "id171",
+ "focus": "0.00990",
+ "gap": 1,
+ },
+ "height": "0.98586",
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ "-0.98586",
+ ],
+ ],
+ "startBinding": {
+ "elementId": "id170",
+ "focus": "0.02970",
+ "gap": 1,
+ },
+ },
+ "inserted": {
+ "endBinding": {
+ "elementId": "id171",
+ "focus": "-0.02000",
+ "gap": 1,
+ },
+ "height": "0.00000",
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ "0.00000",
+ ],
+ ],
+ "startBinding": {
+ "elementId": "id170",
+ "focus": "0.02000",
+ "gap": 1,
+ },
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id170" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id172",
+ "type": "arrow",
+ },
+ ],
+ },
+ },
+ "id171" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id172",
+ "type": "arrow",
+ },
+ ],
+ },
+ },
+ "id172" => Delta {
+ "deleted": {
+ "endBinding": {
+ "elementId": "id175",
+ "fixedPoint": [
+ "0.50000",
+ 1,
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "height": "102.35417",
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "101.77517",
+ "102.35417",
+ ],
+ ],
+ "startBinding": null,
+ "y": 0,
+ },
+ "inserted": {
+ "endBinding": {
+ "elementId": "id171",
+ "focus": "0.00990",
+ "gap": 1,
+ },
+ "height": "0.98586",
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ "-0.98586",
+ ],
+ ],
+ "startBinding": {
+ "elementId": "id170",
+ "focus": "0.02970",
+ "gap": 1,
+ },
+ "y": "0.99364",
+ },
+ },
+ "id175" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id172",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id170" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id171" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id172": true,
+ },
+ "selectedLinearElementId": "id172",
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id172" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] number of elements 1`] = `4`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] number of renders 1`] = `21`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id167": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id167": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id165",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 9,
+ "width": 100,
+ "x": 150,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id166",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 9,
+ "width": 100,
+ "x": 150,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id167",
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 30,
+ "width": 50,
+ "x": 200,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id167" => Delta {
+ "deleted": {
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 0,
+ ],
+ ],
+ },
+ "inserted": {
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id165" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id167",
+ "type": "arrow",
+ },
+ ],
+ },
+ },
+ "id166" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id167",
+ "type": "arrow",
+ },
+ ],
+ },
+ },
+ "id167" => Delta {
+ "deleted": {
+ "endBinding": null,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "startBinding": null,
+ },
+ "inserted": {
+ "endBinding": {
+ "elementId": "id166",
+ "focus": -0,
+ "gap": 1,
+ },
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 0,
+ ],
+ ],
+ "startBinding": {
+ "elementId": "id165",
+ "focus": 0,
+ "gap": 1,
+ },
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id165" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id166" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id167": true,
+ },
+ "selectedLinearElementId": "id167",
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id167" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] number of renders 1`] = `23`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added arrow when it's bindable elements are added through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added arrow when it's bindable elements are added through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": null,
+ "endBinding": {
+ "elementId": "id177",
+ "fixedPoint": [
+ "0.50000",
+ 1,
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": "1.30038",
+ "id": "id178",
+ "index": "Zz",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ "1.30038",
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id176",
+ "fixedPoint": [
+ 1,
+ "0.50000",
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 11,
+ "width": "98.58579",
+ "x": "0.70711",
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added arrow when it's bindable elements are added through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id178",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id176",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added arrow when it's bindable elements are added through the history > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id178",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id177",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added arrow when it's bindable elements are added through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id176" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id177" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id178" => Delta {
+ "deleted": {
+ "endBinding": {
+ "elementId": "id177",
+ "fixedPoint": [
+ "0.50000",
+ 1,
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "startBinding": {
+ "elementId": "id176",
+ "fixedPoint": [
+ 1,
+ "0.50000",
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ },
+ "inserted": {
+ "endBinding": null,
+ "startBinding": null,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added arrow when it's bindable elements are added through the history > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added arrow when it's bindable elements are added through the history > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added bindable elements when it's arrow is added through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added bindable elements when it's arrow is added through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": null,
+ "endBinding": {
+ "elementId": "id180",
+ "fixedPoint": [
+ 1,
+ "0.50000",
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": "1.30038",
+ "id": "id181",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ "1.30038",
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id179",
+ "fixedPoint": [
+ "0.50000",
+ 1,
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 11,
+ "width": "98.58579",
+ "x": "0.70711",
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added bindable elements when it's arrow is added through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id181",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id179",
+ "index": "a0V",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 12,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added bindable elements when it's arrow is added through the history > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id181",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id180",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 11,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added bindable elements when it's arrow is added through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id181" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": null,
+ "endBinding": {
+ "elementId": "id180",
+ "fixedPoint": [
+ 1,
+ "0.50000",
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": "11.27227",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ "11.27227",
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id179",
+ "fixedPoint": [
+ "0.50000",
+ 1,
+ ],
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": "98.58579",
+ "x": "0.70711",
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id179" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id181",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id180" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id181",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added bindable elements when it's arrow is added through the history > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added bindable elements when it's arrow is added through the history > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should unbind remotely deleted bindable elements from arrow when the arrow is added through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should unbind remotely deleted bindable elements from arrow when the arrow is added through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id182",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should unbind remotely deleted bindable elements from arrow when the arrow is added through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id183",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should unbind remotely deleted bindable elements from arrow when the arrow is added through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id182" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id183" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should unbind remotely deleted bindable elements from arrow when the arrow is added through the history > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should unbind remotely deleted bindable elements from arrow when the arrow is added through the history > [end of test] number of renders 1`] = `4`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id186": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id186",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id184",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id186",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id185",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": 500,
+ "y": -500,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id185",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": "374.05754",
+ "id": "id186",
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "502.78936",
+ "-374.05754",
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id184",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 10,
+ "width": "502.78936",
+ "x": "-0.83465",
+ "y": "-36.58211",
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id184" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id185" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id186": true,
+ },
+ "selectedLinearElementId": "id186",
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id186" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id185",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id184",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id184" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id186",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id185" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id186",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the container is added through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the container is added through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id153",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id151",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the container is added through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id152",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 6,
+ "verticalAlign": "top",
+ "width": 100,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the container is added through the history > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id151",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id153",
+ "index": "a2",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 11,
+ "verticalAlign": "top",
+ "width": 30,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the container is added through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id151" => Delta {
+ "deleted": {
+ "isDeleted": false,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 10,
+ "y": 10,
+ },
+ },
+ "id152" => Delta {
+ "deleted": {
+ "containerId": null,
+ },
+ "inserted": {
+ "containerId": null,
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the container is added through the history > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the container is added through the history > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the text is added through history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the text is added through history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id156",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id154",
+ "index": "Zz",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 11,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the text is added through history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id154",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id155",
+ "index": "a0",
+ "isDeleted": true,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 9,
+ "verticalAlign": "top",
+ "width": 100,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the text is added through history > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id154",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id156",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 11,
+ "verticalAlign": "top",
+ "width": 30,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the text is added through history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id155" => Delta {
+ "deleted": {
+ "containerId": "id154",
+ "isDeleted": true,
+ },
+ "inserted": {
+ "containerId": null,
+ "isDeleted": false,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {
+ "id154" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id155",
+ "type": "text",
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the text is added through history > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the text is added through history > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the container got bound to a different text in the meantime > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the container got bound to a different text in the meantime > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id143",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id141",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 10,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the container got bound to a different text in the meantime > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id141",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id143",
+ "index": "a0V",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 7,
+ "verticalAlign": "top",
+ "width": 30,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the container got bound to a different text in the meantime > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id142",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 9,
+ "verticalAlign": "top",
+ "width": 80,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the container got bound to a different text in the meantime > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id141" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id143",
+ "type": "text",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id142",
+ "type": "text",
+ },
+ ],
+ },
+ },
+ "id142" => Delta {
+ "deleted": {
+ "containerId": null,
+ },
+ "inserted": {
+ "containerId": "id141",
+ },
+ },
+ "id143" => Delta {
+ "deleted": {
+ "containerId": "id141",
+ },
+ "inserted": {
+ "containerId": null,
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the container got bound to a different text in the meantime > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the container got bound to a different text in the meantime > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the text got bound to a different container in the meantime > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the text got bound to a different container in the meantime > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id144",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the text got bound to a different container in the meantime > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id145",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 60,
+ "id": "id146",
+ "index": "a0V",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 50,
+ "x": 100,
+ "y": 100,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the text got bound to a different container in the meantime > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id146",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id145",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que
+pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 13,
+ "verticalAlign": "top",
+ "width": 40,
+ "x": 105,
+ "y": 105,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the text got bound to a different container in the meantime > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id144" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id145",
+ "type": "text",
+ },
+ ],
+ },
+ },
+ "id145" => Delta {
+ "deleted": {
+ "containerId": "id146",
+ },
+ "inserted": {
+ "containerId": "id144",
+ },
+ },
+ "id146" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id145",
+ "type": "text",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the text got bound to a different container in the meantime > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the text got bound to a different container in the meantime > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and there no conflicting updates in the meantime > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and there no conflicting updates in the meantime > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id139",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 9,
+ "width": 100,
+ "x": 35,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and there no conflicting updates in the meantime > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id140",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 10,
+ "verticalAlign": "top",
+ "width": 80,
+ "x": 40,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and there no conflicting updates in the meantime > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id139" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id140",
+ "type": "text",
+ },
+ ],
+ },
+ },
+ "id140" => Delta {
+ "deleted": {
+ "containerId": null,
+ },
+ "inserted": {
+ "containerId": "id139",
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and there no conflicting updates in the meantime > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and there no conflicting updates in the meantime > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added bound text when it's container is added through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added bound text when it's container is added through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id148",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id147",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added bound text when it's container is added through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id147",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id148",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 12,
+ "verticalAlign": "top",
+ "width": 80,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added bound text when it's container is added through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id147" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id148" => Delta {
+ "deleted": {
+ "containerId": "id147",
+ },
+ "inserted": {
+ "containerId": null,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added bound text when it's container is added through the history > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added bound text when it's container is added through the history > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added container when it's bound text is added through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added container when it's bound text is added through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id150",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id149",
+ "index": "Zz",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 11,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added container when it's bound text is added through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id149",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id150",
+ "index": "a0",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 8,
+ "verticalAlign": "top",
+ "width": 80,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added container when it's bound text is added through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id150" => Delta {
+ "deleted": {
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id149",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "index": "a0",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "verticalAlign": "top",
+ "width": 80,
+ "x": 15,
+ "y": 15,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id149" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id150",
+ "type": "text",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added container when it's bound text is added through the history > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added container when it's bound text is added through the history > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw bound text to match container dimensions when the bound text is updated through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw bound text to match container dimensions when the bound text is updated through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id164",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id163",
+ "index": "Zz",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw bound text to match container dimensions when the bound text is updated through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id163",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id164",
+ "index": "a0",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 7,
+ "verticalAlign": "top",
+ "width": 80,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw bound text to match container dimensions when the bound text is updated through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id164" => Delta {
+ "deleted": {
+ "angle": 0,
+ "x": 15,
+ "y": 15,
+ },
+ "inserted": {
+ "angle": 0,
+ "x": 15,
+ "y": 15,
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw bound text to match container dimensions when the bound text is updated through the history > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw bound text to match container dimensions when the bound text is updated through the history > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw remotely added bound text when it's container is updated through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw remotely added bound text when it's container is updated through the history > [end of test] element 0 1`] = `
+{
+ "angle": 90,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id162",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id161",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": 200,
+ "y": 200,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw remotely added bound text when it's container is updated through the history > [end of test] element 1 1`] = `
+{
+ "angle": 90,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id161",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id162",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 6,
+ "verticalAlign": "top",
+ "width": 80,
+ "x": 205,
+ "y": 205,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw remotely added bound text when it's container is updated through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id161" => Delta {
+ "deleted": {
+ "angle": 90,
+ "x": 200,
+ "y": 200,
+ },
+ "inserted": {
+ "angle": 0,
+ "x": 10,
+ "y": 10,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw remotely added bound text when it's container is updated through the history > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw remotely added bound text when it's container is updated through the history > [end of test] number of renders 1`] = `10`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted bound text from container when the container is added through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted bound text from container when the container is added through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id157",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted bound text from container when the container is added through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id157",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id158",
+ "index": "a1",
+ "isDeleted": true,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 3,
+ "verticalAlign": "top",
+ "width": 100,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted bound text from container when the container is added through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id157" => Delta {
+ "deleted": {
+ "boundElements": [],
+ "isDeleted": false,
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "id158",
+ "type": "text",
+ },
+ ],
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted bound text from container when the container is added through the history > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted bound text from container when the container is added through the history > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted container from bound text when the text is added through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted container from bound text when the text is added through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id160",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id159",
+ "index": "Zz",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted container from bound text when the text is added through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id160",
+ "index": "a0",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "que pasa",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "que pasa",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 8,
+ "verticalAlign": "top",
+ "width": 100,
+ "x": 15,
+ "y": 15,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted container from bound text when the text is added through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id160" => Delta {
+ "deleted": {
+ "containerId": null,
+ "isDeleted": false,
+ },
+ "inserted": {
+ "containerId": "id159",
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted container from bound text when the text is added through the history > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted container from bound text when the text is added through the history > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > conflicts in frames and their children > should not rebind frame child with frame when frame was remotely deleted and frame child is added back through the history > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in frames and their children > should not rebind frame child with frame when frame was remotely deleted and frame child is added back through the history > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id188",
+ "index": "Zz",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 10,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in frames and their children > should not rebind frame child with frame when frame was remotely deleted and frame child is added back through the history > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 500,
+ "id": "id187",
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "name": null,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "frame",
+ "updated": 1,
+ "version": 3,
+ "width": 500,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in frames and their children > should not rebind frame child with frame when frame was remotely deleted and frame child is added back through the history > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id188" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "Zz",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id188" => Delta {
+ "deleted": {
+ "frameId": "id187",
+ },
+ "inserted": {
+ "frameId": null,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > conflicts in frames and their children > should not rebind frame child with frame when frame was remotely deleted and frame child is added back through the history > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > conflicts in frames and their children > should not rebind frame child with frame when frame was remotely deleted and frame child is added back through the history > [end of test] number of renders 1`] = `13`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when editing group contains only remotely deleted elements > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id116": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when editing group contains only remotely deleted elements > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "id": "id115",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when editing group contains only remotely deleted elements > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "id": "id116",
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 100,
+ "y": 100,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when editing group contains only remotely deleted elements > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id115": true,
+ "id116": true,
+ },
+ "selectedGroupIds": {
+ "A": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id115" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id116" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": 100,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "A",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id115": true,
+ },
+ "selectedGroupIds": {
+ "A": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": null,
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "editingGroupId": "A",
+ "selectedElementIds": {
+ "id116": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when editing group contains only remotely deleted elements > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when editing group contains only remotely deleted elements > [end of test] number of renders 1`] = `13`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when element changes relate only to remotely deleted elements > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#ffc9c9",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementBackground",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id103": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when element changes relate only to remotely deleted elements > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id101",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when element changes relate only to remotely deleted elements > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "#ffc9c9",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id102",
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 10,
+ "x": 20,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when element changes relate only to remotely deleted elements > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "#ffc9c9",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id103",
+ "index": "a2",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 10,
+ "x": 50,
+ "y": 50,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when element changes relate only to remotely deleted elements > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id101": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id101" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id102": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id101": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id102" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "#ffc9c9",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 20,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id102" => Delta {
+ "deleted": {
+ "backgroundColor": "#ffc9c9",
+ },
+ "inserted": {
+ "backgroundColor": "transparent",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id103": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id102": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id103" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "#ffc9c9",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id103" => Delta {
+ "deleted": {
+ "x": 50,
+ "y": 50,
+ },
+ "inserted": {
+ "x": 30,
+ "y": 30,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when element changes relate only to remotely deleted elements > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when element changes relate only to remotely deleted elements > [end of test] number of renders 1`] = `17`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected elements relate only to remotely deleted elements > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id106": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id106": true,
+ "id107": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected elements relate only to remotely deleted elements > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id105",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected elements relate only to remotely deleted elements > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id106",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 20,
+ "y": 20,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected elements relate only to remotely deleted elements > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id107",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 30,
+ "y": 30,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected elements relate only to remotely deleted elements > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id105": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id105" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id106" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id107" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 30,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id106": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id105": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id107": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected elements relate only to remotely deleted elements > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected elements relate only to remotely deleted elements > [end of test] number of renders 1`] = `15`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id111": true,
+ "id112": true,
+ "id113": true,
+ "id114": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "A": true,
+ "B": true,
+ },
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "id": "id111",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "id": "id112",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "B",
+ ],
+ "height": 100,
+ "id": "id113",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "B",
+ ],
+ "height": 100,
+ "id": "id114",
+ "index": "a3",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id111": true,
+ "id112": true,
+ },
+ "selectedGroupIds": {
+ "A": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id113": true,
+ "id114": true,
+ },
+ "selectedGroupIds": {
+ "B": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] number of elements 1`] = `4`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] number of renders 1`] = `15`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id119": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id119",
+ "index": "a0",
+ "isDeleted": true,
+ "lastCommittedPoint": [
+ 10,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 7,
+ "width": 10,
+ "x": -10,
+ "y": -10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id119": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id119" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 10,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 10,
+ "x": -10,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedLinearElementId": "id119",
+ },
+ "inserted": {
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingLinearElementId": "id119",
+ },
+ "inserted": {
+ "editingLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingLinearElementId": null,
+ },
+ "inserted": {
+ "editingLinearElementId": "id119",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] number of elements 1`] = `1`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] number of renders 1`] = `10`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when when element change relates to remotely deleted element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#ffc9c9",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementBackground",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when when element change relates to remotely deleted element > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "#ffec99",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id100",
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when when element change relates to remotely deleted element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id100": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id100" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "#ffec99",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id100" => Delta {
+ "deleted": {
+ "backgroundColor": "#ffec99",
+ },
+ "inserted": {
+ "backgroundColor": "transparent",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when when element change relates to remotely deleted element > [end of test] number of elements 1`] = `1`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when when element change relates to remotely deleted element > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced all indices > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced all indices > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id125",
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": 20,
+ "y": 20,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced all indices > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id126",
+ "index": "a3V",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 30,
+ "y": 30,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced all indices > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id124",
+ "index": "a4",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced all indices > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id125" => Delta {
+ "deleted": {
+ "index": "a1",
+ },
+ "inserted": {
+ "index": "a3",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id125": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id124" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a4",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 10,
+ "y": 10,
+ },
+ },
+ "id125" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a3",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 20,
+ "y": 20,
+ },
+ },
+ "id126" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a3V",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 30,
+ "y": 30,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced all indices > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced all indices > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced changed indices > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced changed indices > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id120",
+ "index": "Zx",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced changed indices > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id122",
+ "index": "Zy",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 100,
+ "x": 30,
+ "y": 30,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced changed indices > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id121",
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 100,
+ "x": 20,
+ "y": 20,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced changed indices > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id121" => Delta {
+ "deleted": {
+ "index": "a1",
+ },
+ "inserted": {
+ "index": "Zz",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id121": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id120" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "Zx",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 10,
+ "y": 10,
+ },
+ },
+ "id121" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "Zz",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 20,
+ "y": 20,
+ },
+ },
+ "id122" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "Zy",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 30,
+ "y": 30,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced changed indices > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced changed indices > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress dragging > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id133": true,
+ "id134": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id133": true,
+ "id134": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress dragging > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id133",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 9,
+ "width": 10,
+ "x": 90,
+ "y": 90,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress dragging > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id134",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 9,
+ "width": 10,
+ "x": 110,
+ "y": 110,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress dragging > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id138",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#a5d8ff",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress dragging > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id133": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id133" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id134": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id133": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id134" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id133": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id134": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id134": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id133" => Delta {
+ "deleted": {
+ "x": 90,
+ "y": 90,
+ },
+ "inserted": {
+ "x": 10,
+ "y": 10,
+ },
+ },
+ "id134" => Delta {
+ "deleted": {
+ "x": 110,
+ "y": 110,
+ },
+ "inserted": {
+ "x": 30,
+ "y": 30,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress dragging > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress dragging > [end of test] number of renders 1`] = `25`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress freedraw > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "freedraw",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress freedraw > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id128",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 50,
+ 50,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 20,
+ 20,
+ ],
+ [
+ 50,
+ 50,
+ ],
+ [
+ 50,
+ 50,
+ ],
+ ],
+ "pressures": [
+ 0,
+ 0,
+ 0,
+ 0,
+ ],
+ "roughness": 1,
+ "roundness": null,
+ "simulatePressure": false,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "updated": 1,
+ "version": 7,
+ "width": 50,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress freedraw > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id129",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#a5d8ff",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress freedraw > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id128" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 50,
+ 50,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 20,
+ 20,
+ ],
+ [
+ 50,
+ 50,
+ ],
+ [
+ 50,
+ 50,
+ ],
+ ],
+ "pressures": [
+ 0,
+ 0,
+ 0,
+ 0,
+ ],
+ "roughness": 1,
+ "roundness": null,
+ "simulatePressure": false,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "width": 50,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress freedraw > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress freedraw > [end of test] number of renders 1`] = `8`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress resizing > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id130": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress resizing > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 90,
+ "id": "id130",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 9,
+ "width": 90,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress resizing > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id132",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#a5d8ff",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress resizing > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id130": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id130" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id130" => Delta {
+ "deleted": {
+ "height": 90,
+ "width": 90,
+ },
+ "inserted": {
+ "height": 10,
+ "width": 10,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress resizing > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress resizing > [end of test] number of renders 1`] = `13`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different elements > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#ffc9c9",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementBackground",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id87": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different elements > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id87",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different elements > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "#ffc9c9",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id88",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#a5d8ff",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different elements > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id87" => Delta {
+ "deleted": {
+ "backgroundColor": "transparent",
+ },
+ "inserted": {
+ "backgroundColor": "#ffc9c9",
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id87": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id87" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different elements > [end of test] number of elements 1`] = `2`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different elements > [end of test] number of renders 1`] = `10`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different properties > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#ffc9c9",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementBackground",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id89": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different properties > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "#ffc9c9",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id89",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#ffec99",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different properties > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id89": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id89" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id89" => Delta {
+ "deleted": {
+ "backgroundColor": "#ffc9c9",
+ },
+ "inserted": {
+ "backgroundColor": "transparent",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different properties > [end of test] number of elements 1`] = `1`;
+
+exports[`history > multiplayer undo/redo > should not override remote changes on different properties > [end of test] number of renders 1`] = `9`;
+
+exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ "B",
+ ],
+ "height": 100,
+ "id": "id94",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 6,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ "B",
+ ],
+ "height": 100,
+ "id": "id95",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 6,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "B",
+ ],
+ "height": 100,
+ "id": "id96",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "B",
+ ],
+ "height": 100,
+ "id": "id97",
+ "index": "a3",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id94" => Delta {
+ "deleted": {
+ "groupIds": [
+ "A",
+ "B",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id95" => Delta {
+ "deleted": {
+ "groupIds": [
+ "A",
+ "B",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] number of elements 1`] = `4`;
+
+exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] number of renders 1`] = `8`;
+
+exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id98": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 30,
+ "id": "id98",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 30,
+ 30,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 5,
+ 5,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ [
+ 15,
+ 15,
+ ],
+ [
+ 20,
+ 20,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 13,
+ "width": 30,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id98": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id98" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 10,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id98" => Delta {
+ "deleted": {
+ "height": 30,
+ "lastCommittedPoint": [
+ 30,
+ 30,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 5,
+ 5,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ [
+ 15,
+ 15,
+ ],
+ [
+ 20,
+ 20,
+ ],
+ ],
+ "width": 30,
+ },
+ "inserted": {
+ "height": 10,
+ "lastCommittedPoint": [
+ 10,
+ 10,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "width": 10,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedLinearElementId": "id98",
+ },
+ "inserted": {
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] number of elements 1`] = `1`;
+
+exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] number of renders 1`] = `15`;
+
+exports[`history > multiplayer undo/redo > should redistribute deltas when element gets removed locally but is restored remotely > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should redistribute deltas when element gets removed locally but is restored remotely > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "#ffec99",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id99",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should redistribute deltas when element gets removed locally but is restored remotely > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id99": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id99" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "#ffec99",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id99": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id99" => Delta {
+ "deleted": {
+ "isDeleted": false,
+ },
+ "inserted": {
+ "isDeleted": false,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should redistribute deltas when element gets removed locally but is restored remotely > [end of test] number of elements 1`] = `1`;
+
+exports[`history > multiplayer undo/redo > should redistribute deltas when element gets removed locally but is restored remotely > [end of test] number of renders 1`] = `11`;
+
+exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 126,
+ "id": "KPrBI4g_v9qUB1XxYLgSz",
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 157,
+ "x": 600,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 129,
+ "id": "u2JGnnmoJ0VATV4vCNJE5",
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "updated": 1,
+ "version": 4,
+ "width": 124,
+ "x": 1152,
+ "y": 516,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": true,
+ "endArrowhead": null,
+ "endBinding": {
+ "elementId": "u2JGnnmoJ0VATV4vCNJE5",
+ "fixedPoint": [
+ "0.49919",
+ "-0.03875",
+ ],
+ "focus": "-0.00161",
+ "gap": "3.53708",
+ },
+ "endIsSpecial": false,
+ "fillStyle": "solid",
+ "fixedSegments": [],
+ "frameId": null,
+ "groupIds": [],
+ "height": "236.10000",
+ "id": "6Rm4g567UQM4WjLwej2Vc",
+ "index": "a2",
+ "isDeleted": true,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "178.90000",
+ 0,
+ ],
+ [
+ "178.90000",
+ "236.10000",
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "KPrBI4g_v9qUB1XxYLgSz",
+ "fixedPoint": [
+ "1.03185",
+ "0.49921",
+ ],
+ "focus": "-0.00159",
+ "gap": 5,
+ },
+ "startIsSpecial": false,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 3,
+ "width": "178.90000",
+ "x": 1035,
+ "y": "274.90000",
+}
+`;
+
+exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "6Rm4g567UQM4WjLwej2Vc" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": true,
+ "endArrowhead": null,
+ "endBinding": {
+ "elementId": "u2JGnnmoJ0VATV4vCNJE5",
+ "fixedPoint": [
+ "0.49919",
+ "-0.03875",
+ ],
+ "focus": "-0.00161",
+ "gap": "3.53708",
+ },
+ "endIsSpecial": false,
+ "fillStyle": "solid",
+ "fixedSegments": [],
+ "frameId": null,
+ "groupIds": [],
+ "height": "236.10000",
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "178.90000",
+ 0,
+ ],
+ [
+ "178.90000",
+ "236.10000",
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "KPrBI4g_v9qUB1XxYLgSz",
+ "fixedPoint": [
+ "1.03185",
+ "0.49921",
+ ],
+ "focus": "-0.00159",
+ "gap": 5,
+ },
+ "startIsSpecial": false,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": "178.90000",
+ "x": 1035,
+ "y": "274.90000",
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {
+ "KPrBI4g_v9qUB1XxYLgSz" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "6Rm4g567UQM4WjLwej2Vc",
+ "type": "arrow",
+ },
+ ],
+ },
+ },
+ "u2JGnnmoJ0VATV4vCNJE5" => Delta {
+ "deleted": {
+ "boundElements": [],
+ },
+ "inserted": {
+ "boundElements": [
+ {
+ "id": "6Rm4g567UQM4WjLwej2Vc",
+ "type": "arrow",
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "KPrBI4g_v9qUB1XxYLgSz" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 126,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 157,
+ "x": 600,
+ "y": 0,
+ },
+ },
+ "u2JGnnmoJ0VATV4vCNJE5" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 129,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "width": 124,
+ "x": 1152,
+ "y": 516,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end of test] number of elements 1`] = `3`;
+
+exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end of test] number of renders 1`] = `8`;
+
+exports[`history > multiplayer undo/redo > should update history entries after remote changes on the same properties > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#a5d8ff",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementBackground",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id90": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > multiplayer undo/redo > should update history entries after remote changes on the same properties > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id90",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 13,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > multiplayer undo/redo > should update history entries after remote changes on the same properties > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id90" => Delta {
+ "deleted": {
+ "backgroundColor": "#d0bfff",
+ },
+ "inserted": {
+ "backgroundColor": "#ffec99",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id90" => Delta {
+ "deleted": {
+ "backgroundColor": "transparent",
+ },
+ "inserted": {
+ "backgroundColor": "#d0bfff",
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id90": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id90" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > multiplayer undo/redo > should update history entries after remote changes on the same properties > [end of test] number of elements 1`] = `1`;
+
+exports[`history > multiplayer undo/redo > should update history entries after remote changes on the same properties > [end of test] number of renders 1`] = `15`;
+
+exports[`history > singleplayer undo/redo > remounting undo/redo buttons should initialize undo/redo state correctly > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": false,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > remounting undo/redo buttons should initialize undo/redo state correctly > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "A",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > remounting undo/redo buttons should initialize undo/redo state correctly > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id86",
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 10,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > remounting undo/redo buttons should initialize undo/redo state correctly > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id86": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id86" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > singleplayer undo/redo > remounting undo/redo buttons should initialize undo/redo state correctly > [end of test] number of elements 1`] = `2`;
+
+exports[`history > singleplayer undo/redo > remounting undo/redo buttons should initialize undo/redo state correctly > [end of test] number of renders 1`] = `11`;
+
+exports[`history > singleplayer undo/redo > should clear the redo stack on elements change > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id14": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should clear the redo stack on elements change > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id13",
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should clear the redo stack on elements change > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id14",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 10,
+ "x": 20,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should clear the redo stack on elements change > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id14": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id14" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 20,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should clear the redo stack on elements change > [end of test] number of elements 1`] = `2`;
+
+exports[`history > singleplayer undo/redo > should clear the redo stack on elements change > [end of test] number of renders 1`] = `8`;
+
+exports[`history > singleplayer undo/redo > should create entry when selecting freedraw > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "freedraw",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#e03131",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementStroke",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create entry when selecting freedraw > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id32",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 10,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create entry when selecting freedraw > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id33",
+ "index": "a1",
+ "isDeleted": true,
+ "lastCommittedPoint": [
+ 50,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "pressures": [
+ 0,
+ 0,
+ 0,
+ ],
+ "roughness": 1,
+ "roundness": null,
+ "simulatePressure": false,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "updated": 1,
+ "version": 5,
+ "width": 50,
+ "x": 60,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create entry when selecting freedraw > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id34",
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 50,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "pressures": [
+ 0,
+ 0,
+ 0,
+ ],
+ "roughness": 1,
+ "roundness": null,
+ "simulatePressure": false,
+ "strokeColor": "#e03131",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "updated": 1,
+ "version": 4,
+ "width": 50,
+ "x": 150,
+ "y": -10,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create entry when selecting freedraw > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id32": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id32" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id32": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id34" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 50,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "pressures": [
+ 0,
+ 0,
+ 0,
+ ],
+ "roughness": 1,
+ "roundness": null,
+ "simulatePressure": false,
+ "strokeColor": "#e03131",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "width": 50,
+ "x": 150,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create entry when selecting freedraw > [end of test] number of elements 1`] = `3`;
+
+exports[`history > singleplayer undo/redo > should create entry when selecting freedraw > [end of test] number of renders 1`] = `12`;
+
+exports[`history > singleplayer undo/redo > should create new history entry on scene import via drag&drop > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": -50,
+ "scrollY": -50,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": false,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#000",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create new history entry on scene import via drag&drop > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "A",
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create new history entry on scene import via drag&drop > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "B",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create new history entry on scene import via drag&drop > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "viewBackgroundColor": "#000",
+ },
+ "inserted": {
+ "viewBackgroundColor": "#FFF",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "A" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "isDeleted": false,
+ },
+ },
+ },
+ "removed": Map {
+ "B" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should create new history entry on scene import via drag&drop > [end of test] number of elements 1`] = `2`;
+
+exports[`history > singleplayer undo/redo > should create new history entry on scene import via drag&drop > [end of test] number of renders 1`] = `6`;
+
+exports[`history > singleplayer undo/redo > should disable undo/redo buttons when stacks empty > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id84": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": false,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should disable undo/redo buttons when stacks empty > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "A",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should disable undo/redo buttons when stacks empty > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id84",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 10,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should disable undo/redo buttons when stacks empty > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id84": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id84" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should disable undo/redo buttons when stacks empty > [end of test] number of elements 1`] = `2`;
+
+exports[`history > singleplayer undo/redo > should disable undo/redo buttons when stacks empty > [end of test] number of renders 1`] = `7`;
+
+exports[`history > singleplayer undo/redo > should end up with no history entry after initializing scene > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id19": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": false,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": true,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should end up with no history entry after initializing scene > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "A",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should end up with no history entry after initializing scene > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id19",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 10,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should end up with no history entry after initializing scene > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id19": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id19" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should end up with no history entry after initializing scene > [end of test] number of elements 1`] = `2`;
+
+exports[`history > singleplayer undo/redo > should end up with no history entry after initializing scene > [end of test] number of renders 1`] = `7`;
+
+exports[`history > singleplayer undo/redo > should iterate through the history when selection changes do not produce visible change > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id15": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should iterate through the history when selection changes do not produce visible change > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id15",
+ "index": "a0",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should iterate through the history when selection changes do not produce visible change > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id15": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id15": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id15": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id15" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+ "undoStack": [],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should iterate through the history when selection changes do not produce visible change > [end of test] number of elements 1`] = `1`;
+
+exports[`history > singleplayer undo/redo > should iterate through the history when selection changes do not produce visible change > [end of test] number of renders 1`] = `13`;
+
+exports[`history > singleplayer undo/redo > should not clear the redo stack on standalone appstate change > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id8": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not clear the redo stack on standalone appstate change > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id7",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not clear the redo stack on standalone appstate change > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id8",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 10,
+ "x": 20,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not clear the redo stack on standalone appstate change > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id7": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id7" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id7": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id7": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id8": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id7": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id8" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 20,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not clear the redo stack on standalone appstate change > [end of test] number of elements 1`] = `2`;
+
+exports[`history > singleplayer undo/redo > should not clear the redo stack on standalone appstate change > [end of test] number of renders 1`] = `12`;
+
+exports[`history > singleplayer undo/redo > should not collapse when applying corrupted history entry > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not collapse when applying corrupted history entry > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not collapse when applying corrupted history entry > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not collapse when applying corrupted history entry > [end of test] number of elements 1`] = `1`;
+
+exports[`history > singleplayer undo/redo > should not collapse when applying corrupted history entry > [end of test] number of renders 1`] = `4`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no appstate changes > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ "id2": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "A": true,
+ },
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no appstate changes > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "id": "id1",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no appstate changes > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "id": "id2",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no appstate changes > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ "id2": true,
+ },
+ "selectedGroupIds": {
+ "A": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no appstate changes > [end of test] number of elements 1`] = `2`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no appstate changes > [end of test] number of renders 1`] = `7`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no elements changes > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no elements changes > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id5",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no elements changes > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id6",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no elements changes > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id5" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id6" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no elements changes > [end of test] number of elements 1`] = `2`;
+
+exports[`history > singleplayer undo/redo > should not end up with history entry when there are no elements changes > [end of test] number of renders 1`] = `5`;
+
+exports[`history > singleplayer undo/redo > should not override appstate changes when redo stack is not cleared > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#a5d8ff",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementBackground",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id11": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id11": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not override appstate changes when redo stack is not cleared > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id11",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 11,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not override appstate changes when redo stack is not cleared > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id11" => Delta {
+ "deleted": {
+ "backgroundColor": "#ffc9c9",
+ },
+ "inserted": {
+ "backgroundColor": "#a5d8ff",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id11" => Delta {
+ "deleted": {
+ "backgroundColor": "transparent",
+ },
+ "inserted": {
+ "backgroundColor": "#ffc9c9",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id11": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id11": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id11" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should not override appstate changes when redo stack is not cleared > [end of test] number of elements 1`] = `1`;
+
+exports[`history > singleplayer undo/redo > should not override appstate changes when redo stack is not cleared > [end of test] number of renders 1`] = `15`;
+
+exports[`history > singleplayer undo/redo > should support appstate name or viewBackgroundColor change > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#000",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support appstate name or viewBackgroundColor change > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "name": "New name",
+ },
+ "inserted": {
+ "name": "Old name",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "viewBackgroundColor": "#000",
+ },
+ "inserted": {
+ "viewBackgroundColor": "#FFF",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support appstate name or viewBackgroundColor change > [end of test] number of elements 1`] = `0`;
+
+exports[`history > singleplayer undo/redo > should support appstate name or viewBackgroundColor change > [end of test] number of renders 1`] = `8`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id56": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id61": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id57",
+ "type": "text",
+ },
+ {
+ "id": "id61",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id56",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id56",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id57",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "center",
+ "type": "text",
+ "updated": 1,
+ "version": 6,
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id61",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id58",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id58",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id61",
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id56",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 10,
+ "width": "98.58579",
+ "x": "0.70711",
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id61": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id61" => Delta {
+ "deleted": {
+ "isDeleted": false,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ },
+ "inserted": {
+ "isDeleted": true,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ },
+ },
+ },
+ "updated": Map {
+ "id56" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id61",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id58" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id61",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id56" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id57" => Delta {
+ "deleted": {
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "left",
+ "type": "text",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id58" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id56": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id57": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id57": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id56" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id57",
+ "type": "text",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id57" => Delta {
+ "deleted": {
+ "containerId": "id56",
+ "height": 25,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+ },
+ "inserted": {
+ "containerId": null,
+ "height": 100,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id61": true,
+ },
+ "selectedLinearElementId": "id61",
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id56": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id61" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id58",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id56",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id56" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id61",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id58" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id61",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of elements 1`] = `4`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of renders 1`] = `12`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id50": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id55": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id51",
+ "type": "text",
+ },
+ {
+ "id": "id55",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id50",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id50",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id51",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "center",
+ "type": "text",
+ "updated": 1,
+ "version": 8,
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id55",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id52",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id52",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id55",
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id50",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 10,
+ "width": "98.58579",
+ "x": "0.70711",
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id50" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id51" => Delta {
+ "deleted": {
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "left",
+ "type": "text",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id52" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id50": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id51": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id51": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id50" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id51",
+ "type": "text",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id51" => Delta {
+ "deleted": {
+ "containerId": "id50",
+ "height": 25,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+ },
+ "inserted": {
+ "containerId": null,
+ "height": 100,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id55": true,
+ },
+ "selectedLinearElementId": "id55",
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id50": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id55" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id52",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id50",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id50" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id55",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id52" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id55",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of elements 1`] = `4`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of renders 1`] = `12`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id62": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id67": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id63",
+ "type": "text",
+ },
+ {
+ "id": "id67",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id62",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 12,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id62",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id63",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "center",
+ "type": "text",
+ "updated": 1,
+ "version": 12,
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id67",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id64",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 9,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id64",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id67",
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id62",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 10,
+ "width": "98.58579",
+ "x": "0.70711",
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id62" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id63" => Delta {
+ "deleted": {
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "left",
+ "type": "text",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id64" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id62": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id63": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id63": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id62" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id63",
+ "type": "text",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id63" => Delta {
+ "deleted": {
+ "containerId": "id62",
+ "height": 25,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+ },
+ "inserted": {
+ "containerId": null,
+ "height": 100,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id67": true,
+ },
+ "selectedLinearElementId": "id67",
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id62": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id67" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id64",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id62",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id62" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id67",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id64" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id67",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of elements 1`] = `4`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of renders 1`] = `20`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id68": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id73",
+ "type": "arrow",
+ },
+ {
+ "id": "id69",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id68",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id68",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id69",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "center",
+ "type": "text",
+ "updated": 1,
+ "version": 8,
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id73",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id70",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id70",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id73",
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id68",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 10,
+ "width": "98.58579",
+ "x": "0.70711",
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id68": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id68" => Delta {
+ "deleted": {
+ "isDeleted": false,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id69" => Delta {
+ "deleted": {
+ "isDeleted": false,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id73" => Delta {
+ "deleted": {
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "startBinding": {
+ "elementId": "id68",
+ "focus": 0,
+ "gap": 1,
+ },
+ },
+ "inserted": {
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "startBinding": null,
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id68" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id69" => Delta {
+ "deleted": {
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "left",
+ "type": "text",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id70" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id68": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id69": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id69": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id68" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id69",
+ "type": "text",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id69" => Delta {
+ "deleted": {
+ "containerId": "id68",
+ "height": 25,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+ },
+ "inserted": {
+ "containerId": null,
+ "height": 100,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id73": true,
+ },
+ "selectedLinearElementId": "id73",
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id68": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id73" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id70",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id68",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id68" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id73",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id70" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id73",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id68": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id73": true,
+ },
+ "selectedLinearElementId": "id73",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] number of elements 1`] = `4`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `14`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id75": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id75": true,
+ "id77": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id80",
+ "type": "arrow",
+ },
+ {
+ "id": "id76",
+ "type": "text",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id75",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 100,
+ "x": -100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": "id75",
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 25,
+ "id": "id76",
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "center",
+ "type": "text",
+ "updated": 1,
+ "version": 8,
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id80",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id77",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 100,
+ "x": 100,
+ "y": -50,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id77",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id80",
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "98.58579",
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id75",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 11,
+ "width": "98.58579",
+ "x": "0.70711",
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id75": true,
+ "id77": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id75" => Delta {
+ "deleted": {
+ "isDeleted": false,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id76" => Delta {
+ "deleted": {
+ "isDeleted": false,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id77" => Delta {
+ "deleted": {
+ "isDeleted": false,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id80" => Delta {
+ "deleted": {
+ "endBinding": {
+ "elementId": "id77",
+ "focus": -0,
+ "gap": 1,
+ },
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "startBinding": {
+ "elementId": "id75",
+ "focus": 0,
+ "gap": 1,
+ },
+ },
+ "inserted": {
+ "endBinding": null,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "startBinding": null,
+ },
+ },
+ },
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id75" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": -100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id76" => Delta {
+ "deleted": {
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 5,
+ "fontSize": 20,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "ola",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "ola",
+ "textAlign": "left",
+ "type": "text",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id77" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": -50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id75": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id76": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id76": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id75" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id76",
+ "type": "text",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id76" => Delta {
+ "deleted": {
+ "containerId": "id75",
+ "height": 25,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "width": 30,
+ "x": -65,
+ "y": "-12.50000",
+ },
+ "inserted": {
+ "containerId": null,
+ "height": 100,
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "width": 100,
+ "x": -200,
+ "y": -200,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id80": true,
+ },
+ "selectedLinearElementId": "id80",
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id75": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id80" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id77",
+ "focus": -0,
+ "gap": 1,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 0,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id75",
+ "focus": 0,
+ "gap": 1,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id75" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id80",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ "id77" => Delta {
+ "deleted": {
+ "boundElements": [
+ {
+ "id": "id80",
+ "type": "arrow",
+ },
+ ],
+ },
+ "inserted": {
+ "boundElements": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id75": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id80": true,
+ },
+ "selectedLinearElementId": "id80",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id77": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] number of elements 1`] = `4`;
+
+exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `15`;
+
+exports[`history > singleplayer undo/redo > should support changes in elements' order > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id45": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id45": true,
+ "id47": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support changes in elements' order > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id46",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 10,
+ "x": 20,
+ "y": 20,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support changes in elements' order > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id45",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support changes in elements' order > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id47",
+ "index": "a3",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 10,
+ "width": 10,
+ "x": 40,
+ "y": 40,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support changes in elements' order > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id45": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id45" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id46": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id45": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id46" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id47": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id46": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id47" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 40,
+ "y": 40,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id47" => Delta {
+ "deleted": {
+ "index": "a0V",
+ },
+ "inserted": {
+ "index": "a2",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id45": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id47": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id47": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id45" => Delta {
+ "deleted": {
+ "index": "a2",
+ },
+ "inserted": {
+ "index": "Zz",
+ },
+ },
+ "id47" => Delta {
+ "deleted": {
+ "index": "a3",
+ },
+ "inserted": {
+ "index": "a0",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support changes in elements' order > [end of test] number of elements 1`] = `3`;
+
+exports[`history > singleplayer undo/redo > should support changes in elements' order > [end of test] number of renders 1`] = `20`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id36": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id42": true,
+ "id44": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id43": true,
+ },
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "id": "id35",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "id": "id36",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "width": 100,
+ "x": 100,
+ "y": 100,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id43",
+ ],
+ "height": 100,
+ "id": "id42",
+ "index": "a1G",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] element 3 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id43",
+ ],
+ "height": 100,
+ "id": "id44",
+ "index": "a1V",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "width": 100,
+ "x": 110,
+ "y": 110,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] element 4 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id40",
+ ],
+ "height": 100,
+ "id": "id39",
+ "index": "a2",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 6,
+ "width": 100,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] element 5 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id40",
+ ],
+ "height": 100,
+ "id": "id41",
+ "index": "a3",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 6,
+ "width": 100,
+ "x": 110,
+ "y": 110,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id35": true,
+ "id36": true,
+ },
+ "selectedGroupIds": {
+ "A": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id35" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id36" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "A",
+ ],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 100,
+ "y": 100,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id42": true,
+ "id44": true,
+ },
+ "selectedGroupIds": {
+ "id43": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id35": true,
+ "id36": true,
+ },
+ "selectedGroupIds": {
+ "A": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id42" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id43",
+ ],
+ "height": 100,
+ "index": "a1G",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id44" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id43",
+ ],
+ "height": 100,
+ "index": "a1V",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 110,
+ "y": 110,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] number of elements 1`] = `6`;
+
+exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] number of renders 1`] = `18`;
+
+exports[`history > singleplayer undo/redo > should support element creation, deletion and appstate element selection change > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id23": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support element creation, deletion and appstate element selection change > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id22",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "width": 10,
+ "x": 10,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support element creation, deletion and appstate element selection change > [end of test] element 1 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id23",
+ "index": "a1",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 10,
+ "x": 20,
+ "y": 20,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support element creation, deletion and appstate element selection change > [end of test] element 2 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id24",
+ "index": "a2",
+ "isDeleted": true,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 8,
+ "width": 10,
+ "x": 40,
+ "y": 40,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support element creation, deletion and appstate element selection change > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id22": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id22" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id23": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id22": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id23" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id24": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id23": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id24" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 40,
+ "y": 40,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id23": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id24": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id24": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id23": true,
+ "id24": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id23" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "isDeleted": false,
+ },
+ },
+ "id24" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "isDeleted": false,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support element creation, deletion and appstate element selection change > [end of test] number of elements 1`] = `3`;
+
+exports[`history > singleplayer undo/redo > should support element creation, deletion and appstate element selection change > [end of test] number of renders 1`] = `27`;
+
+exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 0,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id27": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id27": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 0,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "id": "id27",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 20,
+ 0,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ [
+ 20,
+ 20,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 15,
+ "width": 20,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id27": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id27" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 10,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id27" => Delta {
+ "deleted": {
+ "lastCommittedPoint": [
+ 20,
+ 0,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ [
+ 20,
+ 0,
+ ],
+ ],
+ "width": 20,
+ },
+ "inserted": {
+ "lastCommittedPoint": [
+ 10,
+ 10,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "width": 10,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedLinearElementId": "id27",
+ },
+ "inserted": {
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingLinearElementId": "id27",
+ },
+ "inserted": {
+ "editingLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id27" => Delta {
+ "deleted": {
+ "height": 20,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ [
+ 20,
+ 20,
+ ],
+ ],
+ },
+ "inserted": {
+ "height": 10,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ [
+ 20,
+ 0,
+ ],
+ ],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingLinearElementId": null,
+ },
+ "inserted": {
+ "editingLinearElementId": "id27",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] number of elements 1`] = `1`;
+
+exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] number of renders 1`] = `21`;
diff --git a/packages/excalidraw/tests/__snapshots__/linearElementEditor.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/linearElementEditor.test.tsx.snap
new file mode 100644
index 0000000..0085798
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/linearElementEditor.test.tsx.snap
@@ -0,0 +1,57 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Test Linear Elements > Test bound text element > should bind text to arrow when clicked on arrow and enter pressed 1`] = `
+"Online whiteboard
+collaboration made
+easy"
+`;
+
+exports[`Test Linear Elements > Test bound text element > should bind text to arrow when double clicked 1`] = `
+"Online whiteboard
+collaboration made
+easy"
+`;
+
+exports[`Test Linear Elements > Test bound text element > should match styles for text editor 1`] = `
+
+`;
+
+exports[`Test Linear Elements > Test bound text element > should resize and position the bound text and bounding box correctly when 3 pointer arrow element resized 2`] = `
+"Online whiteboard
+collaboration made
+easy"
+`;
+
+exports[`Test Linear Elements > Test bound text element > should resize and position the bound text and bounding box correctly when 3 pointer arrow element resized 6`] = `
+"Online whiteboard
+collaboration made easy"
+`;
+
+exports[`Test Linear Elements > Test bound text element > should resize and position the bound text correctly when 2 pointer linear element resized 2`] = `
+"Online whiteboard
+collaboration made
+easy"
+`;
+
+exports[`Test Linear Elements > Test bound text element > should resize and position the bound text correctly when 2 pointer linear element resized 5`] = `
+"Online whiteboard
+collaboration made easy"
+`;
+
+exports[`Test Linear Elements > Test bound text element > should wrap the bound text when arrow bound container moves 1`] = `
+"Online whiteboard
+collaboration made easy"
+`;
+
+exports[`Test Linear Elements > Test bound text element > should wrap the bound text when arrow bound container moves 2`] = `
+"Online whiteboard
+collaboration made
+easy"
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap
new file mode 100644
index 0000000..90236a4
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap
@@ -0,0 +1,239 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`duplicate element on move when ALT is clicked > rectangle 5`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id2",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 238820263,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 5,
+ "versionNonce": 400692809,
+ "width": 30,
+ "x": 30,
+ "y": 20,
+}
+`;
+
+exports[`duplicate element on move when ALT is clicked > rectangle 6`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 6,
+ "versionNonce": 23633383,
+ "width": 30,
+ "x": -10,
+ "y": 60,
+}
+`;
+
+exports[`move element > rectangle 5`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 1116226695,
+ "width": 30,
+ "x": 0,
+ "y": 40,
+}
+`;
+
+exports[`move element > rectangles with binding arrow 5`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id2",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 1723083209,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`move element > rectangles with binding arrow 6`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [
+ {
+ "id": "id2",
+ "type": "arrow",
+ },
+ ],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 300,
+ "id": "id1",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1150084233,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 7,
+ "versionNonce": 745419401,
+ "width": 300,
+ "x": 201,
+ "y": 2,
+}
+`;
+
+exports[`move element > rectangles with binding arrow 7`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": {
+ "elementId": "id1",
+ "focus": "-0.46667",
+ "gap": 10,
+ },
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": "87.29887",
+ "id": "id2",
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ "86.85786",
+ "87.29887",
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1604849351,
+ "startArrowhead": null,
+ "startBinding": {
+ "elementId": "id0",
+ "focus": "-0.60000",
+ "gap": 10,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 11,
+ "versionNonce": 1051383431,
+ "width": "86.85786",
+ "x": "107.07107",
+ "y": "47.07107",
+}
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap
new file mode 100644
index 0000000..1b312a5
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/multiPointCreate.test.tsx.snap
@@ -0,0 +1,114 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`multi point mode in linear elements > arrow 3`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 110,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 70,
+ 110,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 20,
+ 30,
+ ],
+ [
+ 70,
+ 110,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 8,
+ "versionNonce": 1604849351,
+ "width": 70,
+ "x": 30,
+ "y": 30,
+}
+`;
+
+exports[`multi point mode in linear elements > line 3`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 110,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 70,
+ 110,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 20,
+ 30,
+ ],
+ [
+ 70,
+ 110,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "updated": 1,
+ "version": 8,
+ "versionNonce": 1604849351,
+ "width": 70,
+ "x": 30,
+ "y": 30,
+}
+`;
diff --git a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap
new file mode 100644
index 0000000..5d48ead
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap
@@ -0,0 +1,14782 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`given element A and group of elements B and given both are selected when user clicks on B, on pointer up only elements from B should be selected > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ "id2": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id2": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id5": true,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`given element A and group of elements B and given both are selected when user clicks on B, on pointer up only elements from B should be selected > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 30,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 60,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id5": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id5",
+ ],
+ "index": "a2",
+ },
+ "inserted": {
+ "groupIds": [],
+ "index": "a0",
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id5",
+ ],
+ "index": "a3",
+ },
+ "inserted": {
+ "groupIds": [],
+ "index": "a2",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`given element A and group of elements B and given both are selected when user clicks on B, on pointer up only elements from B should be selected > [end of test] number of elements 1`] = `0`;
+
+exports[`given element A and group of elements B and given both are selected when user clicks on B, on pointer up only elements from B should be selected > [end of test] number of renders 1`] = `18`;
+
+exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ "id2": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id0": true,
+ "id1": true,
+ "id2": true,
+ "id4": false,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 110,
+ "y": 110,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 100,
+ "x": 220,
+ "y": 220,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ "index": "a2",
+ },
+ "inserted": {
+ "groupIds": [],
+ "index": "a0",
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ "index": "a3",
+ },
+ "inserted": {
+ "groupIds": [],
+ "index": "a2",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {
+ "id0": true,
+ "id1": true,
+ "id2": true,
+ "id4": false,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id2": true,
+ },
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected > [end of test] number of elements 1`] = `0`;
+
+exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected > [end of test] number of renders 1`] = `16`;
+
+exports[`regression tests > Cmd/Ctrl-click exclusively select element under pointer > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": "id10",
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": false,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id7": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > Cmd/Ctrl-click exclusively select element under pointer > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id4",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id7": true,
+ },
+ },
+ "inserted": {
+ "editingGroupId": "id4",
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id7" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 60,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id7": true,
+ },
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id7": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id10": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ "id10",
+ ],
+ },
+ "inserted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ "id10",
+ ],
+ },
+ "inserted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ },
+ "id7" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id10",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id4",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id1": true,
+ "id7": true,
+ },
+ "selectedGroupIds": {
+ "id10": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id10",
+ "selectedElementIds": {
+ "id7": true,
+ },
+ },
+ "inserted": {
+ "editingGroupId": "id4",
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > Cmd/Ctrl-click exclusively select element under pointer > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > Cmd/Ctrl-click exclusively select element under pointer > [end of test] number of renders 1`] = `26`;
+
+exports[`regression tests > Drags selected element when hitting only bounding box and keeps element selected > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > Drags selected element when hitting only bounding box and keeps element selected > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "x": 25,
+ "y": 25,
+ },
+ "inserted": {
+ "x": 0,
+ "y": 0,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > Drags selected element when hitting only bounding box and keeps element selected > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > Drags selected element when hitting only bounding box and keeps element selected > [end of test] number of renders 1`] = `10`;
+
+exports[`regression tests > adjusts z order when grouping > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id2": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id5": true,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > adjusts z order when grouping > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id5": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id5",
+ ],
+ "index": "a2",
+ },
+ "inserted": {
+ "groupIds": [],
+ "index": "a0",
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id5",
+ ],
+ "index": "a3",
+ },
+ "inserted": {
+ "groupIds": [],
+ "index": "a2",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > adjusts z order when grouping > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > adjusts z order when grouping > [end of test] number of renders 1`] = `15`;
+
+exports[`regression tests > alt-drag duplicates an element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > alt-drag duplicates an element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "index": "a1",
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "index": "a0",
+ "x": 10,
+ "y": 10,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > alt-drag duplicates an element > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > alt-drag duplicates an element > [end of test] number of renders 1`] = `8`;
+
+exports[`regression tests > arrow keys > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > arrow keys > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > arrow keys > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > arrow keys > [end of test] number of renders 1`] = `12`;
+
+exports[`regression tests > can drag element that covers another element, while another elem is selected > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id2": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > can drag element that covers another element, while another elem is selected > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 200,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 200,
+ "x": 100,
+ "y": 100,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 200,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 200,
+ "x": 100,
+ "y": 100,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 350,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 350,
+ "x": 300,
+ "y": 300,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id1" => Delta {
+ "deleted": {
+ "x": 300,
+ "y": 300,
+ },
+ "inserted": {
+ "x": 100,
+ "y": 100,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > can drag element that covers another element, while another elem is selected > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > can drag element that covers another element, while another elem is selected > [end of test] number of renders 1`] = `15`;
+
+exports[`regression tests > change the properties of a shape > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#ffc9c9",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1971c2",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementStroke",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > change the properties of a shape > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "backgroundColor": "#ffec99",
+ },
+ "inserted": {
+ "backgroundColor": "transparent",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "backgroundColor": "#ffc9c9",
+ },
+ "inserted": {
+ "backgroundColor": "#ffec99",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "strokeColor": "#1971c2",
+ },
+ "inserted": {
+ "strokeColor": "#1e1e1e",
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > change the properties of a shape > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > change the properties of a shape > [end of test] number of renders 1`] = `9`;
+
+exports[`regression tests > click on an element and drag it > [dragged] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > click on an element and drag it > [dragged] element 0 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 1116226695,
+ "width": 10,
+ "x": 20,
+ "y": 20,
+}
+`;
+
+exports[`regression tests > click on an element and drag it > [dragged] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [
+ [Function],
+ [Function],
+ ],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "x": 10,
+ "y": 10,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > click on an element and drag it > [dragged] number of elements 1`] = `1`;
+
+exports[`regression tests > click on an element and drag it > [dragged] number of renders 1`] = `8`;
+
+exports[`regression tests > click on an element and drag it > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > click on an element and drag it > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "x": 10,
+ "y": 10,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "x": 20,
+ "y": 20,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > click on an element and drag it > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > click on an element and drag it > [end of test] number of renders 1`] = `10`;
+
+exports[`regression tests > click to select a shape > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id1": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > click to select a shape > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > click to select a shape > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > click to select a shape > [end of test] number of renders 1`] = `10`;
+
+exports[`regression tests > click-drag to select a group > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id2": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > click-drag to select a group > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > click-drag to select a group > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > click-drag to select a group > [end of test] number of renders 1`] = `14`;
+
+exports[`regression tests > deleting last but one element in editing group should unselect the group > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id4": false,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > deleting last but one element in editing group should unselect the group > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id4",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id4": false,
+ },
+ },
+ "inserted": {
+ "editingGroupId": "id4",
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id0" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "isDeleted": false,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id4": false,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id4": false,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > deleting last but one element in editing group should unselect the group > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > deleting last but one element in editing group should unselect the group > [end of test] number of renders 1`] = `17`;
+
+exports[`regression tests > deselects group of selected elements on pointer down when pointer doesn't hit any element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "down",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id3",
+ "index": null,
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1505387817,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "selection",
+ "updated": 1,
+ "version": 1,
+ "versionNonce": 0,
+ "width": 0,
+ "x": 500,
+ "y": 500,
+ },
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > deselects group of selected elements on pointer down when pointer doesn't hit any element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 10,
+ "x": 110,
+ "y": 110,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > deselects group of selected elements on pointer down when pointer doesn't hit any element > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > deselects group of selected elements on pointer down when pointer doesn't hit any element > [end of test] number of renders 1`] = `11`;
+
+exports[`regression tests > deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 10,
+ "x": 110,
+ "y": 110,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element > [end of test] number of renders 1`] = `11`;
+
+exports[`regression tests > deselects selected element on pointer down when pointer doesn't hit any element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "down",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id1",
+ "index": null,
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1150084233,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "selection",
+ "updated": 1,
+ "version": 1,
+ "versionNonce": 0,
+ "width": 0,
+ "x": 110,
+ "y": 110,
+ },
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > deselects selected element on pointer down when pointer doesn't hit any element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > deselects selected element on pointer down when pointer doesn't hit any element > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > deselects selected element on pointer down when pointer doesn't hit any element > [end of test] number of renders 1`] = `7`;
+
+exports[`regression tests > deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element > [end of test] number of renders 1`] = `7`;
+
+exports[`regression tests > double click to edit a group > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": "id3",
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id2": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > double click to edit a group > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id3",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > double click to edit a group > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > double click to edit a group > [end of test] number of renders 1`] = `15`;
+
+exports[`regression tests > drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 10,
+ "x": 110,
+ "y": 110,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "x": 25,
+ "y": 25,
+ },
+ "inserted": {
+ "x": 0,
+ "y": 0,
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "x": 135,
+ "y": 135,
+ },
+ "inserted": {
+ "x": 110,
+ "y": 110,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging > [end of test] number of renders 1`] = `12`;
+
+exports[`regression tests > draw every type of shape > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "freedraw",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > draw every type of shape > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 10,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "width": 20,
+ "x": 40,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 20,
+ "x": 70,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id3": true,
+ },
+ "selectedLinearElementId": "id3",
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id3" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a3",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 50,
+ "x": 130,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id4": true,
+ },
+ "selectedLinearElementId": "id4",
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id3": true,
+ },
+ "selectedLinearElementId": "id3",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id4" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a4",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "width": 50,
+ "x": 220,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id5": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id4": true,
+ },
+ "selectedLinearElementId": "id4",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id5" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a5",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 50,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 50,
+ "x": 310,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id5" => Delta {
+ "deleted": {
+ "height": 20,
+ "lastCommittedPoint": [
+ 80,
+ 20,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ [
+ 80,
+ 20,
+ ],
+ ],
+ "width": 80,
+ },
+ "inserted": {
+ "height": 10,
+ "lastCommittedPoint": [
+ 50,
+ 10,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "width": 50,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedLinearElementId": "id5",
+ },
+ "inserted": {
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id6": true,
+ },
+ "selectedLinearElementId": null,
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id5": true,
+ },
+ "selectedLinearElementId": "id5",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id6" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a6",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 50,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "width": 50,
+ "x": 430,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id6" => Delta {
+ "deleted": {
+ "height": 20,
+ "lastCommittedPoint": [
+ 80,
+ 20,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ [
+ 80,
+ 20,
+ ],
+ ],
+ "width": 80,
+ },
+ "inserted": {
+ "height": 10,
+ "lastCommittedPoint": [
+ 50,
+ 10,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "width": 50,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedLinearElementId": "id6",
+ },
+ "inserted": {
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id6": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedLinearElementId": null,
+ },
+ "inserted": {
+ "selectedLinearElementId": "id6",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id7" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a7",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 50,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ [
+ 50,
+ 10,
+ ],
+ ],
+ "pressures": [
+ 0,
+ 0,
+ 0,
+ ],
+ "roughness": 1,
+ "roundness": null,
+ "simulatePressure": false,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "width": 50,
+ "x": 550,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > draw every type of shape > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > draw every type of shape > [end of test] number of renders 1`] = `33`;
+
+exports[`regression tests > given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id2": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 100,
+ "x": 110,
+ "y": 110,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "width": 100,
+ "x": 310,
+ "y": 310,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id2": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up > [end of test] number of renders 1`] = `14`;
+
+exports[`regression tests > given a selected element A and a not selected element B with higher z-index than A and given B partially overlaps A when there's a shift-click on the overlapped section B is added to the selection > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "#ffc9c9",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": "elementBackground",
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > given a selected element A and a not selected element B with higher z-index than A and given B partially overlaps A when there's a shift-click on the overlapped section B is added to the selection > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "#ffc9c9",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 1000,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 1000,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "#ffc9c9",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 1000,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 1000,
+ "x": 500,
+ "y": 500,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > given a selected element A and a not selected element B with higher z-index than A and given B partially overlaps A when there's a shift-click on the overlapped section B is added to the selection > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > given a selected element A and a not selected element B with higher z-index than A and given B partially overlaps A when there's a shift-click on the overlapped section B is added to the selection > [end of test] number of renders 1`] = `12`;
+
+exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "red",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 1000,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 1000,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "red",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 500,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 500,
+ "x": 500,
+ "y": 500,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up > [end of test] number of renders 1`] = `7`;
+
+exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "red",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 1000,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 1000,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "red",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 500,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 500,
+ "x": 500,
+ "y": 500,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "x": 100,
+ "y": 100,
+ },
+ "inserted": {
+ "x": 0,
+ "y": 0,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected > [end of test] number of renders 1`] = `8`;
+
+exports[`regression tests > key 2 selects rectangle tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key 2 selects rectangle tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key 2 selects rectangle tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key 2 selects rectangle tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key 3 selects diamond tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key 3 selects diamond tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key 3 selects diamond tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key 3 selects diamond tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key 4 selects ellipse tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key 4 selects ellipse tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key 4 selects ellipse tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key 4 selects ellipse tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key 5 selects arrow tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": LinearElementEditor {
+ "elbowed": false,
+ "elementId": "id0",
+ "endBindingElement": "keep",
+ "hoverPointIndex": -1,
+ "isDragging": false,
+ "lastUncommittedPoint": null,
+ "pointerDownState": {
+ "lastClickedIsEndPoint": false,
+ "lastClickedPoint": -1,
+ "origin": null,
+ "prevSelectedPointsIndices": null,
+ "segmentMidpoint": {
+ "added": false,
+ "index": null,
+ "value": null,
+ },
+ },
+ "pointerOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "segmentMidPointHoveredCoords": null,
+ "selectedPointsIndices": null,
+ "startBindingElement": "keep",
+ },
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key 5 selects arrow tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedLinearElementId": "id0",
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key 5 selects arrow tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key 5 selects arrow tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key 6 selects line tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": LinearElementEditor {
+ "elbowed": false,
+ "elementId": "id0",
+ "endBindingElement": "keep",
+ "hoverPointIndex": -1,
+ "isDragging": false,
+ "lastUncommittedPoint": null,
+ "pointerDownState": {
+ "lastClickedIsEndPoint": false,
+ "lastClickedPoint": -1,
+ "origin": null,
+ "prevSelectedPointsIndices": null,
+ "segmentMidpoint": {
+ "added": false,
+ "index": null,
+ "value": null,
+ },
+ },
+ "pointerOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "segmentMidPointHoveredCoords": null,
+ "selectedPointsIndices": null,
+ "startBindingElement": "keep",
+ },
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key 6 selects line tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedLinearElementId": "id0",
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key 6 selects line tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key 6 selects line tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key 7 selects freedraw tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "freedraw",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key 7 selects freedraw tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 10,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "pressures": [
+ 0,
+ 0,
+ 0,
+ ],
+ "roughness": 1,
+ "roundness": null,
+ "simulatePressure": false,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key 7 selects freedraw tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key 7 selects freedraw tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key a selects arrow tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": LinearElementEditor {
+ "elbowed": false,
+ "elementId": "id0",
+ "endBindingElement": "keep",
+ "hoverPointIndex": -1,
+ "isDragging": false,
+ "lastUncommittedPoint": null,
+ "pointerDownState": {
+ "lastClickedIsEndPoint": false,
+ "lastClickedPoint": -1,
+ "origin": null,
+ "prevSelectedPointsIndices": null,
+ "segmentMidpoint": {
+ "added": false,
+ "index": null,
+ "value": null,
+ },
+ },
+ "pointerOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "segmentMidPointHoveredCoords": null,
+ "selectedPointsIndices": null,
+ "startBindingElement": "keep",
+ },
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key a selects arrow tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedLinearElementId": "id0",
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key a selects arrow tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key a selects arrow tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key d selects diamond tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key d selects diamond tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key d selects diamond tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key d selects diamond tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key l selects line tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": LinearElementEditor {
+ "elbowed": false,
+ "elementId": "id0",
+ "endBindingElement": "keep",
+ "hoverPointIndex": -1,
+ "isDragging": false,
+ "lastUncommittedPoint": null,
+ "pointerDownState": {
+ "lastClickedIsEndPoint": false,
+ "lastClickedPoint": -1,
+ "origin": null,
+ "prevSelectedPointsIndices": null,
+ "segmentMidpoint": {
+ "added": false,
+ "index": null,
+ "value": null,
+ },
+ },
+ "pointerOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "segmentMidPointHoveredCoords": null,
+ "selectedPointsIndices": null,
+ "startBindingElement": "keep",
+ },
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key l selects line tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedLinearElementId": "id0",
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedLinearElementId": null,
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key l selects line tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key l selects line tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key o selects ellipse tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key o selects ellipse tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key o selects ellipse tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key o selects ellipse tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key p selects freedraw tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "freedraw",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key p selects freedraw tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 10,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "pressures": [
+ 0,
+ 0,
+ 0,
+ ],
+ "roughness": 1,
+ "roundness": null,
+ "simulatePressure": false,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key p selects freedraw tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key p selects freedraw tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > key r selects rectangle tool > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > key r selects rectangle tool > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > key r selects rectangle tool > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > key r selects rectangle tool > [end of test] number of renders 1`] = `6`;
+
+exports[`regression tests > make a group and duplicate it > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ "id2": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ "id2": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > make a group and duplicate it > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id6" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id7",
+ ],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id8" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id7",
+ ],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ "id9" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [
+ "id7",
+ ],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "index": "a3",
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "index": "a0",
+ "x": 10,
+ "y": 10,
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "index": "a4",
+ "x": 40,
+ "y": 20,
+ },
+ "inserted": {
+ "index": "a1",
+ "x": 30,
+ "y": 10,
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "index": "a5",
+ "x": 60,
+ "y": 20,
+ },
+ "inserted": {
+ "index": "a2",
+ "x": 50,
+ "y": 10,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > make a group and duplicate it > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > make a group and duplicate it > [end of test] number of renders 1`] = `17`;
+
+exports[`regression tests > noop interaction after undo shouldn't create history entry > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > noop interaction after undo shouldn't create history entry > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > noop interaction after undo shouldn't create history entry > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > noop interaction after undo shouldn't create history entry > [end of test] number of renders 1`] = `14`;
+
+exports[`regression tests > pinch-to-zoom works > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "down",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "touch",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": "-6.25000",
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": true,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > pinch-to-zoom works > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [],
+}
+`;
+
+exports[`regression tests > pinch-to-zoom works > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > pinch-to-zoom works > [end of test] number of renders 1`] = `7`;
+
+exports[`regression tests > shift click on selected element should deselect it on pointer up > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > shift click on selected element should deselect it on pointer up > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > shift click on selected element should deselect it on pointer up > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > shift click on selected element should deselect it on pointer up > [end of test] number of renders 1`] = `7`;
+
+exports[`regression tests > shift-click to multiselect, then drag > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > shift-click to multiselect, then drag > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "x": 10,
+ "y": 10,
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "x": 40,
+ "y": 20,
+ },
+ "inserted": {
+ "x": 30,
+ "y": 10,
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > shift-click to multiselect, then drag > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > shift-click to multiselect, then drag > [end of test] number of renders 1`] = `13`;
+
+exports[`regression tests > should group elements and ungroup them > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ "id2": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ "id2": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > should group elements and ungroup them > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 30,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [],
+ },
+ "inserted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [],
+ },
+ "inserted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [],
+ },
+ "inserted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > should group elements and ungroup them > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > should group elements and ungroup them > [end of test] number of renders 1`] = `18`;
+
+exports[`regression tests > single-clicking on a subgroup of a selected group should not alter selection > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ "id1": true,
+ "id5": true,
+ "id6": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ "id5": true,
+ "id6": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {
+ "id10": true,
+ },
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > single-clicking on a subgroup of a selected group should not alter selection > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id5": true,
+ },
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id5" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 10,
+ "y": 50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id6": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id5": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id6" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a3",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 50,
+ "y": 50,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id5": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id6": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id6": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id9": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id5" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id9",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id6" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id9",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id4": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id10": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {
+ "id4": true,
+ "id9": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ "id10",
+ ],
+ },
+ "inserted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id4",
+ "id10",
+ ],
+ },
+ "inserted": {
+ "groupIds": [
+ "id4",
+ ],
+ },
+ },
+ "id5" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id9",
+ "id10",
+ ],
+ },
+ "inserted": {
+ "groupIds": [
+ "id9",
+ ],
+ },
+ },
+ "id6" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id9",
+ "id10",
+ ],
+ },
+ "inserted": {
+ "groupIds": [
+ "id9",
+ ],
+ },
+ },
+ },
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > single-clicking on a subgroup of a selected group should not alter selection > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > single-clicking on a subgroup of a selected group should not alter selection > [end of test] number of renders 1`] = `25`;
+
+exports[`regression tests > spacebar + drag scrolls the canvas > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 60,
+ "scrollY": 60,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > spacebar + drag scrolls the canvas > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [],
+}
+`;
+
+exports[`regression tests > spacebar + drag scrolls the canvas > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > spacebar + drag scrolls the canvas > [end of test] number of renders 1`] = `5`;
+
+exports[`regression tests > supports nested groups > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": "id3",
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id0": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > supports nested groups > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 50,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 50,
+ "x": 100,
+ "y": 100,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 50,
+ "x": 200,
+ "y": 200,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id1" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id3",
+ ],
+ },
+ "inserted": {
+ "groupIds": [],
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id3",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id0": true,
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedGroupIds": {
+ "id5": true,
+ },
+ },
+ "inserted": {
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id0" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id5",
+ "id3",
+ ],
+ "index": "a2",
+ },
+ "inserted": {
+ "groupIds": [
+ "id3",
+ ],
+ "index": "a0",
+ },
+ },
+ "id2" => Delta {
+ "deleted": {
+ "groupIds": [
+ "id5",
+ "id3",
+ ],
+ "index": "a3",
+ },
+ "inserted": {
+ "groupIds": [
+ "id3",
+ ],
+ "index": "a2",
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ "inserted": {
+ "editingGroupId": "id3",
+ "selectedElementIds": {},
+ "selectedGroupIds": {
+ "id5": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id3",
+ "selectedElementIds": {},
+ "selectedGroupIds": {
+ "id5": true,
+ },
+ },
+ "inserted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id5",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "editingGroupId": "id3",
+ "selectedElementIds": {
+ "id2": true,
+ },
+ "selectedGroupIds": {
+ "id5": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id1": true,
+ "id2": true,
+ },
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ "inserted": {
+ "editingGroupId": "id5",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "editingGroupId": "id3",
+ "selectedElementIds": {},
+ "selectedGroupIds": {},
+ },
+ "inserted": {
+ "editingGroupId": null,
+ "selectedElementIds": {
+ "id0": true,
+ "id2": true,
+ },
+ "selectedGroupIds": {
+ "id3": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > supports nested groups > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > supports nested groups > [end of test] number of renders 1`] = `23`;
+
+exports[`regression tests > switches from group of selected elements to another element on pointer down > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "down",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id1": true,
+ "id2": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id4",
+ "index": null,
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1723083209,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "selection",
+ "updated": 1,
+ "version": 1,
+ "versionNonce": 0,
+ "width": 0,
+ "x": 0,
+ "y": 0,
+ },
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > switches from group of selected elements to another element on pointer down > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 100,
+ "x": 110,
+ "y": 110,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id2" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "width": 100,
+ "x": 310,
+ "y": 310,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > switches from group of selected elements to another element on pointer down > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > switches from group of selected elements to another element on pointer down > [end of test] number of renders 1`] = `14`;
+
+exports[`regression tests > switches selected element on pointer down > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "down",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {
+ "id1": true,
+ },
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id0": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 0,
+ "id": "id2",
+ "index": null,
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1604849351,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "selection",
+ "updated": 1,
+ "version": 1,
+ "versionNonce": 0,
+ "width": 0,
+ "x": 0,
+ "y": 0,
+ },
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > switches selected element on pointer down > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 10,
+ "x": 0,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "width": 10,
+ "x": 20,
+ "y": 20,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > switches selected element on pointer down > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > switches selected element on pointer down > [end of test] number of renders 1`] = `10`;
+
+exports[`regression tests > two-finger scroll works > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "down",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "touch",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 20,
+ "scrollY": "-18.53553",
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": true,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > two-finger scroll works > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [],
+}
+`;
+
+exports[`regression tests > two-finger scroll works > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > two-finger scroll works > [end of test] number of renders 1`] = `8`;
+
+exports[`regression tests > undo/redo drawing an element > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {
+ "id1": true,
+ },
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > undo/redo drawing an element > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedLinearElementId": null,
+ },
+ "inserted": {
+ "selectedLinearElementId": "id2",
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {},
+ "inserted": {},
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {},
+ "updated": Map {
+ "id2" => Delta {
+ "deleted": {
+ "height": 10,
+ "lastCommittedPoint": [
+ 60,
+ 10,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 60,
+ 10,
+ ],
+ ],
+ "width": 60,
+ },
+ "inserted": {
+ "height": 20,
+ "lastCommittedPoint": [
+ 100,
+ 20,
+ ],
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 60,
+ 10,
+ ],
+ [
+ 100,
+ 20,
+ ],
+ ],
+ "width": 100,
+ },
+ },
+ },
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id2": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {
+ "id2" => Delta {
+ "deleted": {
+ "isDeleted": true,
+ },
+ "inserted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a2",
+ "isDeleted": false,
+ "lastCommittedPoint": [
+ 60,
+ 10,
+ ],
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 60,
+ 10,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "width": 60,
+ "x": 130,
+ "y": 10,
+ },
+ },
+ },
+ "removed": Map {},
+ "updated": Map {},
+ },
+ },
+ ],
+ "undoStack": [
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {},
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id0" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 10,
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 20,
+ "x": 10,
+ "y": -10,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ HistoryEntry {
+ "appStateChange": AppStateChange {
+ "delta": Delta {
+ "deleted": {
+ "selectedElementIds": {
+ "id1": true,
+ },
+ },
+ "inserted": {
+ "selectedElementIds": {
+ "id0": true,
+ },
+ },
+ },
+ },
+ "elementsChange": ElementsChange {
+ "added": Map {},
+ "removed": Map {
+ "id1" => Delta {
+ "deleted": {
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 20,
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "width": 30,
+ "x": 40,
+ "y": 0,
+ },
+ "inserted": {
+ "isDeleted": true,
+ },
+ },
+ },
+ "updated": Map {},
+ },
+ },
+ ],
+}
+`;
+
+exports[`regression tests > undo/redo drawing an element > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > undo/redo drawing an element > [end of test] number of renders 1`] = `20`;
+
+exports[`regression tests > updates fontSize & fontFamily appState > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "text",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 8,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": null,
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > updates fontSize & fontFamily appState > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [],
+}
+`;
+
+exports[`regression tests > updates fontSize & fontFamily appState > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > updates fontSize & fontFamily appState > [end of test] number of renders 1`] = `5`;
+
+exports[`regression tests > zoom hotkeys > [end of test] appState 1`] = `
+{
+ "activeEmbeddable": null,
+ "activeTool": {
+ "customType": null,
+ "lastActiveTool": null,
+ "locked": false,
+ "type": "selection",
+ },
+ "collaborators": Map {},
+ "contextMenu": null,
+ "croppingElementId": null,
+ "currentChartType": "bar",
+ "currentHoveredFontFamily": null,
+ "currentItemArrowType": "round",
+ "currentItemBackgroundColor": "transparent",
+ "currentItemEndArrowhead": "arrow",
+ "currentItemFillStyle": "solid",
+ "currentItemFontFamily": 5,
+ "currentItemFontSize": 20,
+ "currentItemOpacity": 100,
+ "currentItemRoughness": 1,
+ "currentItemRoundness": "round",
+ "currentItemStartArrowhead": null,
+ "currentItemStrokeColor": "#1e1e1e",
+ "currentItemStrokeStyle": "solid",
+ "currentItemStrokeWidth": 2,
+ "currentItemTextAlign": "left",
+ "cursorButton": "up",
+ "defaultSidebarDockedPreference": false,
+ "editingFrame": null,
+ "editingGroupId": null,
+ "editingLinearElement": null,
+ "editingTextElement": null,
+ "elementsToHighlight": null,
+ "errorMessage": null,
+ "exportBackground": true,
+ "exportEmbedScene": false,
+ "exportScale": 1,
+ "exportWithDarkMode": false,
+ "fileHandle": null,
+ "followedBy": Set {},
+ "frameRendering": {
+ "clip": true,
+ "enabled": true,
+ "name": true,
+ "outline": true,
+ },
+ "frameToHighlight": null,
+ "gridModeEnabled": false,
+ "gridSize": 20,
+ "gridStep": 5,
+ "height": 768,
+ "hoveredElementIds": {},
+ "isBindingEnabled": true,
+ "isCropping": false,
+ "isLoading": false,
+ "isResizing": false,
+ "isRotating": false,
+ "lastPointerDownWith": "mouse",
+ "multiElement": null,
+ "name": "Untitled-201933152653",
+ "newElement": null,
+ "objectsSnapModeEnabled": false,
+ "offsetLeft": 0,
+ "offsetTop": 0,
+ "openDialog": null,
+ "openMenu": null,
+ "openPopup": null,
+ "openSidebar": null,
+ "originSnapOffset": {
+ "x": 0,
+ "y": 0,
+ },
+ "pasteDialog": {
+ "data": null,
+ "shown": false,
+ },
+ "penDetected": false,
+ "penMode": false,
+ "pendingImageElementId": null,
+ "previousSelectedElementIds": {},
+ "resizingElement": null,
+ "scrollX": 0,
+ "scrollY": 0,
+ "scrolledOutside": false,
+ "searchMatches": [],
+ "selectedElementIds": {},
+ "selectedElementsAreBeingDragged": false,
+ "selectedGroupIds": {},
+ "selectedLinearElement": null,
+ "selectionElement": null,
+ "shouldCacheIgnoreZoom": false,
+ "showHyperlinkPopup": false,
+ "showWelcomeScreen": true,
+ "snapLines": [],
+ "startBoundElement": null,
+ "stats": {
+ "open": false,
+ "panels": 3,
+ },
+ "suggestedBindings": [],
+ "theme": "light",
+ "toast": null,
+ "userToFollow": null,
+ "viewBackgroundColor": "#ffffff",
+ "viewModeEnabled": false,
+ "width": 1024,
+ "zenModeEnabled": false,
+ "zoom": {
+ "value": 1,
+ },
+}
+`;
+
+exports[`regression tests > zoom hotkeys > [end of test] history 1`] = `
+History {
+ "onHistoryChangedEmitter": Emitter {
+ "subscribers": [],
+ },
+ "redoStack": [],
+ "undoStack": [],
+}
+`;
+
+exports[`regression tests > zoom hotkeys > [end of test] number of elements 1`] = `0`;
+
+exports[`regression tests > zoom hotkeys > [end of test] number of renders 1`] = `6`;
diff --git a/packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap
new file mode 100644
index 0000000..2eea908
--- /dev/null
+++ b/packages/excalidraw/tests/__snapshots__/selection.test.tsx.snap
@@ -0,0 +1,202 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`select single element on the scene > arrow 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": "arrow",
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 30,
+ 50,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 2019559783,
+ "width": 30,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`select single element on the scene > arrow escape 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 30,
+ 50,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "updated": 1,
+ "version": 4,
+ "versionNonce": 2019559783,
+ "width": 30,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`select single element on the scene > diamond 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 401146281,
+ "width": 30,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`select single element on the scene > ellipse 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 401146281,
+ "width": 30,
+ "x": 10,
+ "y": 10,
+}
+`;
+
+exports[`select single element on the scene > rectangle 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 50,
+ "id": "id0",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": 1278240551,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": 401146281,
+ "width": 30,
+ "x": 10,
+ "y": 10,
+}
+`;
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();
+ });
+
+ 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);
+ });
+});
diff --git a/packages/excalidraw/tests/align.test.tsx b/packages/excalidraw/tests/align.test.tsx
new file mode 100644
index 0000000..47624e8
--- /dev/null
+++ b/packages/excalidraw/tests/align.test.tsx
@@ -0,0 +1,579 @@
+import React from "react";
+import { act, unmountComponent, render } from "./test-utils";
+import { Excalidraw } from "../index";
+import { defaultLang, setLanguage } from "../i18n";
+import { UI, Pointer, Keyboard } from "./helpers/ui";
+import { API } from "./helpers/api";
+import { KEYS } from "../keys";
+import {
+ actionAlignVerticallyCentered,
+ actionAlignHorizontallyCentered,
+ actionGroup,
+ actionAlignTop,
+ actionAlignBottom,
+ actionAlignLeft,
+ actionAlignRight,
+} from "../actions";
+
+const mouse = new Pointer("mouse");
+
+const createAndSelectTwoRectangles = () => {
+ UI.clickTool("rectangle");
+ mouse.down();
+ mouse.up(100, 100);
+
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(100, 100);
+
+ // Select the first element.
+ // The second rectangle is already reselected because it was the last element created
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+};
+
+const createAndSelectTwoRectanglesWithDifferentSizes = () => {
+ UI.clickTool("rectangle");
+ mouse.down();
+ mouse.up(100, 100);
+
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(110, 110);
+
+ // Select the first element.
+ // The second rectangle is already reselected because it was the last element created
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+};
+
+describe("aligning", () => {
+ beforeEach(async () => {
+ unmountComponent();
+ mouse.reset();
+
+ await act(() => {
+ return setLanguage(defaultLang);
+ });
+ await render();
+ });
+
+ it("aligns two objects correctly to the top", () => {
+ createAndSelectTwoRectangles();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+
+ Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
+ Keyboard.keyPress(KEYS.ARROW_UP);
+ });
+
+ // Check if x position did not change
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(0);
+ });
+
+ it("aligns two objects correctly to the bottom", () => {
+ createAndSelectTwoRectangles();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+
+ Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
+ Keyboard.keyPress(KEYS.ARROW_DOWN);
+ });
+
+ // Check if x position did not change
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(110);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+ });
+
+ it("aligns two objects correctly to the left", () => {
+ createAndSelectTwoRectangles();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+
+ Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
+ Keyboard.keyPress(KEYS.ARROW_LEFT);
+ });
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(0);
+
+ // Check if y position did not change
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+ });
+
+ it("aligns two objects correctly to the right", () => {
+ createAndSelectTwoRectangles();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+
+ Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
+ Keyboard.keyPress(KEYS.ARROW_RIGHT);
+ });
+
+ expect(API.getSelectedElements()[0].x).toEqual(110);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ // Check if y position did not change
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+ });
+
+ it("centers two objects with different sizes correctly vertically", () => {
+ createAndSelectTwoRectanglesWithDifferentSizes();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+
+ API.executeAction(actionAlignVerticallyCentered);
+
+ // Check if x position did not change
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(60);
+ expect(API.getSelectedElements()[1].y).toEqual(55);
+ });
+
+ it("centers two objects with different sizes correctly horizontally", () => {
+ createAndSelectTwoRectanglesWithDifferentSizes();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(110);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+
+ API.executeAction(actionAlignHorizontallyCentered);
+
+ expect(API.getSelectedElements()[0].x).toEqual(60);
+ expect(API.getSelectedElements()[1].x).toEqual(55);
+
+ // Check if y position did not change
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(110);
+ });
+
+ const createAndSelectGroupAndRectangle = () => {
+ UI.clickTool("rectangle");
+ mouse.down();
+ mouse.up(100, 100);
+
+ UI.clickTool("rectangle");
+ mouse.down(0, 0);
+ mouse.up(100, 100);
+
+ // Select the first element.
+ // The second rectangle is already reselected because it was the last element created
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+
+ API.executeAction(actionGroup);
+
+ mouse.reset();
+ UI.clickTool("rectangle");
+ mouse.down(200, 200);
+ mouse.up(100, 100);
+
+ // Add the created group to the current selection
+ mouse.restorePosition(0, 0);
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+ };
+
+ it("aligns a group with another element correctly to the top", () => {
+ createAndSelectGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+
+ API.executeAction(actionAlignTop);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(0);
+ });
+
+ it("aligns a group with another element correctly to the bottom", () => {
+ createAndSelectGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+
+ API.executeAction(actionAlignBottom);
+
+ expect(API.getSelectedElements()[0].y).toEqual(100);
+ expect(API.getSelectedElements()[1].y).toEqual(200);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ });
+
+ it("aligns a group with another element correctly to the left", () => {
+ createAndSelectGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+
+ API.executeAction(actionAlignLeft);
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(0);
+ });
+
+ it("aligns a group with another element correctly to the right", () => {
+ createAndSelectGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+
+ API.executeAction(actionAlignRight);
+
+ expect(API.getSelectedElements()[0].x).toEqual(100);
+ expect(API.getSelectedElements()[1].x).toEqual(200);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ });
+
+ it("centers a group with another element correctly vertically", () => {
+ createAndSelectGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+
+ API.executeAction(actionAlignVerticallyCentered);
+
+ expect(API.getSelectedElements()[0].y).toEqual(50);
+ expect(API.getSelectedElements()[1].y).toEqual(150);
+ expect(API.getSelectedElements()[2].y).toEqual(100);
+ });
+
+ it("centers a group with another element correctly horizontally", () => {
+ createAndSelectGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+
+ API.executeAction(actionAlignHorizontallyCentered);
+
+ expect(API.getSelectedElements()[0].x).toEqual(50);
+ expect(API.getSelectedElements()[1].x).toEqual(150);
+ expect(API.getSelectedElements()[2].x).toEqual(100);
+ });
+
+ const createAndSelectTwoGroups = () => {
+ UI.clickTool("rectangle");
+ mouse.down();
+ mouse.up(100, 100);
+
+ UI.clickTool("rectangle");
+ mouse.down(0, 0);
+ mouse.up(100, 100);
+
+ // Select the first element.
+ // The second rectangle is already selected because it was the last element created
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+
+ API.executeAction(actionGroup);
+
+ mouse.reset();
+ UI.clickTool("rectangle");
+ mouse.down(200, 200);
+ mouse.up(100, 100);
+
+ UI.clickTool("rectangle");
+ mouse.down();
+ mouse.up(100, 100);
+
+ mouse.restorePosition(200, 200);
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+
+ API.executeAction(actionGroup);
+
+ // Select the first group.
+ // The second group is already selected because it was the last group created
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+ };
+
+ it("aligns two groups correctly to the top", () => {
+ createAndSelectTwoGroups();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ expect(API.getSelectedElements()[3].y).toEqual(300);
+
+ API.executeAction(actionAlignTop);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(0);
+ expect(API.getSelectedElements()[3].y).toEqual(100);
+ });
+
+ it("aligns two groups correctly to the bottom", () => {
+ createAndSelectTwoGroups();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ expect(API.getSelectedElements()[3].y).toEqual(300);
+
+ API.executeAction(actionAlignBottom);
+
+ expect(API.getSelectedElements()[0].y).toEqual(200);
+ expect(API.getSelectedElements()[1].y).toEqual(300);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ expect(API.getSelectedElements()[3].y).toEqual(300);
+ });
+
+ it("aligns two groups correctly to the left", () => {
+ createAndSelectTwoGroups();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ expect(API.getSelectedElements()[3].x).toEqual(300);
+
+ API.executeAction(actionAlignLeft);
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(0);
+ expect(API.getSelectedElements()[3].x).toEqual(100);
+ });
+
+ it("aligns two groups correctly to the right", () => {
+ createAndSelectTwoGroups();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ expect(API.getSelectedElements()[3].x).toEqual(300);
+
+ API.executeAction(actionAlignRight);
+
+ expect(API.getSelectedElements()[0].x).toEqual(200);
+ expect(API.getSelectedElements()[1].x).toEqual(300);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ expect(API.getSelectedElements()[3].x).toEqual(300);
+ });
+
+ it("centers two groups correctly vertically", () => {
+ createAndSelectTwoGroups();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ expect(API.getSelectedElements()[3].y).toEqual(300);
+
+ API.executeAction(actionAlignVerticallyCentered);
+
+ expect(API.getSelectedElements()[0].y).toEqual(100);
+ expect(API.getSelectedElements()[1].y).toEqual(200);
+ expect(API.getSelectedElements()[2].y).toEqual(100);
+ expect(API.getSelectedElements()[3].y).toEqual(200);
+ });
+
+ it("centers two groups correctly horizontally", () => {
+ createAndSelectTwoGroups();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ expect(API.getSelectedElements()[3].x).toEqual(300);
+
+ API.executeAction(actionAlignHorizontallyCentered);
+
+ expect(API.getSelectedElements()[0].x).toEqual(100);
+ expect(API.getSelectedElements()[1].x).toEqual(200);
+ expect(API.getSelectedElements()[2].x).toEqual(100);
+ expect(API.getSelectedElements()[3].x).toEqual(200);
+ });
+
+ const createAndSelectNestedGroupAndRectangle = () => {
+ UI.clickTool("rectangle");
+ mouse.down();
+ mouse.up(100, 100);
+
+ UI.clickTool("rectangle");
+ mouse.down(0, 0);
+ mouse.up(100, 100);
+
+ // Select the first element.
+ // The second rectangle is already reselected because it was the last element created
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+
+ // Create first group of rectangles
+ API.executeAction(actionGroup);
+
+ mouse.reset();
+ UI.clickTool("rectangle");
+ mouse.down(200, 200);
+ mouse.up(100, 100);
+
+ // Add group to current selection
+ mouse.restorePosition(0, 0);
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+
+ // Create the nested group
+ API.executeAction(actionGroup);
+
+ mouse.reset();
+ UI.clickTool("rectangle");
+ mouse.down(300, 300);
+ mouse.up(100, 100);
+
+ // Select the nested group, the rectangle is already selected
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click();
+ });
+ };
+
+ it("aligns nested group and other element correctly to the top", () => {
+ createAndSelectNestedGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ expect(API.getSelectedElements()[3].y).toEqual(300);
+
+ API.executeAction(actionAlignTop);
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ expect(API.getSelectedElements()[3].y).toEqual(0);
+ });
+
+ it("aligns nested group and other element correctly to the bottom", () => {
+ createAndSelectNestedGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ expect(API.getSelectedElements()[3].y).toEqual(300);
+
+ API.executeAction(actionAlignBottom);
+
+ expect(API.getSelectedElements()[0].y).toEqual(100);
+ expect(API.getSelectedElements()[1].y).toEqual(200);
+ expect(API.getSelectedElements()[2].y).toEqual(300);
+ expect(API.getSelectedElements()[3].y).toEqual(300);
+ });
+
+ it("aligns nested group and other element correctly to the left", () => {
+ createAndSelectNestedGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ expect(API.getSelectedElements()[3].x).toEqual(300);
+
+ API.executeAction(actionAlignLeft);
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ expect(API.getSelectedElements()[3].x).toEqual(0);
+ });
+
+ it("aligns nested group and other element correctly to the right", () => {
+ createAndSelectNestedGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ expect(API.getSelectedElements()[3].x).toEqual(300);
+
+ API.executeAction(actionAlignRight);
+
+ expect(API.getSelectedElements()[0].x).toEqual(100);
+ expect(API.getSelectedElements()[1].x).toEqual(200);
+ expect(API.getSelectedElements()[2].x).toEqual(300);
+ expect(API.getSelectedElements()[3].x).toEqual(300);
+ });
+
+ it("centers nested group and other element correctly vertically", () => {
+ createAndSelectNestedGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].y).toEqual(0);
+ expect(API.getSelectedElements()[1].y).toEqual(100);
+ expect(API.getSelectedElements()[2].y).toEqual(200);
+ expect(API.getSelectedElements()[3].y).toEqual(300);
+
+ API.executeAction(actionAlignVerticallyCentered);
+
+ expect(API.getSelectedElements()[0].y).toEqual(50);
+ expect(API.getSelectedElements()[1].y).toEqual(150);
+ expect(API.getSelectedElements()[2].y).toEqual(250);
+ expect(API.getSelectedElements()[3].y).toEqual(150);
+ });
+
+ it("centers nested group and other element correctly horizontally", () => {
+ createAndSelectNestedGroupAndRectangle();
+
+ expect(API.getSelectedElements()[0].x).toEqual(0);
+ expect(API.getSelectedElements()[1].x).toEqual(100);
+ expect(API.getSelectedElements()[2].x).toEqual(200);
+ expect(API.getSelectedElements()[3].x).toEqual(300);
+
+ API.executeAction(actionAlignHorizontallyCentered);
+
+ expect(API.getSelectedElements()[0].x).toEqual(50);
+ expect(API.getSelectedElements()[1].x).toEqual(150);
+ expect(API.getSelectedElements()[2].x).toEqual(250);
+ expect(API.getSelectedElements()[3].x).toEqual(150);
+ });
+});
diff --git a/packages/excalidraw/tests/appState.test.tsx b/packages/excalidraw/tests/appState.test.tsx
new file mode 100644
index 0000000..4a937cd
--- /dev/null
+++ b/packages/excalidraw/tests/appState.test.tsx
@@ -0,0 +1,81 @@
+import React from "react";
+import { fireEvent, queryByTestId, render, waitFor } from "./test-utils";
+import { Excalidraw } from "../index";
+import { API } from "./helpers/api";
+import { getDefaultAppState } from "../appState";
+import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants";
+import { Pointer, UI } from "./helpers/ui";
+import type { ExcalidrawTextElement } from "../element/types";
+
+const { h } = window;
+
+describe("appState", () => {
+ it("drag&drop file doesn't reset non-persisted appState", async () => {
+ const defaultAppState = getDefaultAppState();
+ const exportBackground = !defaultAppState.exportBackground;
+
+ await render(
+ ,
+ {},
+ );
+
+ await waitFor(() => {
+ expect(h.state.exportBackground).toBe(exportBackground);
+ expect(h.state.viewBackgroundColor).toBe("#F00");
+ });
+
+ await API.drop(
+ new Blob(
+ [
+ JSON.stringify({
+ type: EXPORT_DATA_TYPES.excalidraw,
+ appState: {
+ viewBackgroundColor: "#000",
+ },
+ elements: [API.createElement({ type: "rectangle", id: "A" })],
+ }),
+ ],
+ { type: MIME_TYPES.json },
+ ),
+ );
+
+ await waitFor(() => {
+ expect(h.elements).toEqual([expect.objectContaining({ id: "A" })]);
+ // non-imported prop → retain
+ expect(h.state.exportBackground).toBe(exportBackground);
+ // imported prop → overwrite
+ expect(h.state.viewBackgroundColor).toBe("#000");
+ });
+ });
+
+ it("changing fontSize with text tool selected (no element created yet)", async () => {
+ const { container } = await render(
+ ,
+ );
+
+ UI.clickTool("text");
+
+ expect(h.state.currentItemFontSize).toBe(30);
+ fireEvent.click(queryByTestId(container, "fontSize-small")!);
+ expect(h.state.currentItemFontSize).toBe(16);
+
+ const mouse = new Pointer("mouse");
+
+ mouse.clickAt(100, 100);
+
+ expect((h.elements[0] as ExcalidrawTextElement).fontSize).toBe(16);
+ });
+});
diff --git a/packages/excalidraw/tests/binding.test.tsx b/packages/excalidraw/tests/binding.test.tsx
new file mode 100644
index 0000000..905a44e
--- /dev/null
+++ b/packages/excalidraw/tests/binding.test.tsx
@@ -0,0 +1,481 @@
+import React from "react";
+import { fireEvent, render } from "./test-utils";
+import { Excalidraw, isLinearElement } from "../index";
+import { UI, Pointer, Keyboard } from "./helpers/ui";
+import { getTransformHandles } from "../element/transformHandles";
+import { API } from "./helpers/api";
+import { KEYS } from "../keys";
+import { actionWrapTextInContainer } from "../actions/actionBoundText";
+import { arrayToMap } from "../utils";
+import { pointFrom } from "@excalidraw/math";
+
+const { h } = window;
+
+const mouse = new Pointer("mouse");
+
+describe("element binding", () => {
+ beforeEach(async () => {
+ await render();
+ });
+
+ it("should create valid binding if duplicate start/end points", async () => {
+ const rect = API.createElement({
+ type: "rectangle",
+ x: 0,
+ y: 0,
+ width: 50,
+ height: 50,
+ });
+ const arrow = API.createElement({
+ type: "arrow",
+ x: 100,
+ y: 0,
+ width: 100,
+ height: 1,
+ points: [
+ pointFrom(0, 0),
+ pointFrom(0, 0),
+ pointFrom(100, 0),
+ pointFrom(100, 0),
+ ],
+ });
+ API.setElements([rect, arrow]);
+ expect(arrow.startBinding).toBe(null);
+
+ // select arrow
+ mouse.clickAt(150, 0);
+
+ // move arrow start to potential binding position
+ mouse.downAt(100, 0);
+ mouse.moveTo(55, 0);
+ mouse.up(0, 0);
+
+ // Point selection is evaluated like the points are rendered,
+ // from right to left. So clicking on the first point should move the joint,
+ // not the start point.
+ expect(arrow.startBinding).toBe(null);
+
+ // Now that the start point is free, move it into overlapping position
+ mouse.downAt(100, 0);
+ mouse.moveTo(55, 0);
+ mouse.up(0, 0);
+
+ expect(API.getSelectedElements()).toEqual([arrow]);
+
+ expect(arrow.startBinding).toEqual({
+ elementId: rect.id,
+ focus: expect.toBeNonNaNNumber(),
+ gap: expect.toBeNonNaNNumber(),
+ });
+
+ // Move the end point to the overlapping binding position
+ mouse.downAt(200, 0);
+ mouse.moveTo(55, 0);
+ mouse.up(0, 0);
+
+ // Both the start and the end points should be bound
+ expect(arrow.startBinding).toEqual({
+ elementId: rect.id,
+ focus: expect.toBeNonNaNNumber(),
+ gap: expect.toBeNonNaNNumber(),
+ });
+ expect(arrow.endBinding).toEqual({
+ elementId: rect.id,
+ focus: expect.toBeNonNaNNumber(),
+ gap: expect.toBeNonNaNNumber(),
+ });
+ });
+
+ //@TODO fix the test with rotation
+ it.skip("rotation of arrow should rebind both ends", () => {
+ const rectLeft = UI.createElement("rectangle", {
+ x: 0,
+ width: 200,
+ height: 500,
+ });
+ const rectRight = UI.createElement("rectangle", {
+ x: 400,
+ width: 200,
+ height: 500,
+ });
+ const arrow = UI.createElement("arrow", {
+ x: 210,
+ y: 250,
+ width: 180,
+ height: 1,
+ });
+ expect(arrow.startBinding?.elementId).toBe(rectLeft.id);
+ expect(arrow.endBinding?.elementId).toBe(rectRight.id);
+
+ const rotation = getTransformHandles(
+ arrow,
+ h.state.zoom,
+ arrayToMap(h.elements),
+ "mouse",
+ ).rotation!;
+ const rotationHandleX = rotation[0] + rotation[2] / 2;
+ const rotationHandleY = rotation[1] + rotation[3] / 2;
+ mouse.down(rotationHandleX, rotationHandleY);
+ mouse.move(300, 400);
+ mouse.up();
+ expect(arrow.angle).toBeGreaterThan(0.7 * Math.PI);
+ expect(arrow.angle).toBeLessThan(1.3 * Math.PI);
+ expect(arrow.startBinding?.elementId).toBe(rectRight.id);
+ expect(arrow.endBinding?.elementId).toBe(rectLeft.id);
+ });
+
+ // TODO fix & reenable once we rewrite tests to work with concurrency
+ it.skip(
+ "editing arrow and moving its head to bind it to element A, finalizing the" +
+ "editing by clicking on element A should end up selecting A",
+ async () => {
+ UI.createElement("rectangle", {
+ y: 0,
+ size: 100,
+ });
+ // Create arrow bound to rectangle
+ UI.clickTool("arrow");
+ mouse.down(50, -100);
+ mouse.up(0, 80);
+
+ // Edit arrow with multi-point
+ mouse.doubleClick();
+ // move arrow head
+ mouse.down();
+ mouse.up(0, 10);
+ expect(API.getSelectedElement().type).toBe("arrow");
+
+ // NOTE this mouse down/up + await needs to be done in order to repro
+ // the issue, due to https://github.com/excalidraw/excalidraw/blob/46bff3daceb602accf60c40a84610797260fca94/src/components/App.tsx#L740
+ mouse.reset();
+ expect(h.state.editingLinearElement).not.toBe(null);
+ mouse.down(0, 0);
+ await new Promise((r) => setTimeout(r, 100));
+ expect(h.state.editingLinearElement).toBe(null);
+ expect(API.getSelectedElement().type).toBe("rectangle");
+ mouse.up();
+ expect(API.getSelectedElement().type).toBe("rectangle");
+ },
+ );
+
+ it("should unbind arrow when moving it with keyboard", () => {
+ const rectangle = UI.createElement("rectangle", {
+ x: 75,
+ y: 0,
+ size: 100,
+ });
+
+ // Creates arrow 1px away from bidding with rectangle
+ const arrow = UI.createElement("arrow", {
+ x: 0,
+ y: 0,
+ size: 50,
+ });
+
+ expect(arrow.endBinding).toBe(null);
+
+ mouse.downAt(50, 50);
+ mouse.moveTo(51, 0);
+ mouse.up(0, 0);
+
+ // Test sticky connection
+ expect(API.getSelectedElement().type).toBe("arrow");
+ Keyboard.keyPress(KEYS.ARROW_RIGHT);
+ expect(arrow.endBinding?.elementId).toBe(rectangle.id);
+ Keyboard.keyPress(KEYS.ARROW_LEFT);
+ expect(arrow.endBinding?.elementId).toBe(rectangle.id);
+
+ // Sever connection
+ expect(API.getSelectedElement().type).toBe("arrow");
+ Keyboard.keyPress(KEYS.ARROW_LEFT);
+ expect(arrow.endBinding).toBe(null);
+ Keyboard.keyPress(KEYS.ARROW_RIGHT);
+ expect(arrow.endBinding).toBe(null);
+ });
+
+ it("should unbind on bound element deletion", () => {
+ const rectangle = UI.createElement("rectangle", {
+ x: 60,
+ y: 0,
+ size: 100,
+ });
+
+ const arrow = UI.createElement("arrow", {
+ x: 0,
+ y: 0,
+ size: 50,
+ });
+
+ expect(arrow.endBinding?.elementId).toBe(rectangle.id);
+
+ mouse.select(rectangle);
+ expect(API.getSelectedElement().type).toBe("rectangle");
+ Keyboard.keyDown(KEYS.DELETE);
+ expect(arrow.endBinding).toBe(null);
+ });
+
+ it("should unbind on text element deletion by submitting empty text", async () => {
+ const text = API.createElement({
+ type: "text",
+ text: "ola",
+ x: 60,
+ y: 0,
+ width: 100,
+ height: 100,
+ });
+
+ API.setElements([text]);
+
+ const arrow = UI.createElement("arrow", {
+ x: 0,
+ y: 0,
+ size: 50,
+ });
+
+ expect(arrow.endBinding?.elementId).toBe(text.id);
+
+ // edit text element and submit
+ // -------------------------------------------------------------------------
+
+ UI.clickTool("text");
+
+ mouse.clickAt(text.x + 50, text.y + 50);
+
+ const editor = document.querySelector(
+ ".excalidraw-textEditorContainer > textarea",
+ ) as HTMLTextAreaElement;
+
+ expect(editor).not.toBe(null);
+
+ fireEvent.change(editor, { target: { value: "" } });
+ fireEvent.keyDown(editor, { key: KEYS.ESCAPE });
+
+ expect(
+ document.querySelector(".excalidraw-textEditorContainer > textarea"),
+ ).toBe(null);
+ expect(arrow.endBinding).toBe(null);
+ });
+
+ it("should keep binding on text update", async () => {
+ const text = API.createElement({
+ type: "text",
+ text: "ola",
+ x: 60,
+ y: 0,
+ width: 100,
+ height: 100,
+ });
+
+ API.setElements([text]);
+
+ const arrow = UI.createElement("arrow", {
+ x: 0,
+ y: 0,
+ size: 50,
+ });
+
+ expect(arrow.endBinding?.elementId).toBe(text.id);
+
+ // delete text element by submitting empty text
+ // -------------------------------------------------------------------------
+
+ UI.clickTool("text");
+
+ mouse.clickAt(text.x + 50, text.y + 50);
+ const editor = document.querySelector(
+ ".excalidraw-textEditorContainer > textarea",
+ ) as HTMLTextAreaElement;
+
+ expect(editor).not.toBe(null);
+
+ fireEvent.change(editor, { target: { value: "asdasdasdasdas" } });
+ fireEvent.keyDown(editor, { key: KEYS.ESCAPE });
+
+ expect(
+ document.querySelector(".excalidraw-textEditorContainer > textarea"),
+ ).toBe(null);
+ expect(arrow.endBinding?.elementId).toBe(text.id);
+ });
+
+ it("should update binding when text containerized", async () => {
+ const rectangle1 = API.createElement({
+ type: "rectangle",
+ id: "rectangle1",
+ width: 100,
+ height: 100,
+ boundElements: [
+ { id: "arrow1", type: "arrow" },
+ { id: "arrow2", type: "arrow" },
+ ],
+ });
+
+ const arrow1 = API.createElement({
+ type: "arrow",
+ id: "arrow1",
+ points: [pointFrom(0, 0), pointFrom(0, -87.45777932247563)],
+ startBinding: {
+ elementId: "rectangle1",
+ focus: 0.2,
+ gap: 7,
+ fixedPoint: [0.5, 1],
+ },
+ endBinding: {
+ elementId: "text1",
+ focus: 0.2,
+ gap: 7,
+ fixedPoint: [1, 0.5],
+ },
+ });
+
+ const arrow2 = API.createElement({
+ type: "arrow",
+ id: "arrow2",
+ points: [pointFrom(0, 0), pointFrom(0, -87.45777932247563)],
+ startBinding: {
+ elementId: "text1",
+ focus: 0.2,
+ gap: 7,
+ fixedPoint: [0.5, 1],
+ },
+ endBinding: {
+ elementId: "rectangle1",
+ focus: 0.2,
+ gap: 7,
+ fixedPoint: [1, 0.5],
+ },
+ });
+
+ const text1 = API.createElement({
+ type: "text",
+ id: "text1",
+ text: "ola",
+ boundElements: [
+ { id: "arrow1", type: "arrow" },
+ { id: "arrow2", type: "arrow" },
+ ],
+ });
+
+ API.setElements([rectangle1, arrow1, arrow2, text1]);
+
+ API.setSelectedElements([text1]);
+
+ expect(h.state.selectedElementIds[text1.id]).toBe(true);
+
+ API.executeAction(actionWrapTextInContainer);
+
+ // new text container will be placed before the text element
+ const container = h.elements.at(-2)!;
+
+ expect(container.type).toBe("rectangle");
+ expect(container.id).not.toBe(rectangle1.id);
+
+ expect(container).toEqual(
+ expect.objectContaining({
+ boundElements: expect.arrayContaining([
+ {
+ type: "text",
+ id: text1.id,
+ },
+ {
+ type: "arrow",
+ id: arrow1.id,
+ },
+ {
+ type: "arrow",
+ id: arrow2.id,
+ },
+ ]),
+ }),
+ );
+
+ expect(arrow1.startBinding?.elementId).toBe(rectangle1.id);
+ expect(arrow1.endBinding?.elementId).toBe(container.id);
+ expect(arrow2.startBinding?.elementId).toBe(container.id);
+ expect(arrow2.endBinding?.elementId).toBe(rectangle1.id);
+ });
+
+ // #6459
+ it("should unbind arrow only from the latest element", () => {
+ const rectLeft = UI.createElement("rectangle", {
+ x: 0,
+ width: 200,
+ height: 500,
+ });
+ const rectRight = UI.createElement("rectangle", {
+ x: 400,
+ width: 200,
+ height: 500,
+ });
+ const arrow = UI.createElement("arrow", {
+ x: 210,
+ y: 250,
+ width: 180,
+ height: 1,
+ });
+ expect(arrow.startBinding?.elementId).toBe(rectLeft.id);
+ expect(arrow.endBinding?.elementId).toBe(rectRight.id);
+
+ // Drag arrow off of bound rectangle range
+ const handles = getTransformHandles(
+ arrow,
+ h.state.zoom,
+ arrayToMap(h.elements),
+ "mouse",
+ ).se!;
+
+ Keyboard.keyDown(KEYS.CTRL_OR_CMD);
+ const elX = handles[0] + handles[2] / 2;
+ const elY = handles[1] + handles[3] / 2;
+ mouse.downAt(elX, elY);
+ mouse.moveTo(300, 400);
+ mouse.up();
+
+ expect(arrow.startBinding).not.toBe(null);
+ expect(arrow.endBinding).toBe(null);
+ });
+
+ it("should not unbind when duplicating via selection group", () => {
+ const rectLeft = UI.createElement("rectangle", {
+ x: 0,
+ width: 200,
+ height: 500,
+ });
+ const rectRight = UI.createElement("rectangle", {
+ x: 400,
+ y: 200,
+ width: 200,
+ height: 500,
+ });
+ const arrow = UI.createElement("arrow", {
+ x: 210,
+ y: 250,
+ width: 177,
+ height: 1,
+ });
+ expect(arrow.startBinding?.elementId).toBe(rectLeft.id);
+ expect(arrow.endBinding?.elementId).toBe(rectRight.id);
+
+ mouse.downAt(-100, -100);
+ mouse.moveTo(650, 750);
+ mouse.up(0, 0);
+
+ expect(API.getSelectedElements().length).toBe(3);
+
+ mouse.moveTo(5, 5);
+ Keyboard.withModifierKeys({ alt: true }, () => {
+ mouse.downAt(5, 5);
+ mouse.moveTo(1000, 1000);
+ mouse.up(0, 0);
+
+ expect(window.h.elements.length).toBe(6);
+ window.h.elements.forEach((element) => {
+ if (isLinearElement(element)) {
+ expect(element.startBinding).not.toBe(null);
+ expect(element.endBinding).not.toBe(null);
+ } else {
+ expect(element.boundElements).not.toBe(null);
+ }
+ });
+ });
+ });
+});
diff --git a/packages/excalidraw/tests/charts.test.tsx b/packages/excalidraw/tests/charts.test.tsx
new file mode 100644
index 0000000..a4bce15
--- /dev/null
+++ b/packages/excalidraw/tests/charts.test.tsx
@@ -0,0 +1,13 @@
+import { tryParseSpreadsheet } from "../charts";
+
+describe("tryParseSpreadsheet", () => {
+ it("works for numbers with comma in them", () => {
+ const result = tryParseSpreadsheet(
+ `Week Index${"\t"}Users
+Week 1${"\t"}814
+Week 2${"\t"}10,301
+Week 3${"\t"}4,264`,
+ );
+ expect(result).toMatchSnapshot();
+ });
+});
diff --git a/packages/excalidraw/tests/clients.test.ts b/packages/excalidraw/tests/clients.test.ts
new file mode 100644
index 0000000..e78cf18
--- /dev/null
+++ b/packages/excalidraw/tests/clients.test.ts
@@ -0,0 +1,39 @@
+import { getNameInitial } from "../clients";
+
+describe("getClientInitials", () => {
+ it("returns substring if one name provided", () => {
+ expect(getNameInitial("Alan")).toBe("A");
+ });
+
+ it("returns initials", () => {
+ expect(getNameInitial("John Doe")).toBe("J");
+ });
+
+ it("returns correct initials if many names provided", () => {
+ expect(getNameInitial("John Alan Doe")).toBe("J");
+ });
+
+ it("returns single initial if 1 letter provided", () => {
+ expect(getNameInitial("z")).toBe("Z");
+ });
+
+ it("trims trailing whitespace", () => {
+ expect(getNameInitial(" q ")).toBe("Q");
+ });
+
+ it('returns "?" if falsey value provided', () => {
+ expect(getNameInitial("")).toBe("?");
+ expect(getNameInitial(undefined)).toBe("?");
+ expect(getNameInitial(null)).toBe("?");
+ });
+
+ it('returns "?" when value is blank', () => {
+ expect(getNameInitial(" ")).toBe("?");
+ });
+
+ it("works with multibyte strings", () => {
+ expect(getNameInitial("😀")).toBe("😀");
+ // but doesn't work with emoji ZWJ sequences
+ expect(getNameInitial("👨👩👦")).toBe("👨");
+ });
+});
diff --git a/packages/excalidraw/tests/clipboard.test.tsx b/packages/excalidraw/tests/clipboard.test.tsx
new file mode 100644
index 0000000..c2c0a5e
--- /dev/null
+++ b/packages/excalidraw/tests/clipboard.test.tsx
@@ -0,0 +1,521 @@
+import React from "react";
+import { vi } from "vitest";
+import {
+ render,
+ waitFor,
+ GlobalTestState,
+ unmountComponent,
+} from "./test-utils";
+import { Pointer, Keyboard } from "./helpers/ui";
+import { Excalidraw } from "../index";
+import { KEYS } from "../keys";
+import { getLineHeightInPx } from "../element/textMeasurements";
+import { getElementBounds } from "../element";
+import type { NormalizedZoomValue } from "../types";
+import { API } from "./helpers/api";
+import { createPasteEvent, serializeAsClipboardJSON } from "../clipboard";
+import { arrayToMap } from "../utils";
+import { mockMermaidToExcalidraw } from "./helpers/mocks";
+import { getLineHeight } from "../fonts";
+
+const { h } = window;
+
+const mouse = new Pointer("mouse");
+
+vi.mock("../keys.ts", async (importOriginal) => {
+ const module: any = await importOriginal();
+ return {
+ __esmodule: true,
+ ...module,
+ isDarwin: false,
+ KEYS: {
+ ...module.KEYS,
+ CTRL_OR_CMD: "ctrlKey",
+ },
+ };
+});
+
+const sendPasteEvent = (text: string) => {
+ const clipboardEvent = createPasteEvent({
+ types: {
+ "text/plain": text,
+ },
+ });
+ document.dispatchEvent(clipboardEvent);
+};
+
+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(text);
+ });
+};
+
+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(text);
+ });
+};
+
+const sleep = (ms: number) => {
+ return new Promise((resolve) => setTimeout(() => resolve(null), ms));
+};
+
+beforeEach(async () => {
+ unmountComponent();
+
+ localStorage.clear();
+
+ mouse.reset();
+
+ await render(
+ ,
+ );
+ Object.assign(document, {
+ elementFromPoint: () => GlobalTestState.canvas,
+ });
+});
+
+describe("general paste behavior", () => {
+ it("should randomize seed on paste", async () => {
+ const rectangle = API.createElement({ type: "rectangle" });
+ const clipboardJSON = await serializeAsClipboardJSON({
+ elements: [rectangle],
+ files: 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 serializeAsClipboardJSON({
+ elements: [rectangle],
+ files: 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";
+ pasteWithCtrlCmdV(text);
+ await waitFor(() => {
+ expect(h.elements.length).toEqual(text.split("\n").length);
+ });
+ });
+
+ it("should ignore empty lines when creating an element for each line", async () => {
+ const text = "\n\nsajgfakfn\n\n\naaksfnknas\n\nakefnkasf\n\n\n";
+ pasteWithCtrlCmdV(text);
+ await waitFor(() => {
+ expect(h.elements.length).toEqual(3);
+ });
+ });
+
+ it("should not create any element if clipboard has only new lines", async () => {
+ const text = "\n\n\n\n\n";
+ pasteWithCtrlCmdV(text);
+ await waitFor(async () => {
+ await sleep(50); // elements lenght will always be zero if we don't wait, since paste is async
+ expect(h.elements.length).toEqual(0);
+ });
+ });
+
+ it("should space items correctly", async () => {
+ const elementsMap = arrayToMap(h.elements);
+
+ const text = "hkhkjhki\njgkjhffjh\njgkjhffjh";
+ const lineHeightPx =
+ getLineHeightInPx(
+ h.app.state.currentItemFontSize,
+ getLineHeight(h.state.currentItemFontFamily),
+ ) +
+ 10 / h.app.state.zoom.value;
+ mouse.moveTo(100, 100);
+ pasteWithCtrlCmdV(text);
+ await waitFor(async () => {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const [fx, firstElY] = getElementBounds(h.elements[0], elementsMap);
+ for (let i = 1; i < h.elements.length; i++) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const [fx, elY] = getElementBounds(h.elements[i], elementsMap);
+ expect(elY).toEqual(firstElY + lineHeightPx * i);
+ }
+ });
+ });
+
+ it("should leave a space for blank new lines", async () => {
+ const elementsMap = arrayToMap(h.elements);
+ const text = "hkhkjhki\n\njgkjhffjh";
+ const lineHeightPx =
+ getLineHeightInPx(
+ h.app.state.currentItemFontSize,
+ getLineHeight(h.state.currentItemFontFamily),
+ ) +
+ 10 / h.app.state.zoom.value;
+ mouse.moveTo(100, 100);
+ pasteWithCtrlCmdV(text);
+
+ await waitFor(async () => {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const [fx, firstElY] = getElementBounds(h.elements[0], elementsMap);
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const [lx, lastElY] = getElementBounds(h.elements[1], elementsMap);
+ expect(lastElY).toEqual(firstElY + lineHeightPx * 2);
+ });
+ });
+});
+
+describe("paste text as a single element", () => {
+ it("should create single text element when copying text with Ctrl/Cmd+Shift+V", async () => {
+ const text = "sajgfakfn\naaksfnknas\nakefnkasf";
+ pasteWithCtrlCmdShiftV(text);
+ await waitFor(() => {
+ expect(h.elements.length).toEqual(1);
+ });
+ });
+ it("should not create any element when only new lines in clipboard", async () => {
+ const text = "\n\n\n\n";
+ pasteWithCtrlCmdShiftV(text);
+ await waitFor(async () => {
+ await sleep(50);
+ expect(h.elements.length).toEqual(0);
+ });
+ });
+});
+
+describe("Paste bound text container", () => {
+ const container = {
+ type: "ellipse",
+ id: "container-id",
+ x: 554.984375,
+ y: 196.0234375,
+ width: 166,
+ height: 187.01953125,
+ roundness: { type: 2 },
+ boundElements: [{ type: "text", id: "text-id" }],
+ };
+ const textElement = {
+ type: "text",
+ id: "text-id",
+ x: 560.51171875,
+ y: 202.033203125,
+ width: 154,
+ height: 175,
+ fontSize: 20,
+ fontFamily: 1,
+ text: "Excalidraw is a\nvirtual \nopensource \nwhiteboard for \nsketching \nhand-drawn like\ndiagrams",
+ baseline: 168,
+ textAlign: "center",
+ verticalAlign: "middle",
+ containerId: container.id,
+ originalText:
+ "Excalidraw is a virtual opensource whiteboard for sketching hand-drawn like diagrams",
+ };
+
+ it("should fix ellipse bounding box", async () => {
+ const data = JSON.stringify({
+ type: "excalidraw/clipboard",
+ elements: [container, textElement],
+ });
+ pasteWithCtrlCmdShiftV(data);
+
+ await waitFor(async () => {
+ await sleep(1);
+ expect(h.elements.length).toEqual(2);
+ const container = h.elements[0];
+ expect(container.height).toBe(368);
+ expect(container.width).toBe(166);
+ });
+ });
+
+ it("should fix diamond bounding box", async () => {
+ const data = JSON.stringify({
+ type: "excalidraw/clipboard",
+ elements: [
+ {
+ ...container,
+ type: "diamond",
+ },
+ textElement,
+ ],
+ });
+ pasteWithCtrlCmdShiftV(data);
+
+ await waitFor(async () => {
+ await sleep(1);
+ expect(h.elements.length).toEqual(2);
+ const container = h.elements[0];
+ expect(container.height).toBe(770);
+ expect(container.width).toBe(166);
+ });
+ });
+});
+
+describe("pasting & frames", () => {
+ it("should add pasted elements to frame under cursor", async () => {
+ const frame = API.createElement({
+ type: "frame",
+ width: 100,
+ height: 100,
+ x: 0,
+ y: 0,
+ });
+ const rect = API.createElement({ type: "rectangle" });
+
+ API.setElements([frame]);
+
+ const clipboardJSON = await serializeAsClipboardJSON({
+ elements: [rect],
+ files: null,
+ });
+
+ mouse.moveTo(50, 50);
+
+ pasteWithCtrlCmdV(clipboardJSON);
+
+ await waitFor(() => {
+ expect(h.elements.length).toBe(2);
+ expect(h.elements[1].type).toBe(rect.type);
+ expect(h.elements[1].frameId).toBe(frame.id);
+ });
+ });
+
+ it("should filter out elements not overlapping frame", async () => {
+ const frame = API.createElement({
+ type: "frame",
+ width: 100,
+ height: 100,
+ x: 0,
+ y: 0,
+ });
+ const rect = API.createElement({
+ type: "rectangle",
+ width: 50,
+ height: 50,
+ });
+ const rect2 = API.createElement({
+ type: "rectangle",
+ width: 50,
+ height: 50,
+ x: 100,
+ y: 100,
+ });
+
+ API.setElements([frame]);
+
+ const clipboardJSON = await serializeAsClipboardJSON({
+ elements: [rect, rect2],
+ files: null,
+ });
+
+ mouse.moveTo(90, 90);
+
+ pasteWithCtrlCmdV(clipboardJSON);
+
+ await waitFor(() => {
+ expect(h.elements.length).toBe(3);
+ expect(h.elements[1].type).toBe(rect.type);
+ expect(h.elements[1].frameId).toBe(frame.id);
+ expect(h.elements[2].type).toBe(rect2.type);
+ expect(h.elements[2].frameId).toBe(null);
+ });
+ });
+
+ it("should not filter out elements not overlapping frame if part of group", async () => {
+ const frame = API.createElement({
+ type: "frame",
+ width: 100,
+ height: 100,
+ x: 0,
+ y: 0,
+ });
+ const rect = API.createElement({
+ type: "rectangle",
+ width: 50,
+ height: 50,
+ groupIds: ["g1"],
+ });
+ const rect2 = API.createElement({
+ type: "rectangle",
+ width: 50,
+ height: 50,
+ x: 100,
+ y: 100,
+ groupIds: ["g1"],
+ });
+
+ API.setElements([frame]);
+
+ const clipboardJSON = await serializeAsClipboardJSON({
+ elements: [rect, rect2],
+ files: null,
+ });
+
+ mouse.moveTo(90, 90);
+
+ pasteWithCtrlCmdV(clipboardJSON);
+
+ await waitFor(() => {
+ expect(h.elements.length).toBe(3);
+ expect(h.elements[1].type).toBe(rect.type);
+ expect(h.elements[1].frameId).toBe(frame.id);
+ expect(h.elements[2].type).toBe(rect2.type);
+ expect(h.elements[2].frameId).toBe(frame.id);
+ });
+ });
+
+ it("should not filter out other frames and their children", async () => {
+ const frame = API.createElement({
+ type: "frame",
+ width: 100,
+ height: 100,
+ x: 0,
+ y: 0,
+ });
+ const rect = API.createElement({
+ type: "rectangle",
+ width: 50,
+ height: 50,
+ groupIds: ["g1"],
+ });
+
+ const frame2 = API.createElement({
+ type: "frame",
+ width: 75,
+ height: 75,
+ x: 0,
+ y: 0,
+ });
+ const rect2 = API.createElement({
+ type: "rectangle",
+ width: 50,
+ height: 50,
+ x: 55,
+ y: 55,
+ frameId: frame2.id,
+ });
+
+ API.setElements([frame]);
+
+ const clipboardJSON = await serializeAsClipboardJSON({
+ elements: [rect, rect2, frame2],
+ files: null,
+ });
+
+ mouse.moveTo(90, 90);
+
+ pasteWithCtrlCmdV(clipboardJSON);
+
+ await waitFor(() => {
+ expect(h.elements.length).toBe(4);
+ expect(h.elements[1].type).toBe(rect.type);
+ expect(h.elements[1].frameId).toBe(frame.id);
+ expect(h.elements[2].type).toBe(rect2.type);
+ expect(h.elements[2].frameId).toBe(h.elements[3].id);
+ expect(h.elements[3].type).toBe(frame2.type);
+ expect(h.elements[3].frameId).toBe(null);
+ });
+ });
+});
+
+describe("clipboard - pasting mermaid definition", () => {
+ beforeAll(() => {
+ mockMermaidToExcalidraw({
+ parseMermaidToExcalidraw: async (definition) => {
+ const lines = definition.split("\n");
+ return new Promise((resolve, reject) => {
+ if (lines.some((line) => line === "flowchart TD")) {
+ resolve({
+ elements: [
+ {
+ id: "rect1",
+ type: "rectangle",
+ groupIds: [],
+ x: 0,
+ y: 0,
+ width: 69.703125,
+ height: 44,
+ strokeWidth: 2,
+ label: {
+ groupIds: [],
+ text: "A",
+ fontSize: 20,
+ },
+ link: null,
+ },
+ ],
+ });
+ } else {
+ reject(new Error("ERROR"));
+ }
+ });
+ },
+ });
+ });
+
+ it("should detect and paste as mermaid", async () => {
+ const text = "flowchart TD\nA";
+
+ pasteWithCtrlCmdV(text);
+ await waitFor(() => {
+ expect(h.elements.length).toEqual(2);
+ expect(h.elements).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({ type: "rectangle" }),
+ expect.objectContaining({ type: "text", text: "A" }),
+ ]),
+ );
+ });
+ });
+
+ it("should support directives", async () => {
+ const text = "%%{init: { **config** } }%%\nflowchart TD\nA";
+
+ pasteWithCtrlCmdV(text);
+ await waitFor(() => {
+ expect(h.elements.length).toEqual(2);
+ expect(h.elements).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({ type: "rectangle" }),
+ expect.objectContaining({ type: "text", text: "A" }),
+ ]),
+ );
+ });
+ });
+
+ it("should paste as normal text if invalid mermaid", async () => {
+ const text = "flowchart TD xx\nA";
+ pasteWithCtrlCmdV(text);
+ await waitFor(() => {
+ expect(h.elements.length).toEqual(2);
+ expect(h.elements).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({ type: "text", text: "flowchart TD xx" }),
+ expect.objectContaining({ type: "text", text: "A" }),
+ ]),
+ );
+ });
+ });
+});
diff --git a/packages/excalidraw/tests/contextmenu.test.tsx b/packages/excalidraw/tests/contextmenu.test.tsx
new file mode 100644
index 0000000..bb3f415
--- /dev/null
+++ b/packages/excalidraw/tests/contextmenu.test.tsx
@@ -0,0 +1,625 @@
+import React from "react";
+import {
+ render,
+ fireEvent,
+ mockBoundingClientRect,
+ restoreOriginalGetBoundingClientRect,
+ GlobalTestState,
+ screen,
+ queryByText,
+ queryAllByText,
+ waitFor,
+ togglePopover,
+ unmountComponent,
+} from "./test-utils";
+import { Excalidraw } from "../index";
+import * as StaticScene from "../renderer/staticScene";
+import { reseed } from "../random";
+import { UI, Pointer, Keyboard } from "./helpers/ui";
+import { KEYS } from "../keys";
+import type { ShortcutName } from "../actions/shortcuts";
+import { copiedStyles } from "../actions/actionStyles";
+import { API } from "./helpers/api";
+import { setDateTimeForTests } from "../utils";
+import { vi } from "vitest";
+import type { ActionName } from "../actions/types";
+
+const checkpoint = (name: string) => {
+ expect(renderStaticScene.mock.calls.length).toMatchSnapshot(
+ `[${name}] number of renders`,
+ );
+ expect(h.state).toMatchSnapshot(`[${name}] appState`);
+ expect(h.history).toMatchSnapshot(`[${name}] history`);
+ expect(h.elements.length).toMatchSnapshot(`[${name}] number of elements`);
+ h.elements.forEach((element, i) =>
+ expect(element).toMatchSnapshot(`[${name}] element ${i}`),
+ );
+};
+
+const mouse = new Pointer("mouse");
+
+unmountComponent();
+
+const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene");
+beforeEach(() => {
+ localStorage.clear();
+ renderStaticScene.mockClear();
+ reseed(7);
+});
+
+const { h } = window;
+
+describe("contextMenu element", () => {
+ beforeEach(async () => {
+ localStorage.clear();
+ renderStaticScene.mockClear();
+ reseed(7);
+ setDateTimeForTests("201933152653");
+
+ await render();
+ });
+
+ beforeAll(() => {
+ mockBoundingClientRect();
+ });
+
+ afterAll(() => {
+ restoreOriginalGetBoundingClientRect();
+ });
+
+ afterEach(() => {
+ checkpoint("end of test");
+
+ mouse.reset();
+ mouse.down(0, 0);
+ });
+
+ it("shows context menu for canvas", () => {
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 1,
+ clientY: 1,
+ });
+ const contextMenu = UI.queryContextMenu();
+ const contextMenuOptions =
+ contextMenu?.querySelectorAll(".context-menu li");
+ const expectedShortcutNames: ShortcutName[] = [
+ "paste",
+ "selectAll",
+ "gridMode",
+ "zenMode",
+ "viewMode",
+ "objectsSnapMode",
+ "stats",
+ ];
+
+ expect(contextMenu).not.toBeNull();
+ expect(contextMenuOptions?.length).toBe(expectedShortcutNames.length);
+ expectedShortcutNames.forEach((shortcutName) => {
+ expect(
+ contextMenu?.querySelector(`li[data-testid="${shortcutName}"]`),
+ ).not.toBeNull();
+ });
+ });
+
+ it("shows context menu for element", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+ const contextMenu = UI.queryContextMenu();
+ const contextMenuOptions =
+ contextMenu?.querySelectorAll(".context-menu li");
+ const expectedContextMenuItems: ActionName[] = [
+ "cut",
+ "copy",
+ "paste",
+ "wrapSelectionInFrame",
+ "copyStyles",
+ "pasteStyles",
+ "deleteSelectedElements",
+ "addToLibrary",
+ "flipHorizontal",
+ "flipVertical",
+ "sendBackward",
+ "bringForward",
+ "sendToBack",
+ "bringToFront",
+ "duplicateSelection",
+ "hyperlink",
+ "copyElementLink",
+ "toggleElementLock",
+ ];
+
+ expect(contextMenu).not.toBeNull();
+ expect(contextMenuOptions?.length).toBe(expectedContextMenuItems.length);
+ expectedContextMenuItems.forEach((item) => {
+ expect(
+ contextMenu?.querySelector(`li[data-testid="${item}"]`),
+ ).not.toBeNull();
+ });
+ });
+
+ it("shows context menu for element", () => {
+ const rect1 = API.createElement({
+ type: "rectangle",
+ x: 0,
+ y: 0,
+ height: 200,
+ width: 200,
+ backgroundColor: "red",
+ });
+ const rect2 = API.createElement({
+ type: "rectangle",
+ x: 0,
+ y: 0,
+ height: 200,
+ width: 200,
+ backgroundColor: "red",
+ });
+ API.setElements([rect1, rect2]);
+ API.setSelectedElements([rect1]);
+
+ // lower z-index
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 100,
+ clientY: 100,
+ });
+ expect(UI.queryContextMenu()).not.toBeNull();
+ expect(API.getSelectedElement().id).toBe(rect1.id);
+
+ // higher z-index
+ API.setSelectedElements([rect2]);
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 100,
+ clientY: 100,
+ });
+ expect(UI.queryContextMenu()).not.toBeNull();
+ expect(API.getSelectedElement().id).toBe(rect2.id);
+ });
+
+ it("shows 'Group selection' in context menu for multiple selected elements", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(10, 10);
+
+ UI.clickTool("rectangle");
+ mouse.down(12, -10);
+ mouse.up(10, 10);
+
+ mouse.reset();
+ mouse.click(10, 10);
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click(22, 0);
+ });
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+
+ const contextMenu = UI.queryContextMenu();
+ const contextMenuOptions =
+ contextMenu?.querySelectorAll(".context-menu li");
+ const expectedShortcutNames: ShortcutName[] = [
+ "cut",
+ "copy",
+ "paste",
+ "wrapSelectionInFrame",
+ "copyStyles",
+ "pasteStyles",
+ "deleteSelectedElements",
+ "group",
+ "addToLibrary",
+ "flipHorizontal",
+ "flipVertical",
+ "sendBackward",
+ "bringForward",
+ "sendToBack",
+ "bringToFront",
+ "duplicateSelection",
+ "toggleElementLock",
+ ];
+
+ expect(contextMenu).not.toBeNull();
+ expect(contextMenuOptions?.length).toBe(expectedShortcutNames.length);
+ expectedShortcutNames.forEach((shortcutName) => {
+ expect(
+ contextMenu?.querySelector(`li[data-testid="${shortcutName}"]`),
+ ).not.toBeNull();
+ });
+ });
+
+ it("shows 'Ungroup selection' in context menu for group inside selected elements", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(10, 10);
+
+ UI.clickTool("rectangle");
+ mouse.down(12, -10);
+ mouse.up(10, 10);
+
+ mouse.reset();
+ mouse.click(10, 10);
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click(22, 0);
+ });
+
+ Keyboard.withModifierKeys({ ctrl: true }, () => {
+ Keyboard.keyPress(KEYS.G);
+ });
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+
+ const contextMenu = UI.queryContextMenu();
+ const contextMenuOptions =
+ contextMenu?.querySelectorAll(".context-menu li");
+ const expectedContextMenuItems: ActionName[] = [
+ "cut",
+ "copy",
+ "paste",
+ "wrapSelectionInFrame",
+ "copyStyles",
+ "pasteStyles",
+ "deleteSelectedElements",
+ "copyElementLink",
+ "ungroup",
+ "addToLibrary",
+ "flipHorizontal",
+ "flipVertical",
+ "sendBackward",
+ "bringForward",
+ "sendToBack",
+ "bringToFront",
+ "duplicateSelection",
+ "toggleElementLock",
+ ];
+
+ expect(contextMenu).not.toBeNull();
+ expect(contextMenuOptions?.length).toBe(expectedContextMenuItems.length);
+ expectedContextMenuItems.forEach((item) => {
+ expect(
+ contextMenu?.querySelector(`li[data-testid="${item}"]`),
+ ).not.toBeNull();
+ });
+ });
+
+ it("selecting 'Copy styles' in context menu copies styles", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+ const contextMenu = UI.queryContextMenu();
+ expect(copiedStyles).toBe("{}");
+ fireEvent.click(queryByText(contextMenu!, "Copy styles")!);
+ expect(copiedStyles).not.toBe("{}");
+ const element = JSON.parse(copiedStyles)[0];
+ expect(element).toEqual(API.getSelectedElement());
+ });
+
+ it("selecting 'Paste styles' in context menu pastes styles", () => {
+ 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" },
+ });
+
+ // closing the background popover as this blocks
+ // context menu from rendering after we started focussing
+ // the popover once rendered :/
+ togglePopover("Background");
+
+ mouse.reset();
+
+ // Copy styles of second rectangle
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 40,
+ clientY: 40,
+ });
+
+ let contextMenu = UI.queryContextMenu();
+ fireEvent.click(queryByText(contextMenu!, "Copy styles")!);
+ const secondRect = JSON.parse(copiedStyles)[0];
+ expect(secondRect.id).toBe(h.elements[1].id);
+
+ mouse.reset();
+ // Paste styles to first rectangle
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 10,
+ clientY: 10,
+ });
+ contextMenu = UI.queryContextMenu();
+ fireEvent.click(queryByText(contextMenu!, "Paste styles")!);
+
+ 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);
+ });
+
+ it("selecting 'Delete' in context menu deletes element", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+ const contextMenu = UI.queryContextMenu();
+ fireEvent.click(queryAllByText(contextMenu!, "Delete")[0]);
+ expect(API.getSelectedElements()).toHaveLength(0);
+ expect(h.elements[0].isDeleted).toBe(true);
+ });
+
+ it("selecting 'Add to library' in context menu adds element to library", async () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+ const contextMenu = UI.queryContextMenu();
+ fireEvent.click(queryByText(contextMenu!, "Add to library")!);
+
+ await waitFor(async () => {
+ const libraryItems = await h.app.library.getLatestLibrary();
+ expect(libraryItems[0].elements[0]).toEqual(h.elements[0]);
+ });
+ });
+
+ it("selecting 'Duplicate' in context menu duplicates element", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+ const contextMenu = UI.queryContextMenu();
+ fireEvent.click(queryByText(contextMenu!, "Duplicate")!);
+ expect(h.elements).toHaveLength(2);
+ const {
+ id: _id0,
+ seed: _seed0,
+ x: _x0,
+ y: _y0,
+ index: _fractionalIndex0,
+ version: _version0,
+ versionNonce: _versionNonce0,
+ ...rect1
+ } = h.elements[0];
+ const {
+ id: _id1,
+ seed: _seed1,
+ x: _x1,
+ y: _y1,
+ index: _fractionalIndex1,
+ version: _version1,
+ versionNonce: _versionNonce1,
+ ...rect2
+ } = h.elements[1];
+ expect(rect1).toEqual(rect2);
+ });
+
+ it("selecting 'Send backward' in context menu sends element backward", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ mouse.reset();
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 40,
+ clientY: 40,
+ });
+ const contextMenu = UI.queryContextMenu();
+ const elementsBefore = h.elements;
+ fireEvent.click(queryByText(contextMenu!, "Send backward")!);
+ expect(elementsBefore[0].id).toEqual(h.elements[1].id);
+ expect(elementsBefore[1].id).toEqual(h.elements[0].id);
+ });
+
+ it("selecting 'Bring forward' in context menu brings element forward", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ mouse.reset();
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 10,
+ clientY: 10,
+ });
+ const contextMenu = UI.queryContextMenu();
+ const elementsBefore = h.elements;
+ fireEvent.click(queryByText(contextMenu!, "Bring forward")!);
+ expect(elementsBefore[0].id).toEqual(h.elements[1].id);
+ expect(elementsBefore[1].id).toEqual(h.elements[0].id);
+ });
+
+ it("selecting 'Send to back' in context menu sends element to back", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ mouse.reset();
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 40,
+ clientY: 40,
+ });
+ const contextMenu = UI.queryContextMenu();
+ const elementsBefore = h.elements;
+ fireEvent.click(queryByText(contextMenu!, "Send to back")!);
+ expect(elementsBefore[1].id).toEqual(h.elements[0].id);
+ });
+
+ it("selecting 'Bring to front' in context menu brings element to front", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ mouse.reset();
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 10,
+ clientY: 10,
+ });
+ const contextMenu = UI.queryContextMenu();
+ const elementsBefore = h.elements;
+ fireEvent.click(queryByText(contextMenu!, "Bring to front")!);
+ expect(elementsBefore[0].id).toEqual(h.elements[1].id);
+ });
+
+ it("selecting 'Group selection' in context menu groups selected elements", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click(10, 10);
+ });
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+ const contextMenu = UI.queryContextMenu();
+ fireEvent.click(queryByText(contextMenu!, "Group selection")!);
+ const selectedGroupIds = Object.keys(h.state.selectedGroupIds);
+ expect(h.elements[0].groupIds).toEqual(selectedGroupIds);
+ expect(h.elements[1].groupIds).toEqual(selectedGroupIds);
+ });
+
+ it("selecting 'Ungroup selection' in context menu ungroups selected group", () => {
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ UI.clickTool("rectangle");
+ mouse.down(10, 10);
+ mouse.up(20, 20);
+
+ mouse.reset();
+ Keyboard.withModifierKeys({ shift: true }, () => {
+ mouse.click(10, 10);
+ });
+
+ Keyboard.withModifierKeys({ ctrl: true }, () => {
+ Keyboard.keyPress(KEYS.G);
+ });
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 3,
+ clientY: 3,
+ });
+
+ const contextMenu = UI.queryContextMenu();
+ expect(contextMenu).not.toBeNull();
+ fireEvent.click(queryByText(contextMenu!, "Ungroup selection")!);
+
+ const selectedGroupIds = Object.keys(h.state.selectedGroupIds);
+ expect(selectedGroupIds).toHaveLength(0);
+ expect(h.elements[0].groupIds).toHaveLength(0);
+ expect(h.elements[1].groupIds).toHaveLength(0);
+ });
+
+ it("right-clicking on a group should select whole group", () => {
+ const rectangle1 = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ groupIds: ["g1"],
+ });
+ const rectangle2 = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ groupIds: ["g1"],
+ });
+ API.setElements([rectangle1, rectangle2]);
+
+ mouse.rightClickAt(50, 50);
+ expect(API.getSelectedElements().length).toBe(2);
+ expect(API.getSelectedElements()).toEqual([
+ expect.objectContaining({ id: rectangle1.id }),
+ expect.objectContaining({ id: rectangle2.id }),
+ ]);
+ });
+});
diff --git a/packages/excalidraw/tests/cropElement.test.tsx b/packages/excalidraw/tests/cropElement.test.tsx
new file mode 100644
index 0000000..a508f5d
--- /dev/null
+++ b/packages/excalidraw/tests/cropElement.test.tsx
@@ -0,0 +1,342 @@
+import React from "react";
+import { vi } from "vitest";
+import { Keyboard, Pointer, UI } from "./helpers/ui";
+import type { ExcalidrawImageElement, ImageCrop } from "../element/types";
+import { act, GlobalTestState, render, unmountComponent } from "./test-utils";
+import { Excalidraw, exportToCanvas, exportToSvg } from "..";
+import { API } from "./helpers/api";
+import type { NormalizedZoomValue } from "../types";
+import { KEYS } from "../keys";
+import { duplicateElement } from "../element";
+import { cloneJSON } from "../utils";
+import { actionFlipHorizontal, actionFlipVertical } from "../actions";
+
+const { h } = window;
+const mouse = new Pointer("mouse");
+
+beforeEach(async () => {
+ unmountComponent();
+
+ mouse.reset();
+ localStorage.clear();
+ sessionStorage.clear();
+ vi.clearAllMocks();
+
+ Object.assign(document, {
+ elementFromPoint: () => GlobalTestState.canvas,
+ });
+ await render();
+ API.setAppState({
+ zoom: {
+ value: 1 as NormalizedZoomValue,
+ },
+ });
+
+ const image = API.createElement({ type: "image", width: 200, height: 100 });
+ API.setElements([image]);
+ API.setAppState({
+ selectedElementIds: {
+ [image.id]: true,
+ },
+ });
+});
+
+const generateRandomNaturalWidthAndHeight = (image: ExcalidrawImageElement) => {
+ const initialWidth = image.width;
+ const initialHeight = image.height;
+
+ const scale = 1 + Math.random() * 5;
+
+ return {
+ naturalWidth: initialWidth * scale,
+ naturalHeight: initialHeight * scale,
+ };
+};
+
+const compareCrops = (cropA: ImageCrop, cropB: ImageCrop) => {
+ (Object.keys(cropA) as [keyof ImageCrop]).forEach((key) => {
+ const propA = cropA[key];
+ const propB = cropB[key];
+
+ expect(propA as number).toBeCloseTo(propB as number);
+ });
+};
+
+describe("Enter and leave the crop editor", () => {
+ it("enter the editor by double clicking", () => {
+ const image = h.elements[0];
+ expect(h.state.croppingElementId).toBe(null);
+ mouse.doubleClickOn(image);
+ expect(h.state.croppingElementId).not.toBe(null);
+ expect(h.state.croppingElementId).toBe(image.id);
+ });
+
+ it("enter the editor by pressing enter", () => {
+ const image = h.elements[0];
+ expect(h.state.croppingElementId).toBe(null);
+ Keyboard.keyDown(KEYS.ENTER);
+ expect(h.state.croppingElementId).not.toBe(null);
+ expect(h.state.croppingElementId).toBe(image.id);
+ });
+
+ it("leave the editor by clicking outside", () => {
+ const image = h.elements[0];
+ Keyboard.keyDown(KEYS.ENTER);
+ expect(h.state.croppingElementId).not.toBe(null);
+
+ mouse.click(image.x - 20, image.y - 20);
+ expect(h.state.croppingElementId).toBe(null);
+ });
+
+ it("leave the editor by pressing escape", () => {
+ const image = h.elements[0];
+ mouse.doubleClickOn(image);
+ expect(h.state.croppingElementId).not.toBe(null);
+
+ Keyboard.keyDown(KEYS.ESCAPE);
+ expect(h.state.croppingElementId).toBe(null);
+ });
+});
+
+describe("Crop an image", () => {
+ it("Cropping changes the dimension", async () => {
+ const image = h.elements[0] as ExcalidrawImageElement;
+
+ const initialWidth = image.width;
+ const initialHeight = image.height;
+
+ const { naturalWidth, naturalHeight } =
+ generateRandomNaturalWidthAndHeight(image);
+
+ UI.crop(image, "w", naturalWidth, naturalHeight, [initialWidth / 2, 0]);
+
+ expect(image.width).toBeLessThan(initialWidth);
+ UI.crop(image, "n", naturalWidth, naturalHeight, [0, initialHeight / 2]);
+ expect(image.height).toBeLessThan(initialHeight);
+ });
+
+ it("Cropping has minimal sizes", async () => {
+ const image = h.elements[0] as ExcalidrawImageElement;
+ const initialWidth = image.width;
+ const initialHeight = image.height;
+
+ const { naturalWidth, naturalHeight } =
+ generateRandomNaturalWidthAndHeight(image);
+
+ UI.crop(image, "w", naturalWidth, naturalHeight, [initialWidth, 0]);
+ expect(image.width).toBeLessThan(initialWidth);
+ expect(image.width).toBeGreaterThan(0);
+ UI.crop(image, "w", naturalWidth, naturalHeight, [-initialWidth, 0]);
+ UI.crop(image, "n", naturalWidth, naturalHeight, [0, initialHeight]);
+ expect(image.height).toBeLessThan(initialHeight);
+ expect(image.height).toBeGreaterThan(0);
+ });
+
+ it("Preserve aspect ratio", async () => {
+ let image = h.elements[0] as ExcalidrawImageElement;
+ const initialWidth = image.width;
+ const initialHeight = image.height;
+
+ const { naturalWidth, naturalHeight } =
+ generateRandomNaturalWidthAndHeight(image);
+
+ UI.crop(image, "w", naturalWidth, naturalHeight, [initialWidth / 3, 0]);
+
+ let resizedWidth = image.width;
+ let resizedHeight = image.height;
+
+ // max height, cropping should not change anything
+ UI.crop(
+ image,
+ "w",
+ naturalWidth,
+ naturalHeight,
+ [-initialWidth / 3, 0],
+ true,
+ );
+ expect(image.width).toBeCloseTo(resizedWidth, 10);
+ expect(image.height).toBeCloseTo(resizedHeight, 10);
+
+ // re-crop to initial state
+ UI.crop(image, "w", naturalWidth, naturalHeight, [-initialWidth / 3, 0]);
+ // change crop height and width
+ UI.crop(image, "s", naturalWidth, naturalHeight, [0, -initialHeight / 2]);
+ UI.crop(image, "e", naturalWidth, naturalHeight, [-initialWidth / 3, 0]);
+
+ resizedWidth = image.width;
+ resizedHeight = image.height;
+
+ // test corner handle aspect ratio preserving
+ UI.crop(image, "se", naturalWidth, naturalHeight, [initialWidth, 0], true);
+ expect(image.width / image.height).toBe(resizedWidth / resizedHeight);
+ expect(image.width).toBeLessThanOrEqual(initialWidth + 0.0001);
+ expect(image.height).toBeLessThanOrEqual(initialHeight + 0.0001);
+
+ // reset
+ image = API.createElement({ type: "image", width: 200, height: 100 });
+ API.setElements([image]);
+ API.setAppState({
+ selectedElementIds: {
+ [image.id]: true,
+ },
+ });
+
+ // 50 x 50 square
+ UI.crop(image, "nw", naturalWidth, naturalHeight, [150, 50]);
+ UI.crop(image, "n", naturalWidth, naturalHeight, [0, -100], true);
+ expect(image.width).toBeCloseTo(image.height);
+ // image is at the corner, not space to its right to expand, should not be able to resize
+ expect(image.height).toBeCloseTo(50);
+
+ UI.crop(image, "nw", naturalWidth, naturalHeight, [-150, -100], true);
+ expect(image.width).toBeCloseTo(image.height);
+ // max height should be reached
+ expect(image.height).toBeCloseTo(initialHeight);
+ expect(image.width).toBeCloseTo(initialHeight);
+ });
+});
+
+describe("Cropping and other features", async () => {
+ it("Cropping works independently of duplication", async () => {
+ const image = h.elements[0] as ExcalidrawImageElement;
+ const initialWidth = image.width;
+ const initialHeight = image.height;
+
+ const { naturalWidth, naturalHeight } =
+ generateRandomNaturalWidthAndHeight(image);
+
+ UI.crop(image, "nw", naturalWidth, naturalHeight, [
+ initialWidth / 2,
+ initialHeight / 2,
+ ]);
+ Keyboard.keyDown(KEYS.ESCAPE);
+ const duplicatedImage = duplicateElement(null, new Map(), image, {});
+ act(() => {
+ h.app.scene.insertElement(duplicatedImage);
+ });
+
+ expect(duplicatedImage.width).toBe(image.width);
+ expect(duplicatedImage.height).toBe(image.height);
+
+ UI.crop(duplicatedImage, "nw", naturalWidth, naturalHeight, [
+ -initialWidth / 2,
+ -initialHeight / 2,
+ ]);
+ expect(duplicatedImage.width).toBe(initialWidth);
+ expect(duplicatedImage.height).toBe(initialHeight);
+ const resizedWidth = image.width;
+ const resizedHeight = image.height;
+
+ expect(image.width).not.toBe(duplicatedImage.width);
+ expect(image.height).not.toBe(duplicatedImage.height);
+ UI.crop(duplicatedImage, "se", naturalWidth, naturalHeight, [
+ -initialWidth / 1.5,
+ -initialHeight / 1.5,
+ ]);
+ expect(duplicatedImage.width).not.toBe(initialWidth);
+ expect(image.width).toBe(resizedWidth);
+ expect(duplicatedImage.height).not.toBe(initialHeight);
+ expect(image.height).toBe(resizedHeight);
+ });
+
+ it("Resizing should not affect crop", async () => {
+ const image = h.elements[0] as ExcalidrawImageElement;
+ const initialWidth = image.width;
+ const initialHeight = image.height;
+
+ const { naturalWidth, naturalHeight } =
+ generateRandomNaturalWidthAndHeight(image);
+
+ UI.crop(image, "nw", naturalWidth, naturalHeight, [
+ initialWidth / 2,
+ initialHeight / 2,
+ ]);
+ const cropBeforeResizing = image.crop;
+ const cropBeforeResizingCloned = cloneJSON(image.crop) as ImageCrop;
+ expect(cropBeforeResizing).not.toBe(null);
+
+ UI.crop(image, "e", naturalWidth, naturalHeight, [200, 0]);
+ expect(cropBeforeResizing).toBe(image.crop);
+ compareCrops(cropBeforeResizingCloned, image.crop!);
+
+ UI.resize(image, "s", [0, -100]);
+ expect(cropBeforeResizing).toBe(image.crop);
+ compareCrops(cropBeforeResizingCloned, image.crop!);
+
+ UI.resize(image, "ne", [-50, -50]);
+ expect(cropBeforeResizing).toBe(image.crop);
+ compareCrops(cropBeforeResizingCloned, image.crop!);
+ });
+
+ it("Flipping does not change crop", async () => {
+ const image = h.elements[0] as ExcalidrawImageElement;
+ const initialWidth = image.width;
+ const initialHeight = image.height;
+
+ const { naturalWidth, naturalHeight } =
+ generateRandomNaturalWidthAndHeight(image);
+
+ mouse.doubleClickOn(image);
+ expect(h.state.croppingElementId).not.toBe(null);
+ UI.crop(image, "nw", naturalWidth, naturalHeight, [
+ initialWidth / 2,
+ initialHeight / 2,
+ ]);
+ Keyboard.keyDown(KEYS.ESCAPE);
+ const cropBeforeResizing = image.crop;
+ const cropBeforeResizingCloned = cloneJSON(image.crop) as ImageCrop;
+
+ API.executeAction(actionFlipHorizontal);
+ expect(image.crop).toBe(cropBeforeResizing);
+ compareCrops(cropBeforeResizingCloned, image.crop!);
+
+ API.executeAction(actionFlipVertical);
+ expect(image.crop).toBe(cropBeforeResizing);
+ compareCrops(cropBeforeResizingCloned, image.crop!);
+ });
+
+ it("Exports should preserve crops", async () => {
+ const image = h.elements[0] as ExcalidrawImageElement;
+ const initialWidth = image.width;
+ const initialHeight = image.height;
+
+ const { naturalWidth, naturalHeight } =
+ generateRandomNaturalWidthAndHeight(image);
+
+ mouse.doubleClickOn(image);
+ expect(h.state.croppingElementId).not.toBe(null);
+ UI.crop(image, "nw", naturalWidth, naturalHeight, [
+ initialWidth / 2,
+ initialHeight / 4,
+ ]);
+ Keyboard.keyDown(KEYS.ESCAPE);
+ const widthToHeightRatio = image.width / image.height;
+
+ const canvas = await exportToCanvas({
+ elements: [image],
+ // @ts-ignore
+ appState: h.state,
+ files: h.app.files,
+ exportPadding: 0,
+ });
+ const exportedCanvasRatio = canvas.width / canvas.height;
+
+ expect(widthToHeightRatio).toBeCloseTo(exportedCanvasRatio);
+
+ const svg = await exportToSvg({
+ elements: [image],
+ // @ts-ignore
+ appState: h.state,
+ files: h.app.files,
+ exportPadding: 0,
+ });
+ const svgWidth = svg.getAttribute("width");
+ const svgHeight = svg.getAttribute("height");
+
+ expect(svgWidth).toBeDefined();
+ expect(svgHeight).toBeDefined();
+
+ const exportedSvgRatio = Number(svgWidth) / Number(svgHeight);
+ expect(widthToHeightRatio).toBeCloseTo(exportedSvgRatio);
+ });
+});
diff --git a/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap b/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap
new file mode 100644
index 0000000..7dd0c01
--- /dev/null
+++ b/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap
@@ -0,0 +1,397 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`restoreElements > should restore arrow element correctly 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "elbowed": false,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id-arrow01",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 100,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": Any,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "arrow",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": Any,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`restoreElements > should restore correctly with rectangle, ellipse and diamond elements 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "blue",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "cross-hatch",
+ "frameId": null,
+ "groupIds": [
+ "1",
+ "2",
+ "3",
+ ],
+ "height": 200,
+ "id": "1",
+ "index": "a0",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 10,
+ "roughness": 2,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": Any,
+ "strokeColor": "red",
+ "strokeStyle": "dashed",
+ "strokeWidth": 2,
+ "type": "rectangle",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": Any,
+ "width": 100,
+ "x": 10,
+ "y": 20,
+}
+`;
+
+exports[`restoreElements > should restore correctly with rectangle, ellipse and diamond elements 2`] = `
+{
+ "angle": 0,
+ "backgroundColor": "blue",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "cross-hatch",
+ "frameId": null,
+ "groupIds": [
+ "1",
+ "2",
+ "3",
+ ],
+ "height": 200,
+ "id": "2",
+ "index": "a1",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 10,
+ "roughness": 2,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": Any,
+ "strokeColor": "red",
+ "strokeStyle": "dashed",
+ "strokeWidth": 2,
+ "type": "ellipse",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": Any,
+ "width": 100,
+ "x": 10,
+ "y": 20,
+}
+`;
+
+exports[`restoreElements > should restore correctly with rectangle, ellipse and diamond elements 3`] = `
+{
+ "angle": 0,
+ "backgroundColor": "blue",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "cross-hatch",
+ "frameId": null,
+ "groupIds": [
+ "1",
+ "2",
+ "3",
+ ],
+ "height": 200,
+ "id": "3",
+ "index": "a2",
+ "isDeleted": false,
+ "link": null,
+ "locked": false,
+ "opacity": 10,
+ "roughness": 2,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": Any,
+ "strokeColor": "red",
+ "strokeStyle": "dashed",
+ "strokeWidth": 2,
+ "type": "diamond",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": Any,
+ "width": 100,
+ "x": 10,
+ "y": 20,
+}
+`;
+
+exports[`restoreElements > should restore freedraw element correctly 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id-freedraw01",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 10,
+ 10,
+ ],
+ ],
+ "pressures": [],
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": Any,
+ "simulatePressure": true,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "freedraw",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": Any,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`restoreElements > should restore line and draw elements correctly 1`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id-line01",
+ "index": "a0",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 100,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": Any,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": Any,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`restoreElements > should restore line and draw elements correctly 2`] = `
+{
+ "angle": 0,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "customData": undefined,
+ "endArrowhead": null,
+ "endBinding": null,
+ "fillStyle": "solid",
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id-draw01",
+ "index": "a1",
+ "isDeleted": false,
+ "lastCommittedPoint": null,
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "points": [
+ [
+ 0,
+ 0,
+ ],
+ [
+ 100,
+ 100,
+ ],
+ ],
+ "roughness": 1,
+ "roundness": {
+ "type": 2,
+ },
+ "seed": Any,
+ "startArrowhead": null,
+ "startBinding": null,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "type": "line",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": Any,
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
+
+exports[`restoreElements > should restore text element correctly passing value for each attribute 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "fontFamily": 1,
+ "fontSize": 14,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id-text01",
+ "index": "a0",
+ "isDeleted": false,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "text",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": Any,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "text",
+ "textAlign": "center",
+ "type": "text",
+ "updated": 1,
+ "version": 2,
+ "versionNonce": Any,
+ "verticalAlign": "middle",
+ "width": 100,
+ "x": -20,
+ "y": "-8.75000",
+}
+`;
+
+exports[`restoreElements > should restore text element correctly with unknown font family, null text and undefined alignment 1`] = `
+{
+ "angle": 0,
+ "autoResize": true,
+ "backgroundColor": "transparent",
+ "boundElements": [],
+ "containerId": null,
+ "customData": undefined,
+ "fillStyle": "solid",
+ "font": "10 unknown",
+ "fontFamily": 5,
+ "fontSize": 10,
+ "frameId": null,
+ "groupIds": [],
+ "height": 100,
+ "id": "id-text01",
+ "index": "a0",
+ "isDeleted": true,
+ "lineHeight": "1.25000",
+ "link": null,
+ "locked": false,
+ "opacity": 100,
+ "originalText": "",
+ "roughness": 1,
+ "roundness": {
+ "type": 3,
+ },
+ "seed": Any,
+ "strokeColor": "#1e1e1e",
+ "strokeStyle": "solid",
+ "strokeWidth": 2,
+ "text": "",
+ "textAlign": "left",
+ "type": "text",
+ "updated": 1,
+ "version": 3,
+ "versionNonce": Any,
+ "verticalAlign": "top",
+ "width": 100,
+ "x": 0,
+ "y": 0,
+}
+`;
diff --git a/packages/excalidraw/tests/data/reconcile.test.ts b/packages/excalidraw/tests/data/reconcile.test.ts
new file mode 100644
index 0000000..f0e8105
--- /dev/null
+++ b/packages/excalidraw/tests/data/reconcile.test.ts
@@ -0,0 +1,382 @@
+import type { RemoteExcalidrawElement } from "../../data/reconcile";
+import { reconcileElements } from "../../data/reconcile";
+import type {
+ ExcalidrawElement,
+ OrderedExcalidrawElement,
+} from "../../element/types";
+import { syncInvalidIndices } from "../../fractionalIndex";
+import { randomInteger } from "../../random";
+import type { AppState } from "../../types";
+import { cloneJSON } from "../../utils";
+
+type Id = string;
+type ElementLike = {
+ id: string;
+ version: number;
+ versionNonce: number;
+ index: string;
+};
+
+type Cache = Record;
+
+const createElement = (opts: { uid: string } | ElementLike) => {
+ let uid: string;
+ let id: string;
+ let version: number | null;
+ let versionNonce: number | null = null;
+ if ("uid" in opts) {
+ const match = opts.uid.match(/^(\w+)(?::(\d+))?$/)!;
+ id = match[1];
+ version = match[2] ? parseInt(match[2]) : null;
+ uid = version ? `${id}:${version}` : id;
+ } else {
+ ({ id, version, versionNonce } = opts);
+ uid = id;
+ }
+ return {
+ uid,
+ id,
+ version,
+ versionNonce: versionNonce || randomInteger(),
+ };
+};
+
+const idsToElements = (ids: (Id | ElementLike)[], cache: Cache = {}) => {
+ return syncInvalidIndices(
+ ids.reduce((acc, _uid) => {
+ const { uid, id, version, versionNonce } = createElement(
+ typeof _uid === "string" ? { uid: _uid } : _uid,
+ );
+ const cached = cache[uid];
+ const elem = {
+ id,
+ version: version ?? 0,
+ versionNonce,
+ ...cached,
+ } as ExcalidrawElement;
+ // @ts-ignore
+ cache[uid] = elem;
+ acc.push(elem);
+ return acc;
+ }, [] as ExcalidrawElement[]),
+ );
+};
+
+const test = (
+ local: (Id | ElementLike)[],
+ remote: (Id | ElementLike)[],
+ target: U[],
+) => {
+ const cache: Cache = {};
+ const _local = idsToElements(local, cache);
+ const _remote = idsToElements(remote, cache);
+
+ const reconciled = reconcileElements(
+ cloneJSON(_local),
+ cloneJSON(_remote) as RemoteExcalidrawElement[],
+ {} as AppState,
+ );
+
+ const reconciledIds = reconciled.map((x) => x.id);
+ const reconciledIndices = reconciled.map((x) => x.index);
+
+ expect(target.length).toEqual(reconciled.length);
+ expect(reconciledIndices.length).toEqual(
+ new Set([...reconciledIndices]).size,
+ ); // expect no duplicated indices
+ assert.deepEqual(
+ reconciledIds,
+ target.map((uid) => {
+ const [, id, source] = uid.match(/^(\w+):([LR])$/)!;
+ const element = (source === "L" ? _local : _remote).find(
+ (e) => e.id === id,
+ )!;
+
+ return element.id;
+ }),
+ "remote reconciliation",
+ );
+
+ // convergent reconciliation on the remote client
+ try {
+ assert.deepEqual(
+ reconcileElements(
+ cloneJSON(_remote),
+ cloneJSON(_local as RemoteExcalidrawElement[]),
+ {} as AppState,
+ ).map((x) => x.id),
+ reconciledIds,
+ "convergent reconciliation",
+ );
+ } catch (error: any) {
+ console.error("local original", _remote);
+ console.error("remote original", _local);
+ throw error;
+ }
+
+ // bidirectional re-reconciliation on remote client
+ try {
+ assert.deepEqual(
+ reconcileElements(
+ cloneJSON(_remote),
+ cloneJSON(reconciled as unknown as RemoteExcalidrawElement[]),
+ {} as AppState,
+ ).map((x) => x.id),
+ reconciledIds,
+ "local re-reconciliation",
+ );
+ } catch (error: any) {
+ console.error("local original", _remote);
+ console.error("remote reconciled", reconciled);
+ throw error;
+ }
+};
+
+describe("elements reconciliation", () => {
+ it("reconcileElements()", () => {
+ // -------------------------------------------------------------------------
+ //
+ // in following tests, we pass:
+ // (1) an array of local elements and their version (:1, :2...)
+ // (2) an array of remote elements and their version (:1, :2...)
+ // (3) expected reconciled elements
+ //
+ // in the reconciled array:
+ // :L means local element was resolved
+ // :R means remote element was resolved
+ //
+ // if versions are missing, it defaults to version 0
+ // -------------------------------------------------------------------------
+
+ test(["A:1", "B:1", "C:1"], ["B:2"], ["A:L", "B:R", "C:L"]);
+ test(["A:1", "B:1", "C"], ["B:2", "A:2"], ["B:R", "A:R", "C:L"]);
+ test(["A:2", "B:1", "C"], ["B:2", "A:1"], ["A:L", "B:R", "C:L"]);
+ test(["A:1", "C:1"], ["B:1"], ["A:L", "B:R", "C:L"]);
+ test(["A", "B"], ["A:1"], ["A:R", "B:L"]);
+ test(["A"], ["A", "B"], ["A:L", "B:R"]);
+ test(["A"], ["A:1", "B"], ["A:R", "B:R"]);
+ test(["A:2"], ["A:1", "B"], ["A:L", "B:R"]);
+ test(["A:2"], ["B", "A:1"], ["A:L", "B:R"]);
+ test(["A:1"], ["B", "A:2"], ["B:R", "A:R"]);
+ test(["A"], ["A:1"], ["A:R"]);
+ test(["A", "B:1", "D"], ["B", "C:2", "A"], ["C:R", "A:R", "B:L", "D:L"]);
+
+ // some of the following tests are kinda arbitrary and they're less
+ // likely to happen in real-world cases
+ test(["A", "B"], ["B:1", "A:1"], ["B:R", "A:R"]);
+ test(["A:2", "B:2"], ["B:1", "A:1"], ["A:L", "B:L"]);
+ test(["A", "B", "C"], ["A", "B:2", "G", "C"], ["A:L", "B:R", "G:R", "C:L"]);
+ test(["A", "B", "C"], ["A", "B:2", "G"], ["A:R", "B:R", "C:L", "G:R"]);
+ test(
+ ["A:2", "B:2", "C"],
+ ["D", "B:1", "A:3"],
+ ["D:R", "B:L", "A:R", "C:L"],
+ );
+ test(
+ ["A:2", "B:2", "C"],
+ ["D", "B:2", "A:3", "C"],
+ ["D:R", "B:L", "A:R", "C:L"],
+ );
+ test(
+ ["A", "B", "C", "D", "E", "F"],
+ ["A", "B:2", "X", "E:2", "F", "Y"],
+ ["A:L", "B:R", "X:R", "C:L", "E:R", "D:L", "F:L", "Y:R"],
+ );
+
+ // fractional elements (previously annotated)
+ test(
+ ["A", "B", "C"],
+ ["A", "B", "X", "Y", "Z"],
+ ["A:R", "B:R", "C:L", "X:R", "Y:R", "Z:R"],
+ );
+
+ test(["A"], ["X", "Y"], ["A:L", "X:R", "Y:R"]);
+ test(["A"], ["X", "Y", "Z"], ["A:L", "X:R", "Y:R", "Z:R"]);
+ test(["A", "B"], ["C", "D", "F"], ["A:L", "C:R", "B:L", "D:R", "F:R"]);
+
+ test(
+ ["A", "B", "C", "D"],
+ ["C:1", "B", "D:1"],
+ ["A:L", "C:R", "B:L", "D:R"],
+ );
+ test(
+ ["A", "B", "C"],
+ ["X", "A", "Y", "B", "Z"],
+ ["X:R", "A:R", "Y:R", "B:L", "C:L", "Z:R"],
+ );
+ test(
+ ["B", "A", "C"],
+ ["X", "A", "Y", "B", "Z"],
+ ["X:R", "A:R", "C:L", "Y:R", "B:R", "Z:R"],
+ );
+ test(["A", "B"], ["A", "X", "Y"], ["A:R", "B:L", "X:R", "Y:R"]);
+ test(
+ ["A", "B", "C", "D", "E"],
+ ["A", "X", "C", "Y", "D", "Z"],
+ ["A:R", "B:L", "X:R", "C:R", "Y:R", "D:R", "E:L", "Z:R"],
+ );
+ test(
+ ["X", "Y", "Z"],
+ ["A", "B", "C"],
+ ["A:R", "X:L", "B:R", "Y:L", "C:R", "Z:L"],
+ );
+ test(
+ ["X", "Y", "Z"],
+ ["A", "B", "C", "X", "D", "Y", "Z"],
+ ["A:R", "B:R", "C:R", "X:L", "D:R", "Y:L", "Z:L"],
+ );
+ test(
+ ["A", "B", "C", "D", "E"],
+ ["C", "X", "A", "Y", "D", "E:1"],
+ ["B:L", "C:L", "X:R", "A:R", "Y:R", "D:R", "E:R"],
+ );
+ test(
+ ["C:1", "B", "D:1"],
+ ["A", "B", "C:1", "D:1"],
+ ["A:R", "B:R", "C:R", "D:R"],
+ );
+
+ test(
+ ["C:1", "B", "D:1"],
+ ["A", "B", "C:2", "D:1"],
+ ["A:R", "B:L", "C:R", "D:L"],
+ );
+
+ test(
+ ["A", "B", "C", "D"],
+ ["A", "C:1", "B", "D:1"],
+ ["A:L", "C:R", "B:L", "D:R"],
+ );
+
+ test(
+ ["A", "B", "C", "D"],
+ ["C", "X", "B", "Y", "A", "Z"],
+ ["C:R", "D:L", "X:R", "B:R", "Y:R", "A:R", "Z:R"],
+ );
+
+ test(
+ ["A", "B", "C", "D"],
+ ["A", "B:1", "C:1"],
+ ["A:R", "B:R", "C:R", "D:L"],
+ );
+
+ test(
+ ["A", "B", "C", "D"],
+ ["A", "C:1", "B:1"],
+ ["A:R", "C:R", "B:R", "D:L"],
+ );
+
+ test(
+ ["A", "B", "C", "D"],
+ ["A", "C:1", "B", "D:1"],
+ ["A:R", "C:R", "B:R", "D:R"],
+ );
+
+ test(["A:1", "B:1", "C"], ["B:2"], ["A:L", "B:R", "C:L"]);
+ test(["A:1", "B:1", "C"], ["B:2", "C:2"], ["A:L", "B:R", "C:R"]);
+ test(["A", "B"], ["A", "C", "B", "D"], ["A:R", "C:R", "B:R", "D:R"]);
+ test(["A", "B"], ["B", "C", "D"], ["A:L", "B:R", "C:R", "D:R"]);
+ test(["A", "B"], ["C", "D"], ["A:L", "C:R", "B:L", "D:R"]);
+ test(["A", "B"], ["A", "B:1"], ["A:L", "B:R"]);
+ test(["A:2", "B"], ["A", "B:1"], ["A:L", "B:R"]);
+ test(["A:2", "B:2"], ["B:1"], ["A:L", "B:L"]);
+ test(["A:2", "B:2"], ["B:1", "C"], ["A:L", "B:L", "C:R"]);
+ test(["A:2", "B:2"], ["A", "C", "B:1"], ["A:L", "B:L", "C:R"]);
+
+ // concurrent convergency
+ test(["A", "B", "C"], ["A", "B", "D"], ["A:R", "B:R", "C:L", "D:R"]);
+ test(["A", "B", "E"], ["A", "B", "D"], ["A:R", "B:R", "D:R", "E:L"]);
+ test(
+ ["A", "B", "C"],
+ ["A", "B", "D", "E"],
+ ["A:R", "B:R", "C:L", "D:R", "E:R"],
+ );
+ test(
+ ["A", "B", "E"],
+ ["A", "B", "D", "C"],
+ ["A:R", "B:R", "D:R", "E:L", "C:R"],
+ );
+ test(["A", "B"], ["B", "D"], ["A:L", "B:R", "D:R"]);
+ test(["C", "A", "B"], ["C", "B", "D"], ["C:R", "A:L", "B:R", "D:R"]);
+ });
+
+ it("test identical elements reconciliation", () => {
+ const testIdentical = (
+ local: ElementLike[],
+ remote: ElementLike[],
+ expected: Id[],
+ ) => {
+ const ret = reconcileElements(
+ local as unknown as OrderedExcalidrawElement[],
+ remote as unknown as RemoteExcalidrawElement[],
+ {} as AppState,
+ );
+
+ if (new Set(ret.map((x) => x.id)).size !== ret.length) {
+ throw new Error("reconcileElements: duplicate elements found");
+ }
+
+ assert.deepEqual(
+ ret.map((x) => x.id),
+ expected,
+ );
+ };
+
+ // identical id/version/versionNonce/index
+ // -------------------------------------------------------------------------
+
+ testIdentical(
+ [{ id: "A", version: 1, versionNonce: 1, index: "a0" }],
+ [{ id: "A", version: 1, versionNonce: 1, index: "a0" }],
+ ["A"],
+ );
+ testIdentical(
+ [
+ { id: "A", version: 1, versionNonce: 1, index: "a0" },
+ { id: "B", version: 1, versionNonce: 1, index: "a0" },
+ ],
+ [
+ { id: "B", version: 1, versionNonce: 1, index: "a0" },
+ { id: "A", version: 1, versionNonce: 1, index: "a0" },
+ ],
+ ["A", "B"],
+ );
+
+ // actually identical (arrays and element objects)
+ // -------------------------------------------------------------------------
+
+ const elements1 = [
+ {
+ id: "A",
+ version: 1,
+ versionNonce: 1,
+ index: "a0",
+ },
+ {
+ id: "B",
+ version: 1,
+ versionNonce: 1,
+ index: "a0",
+ },
+ ];
+
+ testIdentical(elements1, elements1, ["A", "B"]);
+ testIdentical(elements1, elements1.slice(), ["A", "B"]);
+ testIdentical(elements1.slice(), elements1, ["A", "B"]);
+ testIdentical(elements1.slice(), elements1.slice(), ["A", "B"]);
+
+ const el1 = {
+ id: "A",
+ version: 1,
+ versionNonce: 1,
+ index: "a0",
+ };
+ const el2 = {
+ id: "B",
+ version: 1,
+ versionNonce: 1,
+ index: "a0",
+ };
+ testIdentical([el1, el2], [el2, el1], ["A", "B"]);
+ });
+});
diff --git a/packages/excalidraw/tests/data/restore.test.ts b/packages/excalidraw/tests/data/restore.test.ts
new file mode 100644
index 0000000..37a27ac
--- /dev/null
+++ b/packages/excalidraw/tests/data/restore.test.ts
@@ -0,0 +1,815 @@
+import * as restore from "../../data/restore";
+import type {
+ ExcalidrawElement,
+ ExcalidrawFreeDrawElement,
+ ExcalidrawLinearElement,
+ ExcalidrawTextElement,
+} from "../../element/types";
+import * as sizeHelpers from "../../element/sizeHelpers";
+import { API } from "../helpers/api";
+import { getDefaultAppState } from "../../appState";
+import type { ImportedDataState } from "../../data/types";
+import type { NormalizedZoomValue } from "../../types";
+import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants";
+import { newElementWith } from "../../element/mutateElement";
+import { vi } from "vitest";
+import { pointFrom } from "@excalidraw/math";
+
+describe("restoreElements", () => {
+ const mockSizeHelper = vi.spyOn(sizeHelpers, "isInvisiblySmallElement");
+
+ beforeEach(() => {
+ mockSizeHelper.mockReset();
+ });
+
+ afterAll(() => {
+ mockSizeHelper.mockRestore();
+ });
+
+ it("should return empty array when element is null", () => {
+ expect(restore.restoreElements(null, null)).toStrictEqual([]);
+ });
+
+ it("should not call isInvisiblySmallElement when element is a selection element", () => {
+ const selectionEl = { type: "selection" } as ExcalidrawElement;
+ const restoreElements = restore.restoreElements([selectionEl], null);
+ expect(restoreElements.length).toBe(0);
+ expect(sizeHelpers.isInvisiblySmallElement).toBeCalledTimes(0);
+ });
+
+ it("should return empty array when input type is not supported", () => {
+ const dummyNotSupportedElement: any = API.createElement({
+ type: "text",
+ });
+
+ dummyNotSupportedElement.type = "not supported";
+ expect(
+ restore.restoreElements([dummyNotSupportedElement], null).length,
+ ).toBe(0);
+ });
+
+ it("should return empty array when isInvisiblySmallElement is true", () => {
+ const rectElement = API.createElement({ type: "rectangle" });
+ mockSizeHelper.mockImplementation(() => true);
+
+ expect(restore.restoreElements([rectElement], null).length).toBe(0);
+ });
+
+ it("should restore text element correctly passing value for each attribute", () => {
+ const textElement = API.createElement({
+ type: "text",
+ fontSize: 14,
+ fontFamily: FONT_FAMILY.Virgil,
+ text: "text",
+ textAlign: "center",
+ verticalAlign: "middle",
+ id: "id-text01",
+ });
+
+ const restoredText = restore.restoreElements(
+ [textElement],
+ null,
+ )[0] as ExcalidrawTextElement;
+
+ expect(restoredText).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ });
+
+ it("should restore text element correctly with unknown font family, null text and undefined alignment", () => {
+ const textElement: any = API.createElement({
+ type: "text",
+ textAlign: undefined,
+ verticalAlign: undefined,
+ id: "id-text01",
+ });
+
+ textElement.text = null;
+ textElement.font = "10 unknown";
+
+ expect(textElement.isDeleted).toBe(false);
+ const restoredText = restore.restoreElements(
+ [textElement],
+ null,
+ )[0] as ExcalidrawTextElement;
+ expect(restoredText.isDeleted).toBe(true);
+ expect(restoredText).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ });
+
+ it("should restore freedraw element correctly", () => {
+ const freedrawElement = API.createElement({
+ type: "freedraw",
+ id: "id-freedraw01",
+ points: [pointFrom(0, 0), pointFrom(10, 10)],
+ });
+
+ const restoredFreedraw = restore.restoreElements(
+ [freedrawElement],
+ null,
+ )[0] as ExcalidrawFreeDrawElement;
+
+ expect(restoredFreedraw).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ });
+
+ it("should restore line and draw elements correctly", () => {
+ const lineElement = API.createElement({ type: "line", id: "id-line01" });
+
+ const drawElement: any = API.createElement({
+ type: "line",
+ id: "id-draw01",
+ });
+ drawElement.type = "draw";
+
+ const restoredElements = restore.restoreElements(
+ [lineElement, drawElement],
+ null,
+ );
+
+ const restoredLine = restoredElements[0] as ExcalidrawLinearElement;
+ const restoredDraw = restoredElements[1] as ExcalidrawLinearElement;
+
+ expect(restoredLine).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ expect(restoredDraw).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ });
+
+ it("should restore arrow element correctly", () => {
+ const arrowElement = API.createElement({ type: "arrow", id: "id-arrow01" });
+
+ const restoredElements = restore.restoreElements([arrowElement], null);
+
+ const restoredArrow = restoredElements[0] as ExcalidrawLinearElement;
+
+ expect(restoredArrow).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ });
+
+ it('should set arrow element endArrowHead as "arrow" when arrow element endArrowHead is null', () => {
+ const arrowElement = API.createElement({ type: "arrow" });
+ const restoredElements = restore.restoreElements([arrowElement], null);
+
+ const restoredArrow = restoredElements[0] as ExcalidrawLinearElement;
+
+ expect(arrowElement.endArrowhead).toBe(restoredArrow.endArrowhead);
+ });
+
+ it('should set arrow element endArrowHead as "arrow" when arrow element endArrowHead is undefined', () => {
+ const arrowElement = API.createElement({ type: "arrow" });
+ Object.defineProperty(arrowElement, "endArrowhead", {
+ get: vi.fn(() => undefined),
+ });
+
+ const restoredElements = restore.restoreElements([arrowElement], null);
+
+ const restoredArrow = restoredElements[0] as ExcalidrawLinearElement;
+
+ expect(restoredArrow.endArrowhead).toBe("arrow");
+ });
+
+ it("when element.points of a line element is not an array", () => {
+ const lineElement: any = API.createElement({
+ type: "line",
+ width: 100,
+ height: 200,
+ });
+
+ lineElement.points = "not an array";
+
+ const expectedLinePoints = [
+ [0, 0],
+ [lineElement.width, lineElement.height],
+ ];
+
+ const restoredLine = restore.restoreElements(
+ [lineElement],
+ null,
+ )[0] as ExcalidrawLinearElement;
+
+ expect(restoredLine.points).toMatchObject(expectedLinePoints);
+ });
+
+ it("when the number of points of a line is greater or equal 2", () => {
+ const lineElement_0 = API.createElement({
+ type: "line",
+ width: 100,
+ height: 200,
+ x: 10,
+ y: 20,
+ });
+ const lineElement_1 = API.createElement({
+ type: "line",
+ width: 200,
+ height: 400,
+ x: 30,
+ y: 40,
+ });
+
+ const pointsEl_0 = [
+ [0, 0],
+ [1, 1],
+ ];
+ Object.defineProperty(lineElement_0, "points", {
+ get: vi.fn(() => pointsEl_0),
+ });
+
+ const pointsEl_1 = [
+ [3, 4],
+ [5, 6],
+ ];
+ Object.defineProperty(lineElement_1, "points", {
+ get: vi.fn(() => pointsEl_1),
+ });
+
+ const restoredElements = restore.restoreElements(
+ [lineElement_0, lineElement_1],
+ null,
+ );
+
+ const restoredLine_0 = restoredElements[0] as ExcalidrawLinearElement;
+ const restoredLine_1 = restoredElements[1] as ExcalidrawLinearElement;
+
+ expect(restoredLine_0.points).toMatchObject(pointsEl_0);
+
+ const offsetX = pointsEl_1[0][0];
+ const offsetY = pointsEl_1[0][1];
+ const restoredPointsEl1 = [
+ [pointsEl_1[0][0] - offsetX, pointsEl_1[0][1] - offsetY],
+ [pointsEl_1[1][0] - offsetX, pointsEl_1[1][1] - offsetY],
+ ];
+ expect(restoredLine_1.points).toMatchObject(restoredPointsEl1);
+ expect(restoredLine_1.x).toBe(lineElement_1.x + offsetX);
+ expect(restoredLine_1.y).toBe(lineElement_1.y + offsetY);
+ });
+
+ it("should restore correctly with rectangle, ellipse and diamond elements", () => {
+ const types = ["rectangle", "ellipse", "diamond"];
+
+ const elements: ExcalidrawElement[] = [];
+ let idCount = 0;
+ types.forEach((elType) => {
+ idCount += 1;
+ const element = API.createElement({
+ type: elType as "rectangle" | "ellipse" | "diamond" | "embeddable",
+ id: idCount.toString(),
+ fillStyle: "cross-hatch",
+ strokeWidth: 2,
+ strokeStyle: "dashed",
+ roughness: 2,
+ opacity: 10,
+ x: 10,
+ y: 20,
+ strokeColor: "red",
+ backgroundColor: "blue",
+ width: 100,
+ height: 200,
+ groupIds: ["1", "2", "3"],
+ roundness: { type: ROUNDNESS.PROPORTIONAL_RADIUS },
+ });
+
+ elements.push(element);
+ });
+
+ const restoredElements = restore.restoreElements(elements, null);
+
+ expect(restoredElements[0]).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ expect(restoredElements[1]).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ expect(restoredElements[2]).toMatchSnapshot({
+ seed: expect.any(Number),
+ versionNonce: expect.any(Number),
+ });
+ });
+
+ it("bump versions of local duplicate elements when supplied", () => {
+ const rectangle = API.createElement({ type: "rectangle" });
+ const ellipse = API.createElement({ type: "ellipse" });
+ const rectangle_modified = newElementWith(rectangle, { isDeleted: true });
+
+ const restoredElements = restore.restoreElements(
+ [rectangle, ellipse],
+ [rectangle_modified],
+ );
+
+ expect(restoredElements[0].id).toBe(rectangle.id);
+ expect(restoredElements[0].versionNonce).not.toBe(rectangle.versionNonce);
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: rectangle.id,
+ version: rectangle_modified.version + 2,
+ }),
+ expect.objectContaining({
+ id: ellipse.id,
+ version: ellipse.version + 1,
+ }),
+ ]);
+ });
+});
+
+describe("restoreAppState", () => {
+ it("should restore with imported data", () => {
+ const stubImportedAppState = getDefaultAppState();
+ stubImportedAppState.activeTool.type = "selection";
+ stubImportedAppState.cursorButton = "down";
+ stubImportedAppState.name = "imported app state";
+
+ const stubLocalAppState = getDefaultAppState();
+ stubLocalAppState.activeTool.type = "rectangle";
+ stubLocalAppState.cursorButton = "up";
+ stubLocalAppState.name = "local app state";
+
+ const restoredAppState = restore.restoreAppState(
+ stubImportedAppState,
+ stubLocalAppState,
+ );
+ expect(restoredAppState.activeTool).toEqual(
+ stubImportedAppState.activeTool,
+ );
+ expect(restoredAppState.cursorButton).toBe("up");
+ expect(restoredAppState.name).toBe(stubImportedAppState.name);
+ });
+
+ it("should restore with current app state when imported data state is undefined", () => {
+ const stubImportedAppState = {
+ ...getDefaultAppState(),
+ cursorButton: undefined,
+ name: undefined,
+ };
+
+ const stubLocalAppState = getDefaultAppState();
+ stubLocalAppState.cursorButton = "down";
+ stubLocalAppState.name = "local app state";
+
+ const restoredAppState = restore.restoreAppState(
+ stubImportedAppState,
+ stubLocalAppState,
+ );
+ expect(restoredAppState.cursorButton).toBe(stubLocalAppState.cursorButton);
+ expect(restoredAppState.name).toBe(stubLocalAppState.name);
+ });
+
+ it("should return imported data when local app state is null", () => {
+ const stubImportedAppState = getDefaultAppState();
+ stubImportedAppState.cursorButton = "down";
+ stubImportedAppState.name = "imported app state";
+
+ const restoredAppState = restore.restoreAppState(
+ stubImportedAppState,
+ null,
+ );
+ expect(restoredAppState.cursorButton).toBe("up");
+ expect(restoredAppState.name).toBe(stubImportedAppState.name);
+ });
+
+ it("should return local app state when imported data state is null", () => {
+ const stubLocalAppState = getDefaultAppState();
+ stubLocalAppState.cursorButton = "down";
+ stubLocalAppState.name = "local app state";
+
+ const restoredAppState = restore.restoreAppState(null, stubLocalAppState);
+ expect(restoredAppState.cursorButton).toBe(stubLocalAppState.cursorButton);
+ expect(restoredAppState.name).toBe(stubLocalAppState.name);
+ });
+
+ it("should return default app state when imported data state and local app state are undefined", () => {
+ const stubImportedAppState = {
+ ...getDefaultAppState(),
+ cursorButton: undefined,
+ };
+
+ const stubLocalAppState = {
+ ...getDefaultAppState(),
+ cursorButton: undefined,
+ };
+
+ const restoredAppState = restore.restoreAppState(
+ stubImportedAppState,
+ stubLocalAppState,
+ );
+ expect(restoredAppState.cursorButton).toBe(
+ getDefaultAppState().cursorButton,
+ );
+ });
+
+ it("should return default app state when imported data state and local app state are null", () => {
+ const restoredAppState = restore.restoreAppState(null, null);
+ expect(restoredAppState.cursorButton).toBe(
+ getDefaultAppState().cursorButton,
+ );
+ });
+
+ it("when imported data state has a not allowed Excalidraw Element Types", () => {
+ const stubImportedAppState: any = getDefaultAppState();
+
+ stubImportedAppState.activeTool = "not allowed Excalidraw Element Types";
+ const stubLocalAppState = getDefaultAppState();
+
+ const restoredAppState = restore.restoreAppState(
+ stubImportedAppState,
+ stubLocalAppState,
+ );
+ expect(restoredAppState.activeTool.type).toBe("selection");
+ });
+
+ describe("with zoom in imported data state", () => {
+ it("when imported data state has zoom as a number", () => {
+ const stubImportedAppState: any = getDefaultAppState();
+
+ stubImportedAppState.zoom = 10;
+
+ const stubLocalAppState = getDefaultAppState();
+
+ const restoredAppState = restore.restoreAppState(
+ stubImportedAppState,
+ stubLocalAppState,
+ );
+
+ expect(restoredAppState.zoom.value).toBe(10);
+ });
+
+ it("when the zoom of imported data state is not a number", () => {
+ const stubImportedAppState = getDefaultAppState();
+ stubImportedAppState.zoom = {
+ value: 10 as NormalizedZoomValue,
+ };
+
+ const stubLocalAppState = getDefaultAppState();
+
+ const restoredAppState = restore.restoreAppState(
+ stubImportedAppState,
+ stubLocalAppState,
+ );
+
+ expect(restoredAppState.zoom.value).toBe(10);
+ expect(restoredAppState.zoom).toMatchObject(stubImportedAppState.zoom);
+ });
+
+ it("when the zoom of imported data state zoom is null", () => {
+ const stubImportedAppState = getDefaultAppState();
+
+ Object.defineProperty(stubImportedAppState, "zoom", {
+ get: vi.fn(() => null),
+ });
+
+ const stubLocalAppState = getDefaultAppState();
+
+ const restoredAppState = restore.restoreAppState(
+ stubImportedAppState,
+ stubLocalAppState,
+ );
+
+ expect(restoredAppState.zoom).toMatchObject(getDefaultAppState().zoom);
+ });
+ });
+
+ it("should handle appState.openSidebar legacy values", () => {
+ expect(restore.restoreAppState({}, null).openSidebar).toBe(null);
+ expect(
+ restore.restoreAppState({ openSidebar: "library" } as any, null)
+ .openSidebar,
+ ).toEqual({ name: DEFAULT_SIDEBAR.name });
+ expect(
+ restore.restoreAppState({ openSidebar: "xxx" } as any, null).openSidebar,
+ ).toEqual({ name: DEFAULT_SIDEBAR.name });
+ // while "library" was our legacy sidebar name, we can't assume it's legacy
+ // value as it may be some host app's custom sidebar name ¯\_(ツ)_/¯
+ expect(
+ restore.restoreAppState({ openSidebar: { name: "library" } } as any, null)
+ .openSidebar,
+ ).toEqual({ name: "library" });
+ expect(
+ restore.restoreAppState(
+ { openSidebar: { name: DEFAULT_SIDEBAR.name, tab: "ola" } } as any,
+ null,
+ ).openSidebar,
+ ).toEqual({ name: DEFAULT_SIDEBAR.name, tab: "ola" });
+ });
+});
+
+describe("restore", () => {
+ it("when imported data state is null it should return an empty array of elements", () => {
+ const stubLocalAppState = getDefaultAppState();
+
+ const restoredData = restore.restore(null, stubLocalAppState, null);
+ expect(restoredData.elements.length).toBe(0);
+ });
+
+ it("when imported data state is null it should return the local app state property", () => {
+ const stubLocalAppState = getDefaultAppState();
+ stubLocalAppState.cursorButton = "down";
+ stubLocalAppState.name = "local app state";
+
+ const restoredData = restore.restore(null, stubLocalAppState, null);
+ expect(restoredData.appState.cursorButton).toBe(
+ stubLocalAppState.cursorButton,
+ );
+ expect(restoredData.appState.name).toBe(stubLocalAppState.name);
+ });
+
+ it("when imported data state has elements", () => {
+ const stubLocalAppState = getDefaultAppState();
+
+ const textElement = API.createElement({ type: "text" });
+ const rectElement = API.createElement({ type: "rectangle" });
+ const elements = [textElement, rectElement];
+
+ const importedDataState = {} as ImportedDataState;
+ importedDataState.elements = elements;
+
+ const restoredData = restore.restore(
+ importedDataState,
+ stubLocalAppState,
+ null,
+ );
+ expect(restoredData.elements.length).toBe(elements.length);
+ });
+
+ it("when local app state is null but imported app state is supplied", () => {
+ const stubImportedAppState = getDefaultAppState();
+ stubImportedAppState.cursorButton = "down";
+ stubImportedAppState.name = "imported app state";
+
+ const importedDataState = {} as ImportedDataState;
+ importedDataState.appState = stubImportedAppState;
+
+ const restoredData = restore.restore(importedDataState, null, null);
+ expect(restoredData.appState.cursorButton).toBe("up");
+ expect(restoredData.appState.name).toBe(stubImportedAppState.name);
+ });
+
+ it("bump versions of local duplicate elements when supplied", () => {
+ const rectangle = API.createElement({ type: "rectangle" });
+ const ellipse = API.createElement({ type: "ellipse" });
+
+ const rectangle_modified = newElementWith(rectangle, { isDeleted: true });
+
+ const restoredData = restore.restore(
+ { elements: [rectangle, ellipse] },
+ null,
+ [rectangle_modified],
+ );
+
+ expect(restoredData.elements[0].id).toBe(rectangle.id);
+ expect(restoredData.elements[0].versionNonce).not.toBe(
+ rectangle.versionNonce,
+ );
+ expect(restoredData.elements).toEqual([
+ expect.objectContaining({ version: rectangle_modified.version + 2 }),
+ expect.objectContaining({
+ id: ellipse.id,
+ version: ellipse.version + 1,
+ }),
+ ]);
+ });
+});
+
+describe("repairing bindings", () => {
+ it("should repair container boundElements when repair is true", () => {
+ const container = API.createElement({
+ type: "rectangle",
+ boundElements: [],
+ });
+ const boundElement = API.createElement({
+ type: "text",
+ containerId: container.id,
+ });
+
+ expect(container.boundElements).toEqual([]);
+
+ let restoredElements = restore.restoreElements(
+ [container, boundElement],
+ null,
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: container.id,
+ boundElements: [],
+ }),
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: container.id,
+ }),
+ ]);
+
+ restoredElements = restore.restoreElements(
+ [container, boundElement],
+ null,
+ { repairBindings: true },
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: container.id,
+ boundElements: [{ type: boundElement.type, id: boundElement.id }],
+ }),
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: container.id,
+ }),
+ ]);
+ });
+
+ it("should repair containerId of boundElements when repair is true", () => {
+ const boundElement = API.createElement({
+ type: "text",
+ containerId: null,
+ });
+ const container = API.createElement({
+ type: "rectangle",
+ boundElements: [{ type: boundElement.type, id: boundElement.id }],
+ });
+
+ let restoredElements = restore.restoreElements(
+ [container, boundElement],
+ null,
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: container.id,
+ boundElements: [{ type: boundElement.type, id: boundElement.id }],
+ }),
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: null,
+ }),
+ ]);
+
+ restoredElements = restore.restoreElements(
+ [container, boundElement],
+ null,
+ { repairBindings: true },
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: container.id,
+ boundElements: [{ type: boundElement.type, id: boundElement.id }],
+ }),
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: container.id,
+ }),
+ ]);
+ });
+
+ it("should ignore bound element if deleted", () => {
+ const container = API.createElement({
+ type: "rectangle",
+ boundElements: [],
+ });
+ const boundElement = API.createElement({
+ type: "text",
+ containerId: container.id,
+ isDeleted: true,
+ });
+
+ expect(container.boundElements).toEqual([]);
+
+ const restoredElements = restore.restoreElements(
+ [container, boundElement],
+ null,
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: container.id,
+ boundElements: [],
+ }),
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: container.id,
+ }),
+ ]);
+ });
+
+ it("should remove bindings of deleted elements from boundElements when repair is true", () => {
+ const container = API.createElement({
+ type: "rectangle",
+ boundElements: [],
+ });
+ const boundElement = API.createElement({
+ type: "text",
+ containerId: container.id,
+ isDeleted: true,
+ });
+ const invisibleBoundElement = API.createElement({
+ type: "text",
+ containerId: container.id,
+ width: 0,
+ height: 0,
+ });
+
+ const obsoleteBinding = { type: boundElement.type, id: boundElement.id };
+ const invisibleBinding = {
+ type: invisibleBoundElement.type,
+ id: invisibleBoundElement.id,
+ };
+ expect(container.boundElements).toEqual([]);
+
+ const nonExistentBinding = { type: "text", id: "non-existent" };
+ // @ts-ignore
+ container.boundElements = [
+ obsoleteBinding,
+ invisibleBinding,
+ nonExistentBinding,
+ ];
+
+ let restoredElements = restore.restoreElements(
+ [container, invisibleBoundElement, boundElement],
+ null,
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: container.id,
+ boundElements: [obsoleteBinding, invisibleBinding, nonExistentBinding],
+ }),
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: container.id,
+ }),
+ ]);
+
+ restoredElements = restore.restoreElements(
+ [container, invisibleBoundElement, boundElement],
+ null,
+ { repairBindings: true },
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: container.id,
+ boundElements: [],
+ }),
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: container.id,
+ }),
+ ]);
+ });
+
+ it("should remove containerId if container not exists when repair is true", () => {
+ const boundElement = API.createElement({
+ type: "text",
+ containerId: "non-existent",
+ });
+ const boundElementDeleted = API.createElement({
+ type: "text",
+ containerId: "non-existent",
+ isDeleted: true,
+ });
+
+ let restoredElements = restore.restoreElements(
+ [boundElement, boundElementDeleted],
+ null,
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: "non-existent",
+ }),
+ expect.objectContaining({
+ id: boundElementDeleted.id,
+ containerId: "non-existent",
+ }),
+ ]);
+
+ restoredElements = restore.restoreElements(
+ [boundElement, boundElementDeleted],
+ null,
+ { repairBindings: true },
+ );
+
+ expect(restoredElements).toEqual([
+ expect.objectContaining({
+ id: boundElement.id,
+ containerId: null,
+ }),
+ expect.objectContaining({
+ id: boundElementDeleted.id,
+ containerId: null,
+ }),
+ ]);
+ });
+});
diff --git a/packages/excalidraw/tests/dragCreate.test.tsx b/packages/excalidraw/tests/dragCreate.test.tsx
new file mode 100644
index 0000000..743ba79
--- /dev/null
+++ b/packages/excalidraw/tests/dragCreate.test.tsx
@@ -0,0 +1,347 @@
+import React from "react";
+import { Excalidraw } from "../index";
+import * as StaticScene from "../renderer/staticScene";
+import * as InteractiveScene from "../renderer/interactiveScene";
+import { KEYS } from "../keys";
+import {
+ render,
+ fireEvent,
+ mockBoundingClientRect,
+ restoreOriginalGetBoundingClientRect,
+ unmountComponent,
+} from "./test-utils";
+import type { ExcalidrawLinearElement } from "../element/types";
+import { reseed } from "../random";
+import { vi } from "vitest";
+
+unmountComponent();
+
+const renderInteractiveScene = vi.spyOn(
+ InteractiveScene,
+ "renderInteractiveScene",
+);
+const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene");
+
+beforeEach(() => {
+ localStorage.clear();
+ renderInteractiveScene.mockClear();
+ renderStaticScene.mockClear();
+ reseed(7);
+});
+
+const { h } = window;
+
+describe("Test dragCreate", () => {
+ describe("add element to the scene when pointer dragging long enough", () => {
+ it("rectangle", async () => {
+ const { getByToolName, container } = await render();
+ // select tool
+ const tool = getByToolName("rectangle");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // move to (60,70)
+ fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `5`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`);
+ expect(h.state.selectionElement).toBeNull();
+
+ expect(h.elements.length).toEqual(1);
+ expect(h.elements[0].type).toEqual("rectangle");
+ expect(h.elements[0].x).toEqual(30);
+ expect(h.elements[0].y).toEqual(20);
+ expect(h.elements[0].width).toEqual(30); // 60 - 30
+ expect(h.elements[0].height).toEqual(50); // 70 - 20
+
+ expect(h.elements.length).toMatchSnapshot();
+ h.elements.forEach((element) => expect(element).toMatchSnapshot());
+ });
+
+ it("ellipse", async () => {
+ const { getByToolName, container } = await render();
+ // select tool
+ const tool = getByToolName("ellipse");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // move to (60,70)
+ fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `5`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`);
+
+ expect(h.state.selectionElement).toBeNull();
+
+ expect(h.elements.length).toEqual(1);
+ expect(h.elements[0].type).toEqual("ellipse");
+ expect(h.elements[0].x).toEqual(30);
+ expect(h.elements[0].y).toEqual(20);
+ expect(h.elements[0].width).toEqual(30); // 60 - 30
+ expect(h.elements[0].height).toEqual(50); // 70 - 20
+
+ expect(h.elements.length).toMatchSnapshot();
+ h.elements.forEach((element) => expect(element).toMatchSnapshot());
+ });
+
+ it("diamond", async () => {
+ const { getByToolName, container } = await render();
+ // select tool
+ const tool = getByToolName("diamond");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // move to (60,70)
+ fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `5`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`);
+ expect(h.state.selectionElement).toBeNull();
+
+ expect(h.elements.length).toEqual(1);
+ expect(h.elements[0].type).toEqual("diamond");
+ expect(h.elements[0].x).toEqual(30);
+ expect(h.elements[0].y).toEqual(20);
+ expect(h.elements[0].width).toEqual(30); // 60 - 30
+ expect(h.elements[0].height).toEqual(50); // 70 - 20
+
+ expect(h.elements.length).toMatchSnapshot();
+ h.elements.forEach((element) => expect(element).toMatchSnapshot());
+ });
+
+ it("arrow", async () => {
+ const { getByToolName, container } = await render();
+ // select tool
+ const tool = getByToolName("arrow");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // move to (60,70)
+ fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `5`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`);
+ expect(h.state.selectionElement).toBeNull();
+
+ expect(h.elements.length).toEqual(1);
+
+ const element = h.elements[0] as ExcalidrawLinearElement;
+
+ expect(element.type).toEqual("arrow");
+ expect(element.x).toEqual(30);
+ expect(element.y).toEqual(20);
+ expect(element.points.length).toEqual(2);
+ expect(element.points[0]).toEqual([0, 0]);
+ expect(element.points[1]).toEqual([30, 50]); // (60 - 30, 70 - 20)
+
+ expect(h.elements.length).toMatchSnapshot();
+ h.elements.forEach((element) => expect(element).toMatchSnapshot());
+ });
+
+ it("line", async () => {
+ const { getByToolName, container } = await render();
+ // select tool
+ const tool = getByToolName("line");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // move to (60,70)
+ fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `5`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`);
+ expect(h.state.selectionElement).toBeNull();
+
+ expect(h.elements.length).toEqual(1);
+
+ const element = h.elements[0] as ExcalidrawLinearElement;
+
+ expect(element.type).toEqual("line");
+ expect(element.x).toEqual(30);
+ expect(element.y).toEqual(20);
+ expect(element.points.length).toEqual(2);
+ expect(element.points[0]).toEqual([0, 0]);
+ expect(element.points[1]).toEqual([30, 50]); // (60 - 30, 70 - 20)
+
+ h.elements.forEach((element) => expect(element).toMatchSnapshot());
+ });
+ });
+
+ describe("do not add element to the scene if size is too small", () => {
+ beforeAll(() => {
+ mockBoundingClientRect();
+ });
+ afterAll(() => {
+ restoreOriginalGetBoundingClientRect();
+ });
+
+ it("rectangle", async () => {
+ const { getByToolName, container } = await render();
+ // select tool
+ const tool = getByToolName("rectangle");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `5`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`);
+ expect(h.state.selectionElement).toBeNull();
+ expect(h.elements.length).toEqual(0);
+ });
+
+ it("ellipse", async () => {
+ const { getByToolName, container } = await render();
+ // select tool
+ const tool = getByToolName("ellipse");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `5`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`);
+ expect(h.state.selectionElement).toBeNull();
+ expect(h.elements.length).toEqual(0);
+ });
+
+ it("diamond", async () => {
+ const { getByToolName, container } = await render();
+ // select tool
+ const tool = getByToolName("diamond");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `5`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`5`);
+ expect(h.state.selectionElement).toBeNull();
+ expect(h.elements.length).toEqual(0);
+ });
+
+ it("arrow", async () => {
+ const { getByToolName, container } = await render(
+ ,
+ );
+ // select tool
+ const tool = getByToolName("arrow");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ // we need to finalize it because arrows and lines enter multi-mode
+ fireEvent.keyDown(document, {
+ key: KEYS.ENTER,
+ });
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `6`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`);
+ expect(h.state.selectionElement).toBeNull();
+ expect(h.elements.length).toEqual(0);
+ });
+
+ it("line", async () => {
+ const { getByToolName, container } = await render(
+ ,
+ );
+ // select tool
+ const tool = getByToolName("line");
+ fireEvent.click(tool);
+
+ const canvas = container.querySelector("canvas.interactive")!;
+
+ // start from (30, 20)
+ fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
+
+ // finish (position does not matter)
+ fireEvent.pointerUp(canvas);
+
+ // we need to finalize it because arrows and lines enter multi-mode
+ fireEvent.keyDown(document, {
+ key: KEYS.ENTER,
+ });
+
+ expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
+ `6`,
+ );
+ expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`);
+ expect(h.state.selectionElement).toBeNull();
+ expect(h.elements.length).toEqual(0);
+ });
+ });
+});
diff --git a/packages/excalidraw/tests/elementLocking.test.tsx b/packages/excalidraw/tests/elementLocking.test.tsx
new file mode 100644
index 0000000..281c268
--- /dev/null
+++ b/packages/excalidraw/tests/elementLocking.test.tsx
@@ -0,0 +1,388 @@
+import React from "react";
+import { Excalidraw } from "../index";
+import { render, unmountComponent } from "../tests/test-utils";
+import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
+import { KEYS } from "../keys";
+import { API } from "../tests/helpers/api";
+import { actionSelectAll } from "../actions";
+import { t } from "../i18n";
+import { mutateElement } from "../element/mutateElement";
+
+unmountComponent();
+
+const mouse = new Pointer("mouse");
+const h = window.h;
+
+describe("element locking", () => {
+ beforeEach(async () => {
+ await render();
+ API.setElements([]);
+ });
+
+ it("click-selecting a locked element is disabled", () => {
+ const lockedRectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ locked: true,
+ });
+
+ API.setElements([lockedRectangle]);
+
+ mouse.clickAt(50, 50);
+ expect(API.getSelectedElements().length).toBe(0);
+ });
+
+ it("box-selecting a locked element is disabled", () => {
+ const lockedRectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ locked: true,
+ x: 100,
+ y: 100,
+ });
+
+ API.setElements([lockedRectangle]);
+
+ mouse.downAt(50, 50);
+ mouse.moveTo(250, 250);
+ mouse.upAt(250, 250);
+ expect(API.getSelectedElements().length).toBe(0);
+ });
+
+ it("dragging a locked element is disabled", () => {
+ const lockedRectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ locked: true,
+ });
+
+ API.setElements([lockedRectangle]);
+
+ mouse.downAt(50, 50);
+ mouse.moveTo(100, 100);
+ mouse.upAt(100, 100);
+ expect(lockedRectangle).toEqual(expect.objectContaining({ x: 0, y: 0 }));
+ });
+
+ it("you can drag element that's below a locked element", () => {
+ const rectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ });
+ const lockedRectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ locked: true,
+ });
+
+ API.setElements([rectangle, lockedRectangle]);
+
+ mouse.downAt(50, 50);
+ mouse.moveTo(100, 100);
+ mouse.upAt(100, 100);
+ expect(lockedRectangle).toEqual(expect.objectContaining({ x: 0, y: 0 }));
+ expect(rectangle).toEqual(expect.objectContaining({ x: 50, y: 50 }));
+ expect(API.getSelectedElements().length).toBe(1);
+ expect(API.getSelectedElement().id).toBe(rectangle.id);
+ });
+
+ it("selectAll shouldn't select locked elements", () => {
+ API.setElements([
+ API.createElement({ type: "rectangle" }),
+ API.createElement({ type: "rectangle", locked: true }),
+ ]);
+ API.executeAction(actionSelectAll);
+ expect(API.getSelectedElements().length).toBe(1);
+ });
+
+ it("clicking on a locked element should select the unlocked element beneath it", () => {
+ const rectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ });
+ const lockedRectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ locked: true,
+ });
+
+ API.setElements([rectangle, lockedRectangle]);
+ expect(API.getSelectedElements().length).toBe(0);
+ mouse.clickAt(50, 50);
+ expect(API.getSelectedElements().length).toBe(1);
+ expect(API.getSelectedElement().id).toBe(rectangle.id);
+ });
+
+ it("right-clicking on a locked element should select it & open its contextMenu", () => {
+ const rectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ });
+ const lockedRectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ locked: true,
+ });
+
+ API.setElements([rectangle, lockedRectangle]);
+ expect(API.getSelectedElements().length).toBe(0);
+ mouse.rightClickAt(50, 50);
+ expect(API.getSelectedElements().length).toBe(1);
+ expect(API.getSelectedElement().id).toBe(lockedRectangle.id);
+
+ const contextMenu = UI.queryContextMenu();
+ expect(contextMenu).not.toBeNull();
+ expect(
+ contextMenu?.querySelector(
+ `li[data-testid="toggleElementLock"] .context-menu-item__label`,
+ ),
+ ).toHaveTextContent(t("labels.elementLock.unlock"));
+ });
+
+ it("right-clicking on element covered by locked element should ignore the locked element", () => {
+ const rectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ });
+ const lockedRectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ locked: true,
+ });
+
+ API.setElements([rectangle, lockedRectangle]);
+ API.setSelectedElements([rectangle]);
+ expect(API.getSelectedElements().length).toBe(1);
+ expect(API.getSelectedElement().id).toBe(rectangle.id);
+ mouse.rightClickAt(50, 50);
+ expect(API.getSelectedElements().length).toBe(1);
+ expect(API.getSelectedElement().id).toBe(rectangle.id);
+
+ const contextMenu = UI.queryContextMenu();
+ expect(contextMenu).not.toBeNull();
+ });
+
+ it("selecting a group selects all elements including locked ones", () => {
+ const rectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ groupIds: ["g1"],
+ });
+ const lockedRectangle = API.createElement({
+ type: "rectangle",
+ width: 100,
+ backgroundColor: "red",
+ fillStyle: "solid",
+ locked: true,
+ groupIds: ["g1"],
+ x: 200,
+ y: 200,
+ });
+
+ API.setElements([rectangle, lockedRectangle]);
+
+ mouse.clickAt(250, 250);
+ expect(API.getSelectedElements().length).toBe(0);
+
+ mouse.clickAt(50, 50);
+ expect(API.getSelectedElements().length).toBe(2);
+ });
+
+ it("should ignore locked text element in center of container on ENTER", () => {
+ const container = API.createElement({
+ type: "rectangle",
+ width: 100,
+ });
+ const textSize = 20;
+ const text = API.createElement({
+ type: "text",
+ text: "ola",
+ x: container.width / 2 - textSize / 2,
+ y: container.height / 2 - textSize / 2,
+ width: textSize,
+ height: textSize,
+ containerId: container.id,
+ locked: true,
+ });
+ API.setElements([container, text]);
+ API.setSelectedElements([container]);
+ Keyboard.keyPress(KEYS.ENTER);
+ expect(h.state.editingTextElement?.id).not.toBe(text.id);
+ expect(h.state.editingTextElement?.id).toBe(h.elements[1].id);
+ });
+
+ it("should ignore locked text under cursor when clicked with text tool", () => {
+ const text = API.createElement({
+ type: "text",
+ text: "ola",
+ x: 60,
+ y: 0,
+ width: 100,
+ height: 100,
+ locked: true,
+ });
+ API.setElements([text]);
+ UI.clickTool("text");
+ mouse.clickAt(text.x + 50, text.y + 50);
+ const editor = document.querySelector(
+ ".excalidraw-textEditorContainer > textarea",
+ ) as HTMLTextAreaElement;
+ expect(editor).not.toBe(null);
+ expect(h.state.editingTextElement?.id).not.toBe(text.id);
+ expect(h.elements.length).toBe(2);
+ expect(h.state.editingTextElement?.id).toBe(h.elements[1].id);
+ });
+
+ it("should ignore text under cursor when double-clicked with selection tool", () => {
+ const text = API.createElement({
+ type: "text",
+ text: "ola",
+ x: 60,
+ y: 0,
+ width: 100,
+ height: 100,
+ locked: true,
+ });
+ API.setElements([text]);
+ UI.clickTool("selection");
+ mouse.doubleClickAt(text.x + 50, text.y + 50);
+ const editor = document.querySelector(
+ ".excalidraw-textEditorContainer > textarea",
+ ) as HTMLTextAreaElement;
+ expect(editor).not.toBe(null);
+ expect(h.state.editingTextElement?.id).not.toBe(text.id);
+ expect(h.elements.length).toBe(2);
+ expect(h.state.editingTextElement?.id).toBe(h.elements[1].id);
+ });
+
+ it("locking should include bound text", () => {
+ const container = API.createElement({
+ type: "rectangle",
+ width: 100,
+ });
+ const textSize = 20;
+ const text = API.createElement({
+ type: "text",
+ text: "ola",
+ x: container.width / 2 - textSize / 2,
+ y: container.height / 2 - textSize / 2,
+ width: textSize,
+ height: textSize,
+ containerId: container.id,
+ });
+ mutateElement(container, {
+ boundElements: [{ id: text.id, type: "text" }],
+ });
+
+ API.setElements([container, text]);
+
+ UI.clickTool("selection");
+ mouse.clickAt(container.x + 10, container.y + 10);
+ Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
+ Keyboard.keyPress(KEYS.L);
+ });
+
+ expect(h.elements).toEqual([
+ expect.objectContaining({
+ id: container.id,
+ locked: true,
+ }),
+ expect.objectContaining({
+ id: text.id,
+ locked: true,
+ }),
+ ]);
+ });
+
+ it("bound text shouldn't be editable via double-click", () => {
+ const container = API.createElement({
+ type: "rectangle",
+ width: 100,
+ locked: true,
+ });
+ const textSize = 20;
+ const text = API.createElement({
+ type: "text",
+ text: "ola",
+ x: container.width / 2 - textSize / 2,
+ y: container.height / 2 - textSize / 2,
+ width: textSize,
+ height: textSize,
+ containerId: container.id,
+ locked: true,
+ });
+ mutateElement(container, {
+ boundElements: [{ id: text.id, type: "text" }],
+ });
+ API.setElements([container, text]);
+
+ UI.clickTool("selection");
+ mouse.doubleClickAt(container.width / 2, container.height / 2);
+
+ const editor = document.querySelector(
+ ".excalidraw-textEditorContainer > textarea",
+ ) as HTMLTextAreaElement;
+ expect(editor).not.toBe(null);
+ expect(h.state.editingTextElement?.id).not.toBe(text.id);
+ expect(h.elements.length).toBe(3);
+ expect(h.state.editingTextElement?.id).toBe(h.elements[2].id);
+ });
+
+ it("bound text shouldn't be editable via text tool", () => {
+ const container = API.createElement({
+ type: "rectangle",
+ width: 100,
+ locked: true,
+ });
+ const textSize = 20;
+ const text = API.createElement({
+ type: "text",
+ text: "ola",
+ x: container.width / 2 - textSize / 2,
+ y: container.height / 2 - textSize / 2,
+ width: textSize,
+ height: textSize,
+ containerId: container.id,
+ locked: true,
+ });
+ mutateElement(container, {
+ boundElements: [{ id: text.id, type: "text" }],
+ });
+ API.setElements([container, text]);
+
+ UI.clickTool("text");
+ mouse.clickAt(container.width / 2, container.height / 2);
+
+ const editor = document.querySelector(
+ ".excalidraw-textEditorContainer > textarea",
+ ) as HTMLTextAreaElement;
+ expect(editor).not.toBe(null);
+ expect(h.state.editingTextElement?.id).not.toBe(text.id);
+ expect(h.elements.length).toBe(3);
+ expect(h.state.editingTextElement?.id).toBe(h.elements[2].id);
+ });
+});
diff --git a/packages/excalidraw/tests/excalidraw.test.tsx b/packages/excalidraw/tests/excalidraw.test.tsx
new file mode 100644
index 0000000..6fbcf2a
--- /dev/null
+++ b/packages/excalidraw/tests/excalidraw.test.tsx
@@ -0,0 +1,409 @@
+import React from "react";
+import { fireEvent, GlobalTestState, toggleMenu, render } from "./test-utils";
+import { Excalidraw, Footer, MainMenu } from "../index";
+import { queryByText, queryByTestId } from "@testing-library/react";
+import { THEME } from "../constants";
+import { t } from "../i18n";
+import { useMemo } from "react";
+
+const { h } = window;
+
+describe("", () => {
+ afterEach(() => {
+ const menu = document.querySelector(".dropdown-menu");
+ if (menu) {
+ toggleMenu(document.querySelector(".excalidraw")!);
+ }
+ });
+
+ describe("Test zenModeEnabled prop", () => {
+ it('should show exit zen mode button when zen mode is set and zen mode option in context menu when zenModeEnabled is "undefined"', async () => {
+ const { container } = await render();
+ expect(
+ container.getElementsByClassName("disable-zen-mode--visible").length,
+ ).toBe(0);
+ expect(h.state.zenModeEnabled).toBe(false);
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 1,
+ clientY: 1,
+ });
+ const contextMenu = document.querySelector(".context-menu");
+ fireEvent.click(queryByText(contextMenu as HTMLElement, "Zen mode")!);
+ expect(h.state.zenModeEnabled).toBe(true);
+ expect(
+ container.getElementsByClassName("disable-zen-mode--visible").length,
+ ).toBe(1);
+ });
+
+ it("should not show exit zen mode button and zen mode option in context menu when zenModeEnabled is set", async () => {
+ const { container } = await render();
+ expect(
+ container.getElementsByClassName("disable-zen-mode--visible").length,
+ ).toBe(0);
+ expect(h.state.zenModeEnabled).toBe(true);
+
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 1,
+ clientY: 1,
+ });
+ const contextMenu = document.querySelector(".context-menu");
+ expect(queryByText(contextMenu as HTMLElement, "Zen mode")).toBe(null);
+ expect(h.state.zenModeEnabled).toBe(true);
+ expect(
+ container.getElementsByClassName("disable-zen-mode--visible").length,
+ ).toBe(0);
+ });
+ });
+
+ it("should render the footer only when Footer is passed as children", async () => {
+ //Footer not passed hence it will not render the footer
+ let { container } = await render(
+
+ This is a custom footer
+ ,
+ );
+ expect(container.querySelector(".footer-center")).toBe(null);
+
+ // Footer passed hence it will render the footer
+ ({ container } = await render(
+
+
+ ,
+ ));
+ expect(container.querySelector(".footer-center")).toMatchInlineSnapshot(
+ `
+
+ `,
+ );
+ });
+
+ describe("Test gridModeEnabled prop", () => {
+ it('should show grid mode in context menu when gridModeEnabled is "undefined"', async () => {
+ const { container } = await render();
+ expect(h.state.gridModeEnabled).toBe(false);
+
+ expect(
+ container.getElementsByClassName("disable-zen-mode--visible").length,
+ ).toBe(0);
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 1,
+ clientY: 1,
+ });
+ const contextMenu = document.querySelector(".context-menu");
+ fireEvent.click(queryByText(contextMenu as HTMLElement, "Toggle grid")!);
+ expect(h.state.gridModeEnabled).toBe(true);
+ });
+
+ it('should not show grid mode in context menu when gridModeEnabled is not "undefined"', async () => {
+ const { container } = await render(
+ ,
+ );
+ expect(h.state.gridModeEnabled).toBe(false);
+
+ expect(
+ container.getElementsByClassName("disable-zen-mode--visible").length,
+ ).toBe(0);
+ fireEvent.contextMenu(GlobalTestState.interactiveCanvas, {
+ button: 2,
+ clientX: 1,
+ clientY: 1,
+ });
+ const contextMenu = document.querySelector(".context-menu");
+ expect(queryByText(contextMenu as HTMLElement, "Show grid")).toBe(null);
+ expect(h.state.gridModeEnabled).toBe(false);
+ });
+ });
+
+ describe("Test UIOptions prop", () => {
+ describe("Test canvasActions", () => {
+ it('should render menu with default items when "UIOPtions" is "undefined"', async () => {
+ const { container } = await render(
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "dropdown-menu")).toMatchSnapshot();
+ });
+
+ it("should hide clear canvas button when clearCanvas is false", async () => {
+ const { container } = await render(
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "clear-canvas-button")).toBeNull();
+ });
+
+ it("should hide export button when export is false", async () => {
+ const { container } = await render(
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "json-export-button")).toBeNull();
+ });
+
+ it("should hide 'Save as image' button when 'saveAsImage' is false", async () => {
+ const { container } = await render(
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "image-export-button")).toBeNull();
+ });
+
+ it("should hide load button when loadScene is false", async () => {
+ const { container } = await render(
+ ,
+ );
+
+ expect(queryByTestId(container, "load-button")).toBeNull();
+ });
+
+ it("should hide save as button when saveFileToDisk is false", async () => {
+ const { container } = await render(
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "save-as-button")).toBeNull();
+ });
+
+ it("should hide save button when saveToActiveFile is false", async () => {
+ const { container } = await render(
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "save-button")).toBeNull();
+ });
+
+ it("should hide the canvas background picker when changeViewBackgroundColor is false", async () => {
+ const { container } = await render(
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "canvas-background-label")).toBeNull();
+ expect(queryByTestId(container, "canvas-background-picker")).toBeNull();
+ });
+
+ it("should hide the canvas background picker even if passed if the `canvasActions.changeViewBackgroundColor` is set to false", async () => {
+ const { container } = await render(
+
+
+
+
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "canvas-background-label")).toBeNull();
+ expect(queryByTestId(container, "canvas-background-picker")).toBeNull();
+ });
+
+ it("should hide the theme toggle when theme is false", async () => {
+ const { container } = await render(
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "toggle-dark-mode")).toBeNull();
+ });
+
+ it("should not render default items in custom menu even if passed if the prop in `canvasActions` is set to false", async () => {
+ const { container } = await render(
+
+
+
+
+
+
+
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ // load button shouldn't be rendered since `UIActions.canvasActions.loadScene` is `false`
+ expect(queryByTestId(container, "load-button")).toBeNull();
+ });
+ });
+ });
+
+ describe("Test theme prop", () => {
+ it("should show the theme toggle by default", async () => {
+ const { container } = await render();
+ expect(h.state.theme).toBe(THEME.LIGHT);
+ //open menu
+ toggleMenu(container);
+ const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
+ expect(darkModeToggle).toBeTruthy();
+ });
+
+ it("should not show theme toggle when the theme prop is defined", async () => {
+ const { container } = await render();
+
+ expect(h.state.theme).toBe(THEME.DARK);
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "toggle-dark-mode")).toBe(null);
+ });
+
+ it("should show theme mode toggle when `UIOptions.canvasActions.toggleTheme` is true", async () => {
+ const { container } = await render(
+ ,
+ );
+ expect(h.state.theme).toBe(THEME.DARK);
+ //open menu
+ toggleMenu(container);
+ const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
+ expect(darkModeToggle).toBeTruthy();
+ });
+
+ it("should not show theme toggle when `UIOptions.canvasActions.toggleTheme` is false", async () => {
+ const { container } = await render(
+ ,
+ );
+ expect(h.state.theme).toBe(THEME.DARK);
+ //open menu
+ toggleMenu(container);
+ const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
+ expect(darkModeToggle).toBe(null);
+ });
+ });
+
+ describe("Test name prop", () => {
+ it("should allow editing name", async () => {
+ const { container } = await render();
+ //open menu
+ toggleMenu(container);
+ fireEvent.click(queryByTestId(container, "image-export-button")!);
+ const textInput: HTMLInputElement | null = document.querySelector(
+ ".ImageExportModal .ImageExportModal__preview__filename .TextInput",
+ );
+ expect(textInput?.value).toContain(`${t("labels.untitled")}`);
+ expect(textInput?.nodeName).toBe("INPUT");
+ });
+
+ it('should set the name when the name prop is present"', async () => {
+ const name = "test";
+ const { container } = await render();
+ //open menu
+ toggleMenu(container);
+ await fireEvent.click(queryByTestId(container, "image-export-button")!);
+ const textInput = document.querySelector(
+ ".ImageExportModal .ImageExportModal__preview__filename .TextInput",
+ ) as HTMLInputElement;
+ expect(textInput?.value).toEqual(name);
+ expect(textInput?.nodeName).toBe("INPUT");
+ });
+ });
+
+ describe("Test autoFocus prop", () => {
+ it("should not focus when autoFocus is false", async () => {
+ const { container } = await render();
+
+ expect(
+ container.querySelector(".excalidraw") === document.activeElement,
+ ).toBe(false);
+ });
+
+ it("should focus when autoFocus is true", async () => {
+ const { container } = await render();
+
+ expect(
+ container.querySelector(".excalidraw") === document.activeElement,
+ ).toBe(true);
+ });
+ });
+
+ describe("", () => {
+ it("should render main menu with host menu items if passed from host", async () => {
+ const { container } = await render(
+
+
+ window.alert("Clicked")}>
+ Click me
+
+
+ Excalidraw blog
+
+
+
+
+
+
+ ,
+ );
+ //open menu
+ toggleMenu(container);
+ expect(queryByTestId(container, "dropdown-menu")).toMatchSnapshot();
+ });
+
+ it("should update themeToggle text even if MainMenu memoized", async () => {
+ const CustomExcalidraw = () => {
+ const customMenu = useMemo(() => {
+ return (
+
+
+
+ );
+ }, []);
+
+ return {customMenu};
+ };
+
+ const { container } = await render();
+ //open menu
+ toggleMenu(container);
+
+ expect(h.state.theme).toBe(THEME.LIGHT);
+
+ expect(
+ queryByTestId(container, "toggle-dark-mode")?.textContent,
+ ).toContain(t("buttons.darkMode"));
+
+ fireEvent.click(queryByTestId(container, "toggle-dark-mode")!);
+
+ expect(
+ queryByTestId(container, "toggle-dark-mode")?.textContent,
+ ).toContain(t("buttons.lightMode"));
+ });
+ });
+});
diff --git a/packages/excalidraw/tests/export.test.tsx b/packages/excalidraw/tests/export.test.tsx
new file mode 100644
index 0000000..3547b29
--- /dev/null
+++ b/packages/excalidraw/tests/export.test.tsx
@@ -0,0 +1,197 @@
+import React from "react";
+import { render, waitFor } from "./test-utils";
+import { Excalidraw } from "../index";
+import { API } from "./helpers/api";
+import { encodePngMetadata } from "../data/image";
+import { serializeAsJSON } from "../data/json";
+import {
+ decodeSvgBase64Payload,
+ encodeSvgBase64Payload,
+ exportToSvg,
+} from "../scene/export";
+import type { FileId } from "../element/types";
+import { getDataURL } from "../data/blob";
+import { getDefaultAppState } from "../appState";
+import { SVG_NS } from "../constants";
+
+const { h } = window;
+
+const testElements = [
+ {
+ ...API.createElement({
+ type: "text",
+ id: "A",
+ text: "😀",
+ }),
+ // can't get jsdom text measurement to work so this is a temp hack
+ // to ensure the element isn't stripped as invisible
+ width: 16,
+ height: 16,
+ },
+];
+
+// tiny polyfill for TextDecoder.decode on which we depend
+Object.defineProperty(window, "TextDecoder", {
+ value: class TextDecoder {
+ decode(ab: ArrayBuffer) {
+ return new Uint8Array(ab).reduce(
+ (acc, c) => acc + String.fromCharCode(c),
+ "",
+ );
+ }
+ },
+});
+
+describe("export", () => {
+ beforeEach(async () => {
+ await render();
+ });
+
+ it("export embedded png and reimport", async () => {
+ const pngBlob = await API.loadFile("./fixtures/smiley.png");
+ const pngBlobEmbedded = await encodePngMetadata({
+ blob: pngBlob,
+ metadata: serializeAsJSON(testElements, h.state, {}, "local"),
+ });
+ await API.drop(pngBlobEmbedded);
+
+ await waitFor(() => {
+ expect(h.elements).toEqual([
+ expect.objectContaining({ type: "text", text: "😀" }),
+ ]);
+ });
+ });
+
+ it("test encoding/decoding scene for SVG export", async () => {
+ const metadataElement = document.createElementNS(SVG_NS, "metadata");
+
+ encodeSvgBase64Payload({
+ metadataElement,
+ payload: serializeAsJSON(testElements, h.state, {}, "local"),
+ });
+
+ const decoded = JSON.parse(
+ decodeSvgBase64Payload({ svg: metadataElement.innerHTML }),
+ );
+ expect(decoded.elements).toEqual([
+ expect.objectContaining({ type: "text", text: "😀" }),
+ ]);
+ });
+
+ it("export svg-embedded scene", async () => {
+ const svg = await exportToSvg(
+ testElements,
+ { ...getDefaultAppState(), exportEmbedScene: true },
+ {},
+ );
+ const svgText = svg.outerHTML;
+
+ expect(svgText).toMatchSnapshot(`svg-embdedded scene export output`);
+ });
+
+ it("import embedded png (legacy v1)", async () => {
+ await API.drop(await API.loadFile("./fixtures/test_embedded_v1.png"));
+ await waitFor(() => {
+ expect(h.elements).toEqual([
+ expect.objectContaining({ type: "text", text: "test" }),
+ ]);
+ });
+ });
+
+ it("import embedded png (v2)", async () => {
+ await API.drop(await API.loadFile("./fixtures/smiley_embedded_v2.png"));
+ await waitFor(() => {
+ expect(h.elements).toEqual([
+ expect.objectContaining({ type: "text", text: "😀" }),
+ ]);
+ });
+ });
+
+ it("import embedded svg (legacy v1)", async () => {
+ await API.drop(await API.loadFile("./fixtures/test_embedded_v1.svg"));
+ await waitFor(() => {
+ expect(h.elements).toEqual([
+ expect.objectContaining({ type: "text", text: "test" }),
+ ]);
+ });
+ });
+
+ it("import embedded svg (v2)", async () => {
+ await API.drop(await API.loadFile("./fixtures/smiley_embedded_v2.svg"));
+ await waitFor(() => {
+ expect(h.elements).toEqual([
+ expect.objectContaining({ type: "text", text: "😀" }),
+ ]);
+ });
+ });
+
+ it("exporting svg containing transformed images", async () => {
+ const normalizeAngle = (angle: number) => (angle / 180) * Math.PI;
+
+ const elements = [
+ API.createElement({
+ type: "image",
+ fileId: "file_A",
+ x: 0,
+ y: 0,
+ scale: [1, 1],
+ width: 100,
+ height: 100,
+ angle: normalizeAngle(315),
+ }),
+ API.createElement({
+ type: "image",
+ fileId: "file_A",
+ x: 100,
+ y: 0,
+ scale: [-1, 1],
+ width: 50,
+ height: 50,
+ angle: normalizeAngle(45),
+ }),
+ API.createElement({
+ type: "image",
+ fileId: "file_A",
+ x: 0,
+ y: 100,
+ scale: [1, -1],
+ width: 100,
+ height: 100,
+ angle: normalizeAngle(45),
+ }),
+ API.createElement({
+ type: "image",
+ fileId: "file_A",
+ x: 100,
+ y: 100,
+ scale: [-1, -1],
+ width: 50,
+ height: 50,
+ angle: normalizeAngle(315),
+ }),
+ ];
+ const appState = { ...getDefaultAppState(), exportBackground: false };
+ const files = {
+ file_A: {
+ id: "file_A" as FileId,
+ dataURL: await getDataURL(await API.loadFile("./fixtures/deer.png")),
+ mimeType: "image/png",
+ created: Date.now(),
+ lastRetrieved: Date.now(),
+ },
+ } as const;
+
+ const svg = await exportToSvg(elements, appState, files);
+
+ const svgText = svg.outerHTML;
+
+ // expect 1 element (deduped)
+ expect(svgText.match(/ elements (one for each excalidraw image element)
+ expect(svgText.match(/