Files
MujicaUI/display/image_state_test.go
T

142 lines
4.1 KiB
Go

package display
import (
"errors"
"testing"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/core"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/theme"
)
func TestImageErrorTextNeedsRoom(t *testing.T) {
for _, tc := range []struct {
w float32
text bool
}{{200, true}, {80, false}} {
ready := false
tt := ui.NewTester(func(c *ui.Context) {
core.Use(c, core.Settings{})
if ready {
Image(c, nil, ImageOptions{Width: tc.w, Height: 60, Err: errors.New("404")})
}
}, 300, 200)
ready = true
tt.Frame()
n := 0
for _, s := range tt.Texts() {
if s == "Image failed to load" {
n++
}
}
// One is the box's name; a second is the visible text.
if got := n == 2; got != tc.text {
t.Errorf("width %v: error text shown %v, want %v (%v)", tc.w, got, tc.text, tt.Texts())
}
}
}
// imageStateBoxes returns the box of loaded, loading and error states.
func imageStateBoxes(t *testing.T, opts ImageOptions, parent func(c *ui.Context, fn func())) []ui.Rect {
t.Helper()
bmp := imageTestBitmap()
var got []ui.Rect
for _, state := range []ImageOptions{{}, {Loading: true}, {Err: errors.New("x")}} {
o := opts
o.Loading, o.Err = state.Loading, state.Err
var r ui.Rect
tt := ui.NewTester(func(c *ui.Context) {
core.Use(c, core.Settings{})
parent(c, func() { r = Image(c, bmp, o).Element.Bounds() })
}, 400, 400)
tt.Frame()
got = append(got, r)
}
return got
}
func TestImageStatesShareBoxInColumn(t *testing.T) {
got := imageStateBoxes(t, ImageOptions{}, func(c *ui.Context, fn func()) {
ui.Column(c).Width(200).Children(fn)
})
if got[0].W != 200 || got[0].H != 100 || got[1] != got[0] || got[2] != got[0] {
t.Fatalf("loaded, loading, error boxes %v", got)
}
}
func TestImageStatesShareBoxInSizedParent(t *testing.T) {
got := imageStateBoxes(t, ImageOptions{}, func(c *ui.Context, fn func()) {
ui.Column(c).Size(120, 60).Children(fn)
})
if got[0].W != 120 || got[1] != got[0] || got[2] != got[0] {
t.Fatalf("loaded, loading, error boxes %v", got)
}
}
func TestImageStatesShareExplicitSize(t *testing.T) {
got := imageStateBoxes(t, ImageOptions{Width: 120, Height: 60}, func(c *ui.Context, fn func()) {
ui.Column(c).Width(300).Children(fn)
})
if got[0].W != 120 || got[0].H != 60 || got[1] != got[0] || got[2] != got[0] {
t.Fatalf("loaded, loading, error boxes %v", got)
}
}
func TestImageStatesShareBoxInNarrowRow(t *testing.T) {
got := imageStateBoxes(t, ImageOptions{}, func(c *ui.Context, fn func()) {
ui.Row(c).Width(40).AlignItems(ui.Start).Children(fn)
})
if got[0].W != 40 || got[0].H != 20 || got[1] != got[0] || got[2] != got[0] {
t.Fatalf("loaded, loading, error boxes %v", got)
}
}
func TestImageRetryUnclippedInSmallBox(t *testing.T) {
retries := 0
var box ui.Rect
tt := ui.NewTester(func(c *ui.Context) {
core.Use(c, core.Settings{Mode: core.Light})
ui.Row(c).Padding(40).AlignItems(ui.Start).Children(func() {
ui.Row(c).Width(40).AlignItems(ui.Start).Children(func() {
v := Image(c, imageTestBitmap(), ImageOptions{Err: errors.New("timeout")})
box = v.Element.Bounds()
if v.Retry {
retries++
}
})
})
}, 300, 200)
tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1})
if box.W != 40 || box.H != 20 {
t.Fatalf("box %v", box)
}
r, ok := tt.Find("Retry")
if !ok || r.W != 28 || r.H != 28 {
t.Fatalf("retry bounds %v", r)
}
tt.ClickAt(r.X+r.W/2, r.Y+r.H/2)
if retries != 1 {
t.Fatalf("retries %d, want 1", retries)
}
cx := int(r.X + r.W/2)
ring := func() (above, below ui.Color) {
img := tt.Image()
a := img.RGBAAt(cx, int(r.Y-theme.FocusGap-theme.FocusWidth/2))
b := img.RGBAAt(cx, int(r.Y+r.H+theme.FocusGap+theme.FocusWidth/2))
return ui.Color{R: a.R, G: a.G, B: a.B, A: a.A}, ui.Color{R: b.R, G: b.G, B: b.B, A: b.A}
}
tt.Key(0, ui.KeyTab)
if !tt.Focused("Retry") {
t.Fatal("retry not focused")
}
above, below := ring()
want := theme.Light().Focus
if above != want || below != want {
t.Fatalf("ring above %v below %v, want %v", above, below, want)
}
if r.Y-theme.FocusGap >= box.Y || r.Y+r.H+theme.FocusGap <= box.Y+box.H {
t.Fatalf("ring rows not outside box %v (retry %v)", box, r)
}
}