Gim/internal/action/command_history_test.go
Hayden Hargreaves 3c98dca777 feat: implement command history, tested
The tests are starting to get messy, lots of duplication. Going to
resolve that. Lots of this is due to AI generation of tests.
2026-03-19 15:23:44 -07:00

172 lines
4.2 KiB
Go

package action
import (
"testing"
"git.gophernest.net/azpect/TextEditor/internal/core"
tea "github.com/charmbracelet/bubbletea"
)
// mockModelForHistory is a minimal mock for testing command history
type mockModelForHistory struct {
mockModel
commandHistory []string
commandHistoryCursor int
}
func (m *mockModelForHistory) CommandHistory() []string {
return m.commandHistory
}
func (m *mockModelForHistory) SetCommandHistory(history []string) {
m.commandHistory = history
}
func (m *mockModelForHistory) CommandHistoryCursor() int {
return m.commandHistoryCursor
}
func (m *mockModelForHistory) SetCommandHistoryCursor(cur int) {
m.commandHistoryCursor = cur
}
// mockRegistry for testing command execution without actual command handlers
type mockRegistry struct{}
func (r *mockRegistry) Execute(m Model, cmdLine string) (tea.Cmd, error) {
// Mock implementation - just returns nil
return nil, nil
}
// TestCommandExecuteUpdatesHistory tests that executing commands adds them to history
func TestCommandExecuteUpdatesHistory(t *testing.T) {
t.Run("first command added to empty history", func(t *testing.T) {
m := &mockModelForHistory{
mockModel: mockModel{
mode: core.CommandMode,
command: "w test.txt",
},
commandHistory: []string{},
commandHistoryCursor: 0,
}
registry := &mockRegistry{}
action := CommandExecute{Registry: registry}
action.Execute(m)
history := m.CommandHistory()
if len(history) != 1 {
t.Errorf("History length = %d, want 1", len(history))
}
if history[0] != "w test.txt" {
t.Errorf("History[0] = %q, want %q", history[0], "w test.txt")
}
})
t.Run("multiple commands prepended to history", func(t *testing.T) {
m := &mockModelForHistory{
mockModel: mockModel{
mode: core.CommandMode,
command: "w file1.txt",
},
commandHistory: []string{},
commandHistoryCursor: 0,
}
registry := &mockRegistry{}
action := CommandExecute{Registry: registry}
// Execute first command
action.Execute(m)
// Execute second command
m.command = "q"
action.Execute(m)
// Execute third command
m.command = "set number"
action.Execute(m)
history := m.CommandHistory()
if len(history) != 3 {
t.Errorf("History length = %d, want 3", len(history))
}
// Most recent should be first (prepended)
want := []string{"set number", "q", "w file1.txt"}
for i, cmd := range want {
if history[i] != cmd {
t.Errorf("History[%d] = %q, want %q", i, history[i], cmd)
}
}
})
t.Run("empty command not added to history", func(t *testing.T) {
m := &mockModelForHistory{
mockModel: mockModel{
mode: core.CommandMode,
command: "",
},
commandHistory: []string{"previous command"},
commandHistoryCursor: 0,
}
registry := &mockRegistry{}
action := CommandExecute{Registry: registry}
action.Execute(m)
history := m.CommandHistory()
if len(history) != 1 {
t.Errorf("History length = %d, want 1 (empty command should not be added)", len(history))
}
if history[0] != "previous command" {
t.Errorf("History[0] = %q, want %q", history[0], "previous command")
}
})
t.Run("history cursor resets on execute", func(t *testing.T) {
m := &mockModelForHistory{
mockModel: mockModel{
mode: core.CommandMode,
command: "w",
},
commandHistory: []string{},
commandHistoryCursor: 5, // Set to non-zero
}
registry := &mockRegistry{}
action := CommandExecute{Registry: registry}
action.Execute(m)
if m.CommandHistoryCursor() != 0 {
t.Errorf("CommandHistoryCursor = %d, want 0 after execute", m.CommandHistoryCursor())
}
})
t.Run("duplicate commands are added to history", func(t *testing.T) {
m := &mockModelForHistory{
mockModel: mockModel{
mode: core.CommandMode,
command: "w",
},
commandHistory: []string{"w"},
commandHistoryCursor: 0,
}
registry := &mockRegistry{}
action := CommandExecute{Registry: registry}
action.Execute(m)
history := m.CommandHistory()
if len(history) != 2 {
t.Errorf("History length = %d, want 2 (duplicates should be added)", len(history))
}
if history[0] != "w" || history[1] != "w" {
t.Errorf("History = %v, want ['w', 'w']", history)
}
})
}