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  }