diff --git a/src/actions/actionExport.tsx b/src/actions/actionExport.tsx index 02d43739..6fcf2e7d 100644 --- a/src/actions/actionExport.tsx +++ b/src/actions/actionExport.tsx @@ -125,7 +125,7 @@ export const actionLoadScene = register({ ...loadedAppState, errorMessage: error, }, - commitToHistory: false, + commitToHistory: true, }; }, PanelComponent: ({ updateData, appState }) => ( diff --git a/src/components/App.tsx b/src/components/App.tsx index 31bba08f..55867202 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -556,7 +556,11 @@ class App extends React.Component { ), }; } - this.syncActionResult(scene); + history.clear(); + this.syncActionResult({ + ...scene, + commitToHistory: true, + }); } }; @@ -1163,11 +1167,12 @@ class App extends React.Component { const updateScene = ( decryptedData: SocketUpdateDataSource[SCENE.INIT | SCENE.UPDATE], - { scrollToContent = false }: { scrollToContent?: boolean } = {}, + { init = false }: { init?: boolean } = {}, ) => { const { elements: remoteElements } = decryptedData.payload; - if (scrollToContent) { + if (init) { + history.resumeRecording(); this.setState({ ...this.state, ...calculateScrollCenter( @@ -1292,7 +1297,7 @@ class App extends React.Component { return; case SCENE.INIT: { if (!this.portal.socketInitialized) { - updateScene(decryptedData, { scrollToContent: true }); + updateScene(decryptedData, { init: true }); } break; } @@ -3626,7 +3631,7 @@ class App extends React.Component { ...(appState || this.state), isLoading: false, }, - commitToHistory: false, + commitToHistory: true, }), ) .catch((error) => { diff --git a/src/element/newElement.test.ts b/src/element/newElement.test.ts index a86d1694..94826b1f 100644 --- a/src/element/newElement.test.ts +++ b/src/element/newElement.test.ts @@ -1,9 +1,6 @@ -import { - newTextElement, - duplicateElement, - newLinearElement, -} from "./newElement"; +import { duplicateElement } from "./newElement"; import { mutateElement } from "./mutateElement"; +import { API } from "../tests/helpers/api"; const isPrimitive = (val: any) => { const type = typeof val; @@ -22,7 +19,7 @@ const assertCloneObjects = (source: any, clone: any) => { }; it("clones arrow element", () => { - const element = newLinearElement({ + const element = API.createElement({ type: "arrow", x: 0, y: 0, @@ -68,7 +65,8 @@ it("clones arrow element", () => { }); it("clones text element", () => { - const element = newTextElement({ + const element = API.createElement({ + type: "text", x: 0, y: 0, strokeColor: "#000000", diff --git a/src/tests/__snapshots__/regressionTests.test.tsx.snap b/src/tests/__snapshots__/regressionTests.test.tsx.snap index 93fbb5e8..02961207 100644 --- a/src/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/src/tests/__snapshots__/regressionTests.test.tsx.snap @@ -162,6 +162,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -605,6 +615,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -1034,6 +1054,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -1727,6 +1757,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -1967,6 +2007,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -2365,6 +2415,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -2564,6 +2624,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -2758,6 +2828,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -3155,6 +3235,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -3441,6 +3531,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -3622,6 +3722,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -3865,6 +3975,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -4119,6 +4239,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -4471,6 +4601,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -4719,6 +4859,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -4995,6 +5145,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -5156,6 +5316,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -5353,6 +5523,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -5756,6 +5936,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -8038,6 +8228,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -9096,6 +9296,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -9235,6 +9445,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -9374,6 +9594,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -9526,6 +9756,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -9691,6 +9931,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -9856,6 +10106,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -10021,6 +10281,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -10173,6 +10443,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -10312,6 +10592,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -10464,6 +10754,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -10616,6 +10916,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -10768,6 +11078,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -11073,6 +11393,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -11641,6 +11971,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -11812,7 +12152,18 @@ exports[`regression tests pinch-to-zoom works: [end of test] history 1`] = ` Object { "recording": false, "redoStack": Array [], - "stateHistory": Array [], + "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, + ], } `; @@ -11886,7 +12237,18 @@ exports[`regression tests rerenders UI on language change: [end of test] history Object { "recording": false, "redoStack": Array [], - "stateHistory": Array [], + "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, + ], } `; @@ -12005,6 +12367,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -12863,6 +13235,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -13287,6 +13669,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -13624,6 +14016,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -13878,6 +14280,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -14069,6 +14481,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -14881,6 +15303,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -15590,6 +16022,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -16200,6 +16642,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -16716,6 +17168,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -17185,6 +17647,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -17565,6 +18037,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -17860,6 +18342,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -18090,6 +18582,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -18955,6 +19457,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -19715,6 +20227,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -20374,6 +20896,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -20928,6 +21460,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -21093,6 +21635,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -21376,6 +21928,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -21633,6 +22195,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -21770,6 +22342,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -21969,6 +22551,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -22203,6 +22795,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -22492,6 +23094,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -23306,6 +23918,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -23589,6 +24211,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -23876,6 +24508,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -24203,6 +24845,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -24377,6 +25029,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -24670,6 +25332,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -24906,6 +25578,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -25141,7 +25823,18 @@ exports[`regression tests shows context menu for canvas: [end of test] history 1 Object { "recording": false, "redoStack": Array [], - "stateHistory": Array [], + "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, + ], } `; @@ -25244,6 +25937,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -25484,6 +26187,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -26150,7 +26863,18 @@ exports[`regression tests spacebar + drag scrolls the canvas: [end of test] hist Object { "recording": false, "redoStack": Array [], - "stateHistory": Array [], + "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, + ], } `; @@ -26313,6 +27037,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -27058,6 +27792,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -27410,6 +28154,16 @@ Object { "recording": false, "redoStack": Array [], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -27581,7 +28335,18 @@ exports[`regression tests two-finger scroll works: [end of test] history 1`] = ` Object { "recording": false, "redoStack": Array [], - "stateHistory": Array [], + "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, + ], } `; @@ -27953,6 +28718,16 @@ Object { }, ], "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, Object { "appState": Object { "editingGroupId": null, @@ -28207,7 +28982,18 @@ exports[`regression tests zoom hotkeys: [end of test] history 1`] = ` Object { "recording": false, "redoStack": Array [], - "stateHistory": Array [], + "stateHistory": Array [ + Object { + "appState": Object { + "editingGroupId": null, + "editingLinearElement": null, + "name": "Untitled-201933152653", + "selectedElementIds": Object {}, + "viewBackgroundColor": "#ffffff", + }, + "elements": Array [], + }, + ], } `; diff --git a/src/tests/helpers/api.ts b/src/tests/helpers/api.ts index dcc2dc87..9c39377c 100644 --- a/src/tests/helpers/api.ts +++ b/src/tests/helpers/api.ts @@ -1,4 +1,12 @@ -import { ExcalidrawElement } from "../../element/types"; +import { + ExcalidrawElement, + ExcalidrawGenericElement, + ExcalidrawTextElement, + ExcalidrawLinearElement, +} from "../../element/types"; +import { newElement, newTextElement, newLinearElement } from "../../element"; +import { DEFAULT_VERTICAL_ALIGN } from "../../constants"; +import { getDefaultAppState } from "../../appState"; const { h } = window; @@ -29,4 +37,102 @@ export class API { h.app.clearSelection(null); expect(API.getSelectedElements().length).toBe(0); }; + + static createElement = < + T extends Exclude + >({ + type, + id, + x = 0, + y = x, + width = 100, + height = width, + isDeleted = false, + ...rest + }: { + type: T; + x?: number; + y?: number; + height?: number; + width?: number; + id?: string; + isDeleted?: boolean; + // generic element props + strokeColor?: ExcalidrawGenericElement["strokeColor"]; + backgroundColor?: ExcalidrawGenericElement["backgroundColor"]; + fillStyle?: ExcalidrawGenericElement["fillStyle"]; + strokeWidth?: ExcalidrawGenericElement["strokeWidth"]; + strokeStyle?: ExcalidrawGenericElement["strokeStyle"]; + strokeSharpness?: ExcalidrawGenericElement["strokeSharpness"]; + roughness?: ExcalidrawGenericElement["roughness"]; + opacity?: ExcalidrawGenericElement["opacity"]; + // text props + text?: T extends "text" ? ExcalidrawTextElement["text"] : never; + fontSize?: T extends "text" ? ExcalidrawTextElement["fontSize"] : never; + fontFamily?: T extends "text" ? ExcalidrawTextElement["fontFamily"] : never; + textAlign?: T extends "text" ? ExcalidrawTextElement["textAlign"] : never; + verticalAlign?: T extends "text" + ? ExcalidrawTextElement["verticalAlign"] + : never; + }): T extends "arrow" | "line" | "draw" + ? ExcalidrawLinearElement + : T extends "text" + ? ExcalidrawTextElement + : ExcalidrawGenericElement => { + let element: Mutable = null!; + + const appState = h?.state || getDefaultAppState(); + + const base = { + x, + y, + strokeColor: rest.strokeColor ?? appState.currentItemStrokeColor, + backgroundColor: + rest.backgroundColor ?? appState.currentItemBackgroundColor, + fillStyle: rest.fillStyle ?? appState.currentItemFillStyle, + strokeWidth: rest.strokeWidth ?? appState.currentItemStrokeWidth, + strokeStyle: rest.strokeStyle ?? appState.currentItemStrokeStyle, + strokeSharpness: + rest.strokeSharpness ?? appState.currentItemStrokeSharpness, + roughness: rest.roughness ?? appState.currentItemRoughness, + opacity: rest.opacity ?? appState.currentItemOpacity, + }; + switch (type) { + case "rectangle": + case "diamond": + case "ellipse": + element = newElement({ + type: type as "rectangle" | "diamond" | "ellipse", + width, + height, + ...base, + }); + break; + case "text": + element = newTextElement({ + ...base, + text: rest.text || "test", + fontSize: rest.fontSize ?? appState.currentItemFontSize, + fontFamily: rest.fontFamily ?? appState.currentItemFontFamily, + textAlign: rest.textAlign ?? appState.currentItemTextAlign, + verticalAlign: rest.verticalAlign ?? DEFAULT_VERTICAL_ALIGN, + }); + break; + case "arrow": + case "line": + case "draw": + element = newLinearElement({ + type: type as "arrow" | "line" | "draw", + ...base, + }); + break; + } + if (id) { + element.id = id; + } + if (isDeleted) { + element.isDeleted = isDeleted; + } + return element as any; + }; } diff --git a/src/tests/helpers/ui.ts b/src/tests/helpers/ui.ts index b3c466c6..793f45b7 100644 --- a/src/tests/helpers/ui.ts +++ b/src/tests/helpers/ui.ts @@ -192,7 +192,7 @@ export class UI { size?: number; width?: number; height?: number; - }, + } = {}, ): T extends "arrow" | "line" | "draw" ? ExcalidrawLinearElement : T extends "text" diff --git a/src/tests/history.test.tsx b/src/tests/history.test.tsx new file mode 100644 index 00000000..7a47fb09 --- /dev/null +++ b/src/tests/history.test.tsx @@ -0,0 +1,127 @@ +import React from "react"; +import { render, GlobalTestState } from "./test-utils"; +import App from "../components/App"; +import { UI } from "./helpers/ui"; +import { API } from "./helpers/api"; +import { getDefaultAppState } from "../appState"; +import { waitFor, fireEvent, createEvent } from "@testing-library/react"; +import { createUndoAction, createRedoAction } from "../actions/actionHistory"; + +const { h } = window; + +describe("history", () => { + it("initializing scene should end up with single history entry", async () => { + render( + , + ); + + await waitFor(() => expect(h.state.zenModeEnabled).toBe(true)); + await waitFor(() => + expect(h.elements).toEqual([expect.objectContaining({ id: "A" })]), + ); + const undoAction = createUndoAction(h.history); + const redoAction = createRedoAction(h.history); + h.app.actionManager.executeAction(undoAction); + expect(h.elements).toEqual([ + expect.objectContaining({ id: "A", isDeleted: false }), + ]); + const rectangle = UI.createElement("rectangle"); + expect(h.elements).toEqual([ + expect.objectContaining({ id: "A" }), + expect.objectContaining({ id: rectangle.id }), + ]); + h.app.actionManager.executeAction(undoAction); + expect(h.elements).toEqual([ + expect.objectContaining({ id: "A", isDeleted: false }), + expect.objectContaining({ id: rectangle.id, isDeleted: true }), + ]); + + // noop + h.app.actionManager.executeAction(undoAction); + expect(h.elements).toEqual([ + expect.objectContaining({ id: "A", isDeleted: false }), + expect.objectContaining({ id: rectangle.id, isDeleted: true }), + ]); + expect(API.getStateHistory().length).toBe(1); + + h.app.actionManager.executeAction(redoAction); + expect(h.elements).toEqual([ + expect.objectContaining({ id: "A", isDeleted: false }), + expect.objectContaining({ id: rectangle.id, isDeleted: false }), + ]); + expect(API.getStateHistory().length).toBe(2); + }); + + it("scene import via drag&drop should create new history entry", async () => { + render( + , + ); + + await waitFor(() => expect(h.state.viewBackgroundColor).toBe("#FFF")); + await waitFor(() => + expect(h.elements).toEqual([expect.objectContaining({ id: "A" })]), + ); + const fileDropEvent = createEvent.drop(GlobalTestState.canvas); + const file = new Blob( + [ + JSON.stringify({ + type: "excalidraw", + appState: { + ...getDefaultAppState(), + viewBackgroundColor: "#000", + }, + elements: [API.createElement({ type: "rectangle", id: "B" })], + }), + ], + { + type: "application/json", + }, + ); + Object.defineProperty(fileDropEvent, "dataTransfer", { + value: { + files: [file], + getData: (_type: string) => { + return ""; + }, + }, + }); + fireEvent(GlobalTestState.canvas, fileDropEvent); + + await waitFor(() => expect(API.getStateHistory().length).toBe(2)); + expect(h.state.viewBackgroundColor).toBe("#000"); + expect(h.elements).toEqual([ + expect.objectContaining({ id: "B", isDeleted: false }), + ]); + + const undoAction = createUndoAction(h.history); + const redoAction = createRedoAction(h.history); + h.app.actionManager.executeAction(undoAction); + expect(h.elements).toEqual([ + expect.objectContaining({ id: "A", isDeleted: false }), + expect.objectContaining({ id: "B", isDeleted: true }), + ]); + expect(h.state.viewBackgroundColor).toBe("#FFF"); + h.app.actionManager.executeAction(redoAction); + expect(h.state.viewBackgroundColor).toBe("#000"); + expect(h.elements).toEqual([ + expect.objectContaining({ id: "B", isDeleted: false }), + expect.objectContaining({ id: "A", isDeleted: true }), + ]); + }); +}); diff --git a/src/tests/regressionTests.test.tsx b/src/tests/regressionTests.test.tsx index 98e46f66..32217a6a 100644 --- a/src/tests/regressionTests.test.tsx +++ b/src/tests/regressionTests.test.tsx @@ -451,10 +451,7 @@ describe("regression tests", () => { }); it("noop interaction after undo shouldn't create history entry", () => { - // NOTE: this will fail if this test case is run in isolation. There's - // some leaking state or race conditions in initialization/teardown - // (couldn't figure out) - expect(API.getStateHistory().length).toBe(0); + expect(API.getStateHistory().length).toBe(1); UI.clickTool("rectangle"); mouse.down(10, 10); @@ -468,35 +465,35 @@ describe("regression tests", () => { const secondElementEndPoint = mouse.getPosition(); - expect(API.getStateHistory().length).toBe(2); + expect(API.getStateHistory().length).toBe(3); Keyboard.withModifierKeys({ ctrl: true }, () => { Keyboard.keyPress("z"); }); - expect(API.getStateHistory().length).toBe(1); + expect(API.getStateHistory().length).toBe(2); // clicking an element shouldn't add to history mouse.restorePosition(...firstElementEndPoint); mouse.click(); - expect(API.getStateHistory().length).toBe(1); + expect(API.getStateHistory().length).toBe(2); Keyboard.withModifierKeys({ shift: true, ctrl: true }, () => { Keyboard.keyPress("z"); }); - expect(API.getStateHistory().length).toBe(2); + expect(API.getStateHistory().length).toBe(3); // clicking an element shouldn't add to history mouse.click(); - expect(API.getStateHistory().length).toBe(2); + expect(API.getStateHistory().length).toBe(3); const firstSelectedElementId = API.getSelectedElement().id; // same for clicking the element just redo-ed mouse.restorePosition(...secondElementEndPoint); mouse.click(); - expect(API.getStateHistory().length).toBe(2); + expect(API.getStateHistory().length).toBe(3); expect(API.getSelectedElement().id).not.toEqual(firstSelectedElementId); }); diff --git a/src/tests/zindex.test.tsx b/src/tests/zindex.test.tsx index f86ee628..58029111 100644 --- a/src/tests/zindex.test.tsx +++ b/src/tests/zindex.test.tsx @@ -3,14 +3,13 @@ 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"; -import { ExcalidrawElement } from "../element/types"; +import { API } from "./helpers/api"; // Unmount ReactDOM from root ReactDOM.unmountComponentAtNode(document.getElementById("root")!); @@ -28,21 +27,7 @@ const populateElements = ( const selectedElementIds: any = {}; h.elements = elements.map(({ id, isDeleted = false, isSelected = false }) => { - const element: Mutable = newElement({ - type: "rectangle", - x: 100, - y: 100, - strokeColor: h.state.currentItemStrokeColor, - backgroundColor: h.state.currentItemBackgroundColor, - fillStyle: h.state.currentItemFillStyle, - strokeWidth: h.state.currentItemStrokeWidth, - strokeStyle: h.state.currentItemStrokeStyle, - strokeSharpness: h.state.currentItemStrokeSharpness, - roughness: h.state.currentItemRoughness, - opacity: h.state.currentItemOpacity, - }); - element.id = id; - element.isDeleted = isDeleted; + const element = API.createElement({ type: "rectangle", id, isDeleted }); if (isSelected) { selectedElementIds[element.id] = true; }