Dialogs on DialogBase with focusable panels that harbor parked focus, popovers on PopoverBase, bubbles, drawers, sheets, a lightbox, an RPG dialogue box, notifications, a pause menu and a dithered title card. Kit.Cue moves from feedback to pixel.
336 lines
9.4 KiB
Go
336 lines
9.4 KiB
Go
package overlay_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/egoist/mygo/ui"
|
|
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/overlay"
|
|
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
|
)
|
|
|
|
func TestDialogActsClosesAndHandsFocusBack(t *testing.T) {
|
|
open, action, closed := false, -1, 0
|
|
tt := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if input.Button(c, "OPEN", input.ButtonOptions{}).Clicked {
|
|
open = true
|
|
}
|
|
r := overlay.Dialog(c, "Save game?", &open, overlay.DialogOptions{Actions: []string{"LATER", "SAVE"}}, func() {
|
|
pixel.Text(c, "Slot 1 is free.", pixel.TextOptions{})
|
|
})
|
|
if r.Action >= 0 {
|
|
action = r.Action
|
|
}
|
|
if r.Closed {
|
|
closed++
|
|
}
|
|
})
|
|
click(t, tt, "OPEN")
|
|
if !shows(tt, "Slot 1 is free.") {
|
|
t.Fatal("the dialog did not open")
|
|
}
|
|
click(t, tt, "SAVE")
|
|
if open || action != 1 || shows(tt, "Slot 1 is free.") {
|
|
t.Fatalf("SAVE left open %v, action %d", open, action)
|
|
}
|
|
if !tt.Focused("OPEN") {
|
|
t.Fatal("closing did not hand the focus back")
|
|
}
|
|
tt.Key(0, ui.KeyEnter)
|
|
tt.Key(0, ui.KeyEscape)
|
|
if open || closed != 1 {
|
|
t.Fatalf("Escape left open %v, %d closes", open, closed)
|
|
}
|
|
keeps(t, tt.Image())
|
|
}
|
|
|
|
func TestAlertDialogEnterPressesDefault(t *testing.T) {
|
|
open, pressed := true, -1
|
|
tt := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if r := overlay.AlertDialog(c, "Low HP", "Heal before the boss?", &open, overlay.AlertDialogOptions{Buttons: []string{"NO", "HEAL"}, Default: 1}); r.Pressed >= 0 {
|
|
pressed = r.Pressed
|
|
}
|
|
})
|
|
tt.Key(0, ui.KeyEnter)
|
|
if open || pressed != 1 {
|
|
t.Fatalf("Enter pressed %d, open %v", pressed, open)
|
|
}
|
|
open = true
|
|
tt.Frame()
|
|
click(t, tt, "NO")
|
|
if open || pressed != 0 {
|
|
t.Fatalf("NO pressed %d", pressed)
|
|
}
|
|
defer func() {
|
|
if recover() == nil {
|
|
t.Fatal("a Default past the buttons did not panic")
|
|
}
|
|
}()
|
|
view(100, 100, newClock(), false, func(c *ui.Context) {
|
|
overlay.AlertDialog(c, "x", "y", &open, overlay.AlertDialogOptions{Default: 1})
|
|
})
|
|
}
|
|
|
|
func TestConfirmDialogStartsOnNo(t *testing.T) {
|
|
open, yes, no := true, 0, 0
|
|
tt := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
r := overlay.ConfirmDialog(c, "Drop the sword?", &open, overlay.ConfirmDialogOptions{})
|
|
if r.Confirmed {
|
|
yes++
|
|
}
|
|
if r.Canceled {
|
|
no++
|
|
}
|
|
})
|
|
if !shows(tt, "ARE YOU SURE?") {
|
|
t.Fatalf("texts %q", tt.Texts())
|
|
}
|
|
tt.Key(0, ui.KeyEnter)
|
|
if open || yes != 0 || no != 1 {
|
|
t.Fatalf("Enter on the start gave yes %d no %d", yes, no)
|
|
}
|
|
open = true
|
|
tt.Frame()
|
|
tt.Key(0, ui.KeyUp)
|
|
tt.Key(0, ui.KeyEnter)
|
|
if open || yes != 1 {
|
|
t.Fatalf("Up, Enter gave yes %d", yes)
|
|
}
|
|
open = true
|
|
tt.Frame()
|
|
click(t, tt, "YES")
|
|
tt.Frame()
|
|
open = true
|
|
tt.Frame()
|
|
tt.Key(0, ui.KeyEscape)
|
|
if yes != 2 || no != 2 {
|
|
t.Fatalf("click YES then Escape gave yes %d no %d", yes, no)
|
|
}
|
|
keeps(t, tt.Image())
|
|
}
|
|
|
|
func TestChoicePromptTakesDigitsArrowsAndClicks(t *testing.T) {
|
|
open, chosen, canceled := true, -1, 0
|
|
choices := []string{"Fight", "Talk", "Flee"}
|
|
tt := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
r := overlay.ChoicePrompt(c, "A slime appears!", choices, &open, overlay.ChoicePromptOptions{})
|
|
if r.Chosen >= 0 {
|
|
chosen = r.Chosen
|
|
}
|
|
if r.Canceled {
|
|
canceled++
|
|
}
|
|
})
|
|
tt.Key(0, ui.Key3)
|
|
if open || chosen != 2 {
|
|
t.Fatalf("3 chose %d", chosen)
|
|
}
|
|
open = true
|
|
tt.Frame()
|
|
tt.Key(0, ui.KeyDown)
|
|
tt.Key(0, ui.KeySpace)
|
|
if chosen != 1 {
|
|
t.Fatalf("Down, Space chose %d", chosen)
|
|
}
|
|
open = true
|
|
tt.Frame()
|
|
click(t, tt, "Flee")
|
|
open = true
|
|
tt.Frame()
|
|
tt.Key(0, ui.KeyEscape)
|
|
if chosen != 2 || canceled != 1 || open {
|
|
t.Fatalf("click Flee, Escape: chosen %d, %d cancels", chosen, canceled)
|
|
}
|
|
}
|
|
|
|
func TestPauseMenuResumesAndChooses(t *testing.T) {
|
|
paused, chosen := true, -1
|
|
tt := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if r := overlay.PauseMenu(c, &paused, overlay.PauseMenuOptions{}); r.Chosen >= 0 {
|
|
chosen = r.Chosen
|
|
}
|
|
})
|
|
if !shows(tt, "PAUSED") {
|
|
t.Fatalf("texts %q", tt.Texts())
|
|
}
|
|
tt.Key(0, ui.KeyDown)
|
|
tt.Key(0, ui.KeyEnter)
|
|
if !paused || chosen != 1 {
|
|
t.Fatalf("OPTIONS left paused %v, chosen %d", paused, chosen)
|
|
}
|
|
tt.Key(0, ui.KeyEscape)
|
|
if paused || chosen != 0 {
|
|
t.Fatalf("Escape left paused %v, chosen %d", paused, chosen)
|
|
}
|
|
keeps(t, tt.Image())
|
|
}
|
|
|
|
func TestPromptDialogSubmitsAndCancels(t *testing.T) {
|
|
open, name, sent, canceled := true, "", 0, 0
|
|
tt := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
r := overlay.PromptDialog(c, "ENTER YOUR NAME", &name, &open, overlay.PromptDialogOptions{MaxLength: 8})
|
|
if r.Submitted {
|
|
sent++
|
|
}
|
|
if r.Canceled {
|
|
canceled++
|
|
}
|
|
})
|
|
tt.Type("LINK")
|
|
tt.Key(0, ui.KeyEnter)
|
|
if open || name != "LINK" || sent != 1 {
|
|
t.Fatalf("typing, Enter left %q, open %v, %d sent", name, open, sent)
|
|
}
|
|
open = true
|
|
tt.Frame()
|
|
click(t, tt, "CANCEL")
|
|
if open || canceled != 1 {
|
|
t.Fatalf("CANCEL left open %v, %d cancels", open, canceled)
|
|
}
|
|
}
|
|
|
|
func TestProgressDialogCancels(t *testing.T) {
|
|
open, canceled := true, 0
|
|
tt := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if overlay.ProgressDialog(c, "Saving", 0.5, &open, overlay.ProgressDialogOptions{}).Canceled {
|
|
canceled++
|
|
}
|
|
})
|
|
if !shows(tt, "Saving") {
|
|
t.Fatalf("texts %q", tt.Texts())
|
|
}
|
|
click(t, tt, "CANCEL")
|
|
if open || canceled != 1 {
|
|
t.Fatalf("CANCEL left open %v", open)
|
|
}
|
|
keeps(t, tt.Image())
|
|
}
|
|
|
|
func TestOffDialogsTakeNoAnswers(t *testing.T) {
|
|
for _, inert := range []bool{false, true} {
|
|
open, action := true, -1
|
|
tt := view(640, 400, newClock(), inert, func(c *ui.Context) {
|
|
if r := overlay.Dialog(c, "Quest", &open, overlay.DialogOptions{Actions: []string{"ACCEPT"}, Disabled: !inert}, func() {}); r.Action >= 0 {
|
|
action = r.Action
|
|
}
|
|
})
|
|
click(t, tt, "ACCEPT")
|
|
if action >= 0 || !open {
|
|
t.Fatalf("inert %v: a dialog took action %d", inert, action)
|
|
}
|
|
alert, pressed := true, -1
|
|
tt = view(640, 400, newClock(), inert, func(c *ui.Context) {
|
|
if r := overlay.AlertDialog(c, "Warn", "Careful.", &alert, overlay.AlertDialogOptions{Disabled: !inert}); r.Pressed >= 0 {
|
|
pressed = r.Pressed
|
|
}
|
|
})
|
|
tt.Key(0, ui.KeyEnter)
|
|
click(t, tt, "OK")
|
|
if pressed >= 0 || !alert {
|
|
t.Fatalf("inert %v: an alert took button %d", inert, pressed)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInertMenusTakeNoPicks(t *testing.T) {
|
|
open, paused, chosen, picked := true, true, -1, -1
|
|
tt := view(640, 400, newClock(), true, func(c *ui.Context) {
|
|
if r := overlay.ChoicePrompt(c, "Go?", []string{"Yes", "No"}, &open, overlay.ChoicePromptOptions{}); r.Chosen >= 0 {
|
|
chosen = r.Chosen
|
|
}
|
|
})
|
|
tt.Key(0, ui.Key1)
|
|
click(t, tt, "No")
|
|
tt2 := view(640, 400, newClock(), true, func(c *ui.Context) {
|
|
if r := overlay.PauseMenu(c, &paused, overlay.PauseMenuOptions{}); r.Chosen > 0 {
|
|
picked = r.Chosen
|
|
}
|
|
})
|
|
click(t, tt2, "QUIT")
|
|
if chosen >= 0 || picked >= 0 || !open {
|
|
t.Fatalf("inert menus picked %d and %d", chosen, picked)
|
|
}
|
|
}
|
|
|
|
func TestDisabledMenusAndPromptsTakeNoAnswers(t *testing.T) {
|
|
open, chosen, sure, paused, picked, prompt, name, sent := true, -1, true, true, -1, true, "", 0
|
|
tt := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if r := overlay.ChoicePrompt(c, "Go?", []string{"Yes", "No"}, &open, overlay.ChoicePromptOptions{Disabled: true}); r.Chosen >= 0 {
|
|
chosen = r.Chosen
|
|
}
|
|
})
|
|
tt.Key(0, ui.Key1)
|
|
tt2 := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if overlay.ConfirmDialog(c, "Sure?", &sure, overlay.ConfirmDialogOptions{Disabled: true}).Confirmed {
|
|
chosen = 99
|
|
}
|
|
})
|
|
click(t, tt2, "YES")
|
|
tt3 := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if r := overlay.PauseMenu(c, &paused, overlay.PauseMenuOptions{Disabled: true}); r.Chosen > 0 {
|
|
picked = r.Chosen
|
|
}
|
|
})
|
|
click(t, tt3, "QUIT")
|
|
tt4 := view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if overlay.PromptDialog(c, "NAME", &name, &prompt, overlay.PromptDialogOptions{Disabled: true}).Submitted {
|
|
sent++
|
|
}
|
|
})
|
|
tt4.Type("AB")
|
|
click(t, tt4, "OK")
|
|
if chosen >= 0 || picked >= 0 || sent != 0 || name != "" || !open || !sure || !prompt {
|
|
t.Fatalf("disabled answers: chosen %d picked %d sent %d name %q", chosen, picked, sent, name)
|
|
}
|
|
}
|
|
|
|
func TestFocusComesBackAfterAnOffSpellInADialog(t *testing.T) {
|
|
inert, disabled := false, false
|
|
open, action := true, -1
|
|
tt := ui.NewTester(func(c *ui.Context) {
|
|
pixel.Use(c, pixel.Settings{Palette: pixel.SpringDay, Inert: inert})
|
|
if r := overlay.Dialog(c, "Quest", &open, overlay.DialogOptions{Actions: []string{"ACCEPT"}}, func() {}); r.Action >= 0 {
|
|
action = r.Action
|
|
}
|
|
}, 640, 400)
|
|
tt.Key(0, ui.KeyTab)
|
|
if !tt.Focused("ACCEPT") {
|
|
t.Fatal("Tab did not reach ACCEPT")
|
|
}
|
|
inert = true
|
|
tt.Frame()
|
|
inert = false
|
|
tt.Frame()
|
|
tt.Key(0, ui.KeyEnter)
|
|
if action != 0 {
|
|
t.Fatalf("Enter after the veil gave action %d", action)
|
|
}
|
|
chosen, choice := -1, true
|
|
tt = view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
if r := overlay.ChoicePrompt(c, "Go?", []string{"Yes", "No"}, &choice, overlay.ChoicePromptOptions{Disabled: disabled}); r.Chosen >= 0 {
|
|
chosen = r.Chosen
|
|
}
|
|
})
|
|
disabled = true
|
|
tt.Frame()
|
|
disabled = false
|
|
tt.Frame()
|
|
tt.Key(0, ui.KeyEnter)
|
|
if chosen != 0 {
|
|
t.Fatalf("Enter after a disabled spell chose %d", chosen)
|
|
}
|
|
name, prompt := "", true
|
|
tt = view(640, 400, newClock(), false, func(c *ui.Context) {
|
|
overlay.PromptDialog(c, "NAME", &name, &prompt, overlay.PromptDialogOptions{Disabled: disabled})
|
|
})
|
|
disabled = true
|
|
tt.Frame()
|
|
disabled = false
|
|
tt.Frame()
|
|
tt.Type("AB")
|
|
if name != "AB" {
|
|
t.Fatalf("typing after a disabled spell gave %q", name)
|
|
}
|
|
}
|