history.test.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import React from "react";
  2. import { render } from "./test-utils";
  3. import ExcalidrawApp from "../excalidraw-app";
  4. import { UI } from "./helpers/ui";
  5. import { API } from "./helpers/api";
  6. import { getDefaultAppState } from "../appState";
  7. import { waitFor } from "@testing-library/react";
  8. import { createUndoAction, createRedoAction } from "../actions/actionHistory";
  9. const { h } = window;
  10. describe("history", () => {
  11. it("initializing scene should end up with single history entry", async () => {
  12. await render(<ExcalidrawApp />, {
  13. localStorageData: {
  14. elements: [API.createElement({ type: "rectangle", id: "A" })],
  15. appState: {
  16. zenModeEnabled: true,
  17. },
  18. },
  19. });
  20. await waitFor(() => expect(h.state.zenModeEnabled).toBe(true));
  21. await waitFor(() =>
  22. expect(h.elements).toEqual([expect.objectContaining({ id: "A" })]),
  23. );
  24. const undoAction = createUndoAction(h.history);
  25. const redoAction = createRedoAction(h.history);
  26. h.app.actionManager.executeAction(undoAction);
  27. expect(h.elements).toEqual([
  28. expect.objectContaining({ id: "A", isDeleted: false }),
  29. ]);
  30. const rectangle = UI.createElement("rectangle");
  31. expect(h.elements).toEqual([
  32. expect.objectContaining({ id: "A" }),
  33. expect.objectContaining({ id: rectangle.id }),
  34. ]);
  35. h.app.actionManager.executeAction(undoAction);
  36. expect(h.elements).toEqual([
  37. expect.objectContaining({ id: "A", isDeleted: false }),
  38. expect.objectContaining({ id: rectangle.id, isDeleted: true }),
  39. ]);
  40. // noop
  41. h.app.actionManager.executeAction(undoAction);
  42. expect(h.elements).toEqual([
  43. expect.objectContaining({ id: "A", isDeleted: false }),
  44. expect.objectContaining({ id: rectangle.id, isDeleted: true }),
  45. ]);
  46. expect(API.getStateHistory().length).toBe(1);
  47. h.app.actionManager.executeAction(redoAction);
  48. expect(h.elements).toEqual([
  49. expect.objectContaining({ id: "A", isDeleted: false }),
  50. expect.objectContaining({ id: rectangle.id, isDeleted: false }),
  51. ]);
  52. expect(API.getStateHistory().length).toBe(2);
  53. });
  54. it("scene import via drag&drop should create new history entry", async () => {
  55. await render(<ExcalidrawApp />, {
  56. localStorageData: {
  57. elements: [API.createElement({ type: "rectangle", id: "A" })],
  58. appState: {
  59. viewBackgroundColor: "#FFF",
  60. },
  61. },
  62. });
  63. await waitFor(() => expect(h.state.viewBackgroundColor).toBe("#FFF"));
  64. await waitFor(() =>
  65. expect(h.elements).toEqual([expect.objectContaining({ id: "A" })]),
  66. );
  67. API.drop(
  68. new Blob(
  69. [
  70. JSON.stringify({
  71. type: "excalidraw",
  72. appState: {
  73. ...getDefaultAppState(),
  74. viewBackgroundColor: "#000",
  75. },
  76. elements: [API.createElement({ type: "rectangle", id: "B" })],
  77. }),
  78. ],
  79. { type: "application/json" },
  80. ),
  81. );
  82. await waitFor(() => expect(API.getStateHistory().length).toBe(2));
  83. expect(h.state.viewBackgroundColor).toBe("#000");
  84. expect(h.elements).toEqual([
  85. expect.objectContaining({ id: "B", isDeleted: false }),
  86. ]);
  87. const undoAction = createUndoAction(h.history);
  88. const redoAction = createRedoAction(h.history);
  89. h.app.actionManager.executeAction(undoAction);
  90. expect(h.elements).toEqual([
  91. expect.objectContaining({ id: "A", isDeleted: false }),
  92. expect.objectContaining({ id: "B", isDeleted: true }),
  93. ]);
  94. expect(h.state.viewBackgroundColor).toBe("#FFF");
  95. h.app.actionManager.executeAction(redoAction);
  96. expect(h.state.viewBackgroundColor).toBe("#000");
  97. expect(h.elements).toEqual([
  98. expect.objectContaining({ id: "B", isDeleted: false }),
  99. expect.objectContaining({ id: "A", isDeleted: true }),
  100. ]);
  101. });
  102. });