Factor out collaboration code (#2313)

Co-authored-by: Lipis <lipiridis@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
Aakansha Doshi 2020-12-05 20:00:53 +05:30 committed by GitHub
parent d8a0dc3b4d
commit e617ccc252
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 2250 additions and 2018 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
import { render } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import { setLanguage } from "../i18n";
import { UI, Pointer, Keyboard } from "./helpers/ui";
import { API } from "./helpers/api";
@ -20,15 +20,6 @@ const { h } = window;
const mouse = new Pointer("mouse");
beforeEach(async () => {
// Unmount ReactDOM from root
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
mouse.reset();
await setLanguage("en.json");
render(<App />);
});
const createAndSelectTwoRectangles = () => {
UI.clickTool("rectangle");
mouse.down();
@ -63,517 +54,528 @@ const createAndSelectTwoRectanglesWithDifferentSizes = () => {
});
};
it("aligns two objects correctly to the top", () => {
createAndSelectTwoRectangles();
describe("aligning", () => {
beforeEach(async () => {
// Unmount ReactDOM from root
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
mouse.reset();
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);
await setLanguage("en.json");
await render(<ExcalidrawApp />);
});
// Check if x position did not change
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
it("aligns two objects correctly to the top", () => {
createAndSelectTwoRectangles();
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(0);
});
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
it("aligns two objects correctly to the bottom", () => {
createAndSelectTwoRectangles();
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
Keyboard.keyPress(KEYS.ARROW_UP);
});
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
// Check if x position did not change
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
Keyboard.keyPress(KEYS.ARROW_DOWN);
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(0);
});
// Check if x position did not change
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
it("aligns two objects correctly to the bottom", () => {
createAndSelectTwoRectangles();
expect(API.getSelectedElements()[0].y).toEqual(110);
expect(API.getSelectedElements()[1].y).toEqual(110);
});
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
it("aligns two objects correctly to the left", () => {
createAndSelectTwoRectangles();
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
Keyboard.keyPress(KEYS.ARROW_DOWN);
});
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
// Check if x position did not change
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
Keyboard.keyPress(KEYS.ARROW_LEFT);
expect(API.getSelectedElements()[0].y).toEqual(110);
expect(API.getSelectedElements()[1].y).toEqual(110);
});
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(0);
it("aligns two objects correctly to the left", () => {
createAndSelectTwoRectangles();
// Check if y position did not change
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
});
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
it("aligns two objects correctly to the right", () => {
createAndSelectTwoRectangles();
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
Keyboard.keyPress(KEYS.ARROW_LEFT);
});
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(0);
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
Keyboard.keyPress(KEYS.ARROW_RIGHT);
// Check if y position did not change
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
});
expect(API.getSelectedElements()[0].x).toEqual(110);
expect(API.getSelectedElements()[1].x).toEqual(110);
it("aligns two objects correctly to the right", () => {
createAndSelectTwoRectangles();
// Check if y position did not change
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
});
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
it("centers two objects with different sizes correctly vertically", () => {
createAndSelectTwoRectanglesWithDifferentSizes();
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
Keyboard.keyPress(KEYS.ARROW_RIGHT);
});
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
expect(API.getSelectedElements()[0].x).toEqual(110);
expect(API.getSelectedElements()[1].x).toEqual(110);
h.app.actionManager.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);
h.app.actionManager.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();
// Check if y position did not change
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
});
h.app.actionManager.executeAction(actionGroup);
it("centers two objects with different sizes correctly vertically", () => {
createAndSelectTwoRectanglesWithDifferentSizes();
mouse.reset();
UI.clickTool("rectangle");
mouse.down(200, 200);
mouse.up(100, 100);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
// Add the created group to the current selection
mouse.restorePosition(0, 0);
Keyboard.withModifierKeys({ shift: true }, () => {
mouse.click();
});
};
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
it("aligns a group with another element correctly to the top", () => {
createAndSelectGroupAndRectangle();
h.app.actionManager.executeAction(actionAlignVerticallyCentered);
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(100);
expect(API.getSelectedElements()[2].y).toEqual(200);
// Check if x position did not change
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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();
expect(API.getSelectedElements()[0].y).toEqual(60);
expect(API.getSelectedElements()[1].y).toEqual(55);
});
h.app.actionManager.executeAction(actionGroup);
it("centers two objects with different sizes correctly horizontally", () => {
createAndSelectTwoRectanglesWithDifferentSizes();
mouse.reset();
UI.clickTool("rectangle");
mouse.down(200, 200);
mouse.up(100, 100);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(110);
UI.clickTool("rectangle");
mouse.down();
mouse.up(100, 100);
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(110);
mouse.restorePosition(200, 200);
Keyboard.withModifierKeys({ shift: true }, () => {
mouse.click();
h.app.actionManager.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);
});
h.app.actionManager.executeAction(actionGroup);
const createAndSelectGroupAndRectangle = () => {
UI.clickTool("rectangle");
mouse.down();
mouse.up(100, 100);
// 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();
});
};
UI.clickTool("rectangle");
mouse.down(0, 0);
mouse.up(100, 100);
it("aligns two groups correctly to the top", () => {
createAndSelectTwoGroups();
// 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();
});
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);
h.app.actionManager.executeAction(actionGroup);
h.app.actionManager.executeAction(actionAlignTop);
mouse.reset();
UI.clickTool("rectangle");
mouse.down(200, 200);
mouse.up(100, 100);
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);
});
// Add the created group to the current selection
mouse.restorePosition(0, 0);
Keyboard.withModifierKeys({ shift: true }, () => {
mouse.click();
});
};
it("aligns two groups correctly to the bottom", () => {
createAndSelectTwoGroups();
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);
expect(API.getSelectedElements()[3].y).toEqual(300);
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(100);
expect(API.getSelectedElements()[2].y).toEqual(200);
h.app.actionManager.executeAction(actionAlignBottom);
h.app.actionManager.executeAction(actionAlignTop);
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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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();
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(100);
expect(API.getSelectedElements()[2].y).toEqual(0);
});
// Create first group of rectangles
h.app.actionManager.executeAction(actionGroup);
it("aligns a group with another element correctly to the bottom", () => {
createAndSelectGroupAndRectangle();
mouse.reset();
UI.clickTool("rectangle");
mouse.down(200, 200);
mouse.up(100, 100);
expect(API.getSelectedElements()[0].y).toEqual(0);
expect(API.getSelectedElements()[1].y).toEqual(100);
expect(API.getSelectedElements()[2].y).toEqual(200);
// Add group to current selection
mouse.restorePosition(0, 0);
Keyboard.withModifierKeys({ shift: true }, () => {
mouse.click();
h.app.actionManager.executeAction(actionAlignBottom);
expect(API.getSelectedElements()[0].y).toEqual(100);
expect(API.getSelectedElements()[1].y).toEqual(200);
expect(API.getSelectedElements()[2].y).toEqual(200);
});
// Create the nested group
h.app.actionManager.executeAction(actionGroup);
it("aligns a group with another element correctly to the left", () => {
createAndSelectGroupAndRectangle();
mouse.reset();
UI.clickTool("rectangle");
mouse.down(300, 300);
mouse.up(100, 100);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(100);
expect(API.getSelectedElements()[2].x).toEqual(200);
// Select the nested group, the rectangle is already selected
mouse.reset();
Keyboard.withModifierKeys({ shift: true }, () => {
mouse.click();
h.app.actionManager.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 nested group and other element correctly to the top", () => {
createAndSelectNestedGroupAndRectangle();
it("aligns a group with another element correctly to the right", () => {
createAndSelectGroupAndRectangle();
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);
expect(API.getSelectedElements()[0].x).toEqual(0);
expect(API.getSelectedElements()[1].x).toEqual(100);
expect(API.getSelectedElements()[2].x).toEqual(200);
h.app.actionManager.executeAction(actionAlignTop);
h.app.actionManager.executeAction(actionAlignRight);
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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
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);
h.app.actionManager.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);
h.app.actionManager.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();
});
h.app.actionManager.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();
});
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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
h.app.actionManager.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
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
h.app.actionManager.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);
});
});

