Files
8bitMyGoUI/input/form_test.go
T

224 lines
6.6 KiB
Go

package input_test
import (
"math"
"testing"
"time"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
)
func TestEditableTextEnterKeepsEscapeReverts(t *testing.T) {
hero, changes := "Hero", 0
tt := view(400, 200, nil, func(c *ui.Context) {
input.Button(c, "before", input.ButtonOptions{})
if input.EditableText(c, "Name", &hero, input.EditableTextOptions{}).Changed {
changes++
}
})
click(t, tt, "before")
tt.Key(0, ui.KeyTab)
tt.Key(0, ui.KeyEnter)
if _, ok := tt.TextCaret(); !ok {
t.Fatal("Enter did not open a field")
}
tt.Key(ui.Cmd, ui.KeyA)
tt.Type("Zed")
tt.Key(0, ui.KeyEnter)
if hero != "Zed" || changes != 1 || !tt.Focused("Name") {
t.Fatalf("Enter kept %q after %d changes, focus back %v", hero, changes, tt.Focused("Name"))
}
if _, ok := tt.TextCaret(); ok {
t.Fatal("the field stayed open")
}
r := find(t, tt, "Name")
tt.ClickAt(r.X+r.W/2, r.Y+r.H/2)
tt.ClickAt(r.X+r.W/2, r.Y+r.H/2)
if _, ok := tt.TextCaret(); !ok {
t.Fatal("a double click did not open the field")
}
tt.Type("ox")
tt.Key(0, ui.KeyEscape)
if hero != "Zed" || changes != 1 {
t.Fatalf("Escape kept %q", hero)
}
if _, ok := tt.TextCaret(); ok {
t.Fatal("a double click did not open the field, or Escape left it open")
}
}
func TestFieldAndFieldsetLayOutTheirNotes(t *testing.T) {
name := ""
tt := view(400, 300, nil, func(c *ui.Context) {
input.Fieldset(c, "Hero", input.FieldsetOptions{}, func() {
input.Field(c, "Call sign", input.FieldOptions{Description: "Shown on the board.", Error: "Taken!"}, func() {
input.TextInput(c, "sign", &name, input.TextInputOptions{})
})
})
})
label, field, note, bad := find(t, tt, "Call sign"), find(t, tt, "sign"), find(t, tt, "Shown on the board."), find(t, tt, "Taken!")
if !(label.Y < field.Y && field.Y < note.Y && note.Y < bad.Y) {
t.Fatal("not label, control, description, error from top down")
}
if !has(slots(t, tt.Image(), ui.Rect{X: bad.X - 30, Y: bad.Y, W: 30, H: bad.H}), pixel.Bad) {
t.Fatal("the error has no Bad sign")
}
set := find(t, tt, "Hero")
if !has(slots(t, tt.Image(), ui.Rect{X: set.X, Y: set.Y, W: set.W, H: 2 * pixel.LineHeight}), pixel.Accent) || label.X <= set.X {
t.Fatal("the fieldset has no legend, or its fields sit on its edge")
}
}
func TestColorSlotPicks(t *testing.T) {
slot, changes := pixel.Slot(3), 0
tt := view(400, 200, nil, func(c *ui.Context) {
if input.ColorSlot(c, "Paint", &slot, input.ColorSlotOptions{}).Changed {
changes++
}
})
at(t, tt, "Paint", 6, 12+6)
if slot != pixel.Slot(8) {
t.Fatalf("a click on the ninth cell gave %v", slot)
}
tt.Key(0, ui.KeyUp)
tt.Key(0, ui.KeyRight)
if slot != pixel.Slot(1) || changes != 3 {
t.Fatalf("Up, Right gave %v after %d changes", slot, changes)
}
}
func TestJoystickDragsNudgesAndSprings(t *testing.T) {
clk := &clock{time.Unix(3_000_000, 0)}
var x, y float64
tt := view(400, 200, clk, func(c *ui.Context) {
r := input.Joystick(c, "Stick", input.JoystickOptions{})
x, y = r.X, r.Y
})
r := find(t, tt, "Stick")
cx, cy := r.X+r.W/2, r.Y+r.H/2
tt.Press(cx, cy)
tt.Move(cx+60, cy)
if math.Abs(x-1) > 1e-9 || y != 0 {
t.Fatalf("dragging far right gave %v, %v", x, y)
}
tt.Move(cx, cy-12)
if math.Abs(y+0.5) > 1e-9 {
t.Fatalf("dragging up half way gave y %v", y)
}
tt.Release(cx, cy-12)
if x != 0 || y != 0 {
t.Fatal("letting go did not spring back")
}
tt.Key(0, ui.KeyDown)
tt.Key(0, ui.KeyDown)
if y != 0.5 {
t.Fatalf("two nudges gave y %v", y)
}
clk.t = clk.t.Add(time.Second)
tt.Frame()
if y != 0 {
t.Fatal("a nudge did not spring back")
}
}
func TestCheatCodeUnlocks(t *testing.T) {
unlocked := 0
tt := view(400, 200, nil, func(c *ui.Context) {
if input.CheatCode(c, "Cheat", input.CheatCodeOptions{}).Unlocked {
unlocked++
}
})
click(t, tt, "Cheat")
r := find(t, tt, "Cheat")
if has(slots(t, tt.Image(), r), pixel.Accent) {
t.Fatal("an empty trail is lit")
}
for _, k := range []ui.Key{ui.KeyUp, ui.KeyUp, ui.KeyUp, ui.KeyDown, ui.KeyDown, ui.KeyLeft, ui.KeyRight, ui.KeyLeft, ui.KeyRight, ui.KeyB} {
tt.Key(0, k)
}
if unlocked != 0 || !has(slots(t, tt.Image(), r), pixel.Accent) {
t.Fatal("unlocked early, or the trail is not lit")
}
tt.Key(0, ui.KeyA)
if unlocked != 1 || !has(slots(t, tt.Image(), r), pixel.Good) {
t.Fatal("the code did not unlock")
}
}
func TestCheatCodeBreaksOnOtherKeys(t *testing.T) {
unlocked := 0
tt := view(400, 200, nil, func(c *ui.Context) {
if input.CheatCode(c, "Cheat", input.CheatCodeOptions{Sequence: []ui.Key{ui.KeyA, ui.KeyB}}).Unlocked {
unlocked++
}
})
click(t, tt, "Cheat")
r := find(t, tt, "Cheat")
tt.Key(0, ui.KeyA)
tt.Key(0, ui.KeyX)
if !has(slots(t, tt.Image(), r), pixel.Faint) {
t.Fatal("the wrong key is not in the trail")
}
tt.Key(0, ui.KeyB)
if unlocked != 0 {
t.Fatal("A, X, B unlocked A, B")
}
tt.Key(0, ui.KeyA)
tt.Key(0, ui.KeyB)
if unlocked != 1 {
t.Fatal("A, B did not unlock")
}
}
func TestSlotPickerSpins(t *testing.T) {
reel, changes := 0, 0
tt := view(400, 200, nil, func(c *ui.Context) {
if input.SlotPicker(c, "Reel", &reel, []string{"Cherry", "Bell", "Seven"}, input.SlotPickerOptions{}).Changed {
changes++
}
})
click(t, tt, "Reel")
tt.Key(0, ui.KeyDown)
tt.Key(0, ui.KeyUp)
tt.Key(0, ui.KeyUp)
if reel != 2 || changes != 3 {
t.Fatalf("Down, Up, Up gave %d after %d changes", reel, changes)
}
r := find(t, tt, "Reel")
tt.Scroll(r.X+r.W/2, r.Y+r.H/2, 0, 2*2*pixel.LineHeight)
if reel != 1 {
t.Fatalf("two rows of wheel gave %d", reel)
}
tt.Press(r.X+r.W/2, r.Y+r.H/2)
tt.Move(r.X+r.W/2, r.Y+r.H/2+2*pixel.LineHeight+4)
tt.Release(r.X+r.W/2, r.Y+r.H/2+2*pixel.LineHeight+4)
if reel != 0 {
t.Fatalf("dragging a row down gave %d", reel)
}
}
func TestGridCopyFollowsTheLocale(t *testing.T) {
render := func(l pixel.Locale) (end, banner []pixel.Slot) {
name := ""
tt := ui.NewTester(func(c *ui.Context) {
pixel.Use(c, pixel.Settings{Palette: pixel.SpringDay, Locale: l})
input.NameEntry(c, "Initials", &name, input.NameEntryOptions{})
input.CheatCode(c, "Cheat", input.CheatCodeOptions{Sequence: []ui.Key{ui.KeyA}})
}, 400, 300)
click(t, tt, "Cheat")
tt.Key(0, ui.KeyA)
g, ch := find(t, tt, "Initials"), find(t, tt, "Cheat")
end = slots(t, tt.Image(), ui.Rect{X: g.X + g.W - 28, Y: g.Y + g.H - 32, W: 28, H: 32})
banner = slots(t, tt.Image(), ui.Rect{X: ch.X, Y: ch.Y + 28, W: ch.W, H: ch.H - 28})
return end, banner
}
enEnd, enBanner := render(pixel.En)
zhEnd, zhBanner := render(pixel.Zh)
if equal(enEnd, zhEnd) || equal(enBanner, zhBanner) {
t.Fatal("END or the unlock banner ignores the locale")
}
}