1041 lines
32 KiB
Go
1041 lines
32 KiB
Go
package editor
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.gophernest.net/azpect/TextEditor/internal/core"
|
|
)
|
|
|
|
// ==================================================
|
|
// Replace Char (r) Tests
|
|
// ==================================================
|
|
|
|
func TestReplaceChar(t *testing.T) {
|
|
t.Run("test 'rx' replaces character under cursor", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xello" {
|
|
t.Errorf("lines[0] = %q, want 'xello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' in middle of line", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hexlo" {
|
|
t.Errorf("lines[0] = %q, want 'hexlo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' at end of line", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 4, Line: 0})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hellx" {
|
|
t.Errorf("lines[0] = %q, want 'hellx'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' cursor position remains at replaced char", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveWindow().Cursor.Col != 2 {
|
|
t.Errorf("CursorX() = %d, want 2", m.ActiveWindow().Cursor.Col)
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' stays in normal mode", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.Mode() != core.NormalMode {
|
|
t.Errorf("Mode() = %v, want NormalMode", m.Mode())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' with space replaces with space", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", " ")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != " ello" {
|
|
t.Errorf("lines[0] = %q, want ' ello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' with digit replaces with digit", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "5")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "5ello" {
|
|
t.Errorf("lines[0] = %q, want '5ello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' with special char replaces correctly", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "@")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "@ello" {
|
|
t.Errorf("lines[0] = %q, want '@ello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test multiple 'r' operations in sequence", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x", "l", "r", "y")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xyllo" {
|
|
t.Errorf("lines[0] = %q, want 'xyllo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceCharWithCount(t *testing.T) {
|
|
t.Run("test '3rx' replaces three characters", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "3", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xxxlo" {
|
|
t.Errorf("lines[0] = %q, want 'xxxlo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '3rx' cursor position after replace", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "3", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Cursor should be at last replaced character
|
|
if m.ActiveWindow().Cursor.Col != 2 {
|
|
t.Errorf("CursorX() = %d, want 2", m.ActiveWindow().Cursor.Col)
|
|
}
|
|
})
|
|
|
|
t.Run("test '5rx' replaces all five characters", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "5", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xxxxx" {
|
|
t.Errorf("lines[0] = %q, want 'xxxxx'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '10rx' with overflow stops at line end", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "1", "0", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Should only replace 5 chars (all available)
|
|
if m.ActiveBuffer().Lines[0].String() != "xxxxx" {
|
|
t.Errorf("lines[0] = %q, want 'xxxxx'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '2rx' from middle", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 1, Line: 0})
|
|
sendKeys(tm, "2", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hxxlo" {
|
|
t.Errorf("lines[0] = %q, want 'hxxlo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '2rx' cursor position from middle", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 1, Line: 0})
|
|
sendKeys(tm, "2", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveWindow().Cursor.Col != 2 {
|
|
t.Errorf("CursorX() = %d, want 2", m.ActiveWindow().Cursor.Col)
|
|
}
|
|
})
|
|
|
|
t.Run("test '4rx' from near end stops at line end", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
|
|
sendKeys(tm, "4", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Should only replace 2 chars (3 and 4)
|
|
if m.ActiveBuffer().Lines[0].String() != "helxx" {
|
|
t.Errorf("lines[0] = %q, want 'helxx'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test large count '100rx' doesn't crash", func(t *testing.T) {
|
|
lines := []string{"short"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "1", "0", "0", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xxxxx" {
|
|
t.Errorf("lines[0] = %q, want 'xxxxx'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceCharEdgeCases(t *testing.T) {
|
|
t.Run("test 'r' on empty line does nothing", func(t *testing.T) {
|
|
lines := []string{""}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "" {
|
|
t.Errorf("Line(0) = %q, want ''", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveWindow().Cursor.Col != 0 {
|
|
t.Errorf("CursorX() = %d, want 0", m.ActiveWindow().Cursor.Col)
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' on single character line", func(t *testing.T) {
|
|
lines := []string{"a"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "x" {
|
|
t.Errorf("Line(0) = %q, want 'x'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' at last char replaces it", func(t *testing.T) {
|
|
lines := []string{"ab"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 1, Line: 0})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "ax" {
|
|
t.Errorf("Line(0) = %q, want 'ax'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' with whitespace", func(t *testing.T) {
|
|
lines := []string{"a b c"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 1, Line: 0})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "axb c" {
|
|
t.Errorf("Line(0) = %q, want 'axb c'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' preserves other lines", func(t *testing.T) {
|
|
lines := []string{"hello", "world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().LineCount() != 2 {
|
|
t.Errorf("LineCount() = %d, want 2", m.ActiveBuffer().LineCount())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "world" {
|
|
t.Errorf("Line(1) = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' on line with tabs", func(t *testing.T) {
|
|
lines := []string{"a\tb"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 1, Line: 0})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "axb" {
|
|
t.Errorf("Line(0) = %q, want 'axb'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '5rx' with only 3 chars available", func(t *testing.T) {
|
|
lines := []string{"abc"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "5", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xxx" {
|
|
t.Errorf("Line(0) = %q, want 'xxx'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' in middle preserves surrounding chars", func(t *testing.T) {
|
|
lines := []string{"abcde"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "abxde" {
|
|
t.Errorf("Line(0) = %q, want 'abxde'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' on whitespace-only line", func(t *testing.T) {
|
|
lines := []string{" "}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != " x " {
|
|
t.Errorf("Line(0) = %q, want ' x '", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' on different lines independently", func(t *testing.T) {
|
|
lines := []string{"hello", "world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x", "j", "r", "y")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xello" {
|
|
t.Errorf("Line(0) = %q, want 'xello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "yorld" {
|
|
t.Errorf("Line(1) = %q, want 'yorld'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' does not affect line count", func(t *testing.T) {
|
|
lines := []string{"line 1", "line 2", "line 3"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().LineCount() != 3 {
|
|
t.Errorf("LineCount() = %d, want 3", m.ActiveBuffer().LineCount())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' with newline character is treated as single char", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
// Note: In vim, 'r' with enter doesn't work the same way
|
|
// This test documents the current behavior
|
|
sendKeys(tm, "r", "\n")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Replacing with "\n" string (not actual newline)
|
|
if m.ActiveBuffer().Lines[0].String() != "\nello" {
|
|
t.Errorf("Line(0) = %q, want '\\nello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceCharWithMotion(t *testing.T) {
|
|
t.Run("test 'lrx' moves then replaces", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "l", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hxllo" {
|
|
t.Errorf("lines[0] = %q, want 'hxllo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'wrx' moves to next word start then replaces", func(t *testing.T) {
|
|
lines := []string{"hello world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "w", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello xorld" {
|
|
t.Errorf("lines[0] = %q, want 'hello xorld'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '$rx' moves to end then replaces", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "$", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hellx" {
|
|
t.Errorf("lines[0] = %q, want 'hellx'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '2lrx' moves 2 right then replaces", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "2", "l", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hexlo" {
|
|
t.Errorf("lines[0] = %q, want 'hexlo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceCharUndo(t *testing.T) {
|
|
t.Run("test 'rx' can be undone with 'u'", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x", "u")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello" {
|
|
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '3rx' can be undone with 'u'", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "3", "r", "x", "u")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello" {
|
|
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test multiple 'r' operations can be undone separately", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x", "l", "r", "y", "u")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Only the last 'ry' should be undone
|
|
if m.ActiveBuffer().Lines[0].String() != "xello" {
|
|
t.Errorf("lines[0] = %q, want 'xello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test undo then redo 'rx'", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x", "u", "ctrl+r")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xello" {
|
|
t.Errorf("lines[0] = %q, want 'xello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceCharRepeat(t *testing.T) {
|
|
t.Run("test 'rx' can be repeated with '.'", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "x", "l", ".")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xxllo" {
|
|
t.Errorf("lines[0] = %q, want 'xxllo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '3rx' can be repeated with '.'", func(t *testing.T) {
|
|
lines := []string{"hello world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "3", "r", "x", "w", ".")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// First 3rx at position 0, second at position 6
|
|
if m.ActiveBuffer().Lines[0].String() != "xxxlo xxxld" {
|
|
t.Errorf("lines[0] = %q, want 'xxxlo xxxld'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '.' repeats last replace char", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "r", "a", "l", ".", "l", ".")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "aaalo" {
|
|
t.Errorf("lines[0] = %q, want 'aaalo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
// NOTE: This is the same as Vim's handling, but that is okay, I like this more, feels more honest
|
|
t.Run("test '.' with count multiplies", func(t *testing.T) {
|
|
lines := []string{"hello world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "2", "r", "x", "w", "3", ".")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "xxllo xxxxx" {
|
|
t.Errorf("lines[0] = %q, want 'xxllo xxxxx'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceCharMultiLine(t *testing.T) {
|
|
t.Run("test 'r' on second line", func(t *testing.T) {
|
|
lines := []string{"first", "second"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 1})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "first" {
|
|
t.Errorf("Line(0) = %q, want 'first'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "xecond" {
|
|
t.Errorf("Line(1) = %q, want 'xecond'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' does not cross line boundaries", func(t *testing.T) {
|
|
lines := []string{"ab", "cd"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 1, Line: 0})
|
|
sendKeys(tm, "5", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Should only replace 'b', not cross to next line
|
|
if m.ActiveBuffer().Lines[0].String() != "ax" {
|
|
t.Errorf("Line(0) = %q, want 'ax'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "cd" {
|
|
t.Errorf("Line(1) = %q, want 'cd'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'r' on last line", func(t *testing.T) {
|
|
lines := []string{"first", "second", "third"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 2})
|
|
sendKeys(tm, "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[2].String() != "xhird" {
|
|
t.Errorf("Line(2) = %q, want 'xhird'", m.ActiveBuffer().Lines[2].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceCharCombinations(t *testing.T) {
|
|
t.Run("test 'frx' finds then replaces", func(t *testing.T) {
|
|
lines := []string{"hello world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "f", "w", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello xorld" {
|
|
t.Errorf("lines[0] = %q, want 'hello xorld'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '2frx' finds second occurrence then replaces", func(t *testing.T) {
|
|
lines := []string{"hello hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "2", "f", "l", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Find second 'l', which is at position 3
|
|
if m.ActiveBuffer().Lines[0].String() != "helxo hello" {
|
|
t.Errorf("lines[0] = %q, want 'helxo hello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test '^rx' moves to first non-blank then replaces", func(t *testing.T) {
|
|
lines := []string{" hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "^", "r", "x")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != " xello" {
|
|
t.Errorf("lines[0] = %q, want ' xello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
// ==================================================
|
|
// Replace Mode (R) Tests
|
|
// ==================================================
|
|
|
|
func TestReplaceModeEntry(t *testing.T) {
|
|
t.Run("test 'R' enters replace mode", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.Mode() != core.ReplaceMode {
|
|
t.Errorf("Mode() = %v, want ReplaceMode", m.Mode())
|
|
}
|
|
})
|
|
|
|
t.Run("test 'esc' exits replace mode to normal", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "x", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.Mode() != core.NormalMode {
|
|
t.Errorf("Mode() = %v, want NormalMode", m.Mode())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceModeBasic(t *testing.T) {
|
|
t.Run("test single character overwrites", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "X", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "Xello" {
|
|
t.Errorf("lines[0] = %q, want 'Xello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test multiple characters overwrite", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "abclo" {
|
|
t.Errorf("lines[0] = %q, want 'abclo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test typing past end of line appends", func(t *testing.T) {
|
|
lines := []string{"hi"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "there")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hithere" {
|
|
t.Errorf("lines[0] = %q, want 'hithere'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test replace mode starting at end of line", func(t *testing.T) {
|
|
lines := []string{"hi"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "!!")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hi!!" {
|
|
t.Errorf("lines[0] = %q, want 'hi!!'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test replace mode from middle of line", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "XX")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "heXXo" {
|
|
t.Errorf("lines[0] = %q, want 'heXXo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test cursor position after exiting replace mode", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Cursor should be at last replaced character
|
|
if m.ActiveWindow().Cursor.Col != 2 {
|
|
t.Errorf("CursorX() = %d, want 2", m.ActiveWindow().Cursor.Col)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceModeBackspace(t *testing.T) {
|
|
t.Run("test backspace deletes character", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "backspace", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "ablo" {
|
|
t.Errorf("lines[0] = %q, want 'ablo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test backspace at start does nothing", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "backspace", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello" {
|
|
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test multiple backspaces", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "backspace", "backspace", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "alo" {
|
|
t.Errorf("lines[0] = %q, want 'alo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test backspace then type more", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "backspace")
|
|
sendKeyString(tm, "XY")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "abXY" {
|
|
t.Errorf("lines[0] = %q, want 'abXY'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceModeNavigation(t *testing.T) {
|
|
t.Run("test right arrow moves cursor", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "right", "right", "X", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "heXlo" {
|
|
t.Errorf("lines[0] = %q, want 'heXlo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test left arrow moves cursor", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
|
|
sendKeys(tm, "R", "left", "X", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hXllo" {
|
|
t.Errorf("lines[0] = %q, want 'hXllo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test up/down arrows navigate between lines", func(t *testing.T) {
|
|
lines := []string{"hello", "world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "X", "down", "Y", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "Xello" {
|
|
t.Errorf("lines[0] = %q, want 'Xello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "wYrld" {
|
|
t.Errorf("lines[1] = %q, want 'wYrld'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test up arrow from first line stays on first line", func(t *testing.T) {
|
|
lines := []string{"hello", "world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "up", "X", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "Xello" {
|
|
t.Errorf("lines[0] = %q, want 'Xello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test down arrow from last line stays on last line", func(t *testing.T) {
|
|
lines := []string{"hello", "world"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 1})
|
|
sendKeys(tm, "R", "down", "X", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[1].String() != "Xorld" {
|
|
t.Errorf("lines[1] = %q, want 'Xorld'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceModeSpecialKeys(t *testing.T) {
|
|
t.Run("test enter splits line", func(t *testing.T) {
|
|
lines := []string{"hello world"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 5, Line: 0})
|
|
sendKeys(tm, "R", "enter", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello" {
|
|
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "world" {
|
|
t.Errorf("lines[1] = %q, want 'world'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test tab inserts tab character", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "tab", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Tab is expanded to spaces based on tabstop setting (default 2)
|
|
if m.ActiveBuffer().Lines[0].String() != " ello" {
|
|
t.Errorf("lines[0] = %q, want ' ello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test ctrl+w deletes previous word", func(t *testing.T) {
|
|
lines := []string{"hello world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "foo bar")
|
|
sendKeys(tm, "ctrl+w", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "foo orld" {
|
|
t.Errorf("lines[0] = %q, want 'foo orld'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test ctrl+w at beginning does nothing", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "ctrl+w", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello" {
|
|
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test delete key removes character ahead", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "delete", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "ello" {
|
|
t.Errorf("lines[0] = %q, want 'ello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceModeUndo(t *testing.T) {
|
|
t.Run("test replace mode changes can be undone", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "esc", "u")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello" {
|
|
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test replace mode changes can be redone", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "esc", "u", "ctrl+r")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "abclo" {
|
|
t.Errorf("lines[0] = %q, want 'abclo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test multiple undo operations", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "esc")
|
|
sendKeys(tm, "l", "R")
|
|
sendKeyString(tm, "XY")
|
|
sendKeys(tm, "esc", "u")
|
|
|
|
m := getFinalModel(t, tm)
|
|
// Only the second replace should be undone
|
|
if m.ActiveBuffer().Lines[0].String() != "abclo" {
|
|
t.Errorf("lines[0] = %q, want 'abclo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceModeEdgeCases(t *testing.T) {
|
|
t.Run("test replace mode on empty line", func(t *testing.T) {
|
|
lines := []string{""}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "test")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "test" {
|
|
t.Errorf("lines[0] = %q, want 'test'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test replace mode on different lines", func(t *testing.T) {
|
|
lines := []string{"hello", "world"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 1})
|
|
sendKeys(tm, "R", "X", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "hello" {
|
|
t.Errorf("lines[0] = %q, want 'hello'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "Xorld" {
|
|
t.Errorf("lines[1] = %q, want 'Xorld'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test overwriting tab character", func(t *testing.T) {
|
|
lines := []string{"a\tb"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 1, Line: 0})
|
|
sendKeys(tm, "R", "X", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "aXb" {
|
|
t.Errorf("lines[0] = %q, want 'aXb'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test replace mode with whitespace characters", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "a b")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "a blo" {
|
|
t.Errorf("lines[0] = %q, want 'a blo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test replace mode on single character line", func(t *testing.T) {
|
|
lines := []string{"a"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "X", "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "X" {
|
|
t.Errorf("lines[0] = %q, want 'X'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test replace mode preserves other lines", func(t *testing.T) {
|
|
lines := []string{"first", "second", "third"}
|
|
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 1})
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "XXX")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "first" {
|
|
t.Errorf("lines[0] = %q, want 'first'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "XXXond" {
|
|
t.Errorf("lines[1] = %q, want 'XXXond'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[2].String() != "third" {
|
|
t.Errorf("lines[2] = %q, want 'third'", m.ActiveBuffer().Lines[2].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test replace mode with special characters", func(t *testing.T) {
|
|
lines := []string{"hello"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "@#$")
|
|
sendKeys(tm, "esc")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "@#$lo" {
|
|
t.Errorf("lines[0] = %q, want '@#$lo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceModeRepeat(t *testing.T) {
|
|
t.Run("test replace mode can be repeated with '.'", func(t *testing.T) {
|
|
lines := []string{"hello", "world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "XX")
|
|
sendKeys(tm, "esc", "j", ".")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "XXllo" {
|
|
t.Errorf("lines[0] = %q, want 'XXllo'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[1].String() != "wXXld" {
|
|
t.Errorf("lines[1] = %q, want 'wXXld'", m.ActiveBuffer().Lines[1].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test dot repeats last replace operation", func(t *testing.T) {
|
|
lines := []string{"hello world"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R")
|
|
sendKeyString(tm, "abc")
|
|
sendKeys(tm, "esc", "w", ".")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "abclo abcld" {
|
|
t.Errorf("lines[0] = %q, want 'abclo abcld'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
})
|
|
|
|
t.Run("test dot after navigation", func(t *testing.T) {
|
|
lines := []string{"aaa", "bbb", "ccc"}
|
|
tm := newTestModelWithLines(t, lines)
|
|
sendKeys(tm, "R", "X", "esc", "j", "j", ".")
|
|
|
|
m := getFinalModel(t, tm)
|
|
if m.ActiveBuffer().Lines[0].String() != "Xaa" {
|
|
t.Errorf("lines[0] = %q, want 'Xaa'", m.ActiveBuffer().Lines[0].String())
|
|
}
|
|
if m.ActiveBuffer().Lines[2].String() != "Xcc" {
|
|
t.Errorf("lines[2] = %q, want 'Xcc'", m.ActiveBuffer().Lines[2].String())
|
|
}
|
|
})
|
|
}
|