Files
ZacharyZhang-NY 03680980da Add data components 151-175; clear MyGo row highlights
Lists, tables, trees, grids, inventories and records in data/.
Outline and GridView build on ui.List: ui.Outline strokes its arrows
and ui.GridView spaces and tints items. The pixel theme keeps MyGo's
row highlights clear so scrolled rows stay on whole dots; off lists
take a veil against the wheel. Adds Canvas.Silhouette, SwitchOptions
Label and exports Rarity.Slot.
2026-10-11 22:29:07 -04:00

222 lines
6.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package data_test
import (
"slices"
"testing"
"time"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/data"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
)
func TestCollapsibleShowsContentWhileOpen(t *testing.T) {
open, changes := false, 0
tt := view(300, 200, newClock(), false, func(c *ui.Context) {
if data.Collapsible(c, "Secrets", &open, data.CollapsibleOptions{}, func() {
pixel.Text(c, "Konami", pixel.TextOptions{})
}).Changed {
changes++
}
})
if shows(tt, "Konami") {
t.Fatal("closed content shows")
}
click(t, tt, "Secrets")
if !open || !shows(tt, "Konami") {
t.Fatal("a click did not open it")
}
tt.Key(0, ui.KeyEnter)
if open || shows(tt, "Konami") || changes != 2 {
t.Fatalf("Enter left open %v, %d changes", open, changes)
}
keeps(t, tt.Image())
}
func TestAccordionKeepsOneOpenUnlessMany(t *testing.T) {
for _, many := range []bool{false, true} {
open := []bool{true, false, false}
tt := view(300, 300, newClock(), false, func(c *ui.Context) {
data.Accordion(c, "Help", []string{"Move", "Jump", "Save"}, open, data.AccordionOptions{Many: many}, func(i int) {
pixel.Text(c, []string{"Arrows", "Space", "Start"}[i], pixel.TextOptions{})
})
})
click(t, tt, "Save")
want := []bool{many, false, true}
if !slices.Equal(open, want) || shows(tt, "Arrows") != many || !shows(tt, "Start") {
t.Fatalf("many %v: open %v", many, open)
}
}
}
func TestCollapsibleOffStaysPut(t *testing.T) {
for _, inert := range []bool{false, true} {
open := false
tt := view(300, 200, newClock(), inert, func(c *ui.Context) {
data.Collapsible(c, "Secrets", &open, data.CollapsibleOptions{Disabled: !inert}, func() {})
})
click(t, tt, "Secrets")
if open {
t.Fatalf("inert %v: a click opened it", inert)
}
}
}
func deck(c *ui.Context, page *int, o data.CarouselOptions, changes *int) {
if data.Carousel(c, "Tips", 3, page, o, func(i int) {
pixel.Text(c, []string{"Tip A", "Tip B", "Tip C"}[i], pixel.TextOptions{})
}).Changed {
*changes++
}
}
func TestCarouselTurnsAndWraps(t *testing.T) {
page, changes := 0, 0
tt := view(300, 200, newClock(), false, func(c *ui.Context) { deck(c, &page, data.CarouselOptions{}, &changes) })
click(t, tt, "PREVIOUS")
if page != 2 || !shows(tt, "Tip C") {
t.Fatalf("◀ from the first page went to %d", page)
}
click(t, tt, "NEXT")
click(t, tt, "NEXT")
if page != 1 || !shows(tt, "Tip B") || changes != 3 {
t.Fatalf("▶ ▶ went to %d, %d changes", page, changes)
}
keeps(t, tt.Image())
}
func TestCarouselTurnsByItselfUnlessReduced(t *testing.T) {
for _, reduce := range []bool{false, true} {
clk, page, changes := newClock(), 0, 0
tt := view(300, 200, clk, false, func(c *ui.Context) { deck(c, &page, data.CarouselOptions{Every: 3}, &changes) })
if reduce {
tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1})
}
tt.Move(599, 399)
clk.t = clk.t.Add(2 * time.Second)
tt.Frame()
if page != 0 {
t.Fatalf("reduce %v: turned after 2 s", reduce)
}
clk.t = clk.t.Add(time.Second)
tt.Frame()
if want := map[bool]int{false: 1, true: 0}[reduce]; page != want || !shows(tt, []string{"Tip A", "Tip B"}[want]) {
t.Fatalf("reduce %v: page %d after 3 s", reduce, page)
}
}
}
func TestCarouselWaitsUnderThePointer(t *testing.T) {
clk, page, changes := newClock(), 0, 0
tt := view(300, 200, clk, false, func(c *ui.Context) { deck(c, &page, data.CarouselOptions{Every: 1}, &changes) })
r := find(t, tt, "Tip A")
tt.Move(r.X+2, r.Y+2)
clk.t = clk.t.Add(5 * time.Second)
tt.Frame()
if page != 0 {
t.Fatalf("turned to %d under the pointer", page)
}
}
func TestPagerStepsAndResizes(t *testing.T) {
page, size, changes := 0, 20, 0
total := 312
tt := view(500, 100, newClock(), false, func(c *ui.Context) {
if data.Pager(c, "Pages", total, &page, &size, data.PagerOptions{}).Changed {
changes++
}
})
if !tt.HasText("1–20 OF 312") {
t.Fatalf("texts %q", tt.Texts())
}
click(t, tt, "NEXT")
if page != 1 || !tt.HasText("21–40 OF 312") {
t.Fatalf("▶ went to page %d", page)
}
click(t, tt, "50")
if size != 50 || page != 0 || !tt.HasText("1–50 OF 312") {
t.Fatalf("size 50 left page %d size %d", page, size)
}
page = 6
tt.Frame()
if !tt.HasText("301–312 OF 312") {
t.Fatalf("last page texts %q", tt.Texts())
}
total = 40
tt.Frame()
if page != 0 || changes != 3 {
t.Fatalf("a shorter total left page %d, %d changes", page, changes)
}
}
func TestFilterBarTogglesAndClears(t *testing.T) {
on := []bool{false, false, false}
changes := 0
tt := view(400, 100, newClock(), false, func(c *ui.Context) {
if data.FilterBar(c, "Filters", []string{"Fire", "Ice", "Bolt"}, on, data.FilterBarOptions{}).Changed {
changes++
}
})
click(t, tt, "CLEAR")
if changes != 0 {
t.Fatal("CLEAR worked with nothing on")
}
click(t, tt, "Fire")
click(t, tt, "Bolt")
if !slices.Equal(on, []bool{true, false, true}) {
t.Fatalf("chips left %v", on)
}
click(t, tt, "CLEAR")
if slices.Contains(on, true) || changes != 3 {
t.Fatalf("CLEAR left %v, %d changes", on, changes)
}
}
func TestPropertyGridEditsEachKind(t *testing.T) {
name, speed, fly := "Aria", 3.0, false
changes := 0
props := []data.Property{{Name: "Name", Text: &name}, {Name: "Speed", Number: &speed}, {Name: "Fly", Switch: &fly}}
tt := view(400, 200, newClock(), false, func(c *ui.Context) {
if data.PropertyGrid(c, "Hero", props, data.PropertyGridOptions{}).Changed {
changes++
}
})
// The switch sits past the 80-dot name column.
r := find(t, tt, "Fly")
tt.ClickAt(r.X+180, r.Y+r.H/2)
if !fly {
t.Fatalf("the switch row did not switch: %v", r)
}
n := find(t, tt, "Name")
tt.ClickAt(n.X+380, n.Y+n.H/2)
tt.Type("!")
if name != "Aria!" || changes != 2 {
t.Fatalf("typing gave %q, %d changes", name, changes)
}
defer func() {
if recover() == nil {
t.Fatal("a row with two values did not panic")
}
}()
view(400, 200, newClock(), false, func(c *ui.Context) {
data.PropertyGrid(c, "Bad", []data.Property{{Name: "Both", Text: &name, Switch: &fly}}, data.PropertyGridOptions{})
})
}
func TestPagerRefusesBadSizes(t *testing.T) {
for _, sizes := range [][]int{{20, 0}, {20, -5}} {
func() {
defer func() {
if recover() == nil {
t.Fatalf("sizes %v did not panic", sizes)
}
}()
page, size := 0, 20
view(400, 100, newClock(), false, func(c *ui.Context) {
data.Pager(c, "Pages", 50, &page, &size, data.PagerOptions{Sizes: sizes})
})
}()
}
}