|
@@ -0,0 +1,187 @@
|
|
|
+import React from "react";
|
|
|
+import ReactDOM from "react-dom";
|
|
|
+import { render } from "./test-utils";
|
|
|
+import { App } from "../components/App";
|
|
|
+import { reseed } from "../random";
|
|
|
+import { newElement } from "../element";
|
|
|
+import {
|
|
|
+ actionSendBackward,
|
|
|
+ actionBringForward,
|
|
|
+ actionBringToFront,
|
|
|
+ actionSendToBack,
|
|
|
+} from "../actions";
|
|
|
+
|
|
|
+// Unmount ReactDOM from root
|
|
|
+ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
|
|
+
|
|
|
+beforeEach(() => {
|
|
|
+ localStorage.clear();
|
|
|
+ reseed(7);
|
|
|
+});
|
|
|
+
|
|
|
+const { h } = window;
|
|
|
+
|
|
|
+function populateElements(
|
|
|
+ elements: { id: string; isDeleted?: boolean; isSelected?: boolean }[],
|
|
|
+) {
|
|
|
+ const selectedElementIds: any = {};
|
|
|
+
|
|
|
+ h.elements = elements.map(({ id, isDeleted = false, isSelected = false }) => {
|
|
|
+ const element: Mutable<ReturnType<typeof newElement>> = newElement({
|
|
|
+ type: "rectangle",
|
|
|
+ x: 100,
|
|
|
+ y: 100,
|
|
|
+ strokeColor: h.state.currentItemStrokeColor,
|
|
|
+ backgroundColor: h.state.currentItemBackgroundColor,
|
|
|
+ fillStyle: h.state.currentItemFillStyle,
|
|
|
+ strokeWidth: h.state.currentItemStrokeWidth,
|
|
|
+ roughness: h.state.currentItemRoughness,
|
|
|
+ opacity: h.state.currentItemOpacity,
|
|
|
+ });
|
|
|
+ element.id = id;
|
|
|
+ element.isDeleted = isDeleted;
|
|
|
+ if (isSelected) {
|
|
|
+ selectedElementIds[element.id] = true;
|
|
|
+ }
|
|
|
+ return element;
|
|
|
+ });
|
|
|
+
|
|
|
+ h.setState({
|
|
|
+ ...h.state,
|
|
|
+ selectedElementIds,
|
|
|
+ });
|
|
|
+
|
|
|
+ return selectedElementIds;
|
|
|
+}
|
|
|
+
|
|
|
+type Actions =
|
|
|
+ | typeof actionBringForward
|
|
|
+ | typeof actionSendBackward
|
|
|
+ | typeof actionBringToFront
|
|
|
+ | typeof actionSendToBack;
|
|
|
+
|
|
|
+function assertZindex({
|
|
|
+ elements,
|
|
|
+ operations,
|
|
|
+}: {
|
|
|
+ elements: { id: string; isDeleted?: true; isSelected?: true }[];
|
|
|
+ operations: [Actions, string[]][];
|
|
|
+}) {
|
|
|
+ const selectedElementIds = populateElements(elements);
|
|
|
+ operations.forEach(([action, expected]) => {
|
|
|
+ h.app.actionManager.executeAction(action);
|
|
|
+ expect(h.elements.map((element) => element.id)).toEqual(expected);
|
|
|
+ expect(h.state.selectedElementIds).toEqual(selectedElementIds);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+describe("z-index manipulation", () => {
|
|
|
+ it("send back", () => {
|
|
|
+ render(<App />);
|
|
|
+
|
|
|
+ assertZindex({
|
|
|
+ elements: [
|
|
|
+ { id: "A" },
|
|
|
+ { id: "B", isDeleted: true },
|
|
|
+ { id: "C", isDeleted: true },
|
|
|
+ { id: "D", isSelected: true },
|
|
|
+ ],
|
|
|
+ operations: [
|
|
|
+ [actionSendBackward, ["B", "C", "D", "A"]],
|
|
|
+ // noop
|
|
|
+ [actionSendBackward, ["B", "C", "D", "A"]],
|
|
|
+ ],
|
|
|
+ });
|
|
|
+
|
|
|
+ assertZindex({
|
|
|
+ elements: [
|
|
|
+ { id: "A", isDeleted: true },
|
|
|
+ { id: "B" },
|
|
|
+ { id: "C", isDeleted: true },
|
|
|
+ { id: "D", isSelected: true },
|
|
|
+ ],
|
|
|
+ operations: [[actionSendBackward, ["A", "C", "D", "B"]]],
|
|
|
+ });
|
|
|
+
|
|
|
+ assertZindex({
|
|
|
+ elements: [
|
|
|
+ { id: "A" },
|
|
|
+ { id: "B", isDeleted: true },
|
|
|
+ { id: "C", isDeleted: true },
|
|
|
+ { id: "D", isSelected: true },
|
|
|
+ { id: "E", isSelected: true },
|
|
|
+ ],
|
|
|
+ operations: [[actionSendBackward, ["B", "C", "D", "E", "A"]]],
|
|
|
+ });
|
|
|
+
|
|
|
+ assertZindex({
|
|
|
+ elements: [
|
|
|
+ { id: "A" },
|
|
|
+ { id: "B" },
|
|
|
+ { id: "C", isDeleted: true },
|
|
|
+ { id: "D", isDeleted: true },
|
|
|
+ { id: "E", isSelected: true },
|
|
|
+ { id: "F" },
|
|
|
+ { id: "G", isSelected: true },
|
|
|
+ ],
|
|
|
+ operations: [
|
|
|
+ [actionSendBackward, ["A", "C", "D", "E", "B", "G", "F"]],
|
|
|
+ [actionSendBackward, ["C", "D", "E", "A", "G", "B", "F"]],
|
|
|
+ ],
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it("bring forward", () => {
|
|
|
+ render(<App />);
|
|
|
+
|
|
|
+ assertZindex({
|
|
|
+ elements: [
|
|
|
+ { id: "A", isSelected: true },
|
|
|
+ { id: "B", isDeleted: true },
|
|
|
+ { id: "C", isDeleted: true },
|
|
|
+ { id: "D" },
|
|
|
+ { id: "E", isSelected: true },
|
|
|
+ { id: "F", isDeleted: true },
|
|
|
+ { id: "G" },
|
|
|
+ ],
|
|
|
+ operations: [
|
|
|
+ [actionBringForward, ["D", "A", "B", "C", "G", "E", "F"]],
|
|
|
+ [actionBringForward, ["D", "G", "A", "B", "C", "E", "F"]],
|
|
|
+ ],
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it("bring to front", () => {
|
|
|
+ render(<App />);
|
|
|
+
|
|
|
+ assertZindex({
|
|
|
+ elements: [
|
|
|
+ { id: "A", isSelected: true },
|
|
|
+ { id: "B", isDeleted: true },
|
|
|
+ { id: "C", isDeleted: true },
|
|
|
+ { id: "D" },
|
|
|
+ { id: "E", isSelected: true },
|
|
|
+ { id: "F", isDeleted: true },
|
|
|
+ { id: "G" },
|
|
|
+ ],
|
|
|
+ operations: [[actionBringToFront, ["D", "G", "A", "B", "C", "E", "F"]]],
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it("send to back", () => {
|
|
|
+ render(<App />);
|
|
|
+
|
|
|
+ assertZindex({
|
|
|
+ elements: [
|
|
|
+ { id: "A" },
|
|
|
+ { id: "B", isDeleted: true },
|
|
|
+ { id: "C" },
|
|
|
+ { id: "D", isDeleted: true },
|
|
|
+ { id: "E", isSelected: true },
|
|
|
+ { id: "F", isDeleted: true },
|
|
|
+ { id: "G" },
|
|
|
+ ],
|
|
|
+ operations: [[actionSendToBack, ["D", "E", "A", "B", "C", "F", "G"]]],
|
|
|
+ });
|
|
|
+ });
|
|
|
+});
|