package editor import ( "testing" "git.gophernest.net/azpect/TextEditor/internal/core" ) // NOTE: AI Generated tests // Default settings are: Number=true, RelativeNumber=true, TabSize=2, ScrollOff=8 func TestCommandSetBoolean(t *testing.T) { t.Run("':set nonumber' disables line numbers", func(t *testing.T) { // Default has Number=true lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "n", "o", "n", "u", "m", "b", "e", "r", "enter") m := getFinalModel(t, tm) if m.Settings().Number { t.Error("expected Number to be false after :set nonumber") } }) t.Run("':set number' enables after disable", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) // First disable, then enable sendKeys(tm, ":", "s", "e", "t", " ", "n", "o", "n", "u", "enter") sendKeys(tm, ":", "s", "e", "t", " ", "n", "u", "enter") m := getFinalModel(t, tm) if !m.Settings().Number { t.Error("expected Number to be true after :set nu") } }) t.Run("':set number!' toggles number off", func(t *testing.T) { // Default has Number=true lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "n", "u", "m", "b", "e", "r", "!", "enter") m := getFinalModel(t, tm) if m.Settings().Number { t.Error("expected Number to be false after :set number!") } }) t.Run("':set number!' toggles back on", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) // Toggle off then on sendKeys(tm, ":", "s", "e", "t", " ", "n", "u", "!", "enter") sendKeys(tm, ":", "s", "e", "t", " ", "n", "u", "!", "enter") m := getFinalModel(t, tm) if !m.Settings().Number { t.Error("expected Number to be true after double toggle") } }) t.Run("':set nornu' disables relative numbers", func(t *testing.T) { // Default has RelativeNumber=true lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "n", "o", "r", "n", "u", "enter") m := getFinalModel(t, tm) if m.Settings().RelativeNumber { t.Error("expected RelativeNumber to be false after :set nornu") } }) t.Run("':set rnu' enables after disable", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) // Disable then enable sendKeys(tm, ":", "s", "e", "t", " ", "n", "o", "r", "n", "u", "enter") sendKeys(tm, ":", "s", "e", "t", " ", "r", "n", "u", "enter") m := getFinalModel(t, tm) if !m.Settings().RelativeNumber { t.Error("expected RelativeNumber to be true after :set rnu") } }) } func TestCommandSetInteger(t *testing.T) { t.Run("':set tabstop=4' sets tab size", func(t *testing.T) { // Default TabSize=2 lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "t", "a", "b", "s", "t", "o", "p", "=", "4", "enter") m := getFinalModel(t, tm) if m.Settings().TabSize != 4 { t.Errorf("TabSize = %d, want 4", m.Settings().TabSize) } }) t.Run("':set ts=8' uses short form", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "t", "s", "=", "8", "enter") m := getFinalModel(t, tm) if m.Settings().TabSize != 8 { t.Errorf("TabSize = %d, want 8", m.Settings().TabSize) } }) t.Run("':set scrolloff=5' sets scroll offset", func(t *testing.T) { // Default ScrollOff=8 lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "s", "c", "r", "o", "l", "l", "o", "f", "f", "=", "5", "enter") m := getFinalModel(t, tm) if m.Settings().ScrollOff != 5 { t.Errorf("ScrollOff = %d, want 5", m.Settings().ScrollOff) } }) t.Run("':set so=10' uses short form", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "s", "o", "=", "1", "0", "enter") m := getFinalModel(t, tm) if m.Settings().ScrollOff != 10 { t.Errorf("ScrollOff = %d, want 10", m.Settings().ScrollOff) } }) } func TestCommandModeNavigation(t *testing.T) { t.Run("':' enters command mode and esc exits", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "esc") m := getFinalModel(t, tm) // After esc we should be back in normal mode if m.Mode() != core.NormalMode { t.Errorf("Mode() = %v, want NormalMode after esc", m.Mode()) } }) t.Run("'esc' exits command mode", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "esc") m := getFinalModel(t, tm) if m.Mode() != core.NormalMode { t.Errorf("Mode() = %v, want NormalMode", m.Mode()) } }) t.Run("'enter' executes and exits command mode", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "n", "u", "enter") m := getFinalModel(t, tm) if m.Mode() != core.NormalMode { t.Errorf("Mode() = %v, want NormalMode", m.Mode()) } }) t.Run("command buffer is not cleared after execution", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "t", "e", "s", "t", "enter") m := getFinalModel(t, tm) if m.Command() != "test" { t.Errorf("Command() = %q, want \"test\"", m.Command()) } }) } func TestCommandModeEditing(t *testing.T) { t.Run("backspace deletes character", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) // Type abc, backspace, then enter to execute and check result sendKeys(tm, ":", "a", "b", "c", "backspace", "enter") m := getFinalModel(t, tm) // Command buffer preserves last command after execution if m.Command() != "ab" { t.Errorf("Command() = %q, want \"ab\"", m.Command()) } }) t.Run("backspace at start does nothing", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "backspace", "a", "enter") m := getFinalModel(t, tm) if m.Command() != "a" { t.Errorf("Command() = %q, want \"a\"", m.Command()) } }) t.Run("multiple backspaces", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "a", "b", "c", "backspace", "backspace", "enter") m := getFinalModel(t, tm) if m.Command() != "a" { t.Errorf("Command() = %q, want \"a\"", m.Command()) } }) t.Run("delete key removes character at cursor", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) // Type abc, move left, delete 'c', then enter sendKeys(tm, ":", "a", "b", "c", "left", "delete", "enter") m := getFinalModel(t, tm) if m.Command() != "ab" { t.Errorf("Command() = %q, want \"ab\"", m.Command()) } }) t.Run("delete at end acts as backspace", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "a", "b", "c", "delete", "enter") m := getFinalModel(t, tm) if m.Command() != "ab" { t.Errorf("Command() = %q, want \"ab\"", m.Command()) } }) t.Run("ctrl+w deletes previous word", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "s", "e", "t", " ", "n", "u", "m", "b", "e", "r", "ctrl+w", "enter") m := getFinalModel(t, tm) if m.Command() != "set " { t.Errorf("Command() = %q, want \"set \"", m.Command()) } }) t.Run("ctrl+w deletes word and trailing space", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "o", "n", "e", " ", "t", "w", "o", " ", "ctrl+w", "enter") m := getFinalModel(t, tm) if m.Command() != "one " { t.Errorf("Command() = %q, want \"one \"", m.Command()) } }) t.Run("ctrl+w at start does nothing", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "ctrl+w", "a", "enter") m := getFinalModel(t, tm) if m.Command() != "a" { t.Errorf("Command() = %q, want \"a\"", m.Command()) } }) t.Run("insert at cursor position", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) // Type 'ac', move left, insert 'b' -> 'abc' sendKeys(tm, ":", "a", "c", "left", "b", "enter") m := getFinalModel(t, tm) if m.Command() != "abc" { t.Errorf("Command() = %q, want \"abc\"", m.Command()) } }) } func TestCommandModeErrors(t *testing.T) { t.Run("unknown command sets error", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) sendKeys(tm, ":", "u", "n", "k", "n", "o", "w", "n", "c", "m", "d", "enter") m := getFinalModel(t, tm) if m.commandError == nil { t.Error("expected commandError to be set for unknown command") } }) t.Run("valid command clears error", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) // First cause an error sendKeys(tm, ":", "b", "a", "d", "enter") // Then run a valid command sendKeys(tm, ":", "s", "e", "t", " ", "n", "u", "enter") m := getFinalModel(t, tm) if m.commandError != nil { t.Errorf("expected commandError to be nil, got %v", m.commandError) } }) t.Run("esc clears error", func(t *testing.T) { lines := []string{"hello"} tm := newTestModelWithLines(t, lines) // Cause an error sendKeys(tm, ":", "b", "a", "d", "enter") // Then escape sendKeys(tm, ":", "esc") m := getFinalModel(t, tm) if m.commandError != nil { t.Errorf("expected commandError to be nil after esc, got %v", m.commandError) } }) }