import ReactDOM from "react-dom";
import { render } from "./test-utils";
import App from "../components/App";
import * as Renderer from "../renderer/renderScene";
import { reseed } from "../random";
import { UI, Keyboard } from "./helpers/ui";
import { resize } from "./utils";
import { ExcalidrawTextElement } from "../element/types";
import ExcalidrawApp from "../excalidraw-app";
import { API } from "./helpers/api";
import { KEYS } from "../keys";
import { vi } from "vitest";
// Unmount ReactDOM from root
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
const renderScene = vi.spyOn(Renderer, "renderScene");
beforeEach(() => {
localStorage.clear();
renderScene.mockClear();
reseed(7);
});
const { h } = window;
describe("resize rectangle ellipses and diamond elements", () => {
const elemData = {
x: 0,
y: 0,
width: 100,
height: 100,
};
// Value for irrelevant cursor movements
const _ = 234;
it.each`
handle | move | dimensions | topLeft
${"n"} | ${[_, -100]} | ${[100, 200]} | ${[elemData.x, -100]}
${"s"} | ${[_, 39]} | ${[100, 139]} | ${[elemData.x, elemData.x]}
${"e"} | ${[-20, _]} | ${[80, 100]} | ${[elemData.x, elemData.y]}
${"w"} | ${[-20, _]} | ${[120, 100]} | ${[-20, elemData.y]}
${"ne"} | ${[5, 55]} | ${[105, 45]} | ${[elemData.x, 55]}
${"se"} | ${[-30, -10]} | ${[70, 90]} | ${[elemData.x, elemData.y]}
${"nw"} | ${[-300, -200]} | ${[400, 300]} | ${[-300, -200]}
${"sw"} | ${[40, -20]} | ${[60, 80]} | ${[40, 0]}
`(
"resizes with handle $handle",
async ({ handle, move, dimensions, topLeft }) => {
await render();
const rectangle = UI.createElement("rectangle", elemData);
resize(rectangle, handle, move);
const element = h.elements[0];
expect([element.width, element.height]).toEqual(dimensions);
expect([element.x, element.y]).toEqual(topLeft);
},
);
it.each`
handle | move | dimensions | topLeft
${"n"} | ${[_, -100]} | ${[200, 200]} | ${[-50, -100]}
${"nw"} | ${[-300, -200]} | ${[400, 400]} | ${[-300, -300]}
${"sw"} | ${[40, -20]} | ${[80, 80]} | ${[20, 0]}
`(
"resizes with fixed side ratios on handle $handle",
async ({ handle, move, dimensions, topLeft }) => {
await render();
const rectangle = UI.createElement("rectangle", elemData);
resize(rectangle, handle, move, { shift: true });
const element = h.elements[0];
expect([element.width, element.height]).toEqual(dimensions);
expect([element.x, element.y]).toEqual(topLeft);
},
);
it.each`
handle | move | dimensions | topLeft
${"nw"} | ${[0, 120]} | ${[100, 100]} | ${[0, 100]}
${"ne"} | ${[-120, 0]} | ${[100, 100]} | ${[-100, 0]}
${"sw"} | ${[200, -200]} | ${[100, 100]} | ${[100, -100]}
${"n"} | ${[_, 150]} | ${[50, 50]} | ${[25, 100]}
`(
"Flips while resizing and keeping side ratios on handle $handle",
async ({ handle, move, dimensions, topLeft }) => {
await render();
const rectangle = UI.createElement("rectangle", elemData);
resize(rectangle, handle, move, { shift: true });
const element = h.elements[0];
expect([element.width, element.height]).toEqual(dimensions);
expect([element.x, element.y]).toEqual(topLeft);
},
);
it.each`
handle | move | dimensions | topLeft
${"ne"} | ${[50, -100]} | ${[200, 300]} | ${[-50, -100]}
${"s"} | ${[_, -20]} | ${[100, 60]} | ${[0, 20]}
`(
"Resizes from center on handle $handle",
async ({ handle, move, dimensions, topLeft }) => {
await render();
const rectangle = UI.createElement("rectangle", elemData);
resize(rectangle, handle, move, { alt: true });
const element = h.elements[0];
expect([element.width, element.height]).toEqual(dimensions);
expect([element.x, element.y]).toEqual(topLeft);
},
);
it.each`
handle | move | dimensions | topLeft
${"nw"} | ${[100, 120]} | ${[140, 140]} | ${[-20, -20]}
${"e"} | ${[-130, _]} | ${[160, 160]} | ${[-30, -30]}
`(
"Resizes from center, flips and keeps side rations on handle $handle",
async ({ handle, move, dimensions, topLeft }) => {
await render();
const rectangle = UI.createElement("rectangle", elemData);
resize(rectangle, handle, move, { alt: true, shift: true });
const element = h.elements[0];
expect([element.width, element.height]).toEqual(dimensions);
expect([element.x, element.y]).toEqual(topLeft);
},
);
});
describe("Test text element", () => {
it("should update font size via keyboard", async () => {
await render();
const textElement = API.createElement({
type: "text",
text: "abc",
});
window.h.elements = [textElement];
API.setSelectedElements([textElement]);
const origFontSize = textElement.fontSize;
Keyboard.withModifierKeys({ shift: true, ctrl: true }, () => {
Keyboard.keyDown(KEYS.CHEVRON_RIGHT);
expect((window.h.elements[0] as ExcalidrawTextElement).fontSize).toBe(
origFontSize * 1.1,
);
Keyboard.keyDown(KEYS.CHEVRON_LEFT);
expect((window.h.elements[0] as ExcalidrawTextElement).fontSize).toBe(
origFontSize,
);
});
});
});