151 lines
3.7 KiB
Go
151 lines
3.7 KiB
Go
package model_test
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/StevanFreeborn/term-tier/internal/core"
|
||
|
|
"github.com/StevanFreeborn/term-tier/internal/handlers"
|
||
|
|
"github.com/StevanFreeborn/term-tier/internal/model"
|
||
|
|
"github.com/StevanFreeborn/term-tier/internal/state"
|
||
|
|
"github.com/charmbracelet/bubbles/textinput"
|
||
|
|
tea "github.com/charmbracelet/bubbletea"
|
||
|
|
"github.com/charmbracelet/lipgloss"
|
||
|
|
"github.com/charmbracelet/x/exp/teatest"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestModel_Update_DelegatesKeyMsg(t *testing.T) {
|
||
|
|
s := state.New(state.WithMode(state.NavigationMode))
|
||
|
|
|
||
|
|
mockHandler := &MockKeyHandler{shouldMatch: true}
|
||
|
|
|
||
|
|
m := model.New(s, model.WithKeyMsgHandlers([]handlers.KeyMsgHandler{mockHandler}))
|
||
|
|
|
||
|
|
tm := teatest.NewTestModel(t, m, teatest.WithInitialTermSize(300, 100))
|
||
|
|
|
||
|
|
tm.Send(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("q")})
|
||
|
|
|
||
|
|
tm.WaitFinished(t)
|
||
|
|
|
||
|
|
if !mockHandler.called {
|
||
|
|
t.Error("Expected KeyMsgHandler to be called, but it was not")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestModel_Update_DelegatesWinSizeMsg(t *testing.T) {
|
||
|
|
s := state.New(state.WithWindowWidth(100))
|
||
|
|
mockHandler := &MockWinHandler{shouldMatch: true}
|
||
|
|
|
||
|
|
m := model.New(s, model.WithWinSizeMsgHandlers([]handlers.WinSizeMsgHandler{mockHandler}))
|
||
|
|
tm := teatest.NewTestModel(t, m, teatest.WithInitialTermSize(80, 24))
|
||
|
|
|
||
|
|
tm.Send(tea.WindowSizeMsg{Width: 120, Height: 80})
|
||
|
|
tm.WaitFinished(t)
|
||
|
|
|
||
|
|
if !mockHandler.called {
|
||
|
|
t.Error("Expected WinSizeMsgHandler to be called")
|
||
|
|
}
|
||
|
|
|
||
|
|
if s.WindowWidth() != 120 {
|
||
|
|
t.Errorf("Expected state to update WindowWidth to 120, got %d", s.WindowWidth())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestModel_View_NavMode(t *testing.T) {
|
||
|
|
s := state.New(
|
||
|
|
state.WithMode(state.NavigationMode),
|
||
|
|
state.WithTiers([]core.Tier{
|
||
|
|
{Name: "S Tier", Color: lipgloss.Color("#FFFFFF"), Items: []core.Item{"Go", "Rust"}},
|
||
|
|
}),
|
||
|
|
state.WithCursor(0, 0),
|
||
|
|
state.WithWindowWidth(100),
|
||
|
|
state.WithMode(state.NavigationMode),
|
||
|
|
)
|
||
|
|
|
||
|
|
m := model.New(s)
|
||
|
|
|
||
|
|
output := m.View()
|
||
|
|
|
||
|
|
if !bytes.Contains([]byte(output), []byte("S Tier")) {
|
||
|
|
t.Error("View output missing tier label 'S Tier'")
|
||
|
|
}
|
||
|
|
if !bytes.Contains([]byte(output), []byte("Go")) {
|
||
|
|
t.Error("View output missing item 'Go'")
|
||
|
|
}
|
||
|
|
if bytes.Contains([]byte(output), []byte("Enter to Confirm")) {
|
||
|
|
t.Error("View output contains Input Mode text while in Nav Mode")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestModel_View_InputMode(t *testing.T) {
|
||
|
|
ti := textinput.New()
|
||
|
|
ti.SetValue("Test Value")
|
||
|
|
|
||
|
|
s := state.New(
|
||
|
|
state.WithMode(state.InputMode),
|
||
|
|
state.WithInput(ti, "Create New Item"),
|
||
|
|
)
|
||
|
|
|
||
|
|
m := model.New(s)
|
||
|
|
output := m.View()
|
||
|
|
|
||
|
|
if !bytes.Contains([]byte(output), []byte("Create New Item")) {
|
||
|
|
t.Error("View output missing Input Title")
|
||
|
|
}
|
||
|
|
if !bytes.Contains([]byte(output), []byte("Test Value")) {
|
||
|
|
t.Error("View output missing input value")
|
||
|
|
}
|
||
|
|
if !bytes.Contains([]byte(output), []byte("Esc to Cancel")) {
|
||
|
|
t.Error("View output missing input help text")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestModel_Init(t *testing.T) {
|
||
|
|
s := state.New()
|
||
|
|
m := model.New(s)
|
||
|
|
|
||
|
|
cmd := m.Init()
|
||
|
|
|
||
|
|
if cmd == nil {
|
||
|
|
t.Error("Init should return a command (blink), got nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
type MockKeyHandler struct {
|
||
|
|
called bool
|
||
|
|
shouldMatch bool
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *MockKeyHandler) KeysHandled() []string {
|
||
|
|
return []string{"q"}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *MockKeyHandler) Description() string {
|
||
|
|
return "Mock Quit Handler"
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *MockKeyHandler) Match(s state.State, msg tea.KeyMsg) bool {
|
||
|
|
return m.shouldMatch
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *MockKeyHandler) Handle(s state.State, msg tea.KeyMsg) tea.Cmd {
|
||
|
|
m.called = true
|
||
|
|
return tea.Quit
|
||
|
|
}
|
||
|
|
|
||
|
|
type MockWinHandler struct {
|
||
|
|
called bool
|
||
|
|
shouldMatch bool
|
||
|
|
targetWidth int
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *MockWinHandler) Match(s state.State, msg tea.WindowSizeMsg) bool {
|
||
|
|
return m.shouldMatch
|
||
|
|
}
|
||
|
|
|
||
|
|
func (m *MockWinHandler) Handle(s state.State, msg tea.WindowSizeMsg) tea.Cmd {
|
||
|
|
m.called = true
|
||
|
|
s.SetWindowSize(msg.Width, msg.Height)
|
||
|
|
return tea.Quit
|
||
|
|
}
|