zindex.test.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3. import { render } from "./test-utils";
  4. import { App } from "../components/App";
  5. import { reseed } from "../random";
  6. import { newElement } from "../element";
  7. import {
  8. actionSendBackward,
  9. actionBringForward,
  10. actionBringToFront,
  11. actionSendToBack,
  12. } from "../actions";
  13. // Unmount ReactDOM from root
  14. ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
  15. beforeEach(() => {
  16. localStorage.clear();
  17. reseed(7);
  18. });
  19. const { h } = window;
  20. function populateElements(
  21. elements: { id: string; isDeleted?: boolean; isSelected?: boolean }[],
  22. ) {
  23. const selectedElementIds: any = {};
  24. h.elements = elements.map(({ id, isDeleted = false, isSelected = false }) => {
  25. const element: Mutable<ReturnType<typeof newElement>> = newElement({
  26. type: "rectangle",
  27. x: 100,
  28. y: 100,
  29. strokeColor: h.state.currentItemStrokeColor,
  30. backgroundColor: h.state.currentItemBackgroundColor,
  31. fillStyle: h.state.currentItemFillStyle,
  32. strokeWidth: h.state.currentItemStrokeWidth,
  33. roughness: h.state.currentItemRoughness,
  34. opacity: h.state.currentItemOpacity,
  35. });
  36. element.id = id;
  37. element.isDeleted = isDeleted;
  38. if (isSelected) {
  39. selectedElementIds[element.id] = true;
  40. }
  41. return element;
  42. });
  43. h.setState({
  44. ...h.state,
  45. selectedElementIds,
  46. });
  47. return selectedElementIds;
  48. }
  49. type Actions =
  50. | typeof actionBringForward
  51. | typeof actionSendBackward
  52. | typeof actionBringToFront
  53. | typeof actionSendToBack;
  54. function assertZindex({
  55. elements,
  56. operations,
  57. }: {
  58. elements: { id: string; isDeleted?: true; isSelected?: true }[];
  59. operations: [Actions, string[]][];
  60. }) {
  61. const selectedElementIds = populateElements(elements);
  62. operations.forEach(([action, expected]) => {
  63. h.app.actionManager.executeAction(action);
  64. expect(h.elements.map((element) => element.id)).toEqual(expected);
  65. expect(h.state.selectedElementIds).toEqual(selectedElementIds);
  66. });
  67. }
  68. describe("z-index manipulation", () => {
  69. it("send back", () => {
  70. render(<App />);
  71. assertZindex({
  72. elements: [
  73. { id: "A" },
  74. { id: "B", isDeleted: true },
  75. { id: "C", isDeleted: true },
  76. { id: "D", isSelected: true },
  77. ],
  78. operations: [
  79. [actionSendBackward, ["B", "C", "D", "A"]],
  80. // noop
  81. [actionSendBackward, ["B", "C", "D", "A"]],
  82. ],
  83. });
  84. assertZindex({
  85. elements: [
  86. { id: "A", isDeleted: true },
  87. { id: "B" },
  88. { id: "C", isDeleted: true },
  89. { id: "D", isSelected: true },
  90. ],
  91. operations: [[actionSendBackward, ["A", "C", "D", "B"]]],
  92. });
  93. assertZindex({
  94. elements: [
  95. { id: "A" },
  96. { id: "B", isDeleted: true },
  97. { id: "C", isDeleted: true },
  98. { id: "D", isSelected: true },
  99. { id: "E", isSelected: true },
  100. ],
  101. operations: [[actionSendBackward, ["B", "C", "D", "E", "A"]]],
  102. });
  103. assertZindex({
  104. elements: [
  105. { id: "A" },
  106. { id: "B" },
  107. { id: "C", isDeleted: true },
  108. { id: "D", isDeleted: true },
  109. { id: "E", isSelected: true },
  110. { id: "F" },
  111. { id: "G", isSelected: true },
  112. ],
  113. operations: [
  114. [actionSendBackward, ["A", "C", "D", "E", "B", "G", "F"]],
  115. [actionSendBackward, ["C", "D", "E", "A", "G", "B", "F"]],
  116. ],
  117. });
  118. });
  119. it("bring forward", () => {
  120. render(<App />);
  121. assertZindex({
  122. elements: [
  123. { id: "A", isSelected: true },
  124. { id: "B", isDeleted: true },
  125. { id: "C", isDeleted: true },
  126. { id: "D" },
  127. { id: "E", isSelected: true },
  128. { id: "F", isDeleted: true },
  129. { id: "G" },
  130. ],
  131. operations: [
  132. [actionBringForward, ["D", "A", "B", "C", "G", "E", "F"]],
  133. [actionBringForward, ["D", "G", "A", "B", "C", "E", "F"]],
  134. ],
  135. });
  136. });
  137. it("bring to front", () => {
  138. render(<App />);
  139. assertZindex({
  140. elements: [
  141. { id: "A", isSelected: true },
  142. { id: "B", isDeleted: true },
  143. { id: "C", isDeleted: true },
  144. { id: "D" },
  145. { id: "E", isSelected: true },
  146. { id: "F", isDeleted: true },
  147. { id: "G" },
  148. ],
  149. operations: [[actionBringToFront, ["D", "G", "A", "B", "C", "E", "F"]]],
  150. });
  151. });
  152. it("send to back", () => {
  153. render(<App />);
  154. assertZindex({
  155. elements: [
  156. { id: "A" },
  157. { id: "B", isDeleted: true },
  158. { id: "C" },
  159. { id: "D", isDeleted: true },
  160. { id: "E", isSelected: true },
  161. { id: "F", isDeleted: true },
  162. { id: "G" },
  163. ],
  164. operations: [[actionSendToBack, ["D", "E", "A", "B", "C", "F", "G"]]],
  165. });
  166. });
  167. });