github.com/aretext/aretext@v1.3.0/state/macro_test.go (about) 1 package state 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/assert" 7 ) 8 9 type actionLogEntry struct { 10 name string 11 isReplayingUserMacro bool 12 } 13 14 type actionLogger struct { 15 logEntries []actionLogEntry 16 } 17 18 func (a *actionLogger) buildAction(name string) MacroAction { 19 return func(s *EditorState) { 20 a.logEntries = append(a.logEntries, actionLogEntry{ 21 name: name, 22 isReplayingUserMacro: s.macroState.isReplayingUserMacro, 23 }) 24 } 25 } 26 27 func (a *actionLogger) clear() { 28 a.logEntries = nil 29 } 30 31 func TestLastActionMacro(t *testing.T) { 32 var logger actionLogger 33 state := NewEditorState(100, 100, nil, nil) 34 ReplayLastActionMacro(state, 1) 35 assert.Equal(t, 0, len(logger.logEntries)) 36 37 AddToLastActionMacro(state, logger.buildAction("a")) 38 AddToLastActionMacro(state, logger.buildAction("b")) 39 ReplayLastActionMacro(state, 1) 40 expected := []actionLogEntry{{name: "a"}, {name: "b"}} 41 assert.Equal(t, expected, logger.logEntries) 42 43 logger.clear() 44 ClearLastActionMacro(state) 45 ReplayLastActionMacro(state, 1) 46 assert.Equal(t, 0, len(logger.logEntries)) 47 48 AddToLastActionMacro(state, logger.buildAction("c")) 49 ReplayLastActionMacro(state, 1) 50 assert.Equal(t, []actionLogEntry{{name: "c"}}, logger.logEntries) 51 } 52 53 func TestLastActionMacroWithCount(t *testing.T) { 54 var logger actionLogger 55 state := NewEditorState(100, 100, nil, nil) 56 AddToLastActionMacro(state, logger.buildAction("a")) 57 AddToLastActionMacro(state, logger.buildAction("b")) 58 ReplayLastActionMacro(state, 3) // Repeat 3 times. 59 expected := []actionLogEntry{ 60 {name: "a"}, {name: "b"}, 61 {name: "a"}, {name: "b"}, 62 {name: "a"}, {name: "b"}, 63 } 64 assert.Equal(t, expected, logger.logEntries) 65 } 66 67 func TestRecordAndReplayUserMacro(t *testing.T) { 68 var logger actionLogger 69 state := NewEditorState(100, 100, nil, nil) 70 71 ToggleUserMacroRecording(state) 72 assert.Equal(t, StatusMsg{ 73 Style: StatusMsgStyleSuccess, 74 Text: "Started recording macro", 75 }, state.StatusMsg()) 76 77 AddToRecordingUserMacro(state, logger.buildAction("a")) 78 AddToRecordingUserMacro(state, logger.buildAction("b")) 79 80 ToggleUserMacroRecording(state) 81 assert.Equal(t, StatusMsg{ 82 Style: StatusMsgStyleSuccess, 83 Text: "Recorded macro", 84 }, state.StatusMsg()) 85 86 assert.Equal(t, 0, len(logger.logEntries)) 87 ReplayRecordedUserMacro(state) 88 assert.Equal(t, StatusMsg{ 89 Style: StatusMsgStyleSuccess, 90 Text: "Replayed macro", 91 }, state.StatusMsg()) 92 expected := []actionLogEntry{ 93 {name: "a", isReplayingUserMacro: true}, 94 {name: "b", isReplayingUserMacro: true}, 95 } 96 assert.Equal(t, expected, logger.logEntries) 97 } 98 99 func TestLastActionIsUserMacro(t *testing.T) { 100 var logger actionLogger 101 state := NewEditorState(100, 100, nil, nil) 102 ToggleUserMacroRecording(state) 103 AddToRecordingUserMacro(state, logger.buildAction("a")) 104 AddToRecordingUserMacro(state, logger.buildAction("b")) 105 ToggleUserMacroRecording(state) 106 ReplayRecordedUserMacro(state) 107 ReplayLastActionMacro(state, 1) 108 expected := []actionLogEntry{ 109 {name: "a", isReplayingUserMacro: true}, 110 {name: "b", isReplayingUserMacro: true}, 111 {name: "a", isReplayingUserMacro: true}, 112 {name: "b", isReplayingUserMacro: true}, 113 } 114 assert.Equal(t, expected, logger.logEntries) 115 } 116 117 func TestCancelUserMacro(t *testing.T) { 118 var logger actionLogger 119 state := NewEditorState(100, 100, nil, nil) 120 121 // Record user macro 122 ToggleUserMacroRecording(state) 123 AddToRecordingUserMacro(state, logger.buildAction("a")) 124 AddToRecordingUserMacro(state, logger.buildAction("b")) 125 ToggleUserMacroRecording(state) 126 127 // Start recording another macro, then immediately stop. 128 ToggleUserMacroRecording(state) 129 ToggleUserMacroRecording(state) 130 131 // Status msg should say the macro was cancelled. 132 assert.Equal(t, StatusMsg{ 133 Style: StatusMsgStyleSuccess, 134 Text: "Cancelled macro recording", 135 }, state.StatusMsg()) 136 137 // Original macro should be preserved. 138 ReplayRecordedUserMacro(state) 139 expected := []actionLogEntry{ 140 {name: "a", isReplayingUserMacro: true}, 141 {name: "b", isReplayingUserMacro: true}, 142 } 143 assert.Equal(t, expected, logger.logEntries) 144 } 145 146 func TestReplayWithNoUserMacroRecorded(t *testing.T) { 147 var logger actionLogger 148 state := NewEditorState(100, 100, nil, nil) 149 ReplayRecordedUserMacro(state) 150 assert.Equal(t, 0, len(logger.logEntries)) 151 assert.Equal(t, StatusMsg{ 152 Style: StatusMsgStyleError, 153 Text: "No macro has been recorded", 154 }, state.StatusMsg()) 155 } 156 157 func TestReplayUserMacroWhileRecordingUserMacro(t *testing.T) { 158 var logger actionLogger 159 state := NewEditorState(100, 100, nil, nil) 160 161 // Record a macro. 162 ToggleUserMacroRecording(state) 163 AddToRecordingUserMacro(state, logger.buildAction("a")) 164 ToggleUserMacroRecording(state) 165 166 // Record a second macro, try to replay while recording. 167 ToggleUserMacroRecording(state) 168 ReplayRecordedUserMacro(state) 169 170 // Expect an error status. 171 assert.Equal(t, StatusMsg{ 172 Style: StatusMsgStyleError, 173 Text: "Cannot replay a macro while recording a macro", 174 }, state.StatusMsg()) 175 } 176 177 func TestReplayLastActionWhileRecordingUserMacro(t *testing.T) { 178 state := NewEditorState(100, 100, nil, nil) 179 180 // Start recording a user macro. 181 ToggleUserMacroRecording(state) 182 183 // Attempt to replay the last action. 184 ReplayLastActionMacro(state, 1) 185 186 // Expect an error status. 187 assert.Equal(t, StatusMsg{ 188 Style: StatusMsgStyleError, 189 Text: "Cannot repeat the last action while recording a macro", 190 }, state.StatusMsg()) 191 } 192 193 func TestReplayCheckpointUndo(t *testing.T) { 194 state := NewEditorState(100, 100, nil, nil) 195 196 // Record a macro switching normal -> insert -> normal -> insert -> normal mode. 197 ToggleUserMacroRecording(state) 198 AddToRecordingUserMacro(state, func(s *EditorState) { 199 BeginUndoEntry(s) 200 setInputMode(s, InputModeInsert) 201 InsertRune(s, 'a') 202 }) 203 AddToRecordingUserMacro(state, func(s *EditorState) { 204 CommitUndoEntry(s) 205 setInputMode(s, InputModeNormal) 206 }) 207 AddToRecordingUserMacro(state, func(s *EditorState) { 208 BeginUndoEntry(s) 209 setInputMode(s, InputModeInsert) 210 InsertRune(s, 'b') 211 }) 212 AddToRecordingUserMacro(state, func(s *EditorState) { 213 CommitUndoEntry(s) 214 setInputMode(s, InputModeNormal) 215 }) 216 ToggleUserMacroRecording(state) 217 218 // Replay the macro. 219 ReplayRecordedUserMacro(state) 220 assert.Equal(t, "ab", state.documentBuffer.textTree.String()) 221 222 // Undo to the last checkpoint, which should be at the start of the macro. 223 Undo(state) 224 assert.Equal(t, "", state.documentBuffer.textTree.String()) 225 }