Files
MujicaUI/conversation_list_test.go
T
2026-10-05 14:24:42 -04:00

115 lines
3.4 KiB
Go

package mujica
import (
"fmt"
"slices"
"testing"
"time"
"github.com/egoist/mygo/ui"
)
func chatTester(w, h int, view func(c *ui.Context)) *ui.Tester {
return ui.NewTester(func(c *ui.Context) {
Use(c, Settings{})
ui.Column(c).Padding(10).Fill().Children(func() { view(c) })
}, w, h)
}
func TestConversationListGroups(t *testing.T) {
var s ConversationListState
items := chatConversations()
tt := chatTester(400, 600, func(c *ui.Context) {
ConversationList(c, &s, items, ConversationListOptions{Now: chatNow}, nil).Element.Height(560)
})
want := []string{"Pinned", "Royal letters", "Today", "Garden maze", "Court etiquette notes", "Yesterday",
"Ballroom seating plan", "Previous 7 days", "Harpsichord repair", "Older", "Coronation menu"}
got := slices.Compact(slices.DeleteFunc(tt.Texts(), func(s string) bool { return !slices.Contains(want, s) }))
if !slices.Equal(got, want) {
t.Fatalf("rows %q", got)
}
}
func TestConversationListSelectAndKeys(t *testing.T) {
var s ConversationListState
items := chatConversations()
changes, opened := 0, 0
tt := chatTester(400, 600, func(c *ui.Context) {
v := ConversationList(c, &s, items, ConversationListOptions{Now: chatNow, Label: "History"}, nil)
v.Element.Height(560)
if v.Changed() {
changes++
}
if v.Submitted() {
opened++
}
})
if err := tt.Click("Garden maze"); err != nil {
t.Fatal(err)
}
if s.Selected != "f" || changes != 1 {
t.Fatalf("selected %q changes %d", s.Selected, changes)
}
tt.Key(0, ui.KeyDown)
if s.Selected != "a" {
t.Fatalf("Down chose %q", s.Selected)
}
tt.Key(0, ui.KeyDown)
if s.Selected != "b" {
t.Fatalf("Down over a header chose %q", s.Selected)
}
tt.Key(0, ui.KeyEnter)
if opened != 1 {
t.Fatalf("Enter opened %d", opened)
}
}
func TestConversationListDisabled(t *testing.T) {
var s ConversationListState
items := chatConversations()
tt := chatTester(400, 600, func(c *ui.Context) {
ConversationList(c, &s, items, ConversationListOptions{Now: chatNow, Disabled: true}, nil).Element.Height(560)
})
_ = tt.Click("Garden maze")
tt.Key(0, ui.KeyTab)
tt.Key(0, ui.KeyDown)
if s.Selected != "" {
t.Fatalf("disabled list chose %q", s.Selected)
}
}
func TestConversationListVirtualizesAndGroupsOnce(t *testing.T) {
items := make([]ChatConversation, 100000)
for i := range items {
items[i] = ChatConversation{ID: fmt.Sprint(i), Title: fmt.Sprintf("Conversation %d", i), Updated: chatNow.Add(-time.Duration(i) * time.Minute)}
}
var s ConversationListState
tt := chatTester(400, 600, func(c *ui.Context) {
ConversationList(c, &s, items, ConversationListOptions{Now: chatNow}, nil).Element.Height(560)
})
if n := len(tt.Texts()); n > 80 {
t.Fatalf("built %d texts for 100000 conversations", n)
}
// A marked plan survives frames that bring no new data.
s.plan.rows[1].item = -7
tt.Frame()
if s.plan.rows[1].item != -7 {
t.Fatal("regrouped without a data change")
}
s.plan.rows[1].item = 0
// Today, Yesterday, Previous 7 days and Older head the rows.
if len(s.plan.rows) != len(items)+4 {
t.Fatalf("%d rows", len(s.plan.rows))
}
}
func TestConversationListSnapshot(t *testing.T) {
items := chatConversations()
snapshot(t, "conversation_list", 360, 420, func(c *ui.Context) {
s := &ConversationListState{Selected: "b"}
ui.Column(c).Padding(16).Children(func() {
ConversationList(c, s, items, ConversationListOptions{Now: chatNow, Label: "History"}, nil).Element.Height(380)
})
})
}