View file

@ -1,6 +1,6 @@
import React from "react";
import { render, waitFor } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import { API } from "./helpers/api";
import { getDefaultAppState } from "../appState";
@ -10,18 +10,15 @@ describe("appState", () => {
it("drag&drop file doesn't reset non-persisted appState", async () => {
const defaultAppState = getDefaultAppState();
const exportBackground = !defaultAppState.exportBackground;
render(
<App
initialData={{
appState: {
...defaultAppState,
exportBackground,
viewBackgroundColor: "#F00",
},
elements: [],
}}
/>,
);
await render(<ExcalidrawApp />, {
localStorageData: {
appState: {
exportBackground,
viewBackgroundColor: "#F00",
},
},
});
await waitFor(() => {
expect(h.state.exportBackground).toBe(exportBackground);

View file

@ -1,6 +1,6 @@
import React from "react";
import { render } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import { UI, Pointer, Keyboard } from "./helpers/ui";
import { getTransformHandles } from "../element/transformHandles";
import { API } from "./helpers/api";
@ -11,8 +11,8 @@ const { h } = window;
const mouse = new Pointer("mouse");
describe("element binding", () => {
beforeEach(() => {
render(<App />);
beforeEach(async () => {
await render(<ExcalidrawApp />);
});
it("rotation of arrow should rebind both ends", () => {

View file

@ -1,9 +1,8 @@
import React from "react";
import { render, waitFor } from "./test-utils";
import App from "../components/App";
import { render, updateSceneData, waitFor } from "./test-utils";
import ExcalidrawApp from "../excalidraw-app";
import { API } from "./helpers/api";
import { createUndoAction } from "../actions/actionHistory";
const { h } = window;
Object.defineProperty(window, "crypto", {
@ -17,7 +16,7 @@ Object.defineProperty(window, "crypto", {
},
});
jest.mock("../data/firebase.ts", () => {
jest.mock("../excalidraw-app/data/firebase.ts", () => {
const loadFromFirebase = async () => null;
const saveToFirebase = () => {};
const isSavedToFirebase = () => true;
@ -42,17 +41,18 @@ jest.mock("socket.io-client", () => {
describe("collaboration", () => {
it("creating room should reset deleted elements", async () => {
render(
<App
initialData={{
elements: [
API.createElement({ type: "rectangle", id: "A" }),
API.createElement({ type: "rectangle", id: "B", isDeleted: true }),
],
}}
/>,
);
await render(<ExcalidrawApp />);
// To update the scene with deleted elements before starting collab
updateSceneData({
elements: [
API.createElement({ type: "rectangle", id: "A" }),
API.createElement({
type: "rectangle",
id: "B",
isDeleted: true,
}),
],
});
await waitFor(() => {
expect(h.elements).toEqual([
expect.objectContaining({ id: "A" }),
@ -60,8 +60,7 @@ describe("collaboration", () => {
]);
expect(API.getStateHistory().length).toBe(1);
});
await h.app.openPortal();
h.collab.openPortal();
await waitFor(() => {
expect(h.elements).toEqual([expect.objectContaining({ id: "A" })]);
expect(API.getStateHistory().length).toBe(1);

View file

@ -1,6 +1,6 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import * as Renderer from "../renderer/renderScene";
import { KEYS } from "../keys";
import { render, fireEvent } from "./test-utils";
@ -20,8 +20,8 @@ beforeEach(() => {
const { h } = window;
describe("add element to the scene when pointer dragging long enough", () => {
it("rectangle", () => {
const { getByToolName, container } = render(<App />);
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("rectangle");
fireEvent.click(tool);
@ -37,7 +37,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
// finish (position does not matter)
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
@ -51,8 +51,8 @@ describe("add element to the scene when pointer dragging long enough", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("ellipse", () => {
const { getByToolName, container } = render(<App />);
it("ellipse", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("ellipse");
fireEvent.click(tool);
@ -68,7 +68,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
// finish (position does not matter)
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
@ -82,8 +82,8 @@ describe("add element to the scene when pointer dragging long enough", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("diamond", () => {
const { getByToolName, container } = render(<App />);
it("diamond", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("diamond");
fireEvent.click(tool);
@ -99,7 +99,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
// finish (position does not matter)
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
@ -113,8 +113,8 @@ describe("add element to the scene when pointer dragging long enough", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("arrow", () => {
const { getByToolName, container } = render(<App />);
it("arrow", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("arrow");
fireEvent.click(tool);
@ -130,7 +130,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
// finish (position does not matter)
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
@ -148,8 +148,8 @@ describe("add element to the scene when pointer dragging long enough", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("line", () => {
const { getByToolName, container } = render(<App />);
it("line", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("line");
fireEvent.click(tool);
@ -165,7 +165,7 @@ describe("add element to the scene when pointer dragging long enough", () => {
// finish (position does not matter)
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
@ -184,8 +184,8 @@ describe("add element to the scene when pointer dragging long enough", () => {
});
describe("do not add element to the scene if size is too small", () => {
it("rectangle", () => {
const { getByToolName, container } = render(<App />);
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("rectangle");
fireEvent.click(tool);
@ -198,13 +198,13 @@ describe("do not add element to the scene if size is too small", () => {
// finish (position does not matter)
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(4);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(0);
});
it("ellipse", () => {
const { getByToolName, container } = render(<App />);
it("ellipse", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("ellipse");
fireEvent.click(tool);
@ -217,13 +217,13 @@ describe("do not add element to the scene if size is too small", () => {
// finish (position does not matter)
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(4);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(0);
});
it("diamond", () => {
const { getByToolName, container } = render(<App />);
it("diamond", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("diamond");
fireEvent.click(tool);
@ -236,13 +236,13 @@ describe("do not add element to the scene if size is too small", () => {
// finish (position does not matter)
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(4);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(0);
});
it("arrow", () => {
const { getByToolName, container } = render(<App />);
it("arrow", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("arrow");
fireEvent.click(tool);
@ -258,13 +258,13 @@ describe("do not add element to the scene if size is too small", () => {
// we need to finalize it because arrows and lines enter multi-mode
fireEvent.keyDown(document, { key: KEYS.ENTER });
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(0);
});
it("line", () => {
const { getByToolName, container } = render(<App />);
it("line", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("line");
fireEvent.click(tool);
@ -280,7 +280,7 @@ describe("do not add element to the scene if size is too small", () => {
// we need to finalize it because arrows and lines enter multi-mode
fireEvent.keyDown(document, { key: KEYS.ENTER });
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(0);
});

View file

@ -1,6 +1,6 @@
import React from "react";
import { render, waitFor } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import { API } from "./helpers/api";
import {
encodePngMetadata,
@ -38,8 +38,8 @@ Object.defineProperty(window, "TextDecoder", {
});
describe("export", () => {
beforeEach(() => {
render(<App />);
beforeEach(async () => {
await render(<ExcalidrawApp />);
});
it("export embedded png and reimport", async () => {

View file

@ -1,6 +1,6 @@
import React from "react";
import { render } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import { UI } from "./helpers/ui";
import { API } from "./helpers/api";
import { getDefaultAppState } from "../appState";
@ -11,17 +11,14 @@ const { h } = window;
describe("history", () => {
it("initializing scene should end up with single history entry", async () => {
render(
<App
initialData={{
appState: {
...getDefaultAppState(),
zenModeEnabled: true,
},
elements: [API.createElement({ type: "rectangle", id: "A" })],
}}
/>,
);
await render(<ExcalidrawApp />, {
localStorageData: {
elements: [API.createElement({ type: "rectangle", id: "A" })],
appState: {
zenModeEnabled: true,
},
},
});
await waitFor(() => expect(h.state.zenModeEnabled).toBe(true));
await waitFor(() =>
@ -61,17 +58,14 @@ describe("history", () => {
});
it("scene import via drag&drop should create new history entry", async () => {
render(
<App
initialData={{
appState: {
...getDefaultAppState(),
viewBackgroundColor: "#FFF",
},
elements: [API.createElement({ type: "rectangle", id: "A" })],
}}
/>,
);
await render(<ExcalidrawApp />, {
localStorageData: {
elements: [API.createElement({ type: "rectangle", id: "A" })],
appState: {
viewBackgroundColor: "#FFF",
},
},
});
await waitFor(() => expect(h.state.viewBackgroundColor).toBe("#FFF"));
await waitFor(() =>

View file

@ -1,6 +1,6 @@
import React from "react";
import { render, waitFor } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import { API } from "./helpers/api";
import { MIME_TYPES } from "../constants";
import { LibraryItem } from "../types";
@ -8,9 +8,9 @@ import { LibraryItem } from "../types";
const { h } = window;
describe("library", () => {
beforeEach(() => {
beforeEach(async () => {
h.library.resetLibrary();
render(<App />);
await render(<ExcalidrawApp />);
});
it("import library via drag&drop", async () => {

View file

@ -1,7 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
import { render, fireEvent } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import * as Renderer from "../renderer/renderScene";
import { reseed } from "../random";
import { bindOrUnbindLinearElement } from "../element/binding";
@ -26,8 +26,8 @@ beforeEach(() => {
const { h } = window;
describe("move element", () => {
it("rectangle", () => {
const { getByToolName, container } = render(<App />);
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const canvas = container.querySelector("canvas")!;
{
@ -38,7 +38,7 @@ describe("move element", () => {
fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
@ -59,8 +59,8 @@ describe("move element", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("rectangles with binding arrow", () => {
render(<App />);
it("rectangles with binding arrow", async () => {
await render(<ExcalidrawApp />);
// create elements
const rectA = UI.createElement("rectangle", { size: 100 });
@ -77,7 +77,7 @@ describe("move element", () => {
// select the second rectangles
new Pointer("mouse").clickOn(rectB);
expect(renderScene).toHaveBeenCalledTimes(19);
expect(renderScene).toHaveBeenCalledTimes(20);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(3);
expect(h.state.selectedElementIds[rectB.id]).toBeTruthy();
@ -108,8 +108,8 @@ describe("move element", () => {
});
describe("duplicate element on move when ALT is clicked", () => {
it("rectangle", () => {
const { getByToolName, container } = render(<App />);
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const canvas = container.querySelector("canvas")!;
{
@ -120,7 +120,7 @@ describe("duplicate element on move when ALT is clicked", () => {
fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();

View file

@ -1,7 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
import { render, fireEvent } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import * as Renderer from "../renderer/renderScene";
import { KEYS } from "../keys";
import { ExcalidrawLinearElement } from "../element/types";
@ -20,8 +20,8 @@ beforeEach(() => {
const { h } = window;
describe("remove shape in non linear elements", () => {
it("rectangle", () => {
const { getByToolName, container } = render(<App />);
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("rectangle");
fireEvent.click(tool);
@ -30,12 +30,12 @@ describe("remove shape in non linear elements", () => {
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerUp(canvas, { clientX: 30, clientY: 30 });
expect(renderScene).toHaveBeenCalledTimes(4);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(h.elements.length).toEqual(0);
});
it("ellipse", () => {
const { getByToolName, container } = render(<App />);
it("ellipse", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("ellipse");
fireEvent.click(tool);
@ -44,12 +44,12 @@ describe("remove shape in non linear elements", () => {
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerUp(canvas, { clientX: 30, clientY: 30 });
expect(renderScene).toHaveBeenCalledTimes(4);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(h.elements.length).toEqual(0);
});
it("diamond", () => {
const { getByToolName, container } = render(<App />);
it("diamond", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("diamond");
fireEvent.click(tool);
@ -58,14 +58,14 @@ describe("remove shape in non linear elements", () => {
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerUp(canvas, { clientX: 30, clientY: 30 });
expect(renderScene).toHaveBeenCalledTimes(4);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(h.elements.length).toEqual(0);
});
});
describe("multi point mode in linear elements", () => {
it("arrow", () => {
const { getByToolName, container } = render(<App />);
it("arrow", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("arrow");
fireEvent.click(tool);
@ -88,7 +88,7 @@ describe("multi point mode in linear elements", () => {
fireEvent.pointerUp(canvas);
fireEvent.keyDown(document, { key: KEYS.ENTER });
expect(renderScene).toHaveBeenCalledTimes(11);
expect(renderScene).toHaveBeenCalledTimes(12);
expect(h.elements.length).toEqual(1);
const element = h.elements[0] as ExcalidrawLinearElement;
@ -105,8 +105,8 @@ describe("multi point mode in linear elements", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("line", () => {
const { getByToolName, container } = render(<App />);
it("line", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("line");
fireEvent.click(tool);
@ -129,7 +129,7 @@ describe("multi point mode in linear elements", () => {
fireEvent.pointerUp(canvas);
fireEvent.keyDown(document, { key: KEYS.ENTER });
expect(renderScene).toHaveBeenCalledTimes(11);
expect(renderScene).toHaveBeenCalledTimes(12);
expect(h.elements.length).toEqual(1);
const element = h.elements[0] as ExcalidrawLinearElement;

View file

@ -9,7 +9,7 @@ import {
fireEvent,
GlobalTestState,
} from "./test-utils";
import App from "../components/App";
import Excalidraw from "../packages/excalidraw/index";
import { setLanguage } from "../i18n";
import { setDateTimeForTests } from "../utils";
import { ExcalidrawElement } from "../element/types";
@ -97,7 +97,7 @@ beforeEach(async () => {
finger2.reset();
await setLanguage("en.json");
render(<App offsetLeft={0} offsetTop={0} />);
await render(<Excalidraw offsetLeft={0} offsetTop={0} />);
});
afterEach(() => {

View file

@ -1,7 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
import { render, fireEvent } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import * as Renderer from "../renderer/renderScene";
import { reseed } from "../random";
import { UI, Pointer, Keyboard } from "./helpers/ui";
@ -22,8 +22,8 @@ beforeEach(() => {
const { h } = window;
describe("resize element", () => {
it("rectangle", () => {
const { getByToolName, container } = render(<App />);
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const canvas = container.querySelector("canvas")!;
{
@ -34,7 +34,7 @@ describe("resize element", () => {
fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(renderScene).toHaveBeenCalledTimes(6);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
@ -65,8 +65,8 @@ describe("resize element", () => {
});
describe("resize element with aspect ratio when SHIFT is clicked", () => {
it("rectangle", () => {
render(<App />);
it("rectangle", async () => {
await render(<ExcalidrawApp />);
const rectangle = UI.createElement("rectangle", {
x: 0,

View file

@ -1,7 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
import { render, fireEvent } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import * as Renderer from "../renderer/renderScene";
import { KEYS } from "../keys";
import { reseed } from "../random";
@ -19,8 +19,8 @@ beforeEach(() => {
const { h } = window;
describe("selection element", () => {
it("create selection element on pointer down", () => {
const { getByToolName, container } = render(<App />);
it("create selection element on pointer down", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("selection");
fireEvent.click(tool);
@ -28,7 +28,7 @@ describe("selection element", () => {
const canvas = container.querySelector("canvas")!;
fireEvent.pointerDown(canvas, { clientX: 60, clientY: 100 });
expect(renderScene).toHaveBeenCalledTimes(2);
expect(renderScene).toHaveBeenCalledTimes(3);
const selectionElement = h.state.selectionElement!;
expect(selectionElement).not.toBeNull();
expect(selectionElement.type).toEqual("selection");
@ -39,8 +39,8 @@ describe("selection element", () => {
fireEvent.pointerUp(canvas);
});
it("resize selection element on pointer move", () => {
const { getByToolName, container } = render(<App />);
it("resize selection element on pointer move", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("selection");
fireEvent.click(tool);
@ -49,7 +49,7 @@ describe("selection element", () => {
fireEvent.pointerDown(canvas, { clientX: 60, clientY: 100 });
fireEvent.pointerMove(canvas, { clientX: 150, clientY: 30 });
expect(renderScene).toHaveBeenCalledTimes(3);
expect(renderScene).toHaveBeenCalledTimes(4);
const selectionElement = h.state.selectionElement!;
expect(selectionElement).not.toBeNull();
expect(selectionElement.type).toEqual("selection");
@ -60,8 +60,8 @@ describe("selection element", () => {
fireEvent.pointerUp(canvas);
});
it("remove selection element on pointer up", () => {
const { getByToolName, container } = render(<App />);
it("remove selection element on pointer up", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
// select tool
const tool = getByToolName("selection");
fireEvent.click(tool);
@ -71,14 +71,14 @@ describe("selection element", () => {
fireEvent.pointerMove(canvas, { clientX: 150, clientY: 30 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(4);
expect(renderScene).toHaveBeenCalledTimes(5);
expect(h.state.selectionElement).toBeNull();
});
});
describe("select single element on the scene", () => {
it("rectangle", () => {
const { getByToolName, container } = render(<App />);
it("rectangle", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const canvas = container.querySelector("canvas")!;
{
// create element
@ -96,7 +96,7 @@ describe("select single element on the scene", () => {
fireEvent.pointerDown(canvas, { clientX: 45, clientY: 20 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(8);
expect(renderScene).toHaveBeenCalledTimes(9);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
@ -104,8 +104,8 @@ describe("select single element on the scene", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("diamond", () => {
const { getByToolName, container } = render(<App />);
it("diamond", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const canvas = container.querySelector("canvas")!;
{
// create element
@ -123,7 +123,7 @@ describe("select single element on the scene", () => {
fireEvent.pointerDown(canvas, { clientX: 45, clientY: 20 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(8);
expect(renderScene).toHaveBeenCalledTimes(9);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
@ -131,8 +131,8 @@ describe("select single element on the scene", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("ellipse", () => {
const { getByToolName, container } = render(<App />);
it("ellipse", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const canvas = container.querySelector("canvas")!;
{
// create element
@ -150,7 +150,7 @@ describe("select single element on the scene", () => {
fireEvent.pointerDown(canvas, { clientX: 45, clientY: 20 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(8);
expect(renderScene).toHaveBeenCalledTimes(9);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
@ -158,8 +158,8 @@ describe("select single element on the scene", () => {
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("arrow", () => {
const { getByToolName, container } = render(<App />);
it("arrow", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const canvas = container.querySelector("canvas")!;
{
// create element
@ -190,15 +190,15 @@ describe("select single element on the scene", () => {
fireEvent.pointerDown(canvas, { clientX: 40, clientY: 40 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(8);
expect(renderScene).toHaveBeenCalledTimes(9);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
h.elements.forEach((element) => expect(element).toMatchSnapshot());
});
it("arrow escape", () => {
const { getByToolName, container } = render(<App />);
it("arrow escape", async () => {
const { getByToolName, container } = await render(<ExcalidrawApp />);
const canvas = container.querySelector("canvas")!;
{
// create element
@ -229,7 +229,7 @@ describe("select single element on the scene", () => {
fireEvent.pointerDown(canvas, { clientX: 40, clientY: 40 });
fireEvent.pointerUp(canvas);
expect(renderScene).toHaveBeenCalledTimes(8);
expect(renderScene).toHaveBeenCalledTimes(9);
expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();

View file

@ -5,9 +5,14 @@ import {
queries,
RenderResult,
RenderOptions,
waitFor,
} from "@testing-library/react";
import * as toolQueries from "./queries/toolQueries";
import { ImportedDataState } from "../data/types";
import { STORAGE_KEYS } from "../excalidraw-app/data/localStorage";
import { SceneData } from "../types";
const customQueries = {
...queries,
@ -16,17 +21,40 @@ const customQueries = {
type TestRenderFn = (
ui: React.ReactElement,
options?: Omit<RenderOptions, "queries">,
) => RenderResult<typeof customQueries>;
options?: Omit<
RenderOptions & { localStorageData?: ImportedDataState },
"queries"
>,
) => Promise<RenderResult<typeof customQueries>>;
const renderApp: TestRenderFn = async (ui, options) => {
if (options?.localStorageData) {
initLocalStorage(options.localStorageData);
delete options.localStorageData;
}
const renderApp: TestRenderFn = (ui, options) => {
const renderResult = render(ui, {
queries: customQueries,
...options,
});
GlobalTestState.renderResult = renderResult;
GlobalTestState.canvas = renderResult.container.querySelector("canvas")!;
Object.defineProperty(GlobalTestState, "canvas", {
// must be a getter because at the time of ExcalidrawApp render the
// child App component isn't likely mounted yet (and thus canvas not
// present in DOM)
get() {
return renderResult.container.querySelector("canvas")!;
},
});
await waitFor(() => {
const canvas = renderResult.container.querySelector("canvas");
if (!canvas) {
throw new Error("not initialized yet");
}
});
return renderResult;
};
@ -49,7 +77,28 @@ export class GlobalTestState {
*/
static renderResult: RenderResult<typeof customQueries> = null!;
/**
* automatically updated on each call to render()
* retrieves canvas for currently rendered app instance
*/
static canvas: HTMLCanvasElement = null!;
static get canvas(): HTMLCanvasElement {
return null!;
}
}
const initLocalStorage = (data: ImportedDataState) => {
if (data.elements) {
localStorage.setItem(
STORAGE_KEYS.LOCAL_STORAGE_ELEMENTS,
JSON.stringify(data.elements),
);
}
if (data.appState) {
localStorage.setItem(
STORAGE_KEYS.LOCAL_STORAGE_APP_STATE,
JSON.stringify(data.appState),
);
}
};
export const updateSceneData = (data: SceneData) => {
(window.h.collab as any).excalidrawRef.current.updateScene(data);
};

View file

@ -1,7 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
import { render } from "./test-utils";
import App from "../components/App";
import ExcalidrawApp from "../excalidraw-app";
import { reseed } from "../random";
import {
actionSendBackward,
@ -107,8 +107,8 @@ const assertZindex = ({
};
describe("z-index manipulation", () => {
beforeEach(() => {
render(<App />);
beforeEach(async () => {
await render(<ExcalidrawApp />);
});
it("send back", () => {