mirror of
https://github.com/ollama/ollama.git
synced 2026-08-27 04:06:17 +00:00
252 lines
6.7 KiB
Go
252 lines
6.7 KiB
Go
package tui
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
)
|
|
|
|
func TestConfirmModel_DefaultsToYes(t *testing.T) {
|
|
m := confirmModel{prompt: "Download test?", yes: true}
|
|
if !m.yes {
|
|
t.Error("should default to yes")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_View_ContainsPrompt(t *testing.T) {
|
|
m := confirmModel{prompt: "Download qwen3:8b?", yes: true}
|
|
got := m.View()
|
|
if !strings.Contains(got, "Download qwen3:8b?") {
|
|
t.Error("should contain the prompt text")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_View_PlainPromptDoesNotStylePrompt(t *testing.T) {
|
|
m := confirmModel{prompt: "Sign in?", yes: true, plain: true}
|
|
got := m.View()
|
|
promptBlock := strings.SplitN(got, "\n\n", 2)[0]
|
|
if strings.Contains(promptBlock, "\x1b[") {
|
|
t.Fatalf("plain prompt should not include ANSI styling: %q", promptBlock)
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_View_WrapsPromptToWidth(t *testing.T) {
|
|
m := confirmModel{
|
|
prompt: "Sign in to use web search and cloud models with Ollama, Claude Code, OpenClaw, Hermes and more?\n\nYou can keep using local models without signing in.",
|
|
yes: true,
|
|
width: 52,
|
|
plain: true,
|
|
}
|
|
|
|
got := stripANSI(m.View())
|
|
if !strings.Contains(got, "Hermes and more?") {
|
|
t.Fatalf("wrapped prompt lost trailing text:\n%s", got)
|
|
}
|
|
for _, line := range strings.Split(got, "\n") {
|
|
if len(line) > m.width {
|
|
t.Fatalf("line width = %d, want <= %d: %q\n%s", len(line), m.width, line, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_View_ContainsButtons(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true}
|
|
got := m.View()
|
|
if !strings.Contains(got, "Yes") {
|
|
t.Error("should contain Yes button")
|
|
}
|
|
if !strings.Contains(got, "No") {
|
|
t.Error("should contain No button")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_View_ContainsCustomButtons(t *testing.T) {
|
|
m := confirmModel{
|
|
prompt: "Connect a messaging app now?",
|
|
yesLabel: "Yes",
|
|
noLabel: "Set up later",
|
|
yes: true,
|
|
}
|
|
got := m.View()
|
|
if !strings.Contains(got, "Yes") {
|
|
t.Error("should contain custom yes button")
|
|
}
|
|
if !strings.Contains(got, "Set up later") {
|
|
t.Error("should contain custom no button")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_View_ContainsHelp(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true}
|
|
got := m.View()
|
|
if !strings.Contains(got, "enter confirm") {
|
|
t.Error("should contain help text")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_View_ClearsAfterConfirm(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", confirmed: true}
|
|
if m.View() != "" {
|
|
t.Error("View should return empty string after confirmation")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_View_ClearsAfterCancel(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", cancelled: true}
|
|
if m.View() != "" {
|
|
t.Error("View should return empty string after cancellation")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_EnterConfirmsYes(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true}
|
|
updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
|
|
fm := updated.(confirmModel)
|
|
if !fm.confirmed {
|
|
t.Error("enter should set confirmed=true")
|
|
}
|
|
if !fm.yes {
|
|
t.Error("enter with yes selected should keep yes=true")
|
|
}
|
|
if cmd == nil {
|
|
t.Error("enter should return tea.Quit")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_EnterConfirmsNo(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: false}
|
|
updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
|
|
fm := updated.(confirmModel)
|
|
if !fm.confirmed {
|
|
t.Error("enter should set confirmed=true")
|
|
}
|
|
if fm.yes {
|
|
t.Error("enter with no selected should keep yes=false")
|
|
}
|
|
if cmd == nil {
|
|
t.Error("enter should return tea.Quit")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_EscCancels(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true}
|
|
updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyEsc})
|
|
fm := updated.(confirmModel)
|
|
if !fm.cancelled {
|
|
t.Error("esc should set cancelled=true")
|
|
}
|
|
if cmd == nil {
|
|
t.Error("esc should return tea.Quit")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_CtrlCCancels(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true}
|
|
updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyCtrlC})
|
|
fm := updated.(confirmModel)
|
|
if !fm.cancelled {
|
|
t.Error("ctrl+c should set cancelled=true")
|
|
}
|
|
if cmd == nil {
|
|
t.Error("ctrl+c should return tea.Quit")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_NDoesNothing(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true}
|
|
updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'n'}})
|
|
fm := updated.(confirmModel)
|
|
if fm.cancelled {
|
|
t.Error("'n' should not cancel")
|
|
}
|
|
if fm.confirmed {
|
|
t.Error("'n' should not confirm")
|
|
}
|
|
if cmd != nil {
|
|
t.Error("'n' should not quit")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_YDoesNothing(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: false}
|
|
updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'y'}})
|
|
fm := updated.(confirmModel)
|
|
if fm.confirmed {
|
|
t.Error("'y' should not confirm")
|
|
}
|
|
if fm.yes {
|
|
t.Error("'y' should not change selection")
|
|
}
|
|
if cmd != nil {
|
|
t.Error("'y' should not quit")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_ArrowKeysNavigate(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true}
|
|
|
|
// Right moves to No
|
|
updated, _ := m.Update(tea.KeyMsg{Type: tea.KeyRight})
|
|
fm := updated.(confirmModel)
|
|
if fm.yes {
|
|
t.Error("right should move to No")
|
|
}
|
|
if fm.confirmed || fm.cancelled {
|
|
t.Error("navigation should not confirm or cancel")
|
|
}
|
|
|
|
// Left moves back to Yes
|
|
updated, _ = fm.Update(tea.KeyMsg{Type: tea.KeyLeft})
|
|
fm = updated.(confirmModel)
|
|
if !fm.yes {
|
|
t.Error("left should move to Yes")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_TabDoesNothing(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true}
|
|
|
|
updated, _ := m.Update(tea.KeyMsg{Type: tea.KeyTab})
|
|
fm := updated.(confirmModel)
|
|
if !fm.yes {
|
|
t.Error("tab should not change selection")
|
|
}
|
|
if fm.confirmed || fm.cancelled {
|
|
t.Error("tab should not confirm or cancel")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_WindowSizeUpdatesWidth(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?"}
|
|
updated, _ := m.Update(tea.WindowSizeMsg{Width: 100, Height: 40})
|
|
fm := updated.(confirmModel)
|
|
if fm.width != 100 {
|
|
t.Errorf("expected width 100, got %d", fm.width)
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_ResizeEntersAltScreen(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", width: 80}
|
|
_, cmd := m.Update(tea.WindowSizeMsg{Width: 100, Height: 40})
|
|
if cmd == nil {
|
|
t.Error("resize (width already set) should return a command")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_InitialWindowSizeNoAltScreen(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?"}
|
|
_, cmd := m.Update(tea.WindowSizeMsg{Width: 80, Height: 40})
|
|
if cmd != nil {
|
|
t.Error("initial WindowSizeMsg should not return a command")
|
|
}
|
|
}
|
|
|
|
func TestConfirmModel_ViewMaxWidth(t *testing.T) {
|
|
m := confirmModel{prompt: "Download?", yes: true, width: 40}
|
|
got := m.View()
|
|
// Just ensure it doesn't panic and returns content
|
|
if got == "" {
|
|
t.Error("View with width set should still return content")
|
|
}
|
|
}
|