Gim/internal/editor/integration_textobject_test.go
Hayden Hargreaves aa156971ad feat: text objects initial impl, tested
However, it does not work for multi line delimiters.
2026-03-26 14:09:10 -07:00

597 lines
20 KiB
Go

package editor
import (
"testing"
"git.gophernest.net/azpect/TextEditor/internal/core"
)
// ============================================================================
// Word Text Object Tests (iw/aw)
// ============================================================================
func TestTextObjectInnerWord(t *testing.T) {
t.Run("test 'viw' selects inner word", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "v", "i", "w")
m := getFinalModel(t, tm)
if !m.Mode().IsVisualMode() {
t.Errorf("Expected visual mode")
}
// Should select "hello" (cols 0-4)
if m.ActiveWindow().Anchor.Col != 0 || m.ActiveWindow().Cursor.Col != 4 {
t.Errorf("anchor=%d, cursor=%d, want anchor=0, cursor=4",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'diw' deletes inner word", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "d", "i", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("lines[0] = %q, want ' world'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'ciw' changes inner word", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "c", "i", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " world" {
t.Errorf("lines[0] = %q, want ' world'", m.ActiveBuffer().Lines[0])
}
if m.Mode() != core.InsertMode {
t.Errorf("Expected insert mode after ciw")
}
})
t.Run("test 'yiw' yanks inner word", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "y", "i", "w")
m := getFinalModel(t, tm)
reg, ok := m.GetRegister('"')
if !ok {
t.Fatalf("Default register not found")
}
if len(reg.Content) != 1 || reg.Content[0] != "hello" {
t.Errorf("register content = %v, want ['hello']", reg.Content)
}
})
t.Run("test 'viw' at start of word", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 0})
sendKeys(tm, "v", "i", "w")
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 0 || m.ActiveWindow().Cursor.Col != 4 {
t.Errorf("anchor=%d, cursor=%d, want anchor=0, cursor=4",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'viw' at end of word", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 4, Line: 0})
sendKeys(tm, "v", "i", "w")
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 0 || m.ActiveWindow().Cursor.Col != 4 {
t.Errorf("anchor=%d, cursor=%d, want anchor=0, cursor=4",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'viw' on underscore word", func(t *testing.T) {
lines := []string{"hello_world test"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 7, Line: 0})
sendKeys(tm, "v", "i", "w")
m := getFinalModel(t, tm)
// Should select "hello_world" (cols 0-10)
if m.ActiveWindow().Anchor.Col != 0 || m.ActiveWindow().Cursor.Col != 10 {
t.Errorf("anchor=%d, cursor=%d, want anchor=0, cursor=10",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'viw' on punctuation", func(t *testing.T) {
lines := []string{"foo-bar baz"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", "w")
m := getFinalModel(t, tm)
// Should select just "-" (col 3)
if m.ActiveWindow().Anchor.Col != 3 || m.ActiveWindow().Cursor.Col != 3 {
t.Errorf("anchor=%d, cursor=%d, want anchor=3, cursor=3",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
}
func TestTextObjectAroundWord(t *testing.T) {
t.Run("test 'vaw' selects around word with trailing space", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "v", "a", "w")
m := getFinalModel(t, tm)
// Should select "hello " (cols 0-5, includes trailing space)
if m.ActiveWindow().Anchor.Col != 0 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=0, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'daw' deletes around word", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "d", "a", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "world" {
t.Errorf("lines[0] = %q, want 'world'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'daw' on last word (no trailing space)", func(t *testing.T) {
lines := []string{"hello world"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 7, Line: 0})
sendKeys(tm, "d", "a", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "hello " {
t.Errorf("lines[0] = %q, want 'hello '", m.ActiveBuffer().Lines[0])
}
})
}
// ============================================================================
// WORD Text Object Tests (iW/aW)
// ============================================================================
func TestTextObjectInnerWORD(t *testing.T) {
t.Run("test 'viW' selects inner WORD", func(t *testing.T) {
lines := []string{"foo-bar baz"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "v", "i", "W")
m := getFinalModel(t, tm)
// Should select "foo-bar" (cols 0-6)
if m.ActiveWindow().Anchor.Col != 0 || m.ActiveWindow().Cursor.Col != 6 {
t.Errorf("anchor=%d, cursor=%d, want anchor=0, cursor=6",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'diW' deletes inner WORD", func(t *testing.T) {
lines := []string{"foo-bar.baz test"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 5, Line: 0})
sendKeys(tm, "d", "i", "W")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " test" {
t.Errorf("lines[0] = %q, want ' test'", m.ActiveBuffer().Lines[0])
}
})
}
func TestTextObjectAroundWORD(t *testing.T) {
t.Run("test 'vaW' selects around WORD with trailing space", func(t *testing.T) {
lines := []string{"foo-bar baz"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "v", "a", "W")
m := getFinalModel(t, tm)
// Should select "foo-bar " (cols 0-7, includes trailing space)
if m.ActiveWindow().Anchor.Col != 0 || m.ActiveWindow().Cursor.Col != 7 {
t.Errorf("anchor=%d, cursor=%d, want anchor=0, cursor=7",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'daW' deletes around WORD", func(t *testing.T) {
lines := []string{"foo-bar baz"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 2, Line: 0})
sendKeys(tm, "d", "a", "W")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "baz" {
t.Errorf("lines[0] = %q, want 'baz'", m.ActiveBuffer().Lines[0])
}
})
}
// ============================================================================
// Delimiter Text Object Tests (i</a<, i(/a(, etc.)
// ============================================================================
func TestTextObjectAngleBrackets(t *testing.T) {
t.Run("test 'vi<' selects inner angle brackets", func(t *testing.T) {
lines := []string{"<hello>"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", "<")
m := getFinalModel(t, tm)
// Should select "hello" (cols 1-5)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'vi>' works same as 'vi<'", func(t *testing.T) {
lines := []string{"<hello>"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", ">")
m := getFinalModel(t, tm)
// Should select "hello" (cols 1-5)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'di<' deletes inner angle brackets", func(t *testing.T) {
lines := []string{"<hello>"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "i", "<")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "<>" {
t.Errorf("lines[0] = %q, want '<>'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'da<' deletes around angle brackets", func(t *testing.T) {
lines := []string{"<hello>"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "a", "<")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'vi<' on empty brackets does nothing", func(t *testing.T) {
lines := []string{"<>"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 0})
sendKeys(tm, "d", "i", "<")
m := getFinalModel(t, tm)
// Should remain unchanged
if m.ActiveBuffer().Lines[0] != "<>" {
t.Errorf("lines[0] = %q, want '<>'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'vi<' in nested brackets", func(t *testing.T) {
lines := []string{"<foo<bar>>"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 5, Line: 0})
sendKeys(tm, "v", "i", "<")
m := getFinalModel(t, tm)
// Should select "bar" (cols 5-7, the innermost pair)
if m.ActiveWindow().Anchor.Col != 5 || m.ActiveWindow().Cursor.Col != 7 {
t.Errorf("anchor=%d, cursor=%d, want anchor=5, cursor=7",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
}
func TestTextObjectParentheses(t *testing.T) {
t.Run("test 'vi(' selects inner parentheses", func(t *testing.T) {
lines := []string{"(hello)"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", "(")
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'vi)' works same as 'vi('", func(t *testing.T) {
lines := []string{"(hello)"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", ")")
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'di(' deletes inner parentheses", func(t *testing.T) {
lines := []string{"func(hello)"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 7, Line: 0})
sendKeys(tm, "d", "i", "(")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "func()" {
t.Errorf("lines[0] = %q, want 'func()'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'da(' deletes around parentheses", func(t *testing.T) {
lines := []string{"func(hello)"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 7, Line: 0})
sendKeys(tm, "d", "a", "(")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "func" {
t.Errorf("lines[0] = %q, want 'func'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'vi(' on empty parens does nothing", func(t *testing.T) {
lines := []string{"()"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 0})
sendKeys(tm, "d", "i", "(")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "()" {
t.Errorf("lines[0] = %q, want '()'", m.ActiveBuffer().Lines[0])
}
})
}
func TestTextObjectBraces(t *testing.T) {
t.Run("test 'vi{' selects inner braces", func(t *testing.T) {
lines := []string{"{hello}"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", "{")
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'di{' deletes inner braces", func(t *testing.T) {
lines := []string{"{hello}"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "i", "{")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "{}" {
t.Errorf("lines[0] = %q, want '{}'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'da{' deletes around braces", func(t *testing.T) {
lines := []string{"{hello}"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "a", "{")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
}
})
}
func TestTextObjectBrackets(t *testing.T) {
t.Run("test 'vi[' selects inner brackets", func(t *testing.T) {
lines := []string{"[hello]"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", "[")
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'di[' deletes inner brackets", func(t *testing.T) {
lines := []string{"[hello]"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "i", "[")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "[]" {
t.Errorf("lines[0] = %q, want '[]'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'da[' deletes around brackets", func(t *testing.T) {
lines := []string{"[hello]"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "a", "[")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
}
})
}
func TestTextObjectDoubleQuotes(t *testing.T) {
t.Run("test 'vi\"' selects inner double quotes", func(t *testing.T) {
lines := []string{`"hello"`}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", `"`)
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'di\"' deletes inner double quotes", func(t *testing.T) {
lines := []string{`"hello"`}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "i", `"`)
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != `""` {
t.Errorf("lines[0] = %q, want '\"\"'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'da\"' deletes around double quotes", func(t *testing.T) {
lines := []string{`"hello"`}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "a", `"`)
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'vi\"' on empty quotes does nothing", func(t *testing.T) {
lines := []string{`""`}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 0})
sendKeys(tm, "d", "i", `"`)
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != `""` {
t.Errorf("lines[0] = %q, want '\"\"'", m.ActiveBuffer().Lines[0])
}
})
}
func TestTextObjectSingleQuotes(t *testing.T) {
t.Run("test 'vi'' selects inner single quotes", func(t *testing.T) {
lines := []string{"'hello'"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", "'")
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'di'' deletes inner single quotes", func(t *testing.T) {
lines := []string{"'hello'"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "i", "'")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "''" {
t.Errorf("lines[0] = %q, want \"''\"", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'da'' deletes around single quotes", func(t *testing.T) {
lines := []string{"'hello'"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "a", "'")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
}
})
}
func TestTextObjectBackticks(t *testing.T) {
t.Run("test 'vi`' selects inner backticks", func(t *testing.T) {
lines := []string{"`hello`"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "v", "i", "`")
m := getFinalModel(t, tm)
if m.ActiveWindow().Anchor.Col != 1 || m.ActiveWindow().Cursor.Col != 5 {
t.Errorf("anchor=%d, cursor=%d, want anchor=1, cursor=5",
m.ActiveWindow().Anchor.Col, m.ActiveWindow().Cursor.Col)
}
})
t.Run("test 'di`' deletes inner backticks", func(t *testing.T) {
lines := []string{"`hello`"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "i", "`")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "``" {
t.Errorf("lines[0] = %q, want '``'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'da`' deletes around backticks", func(t *testing.T) {
lines := []string{"`hello`"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "d", "a", "`")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "" {
t.Errorf("lines[0] = %q, want ''", m.ActiveBuffer().Lines[0])
}
})
}
// ============================================================================
// Edge Cases and Complex Scenarios
// ============================================================================
func TestTextObjectEdgeCases(t *testing.T) {
t.Run("test 'diw' on single character word", func(t *testing.T) {
lines := []string{"a b c"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 0})
sendKeys(tm, "d", "i", "w")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != " b c" {
t.Errorf("lines[0] = %q, want ' b c'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'ci<' then type replacement", func(t *testing.T) {
lines := []string{"<hello>"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 3, Line: 0})
sendKeys(tm, "c", "i", "<")
sendKeyString(tm, "world")
sendKeys(tm, "esc")
m := getFinalModel(t, tm)
if m.ActiveBuffer().Lines[0] != "<world>" {
t.Errorf("lines[0] = %q, want '<world>'", m.ActiveBuffer().Lines[0])
}
})
t.Run("test 'yi(' then paste", func(t *testing.T) {
lines := []string{"func(arg)", "test"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 6, Line: 0})
sendKeys(tm, "y", "i", "(")
sendKeys(tm, "j", "p")
m := getFinalModel(t, tm)
// 'p' pastes after cursor, so "arg" is pasted after 't' -> "testarg"
if m.ActiveBuffer().Lines[1] != "testarg" {
t.Errorf("lines[1] = %q, want 'testarg'", m.ActiveBuffer().Lines[1])
}
})
t.Run("test text object cursor outside delimiters does nothing", func(t *testing.T) {
lines := []string{"before (hello) after"}
tm := newTestModelWithLinesAndCursorPos(t, lines, core.Position{Col: 0, Line: 0})
sendKeys(tm, "d", "i", "(")
m := getFinalModel(t, tm)
// Should remain unchanged since cursor is not inside parens
if m.ActiveBuffer().Lines[0] != "before (hello) after" {
t.Errorf("lines[0] = %q, want 'before (hello) after'", m.ActiveBuffer().Lines[0])
}
})
}