package cli import ( "strings" "testing" tea "github.com/charmbracelet/bubbletea" ) func typeIn(m tea.Model, s string) tea.Model { return send(m, tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune(s)}) } func TestTheInitFormBecomesInitsSettings(t *testing.T) { in := &serverInit{pkiDir: "/etc/llmgw/pki"} var m tea.Model = newInitModel(in, []string{"10.0.0.140"}, true) if v := m.View(); !strings.Contains(v, "Already in the certificate: 10.0.0.140") { t.Fatalf("the addresses found are not shown:\n%s", v) } m = typeIn(m, "ops@example.com") m = send(m, tea.KeyMsg{Type: tea.KeyTab}) m = typeIn(m, "llm.example.com, 203.0.113.10") m = send(m, tea.KeyMsg{Type: tea.KeyTab}, tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune(" ")}) // PostgreSQL on m = send(m, tea.KeyMsg{Type: tea.KeyTab}, tea.KeyMsg{Type: tea.KeyTab}, tea.KeyMsg{Type: tea.KeyTab}, tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune(" ")}) // starter model off m = send(m, tea.KeyMsg{Type: tea.KeyTab}, tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune(" ")}) // judge off m = send(m, tea.KeyMsg{Type: tea.KeyTab}, tea.KeyMsg{Type: tea.KeyEnter}) if in.admin != "ops@example.com" || strings.Join(in.hosts, "|") != "llm.example.com|203.0.113.10" { t.Errorf("admin %q hosts %q", in.admin, in.hosts) } if !in.postgres || in.noMirror || in.noNode || !in.noModel || !in.noGuardModel { t.Errorf("toggles: postgres %v mirror %v node %v model %v", in.postgres, !in.noMirror, !in.noNode, !in.noModel) } if m.(initModel).form { t.Error("the form stayed up after Set up") } } func TestAnEmailThatIsNotOneIsSaidSo(t *testing.T) { in := &serverInit{} var m tea.Model = newInitModel(in, nil, true) m = typeIn(m, "not an address") for range fStart { m = send(m, tea.KeyMsg{Type: tea.KeyTab}) } m = send(m, tea.KeyMsg{Type: tea.KeyEnter}) if !m.(initModel).form || !strings.Contains(m.View(), "not an address") { t.Errorf("a bad email was accepted:\n%s", m.View()) } } func TestInitsLinesAreFiledAndThePasswordKeptInView(t *testing.T) { in := &serverInit{admin: "ops@example.com", pkiDir: "/etc/llmgw/pki"} var m tea.Model = newInitModel(in, nil, false) for _, l := range []string{ " ok system user llmgw", " kept certificate authority in /etc/llmgw/pki", " ok administrator ops@example.com (u1)", "", " password: Tr0ub4dor-3", " shown once — sign in and change it from /profile", "", " .. downloading qwen2.5-0.5b-instruct into the mirror", " .. 40%", " .. 80%", " !! an NVIDIA card is on the PCI bus but nvidia-smi does not answer", "The control plane is up. Next:", " llmgw ctl status", } { m = send(m, initLineMsg(l)) } m = send(m, initDoneMsg{}) im := m.(initModel) if im.password != "Tr0ub4dor-3" { t.Errorf("password %q", im.password) } v := m.View() for _, want := range []string{"✓ system user llmgw", "Tr0ub4dor-3", "Shown once", "80%", "! an NVIDIA card", "Back up /etc/llmgw/pki", "node add"} { if !strings.Contains(v, want) { t.Errorf("screen lacks %q:\n%s", want, v) } } if strings.Contains(v, "40%") { t.Error("progress lines piled up instead of replacing each other") } if strings.Contains(v, "llmgw ctl status") { t.Error("the closing text was listed as a step") } } func TestWithAMirrorElsewhereTheFormDoesNotOfferOne(t *testing.T) { in := &serverInit{mirrorURL: "http://10.0.0.150:8082"} var m tea.Model = newInitModel(in, nil, true) if v := m.View(); !strings.Contains(v, "at http://10.0.0.150:8082, from --mirror") { t.Errorf("the mirror in use is not shown:\n%s", v) } // Tab from the addresses goes past the mirror line to PostgreSQL, then // the node. m = send(m, tea.KeyMsg{Type: tea.KeyTab}, tea.KeyMsg{Type: tea.KeyTab}, tea.KeyMsg{Type: tea.KeyTab}) if f := m.(initModel).focus; f != fNode { t.Errorf("focus %d, want the node toggle %d", f, fNode) } }