5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 06:39:30 +08:00
wails/v2/internal/platform/menu/manager_test.go
Lea Anthony b84a2e5255
Windows tray menus (#2181)
* Add example

* Add windows systray

* Add gitkeep

* use windows.GUID
2022-12-06 20:55:56 +11:00

298 lines
7.4 KiB
Go

//go:build windows
package menu_test
import (
"github.com/stretchr/testify/require"
platformMenu "github.com/wailsapp/wails/v2/internal/platform/menu"
"github.com/wailsapp/wails/v2/pkg/menu"
"testing"
)
func TestManager_ProcessClick_Checkbox(t *testing.T) {
checkbox := menu.Label("Checkbox").SetChecked(false)
menu1 := &menu.Menu{
Items: []*menu.MenuItem{
checkbox,
},
}
menu2 := &menu.Menu{
Items: []*menu.MenuItem{
checkbox,
},
}
menuWithNoCheckbox := &menu.Menu{
Items: []*menu.MenuItem{
menu.Label("No Checkbox"),
},
}
clicked := false
tests := []struct {
name string
inputs []*menu.Menu
startState bool
expectedState bool
expectedMenuUpdates map[*menu.Menu][]*menu.MenuItem
click func(*menu.CallbackData)
}{
{
name: "should callback menu checkbox state when clicked (false -> true)",
inputs: []*menu.Menu{menu1},
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
menu1: {checkbox},
},
startState: false,
expectedState: true,
},
{
name: "should callback multiple menus when checkbox state when clicked (false -> true)",
inputs: []*menu.Menu{menu1, menu2},
startState: false,
expectedState: true,
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
menu1: {checkbox},
menu2: {checkbox},
},
},
{
name: "should callback only for the menus that the checkbox is in (false -> true)",
inputs: []*menu.Menu{menu1, menuWithNoCheckbox},
startState: false,
expectedState: true,
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
menu1: {checkbox},
},
},
{
name: "should callback menu checkbox state when clicked (true->false)",
inputs: []*menu.Menu{menu1},
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
menu1: {checkbox},
},
startState: true,
expectedState: false,
},
{
name: "should callback multiple menus when checkbox state when clicked (true->false)",
inputs: []*menu.Menu{menu1, menu2},
startState: true,
expectedState: false,
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
menu1: {checkbox},
menu2: {checkbox},
},
},
{
name: "should callback only for the menus that the checkbox is in (true->false)",
inputs: []*menu.Menu{menu1, menuWithNoCheckbox},
startState: true,
expectedState: false,
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
menu1: {checkbox},
},
},
{
name: "should callback no menus if checkbox not in them",
inputs: []*menu.Menu{menuWithNoCheckbox},
startState: false,
expectedState: false,
expectedMenuUpdates: nil,
},
{
name: "should call Click on the checkbox",
inputs: []*menu.Menu{menu1, menu2},
startState: false,
expectedState: true,
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
menu1: {checkbox},
menu2: {checkbox},
},
click: func(data *menu.CallbackData) {
clicked = true
},
},
}
for _, tt := range tests {
menusUpdated := map[*menu.Menu][]*menu.MenuItem{}
clicked = false
var checkMenuItemStateInMenu func(menu *menu.Menu)
checkMenuItemStateInMenu = func(menu *menu.Menu) {
for _, item := range menusUpdated[menu] {
if item == checkbox {
require.Equal(t, tt.expectedState, item.Checked)
}
if item.SubMenu != nil {
checkMenuItemStateInMenu(item.SubMenu)
}
}
}
t.Run(tt.name, func(t *testing.T) {
m := platformMenu.NewManager()
checkbox.SetChecked(tt.startState)
checkbox.Click = tt.click
for _, thisMenu := range tt.inputs {
thisMenu := thisMenu
m.AddMenu(thisMenu, func(menuItem *menu.MenuItem) {
menusUpdated[thisMenu] = append(menusUpdated[thisMenu], menuItem)
})
}
m.ProcessClick(checkbox)
// Check the item has the correct state in all the menus
for thisMenu := range menusUpdated {
require.EqualValues(t, tt.expectedMenuUpdates[thisMenu], menusUpdated[thisMenu])
}
if tt.click != nil {
require.Equal(t, true, clicked)
}
})
}
}
func TestManager_ProcessClick_RadioGroups(t *testing.T) {
radio1 := menu.Radio("Radio1", false, nil, nil)
radio2 := menu.Radio("Radio2", false, nil, nil)
radio3 := menu.Radio("Radio3", false, nil, nil)
radio4 := menu.Radio("Radio4", false, nil, nil)
radio5 := menu.Radio("Radio5", false, nil, nil)
radio6 := menu.Radio("Radio6", false, nil, nil)
radioGroupOne := &menu.Menu{
Items: []*menu.MenuItem{
radio1,
radio2,
radio3,
},
}
radioGroupTwo := &menu.Menu{
Items: []*menu.MenuItem{
radio4,
radio5,
radio6,
},
}
radioGroupThree := &menu.Menu{
Items: []*menu.MenuItem{
radio1,
radio2,
radio3,
},
}
clicked := false
tests := []struct {
name string
inputs []*menu.Menu
startState map[*menu.MenuItem]bool
selected *menu.MenuItem
expectedMenuUpdates map[*menu.Menu][]*menu.MenuItem
click func(*menu.CallbackData)
expectedState map[*menu.MenuItem]bool
}{
{
name: "should only set the clicked radio item",
inputs: []*menu.Menu{radioGroupOne},
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
radioGroupOne: {radio1, radio2, radio3},
},
startState: map[*menu.MenuItem]bool{
radio1: true,
radio2: false,
radio3: false,
},
selected: radio2,
expectedState: map[*menu.MenuItem]bool{
radio1: false,
radio2: true,
radio3: false,
},
},
{
name: "should not affect other radio groups or menus",
inputs: []*menu.Menu{radioGroupOne, radioGroupTwo},
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
radioGroupOne: {radio1, radio2, radio3},
},
startState: map[*menu.MenuItem]bool{
radio1: true,
radio2: false,
radio3: false,
radio4: true,
radio5: false,
radio6: false,
},
selected: radio2,
expectedState: map[*menu.MenuItem]bool{
radio1: false,
radio2: true,
radio3: false,
radio4: true,
radio5: false,
radio6: false,
},
},
{
name: "menus with the same radio group should be updated",
inputs: []*menu.Menu{radioGroupOne, radioGroupThree},
expectedMenuUpdates: map[*menu.Menu][]*menu.MenuItem{
radioGroupOne: {radio1, radio2, radio3},
radioGroupThree: {radio1, radio2, radio3},
},
startState: map[*menu.MenuItem]bool{
radio1: true,
radio2: false,
radio3: false,
},
selected: radio2,
expectedState: map[*menu.MenuItem]bool{
radio1: false,
radio2: true,
radio3: false,
},
},
}
for _, tt := range tests {
menusUpdated := map[*menu.Menu][]*menu.MenuItem{}
clicked = false
t.Run(tt.name, func(t *testing.T) {
m := platformMenu.NewManager()
for item, value := range tt.startState {
item.SetChecked(value)
}
tt.selected.Click = tt.click
for _, thisMenu := range tt.inputs {
thisMenu := thisMenu
m.AddMenu(thisMenu, func(menuItem *menu.MenuItem) {
menusUpdated[thisMenu] = append(menusUpdated[thisMenu], menuItem)
})
}
m.ProcessClick(tt.selected)
require.Equal(t, tt.expectedMenuUpdates, menusUpdated)
// Check the items have the correct state in all the menus
for item, expectedValue := range tt.expectedState {
require.Equal(t, expectedValue, item.Checked)
}
if tt.click != nil {
require.Equal(t, true, clicked)
}
})
}
}