Every component result type now names its element Element instead of embedding *ui.Element. The eleven element-plus-changed results (AccordionView, CarouselView, CollapsibleView, ImageViewerView, PaginationResult, StepsResult, SidebarResult, TabsResult, RatingParts, FileDropZoneParts, TransferParts) fold into ChoiceResult. Fixes four Gallery demos where .Width(...).Changed() read the element's flag instead of the component's: Accordion, MultiSelect, Cascader, TreeSelect. TestDataAccordionDemoLogsChange covers the Accordion.
174 lines
4.5 KiB
Go
174 lines
4.5 KiB
Go
package mujica
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/egoist/mygo/ui"
|
|
|
|
"mujicaui/icons"
|
|
)
|
|
|
|
func sidebarSample() []SidebarSection {
|
|
return []SidebarSection{
|
|
{Title: "Library", Items: []SidebarItem{
|
|
{ID: "inbox", Label: "Inbox", Icon: icons.Must("inbox"), Count: 12},
|
|
{ID: "starred", Label: "Starred", Icon: icons.Must("star")},
|
|
{Label: "Projects", Items: []SidebarItem{
|
|
{ID: "opera", Label: "Opera", Icon: icons.Must("folder")},
|
|
{ID: "ballet", Label: "Ballet", Icon: icons.Must("folder")},
|
|
}},
|
|
}},
|
|
{Title: "System", Items: []SidebarItem{
|
|
{ID: "settings", Label: "Settings", Icon: icons.Must("settings")},
|
|
}},
|
|
}
|
|
}
|
|
|
|
func TestSidebarChooseAndKeys(t *testing.T) {
|
|
sel, changes := "inbox", 0
|
|
tt := ui.NewTester(func(c *ui.Context) {
|
|
Use(c, Settings{})
|
|
if Sidebar(c, &sel, sidebarSample(), SidebarOptions{}).Changed() {
|
|
changes++
|
|
}
|
|
}, 400, 500)
|
|
if err := tt.Click("Opera"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if sel != "opera" || changes != 1 {
|
|
t.Fatalf("click: %q %d", sel, changes)
|
|
}
|
|
tt.Key(0, ui.KeyDown)
|
|
if sel != "ballet" {
|
|
t.Fatalf("Down chose %q", sel)
|
|
}
|
|
tt.Key(0, ui.KeyEnd)
|
|
if sel != "settings" {
|
|
t.Fatalf("End chose %q", sel)
|
|
}
|
|
tt.Key(0, ui.KeyHome)
|
|
if sel != "inbox" || changes != 4 {
|
|
t.Fatalf("Home chose %q, changes %d", sel, changes)
|
|
}
|
|
}
|
|
|
|
func TestSidebarCollapse(t *testing.T) {
|
|
sel := "inbox"
|
|
tt := ui.NewTester(func(c *ui.Context) {
|
|
Use(c, Settings{})
|
|
Sidebar(c, &sel, sidebarSample(), SidebarOptions{})
|
|
}, 400, 500)
|
|
if err := tt.Click("Projects"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if tt.HasText("Opera") {
|
|
t.Fatal("nested group did not collapse")
|
|
}
|
|
if err := tt.Click("Library"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if tt.HasText("Starred") || !tt.HasText("Settings") {
|
|
t.Fatalf("section did not collapse: %q", tt.Texts())
|
|
}
|
|
_ = tt.Click("Library")
|
|
if !tt.HasText("Starred") || tt.HasText("Opera") {
|
|
t.Fatalf("collapse state lost: %q", tt.Texts())
|
|
}
|
|
}
|
|
|
|
func TestSidebarCompact(t *testing.T) {
|
|
sel := "inbox"
|
|
var w float32
|
|
tt := ui.NewTester(func(c *ui.Context) {
|
|
Use(c, Settings{})
|
|
ui.Row(c).FillHeight().Children(func() {
|
|
w = Sidebar(c, &sel, sidebarSample(), SidebarOptions{Compact: true}).Element.Bounds().W
|
|
})
|
|
}, 400, 500)
|
|
tt.Frame()
|
|
if w != 56 {
|
|
t.Fatalf("compact width %v", w)
|
|
}
|
|
if err := tt.Click("Ballet"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if sel != "ballet" {
|
|
t.Fatalf("compact click chose %q", sel)
|
|
}
|
|
if _, ok := tt.Find("Inbox (12)"); !ok {
|
|
t.Fatalf("compact item lost its name: %q", tt.Texts())
|
|
}
|
|
}
|
|
|
|
func TestSidebarInvalid(t *testing.T) {
|
|
for name, tc := range map[string]struct {
|
|
s []SidebarSection
|
|
opts SidebarOptions
|
|
}{
|
|
"title": {[]SidebarSection{{Items: []SidebarItem{{ID: "a", Label: "A"}}}}, SidebarOptions{}},
|
|
"id": {[]SidebarSection{{Title: "T", Items: []SidebarItem{{Label: "A"}}}}, SidebarOptions{}},
|
|
"compact": {[]SidebarSection{{Title: "T", Items: []SidebarItem{{ID: "a", Label: "A"}}}}, SidebarOptions{Compact: true}},
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
defer func() {
|
|
if recover() == nil {
|
|
t.Fatal("no panic")
|
|
}
|
|
}()
|
|
sel := ""
|
|
ui.Render(func(c *ui.Context) {
|
|
Use(c, Settings{})
|
|
Sidebar(c, &sel, tc.s, tc.opts)
|
|
}, 300, 300, 1)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSidebarGroupKeyboard(t *testing.T) {
|
|
sel := "inbox"
|
|
tt := ui.NewTester(func(c *ui.Context) {
|
|
Use(c, Settings{})
|
|
Sidebar(c, &sel, sidebarSample(), SidebarOptions{})
|
|
}, 400, 500)
|
|
// Tab stops: the item list, the Library title, the Projects group.
|
|
for range 3 {
|
|
tt.Key(0, ui.KeyTab)
|
|
}
|
|
tt.Key(0, ui.KeyEnter)
|
|
if tt.HasText("Opera") {
|
|
t.Fatal("Enter did not collapse the group")
|
|
}
|
|
tt.Key(0, ui.KeySpace)
|
|
if !tt.HasText("Opera") {
|
|
t.Fatal("Space did not expand the group")
|
|
}
|
|
}
|
|
|
|
func TestSidebarSameNamedGroups(t *testing.T) {
|
|
sel := "a1"
|
|
sections := []SidebarSection{
|
|
{Title: "Court", Items: []SidebarItem{{Label: "Drafts", Items: []SidebarItem{{ID: "a1", Label: "Edict"}}}}},
|
|
{Title: "Chapel", Items: []SidebarItem{{Label: "Drafts", Items: []SidebarItem{{ID: "b1", Label: "Hymn"}}}}},
|
|
}
|
|
tt := ui.NewTester(func(c *ui.Context) {
|
|
Use(c, Settings{})
|
|
Sidebar(c, &sel, sections, SidebarOptions{})
|
|
}, 400, 500)
|
|
if err := tt.Click("Drafts"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if tt.HasText("Edict") || !tt.HasText("Hymn") {
|
|
t.Fatalf("same-named groups share state: %q", tt.Texts())
|
|
}
|
|
}
|
|
|
|
func TestSidebarSnapshot(t *testing.T) {
|
|
snapshot(t, "sidebar", 420, 360, func(c *ui.Context) {
|
|
a, b := "opera", "starred"
|
|
ui.Row(c).Fill().Gap(24).Children(func() {
|
|
Sidebar(c, &a, sidebarSample(), SidebarOptions{})
|
|
Sidebar(c, &b, sidebarSample(), SidebarOptions{Compact: true})
|
|
})
|
|
})
|
|
}
|