Files
MujicaUI/menubar_test.go
T

192 lines
5.0 KiB
Go

package mujica
import (
"runtime"
"testing"
"github.com/egoist/mygo/ui"
)
type menubarApp struct {
wrap bool
zoom string
chosen []string
}
func (a *menubarApp) menus() []MenubarMenu {
return []MenubarMenu{
{Label: "File", Items: []MenubarItem{
{ID: "new", Label: "New", Shortcut: MenubarShortcut{ui.Cmd, ui.KeyN}},
{ID: "open", Label: "Open…", Shortcut: MenubarShortcut{ui.Cmd, ui.KeyO}},
{Label: "Export", Items: []MenubarItem{
{ID: "pdf", Label: "PDF"},
{ID: "png", Label: "Image", Disabled: true},
{ID: "svg", Label: "Vector"},
}},
{Kind: MenubarSeparator},
{ID: "quit", Label: "Quit"},
}},
{Label: "View", Items: []MenubarItem{
{ID: "wrap", Label: "Word wrap", Kind: MenubarCheck, Checked: a.wrap},
{Kind: MenubarSeparator},
{ID: "zoom-fit", Label: "Fit", Kind: MenubarRadio, Checked: a.zoom == "zoom-fit"},
{ID: "zoom-100", Label: "Actual size", Kind: MenubarRadio, Checked: a.zoom == "zoom-100"},
}},
{Label: "Help", Items: []MenubarItem{{ID: "about", Label: "About"}}},
}
}
func (a *menubarApp) view(c *ui.Context) {
Use(c, Settings{})
ui.Column(c).Fill().Children(func() {
if id, ok := Menubar(c, a.menus(), MenubarOptions{}).Chosen(); ok {
a.chosen = append(a.chosen, id)
switch id {
case "wrap":
a.wrap = !a.wrap
case "zoom-fit", "zoom-100":
a.zoom = id
}
}
})
}
func TestMenubarPointer(t *testing.T) {
a := &menubarApp{zoom: "zoom-fit"}
tt := ui.NewTester(a.view, 700, 500)
if err := tt.Click("View"); err != nil {
t.Fatal(err)
}
if err := tt.Click("Word wrap"); err != nil {
t.Fatal(err)
}
if !a.wrap || tt.HasText("Actual size") {
t.Fatalf("check item: wrap %v, menu still open %v", a.wrap, tt.HasText("Actual size"))
}
_ = tt.Click("View")
if _, ok := tt.Find("Word wrap, checked"); !ok {
t.Fatal("checked state not named")
}
if err := tt.Click("Actual size"); err != nil {
t.Fatal(err)
}
if a.zoom != "zoom-100" {
t.Fatalf("radio chose %q", a.zoom)
}
_ = tt.Click("File")
r, _ := tt.Find("Export")
tt.Move(r.X+r.W/2, r.Y+r.H/2)
tt.Move(r.X+r.W/2+1, r.Y+r.H/2)
if !tt.HasText("Vector") {
t.Fatalf("hover did not open submenu: %q", tt.Texts())
}
_ = tt.Click("Image")
if err := tt.Click("Vector"); err != nil {
t.Fatal(err)
}
if got := a.chosen; len(got) != 3 || got[2] != "svg" {
t.Fatalf("chosen %q", got)
}
_ = tt.Click("Help")
tt.ClickAt(600, 400)
if tt.HasText("About") {
t.Fatal("click outside did not close")
}
}
func TestMenubarHoverSwitchesMenus(t *testing.T) {
a := &menubarApp{}
tt := ui.NewTester(a.view, 700, 500)
_ = tt.Click("File")
r, _ := tt.Find("Help")
tt.Move(r.X+2, r.Y+2)
if tt.HasText("Quit") || !tt.HasText("About") {
t.Fatalf("hover did not switch: %q", tt.Texts())
}
}
func TestMenubarKeyboard(t *testing.T) {
a := &menubarApp{}
tt := ui.NewTester(a.view, 700, 500)
tt.Key(0, ui.KeyTab)
if !tt.Focused("File") {
t.Fatal("Tab did not reach the bar")
}
tt.Key(0, ui.KeyRight)
tt.Key(0, ui.KeyLeft)
if !tt.Focused("File") {
t.Fatal("arrows did not move between titles")
}
tt.Key(0, ui.KeyDown) // opens File on New
tt.Key(0, ui.KeyDown) // Open
tt.Key(0, ui.KeyDown) // Export
tt.Key(0, ui.KeyRight)
if !tt.HasText("Vector") {
t.Fatal("Right did not open the submenu")
}
tt.Key(0, ui.KeyDown) // skips disabled Image to Vector
tt.Key(0, ui.KeyEnter)
if len(a.chosen) != 1 || a.chosen[0] != "svg" {
t.Fatalf("chosen %q", a.chosen)
}
if tt.HasText("Quit") || !tt.Focused("File") {
t.Fatal("menu did not close back to its title")
}
tt.Key(0, ui.KeyDown)
tt.Key(0, ui.KeyUp) // wraps past the separator to Quit
tt.Key(0, ui.KeyRight)
if !tt.HasText("Word wrap") {
t.Fatal("Right on a plain item did not move to the next menu")
}
tt.Key(0, ui.KeySpace)
if !a.wrap {
t.Fatal("Space did not toggle the check item")
}
tt.Key(0, ui.KeyDown)
tt.Key(0, ui.KeyEscape)
if tt.HasText("Word wrap") {
t.Fatal("Escape did not close")
}
}
func TestMenubarShortcutText(t *testing.T) {
got := menubarShortcutText(MenubarShortcut{ui.Ctrl | ui.Shift, ui.KeyF5})
want := "Ctrl+Shift+F5"
if runtime.GOOS == "darwin" {
want = "⌃⇧F5"
}
if got != want {
t.Fatalf("got %q want %q", got, want)
}
}
func TestMenubarInvalid(t *testing.T) {
for name, menus := range map[string][]MenubarMenu{
"empty": nil,
"title": {{Items: []MenubarItem{{ID: "a", Label: "A"}}}},
"id": {{Label: "M", Items: []MenubarItem{{Label: "A"}}}},
"submenu": {{Label: "M", Items: []MenubarItem{{Label: "A", Kind: MenubarCheck, Items: []MenubarItem{}}}}},
} {
t.Run(name, func(t *testing.T) {
defer func() {
if recover() == nil {
t.Fatal("no panic")
}
}()
ui.Render(func(c *ui.Context) {
Use(c, Settings{})
Menubar(c, menus, MenubarOptions{})
}, 300, 100, 1)
})
}
}
func TestMenubarSnapshot(t *testing.T) {
a := &menubarApp{wrap: true, zoom: "zoom-fit"}
snapshot(t, "menubar", 480, 100, func(c *ui.Context) {
ui.Column(c).Padding(16).Children(func() {
Menubar(c, a.menus(), MenubarOptions{})
})
})
}