From 345afb16bb4fb3506558c27d86bdc4ab311e201a Mon Sep 17 00:00:00 2001 From: Snider Date: Fri, 17 Apr 2026 18:58:23 +0100 Subject: [PATCH] Add Wails stub bridge coverage --- stubs/wails/go.mod | 8 + stubs/wails/go.sum | 10 + stubs/wails/pkg/application/application.go | 10 +- .../application/application_options_test.go | 135 ++++++++++ .../wails/pkg/application/application_test.go | 251 ++++++++++++++++++ .../pkg/application/browser_manager_test.go | 61 +++++ .../pkg/application/browser_window_test.go | 61 +++++ stubs/wails/pkg/application/clipboard_test.go | 73 +++++ .../pkg/application/context_menu_test.go | 72 +++++ stubs/wails/pkg/application/dialog.go | 10 +- stubs/wails/pkg/application/dialog_test.go | 165 ++++++++++++ stubs/wails/pkg/application/environment.go | 12 +- .../wails/pkg/application/environment_test.go | 92 +++++++ stubs/wails/pkg/application/events.go | 6 +- stubs/wails/pkg/application/events_test.go | 137 ++++++++++ .../wails/pkg/application/keybinding_test.go | 71 +++++ stubs/wails/pkg/application/menuitem_test.go | 50 ++++ stubs/wails/pkg/application/screen_test.go | 67 +++++ stubs/wails/pkg/application/services_test.go | 52 ++++ 19 files changed, 1326 insertions(+), 17 deletions(-) create mode 100644 stubs/wails/go.sum create mode 100644 stubs/wails/pkg/application/application_options_test.go create mode 100644 stubs/wails/pkg/application/application_test.go create mode 100644 stubs/wails/pkg/application/browser_manager_test.go create mode 100644 stubs/wails/pkg/application/browser_window_test.go create mode 100644 stubs/wails/pkg/application/clipboard_test.go create mode 100644 stubs/wails/pkg/application/context_menu_test.go create mode 100644 stubs/wails/pkg/application/dialog_test.go create mode 100644 stubs/wails/pkg/application/environment_test.go create mode 100644 stubs/wails/pkg/application/events_test.go create mode 100644 stubs/wails/pkg/application/keybinding_test.go create mode 100644 stubs/wails/pkg/application/menuitem_test.go create mode 100644 stubs/wails/pkg/application/screen_test.go create mode 100644 stubs/wails/pkg/application/services_test.go diff --git a/stubs/wails/go.mod b/stubs/wails/go.mod index 7dcb8325..e8e5a04d 100644 --- a/stubs/wails/go.mod +++ b/stubs/wails/go.mod @@ -1,3 +1,11 @@ module github.com/wailsapp/wails/v3 go 1.26.0 + +require github.com/stretchr/testify v1.11.1 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/stubs/wails/go.sum b/stubs/wails/go.sum new file mode 100644 index 00000000..c4c1710c --- /dev/null +++ b/stubs/wails/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/stubs/wails/pkg/application/application.go b/stubs/wails/pkg/application/application.go index ac3c4d0c..452c2166 100644 --- a/stubs/wails/pkg/application/application.go +++ b/stubs/wails/pkg/application/application.go @@ -187,6 +187,7 @@ type WebviewWindowOptions struct { // WebviewWindow is a lightweight, in-memory window implementation. type WebviewWindow struct { mu sync.RWMutex + id uint opts WebviewWindowOptions title string url string @@ -204,9 +205,10 @@ type WebviewWindow struct { eventHandlers map[events.WindowEventType][]func(*WindowEvent) } -func newWebviewWindow(options WebviewWindowOptions) *WebviewWindow { +func newWebviewWindow(id uint, options WebviewWindowOptions) *WebviewWindow { window := &WebviewWindow{ opts: options, + id: id, title: options.Title, url: options.URL, html: options.HTML, @@ -358,7 +360,7 @@ func (w *WebviewWindow) OnWindowEvent(eventType events.WindowEventType, callback // ID returns a stable numeric identifier for this window. // // id := w.ID() -func (w *WebviewWindow) ID() uint { return 0 } +func (w *WebviewWindow) ID() uint { return w.id } // ClientID returns the client identifier (empty for native windows). // @@ -751,12 +753,14 @@ func (w *WebviewWindow) selectAll() // WindowManager manages in-memory windows. type WindowManager struct { mu sync.RWMutex + nextID uint windows []*WebviewWindow } func (wm *WindowManager) NewWithOptions(options WebviewWindowOptions) *WebviewWindow { - window := newWebviewWindow(options) wm.mu.Lock() + wm.nextID++ + window := newWebviewWindow(wm.nextID, options) wm.windows = append(wm.windows, window) wm.mu.Unlock() return window diff --git a/stubs/wails/pkg/application/application_options_test.go b/stubs/wails/pkg/application/application_options_test.go new file mode 100644 index 00000000..1efd935f --- /dev/null +++ b/stubs/wails/pkg/application/application_options_test.go @@ -0,0 +1,135 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type handlerFunc func() + +func (f handlerFunc) ServeHTTP(_ ResponseWriter, _ *Request) { + f() +} + +type fakeFS struct{} + +func (fakeFS) Open(name string) (interface{ Read([]byte) (int, error) }, error) { + _ = name + return nil, nil +} + +func TestApplicationOptions_ChainMiddleware_Good(t *testing.T) { + calls := make([]string, 0, 3) + base := handlerFunc(func() { + calls = append(calls, "handler") + }) + + first := func(next Handler) Handler { + return handlerFunc(func() { + calls = append(calls, "first") + next.ServeHTTP(nil, nil) + }) + } + second := func(next Handler) Handler { + return handlerFunc(func() { + calls = append(calls, "second") + next.ServeHTTP(nil, nil) + }) + } + + ChainMiddleware(first, second)(base).ServeHTTP(nil, nil) + + assert.Equal(t, []string{"first", "second", "handler"}, calls) +} + +func TestApplicationOptions_ChainMiddleware_Bad(t *testing.T) { + calls := 0 + base := handlerFunc(func() { + calls++ + }) + + ChainMiddleware()(base).ServeHTTP(nil, nil) + + assert.Equal(t, 1, calls) +} + +func TestApplicationOptions_ChainMiddleware_Ugly(t *testing.T) { + calls := 0 + base := handlerFunc(func() { + calls++ + }) + + shortCircuit := func(next Handler) Handler { + _ = next + return handlerFunc(func() {}) + } + + ChainMiddleware(shortCircuit)(base).ServeHTTP(nil, nil) + + assert.Zero(t, calls) +} + +func TestApplicationOptions_NewRGB_Good(t *testing.T) { + got := NewRGB(0x11, 0x22, 0x33) + + assert.Equal(t, RGBA{Red: 0x11, Green: 0x22, Blue: 0x33, Alpha: 255}, got) +} + +func TestApplicationOptions_NewRGB_Bad(t *testing.T) { + got := NewRGB(0, 0, 0) + + assert.Equal(t, RGBA{Alpha: 255}, got) +} + +func TestApplicationOptions_NewRGB_Ugly(t *testing.T) { + got := NewRGB(255, 255, 255) + + assert.Equal(t, RGBA{Red: 255, Green: 255, Blue: 255, Alpha: 255}, got) +} + +func TestApplicationOptions_NewRGBPtr_Good(t *testing.T) { + got := NewRGBPtr(0x11, 0x22, 0x33) + + require.NotNil(t, got) + assert.Equal(t, uint32(0x00332211), *got) +} + +func TestApplicationOptions_NewRGBPtr_Bad(t *testing.T) { + got := NewRGBPtr(0, 0, 0) + + require.NotNil(t, got) + assert.Zero(t, *got) +} + +func TestApplicationOptions_NewRGBPtr_Ugly(t *testing.T) { + got := NewRGBPtr(255, 255, 255) + + require.NotNil(t, got) + assert.Equal(t, uint32(0x00ffffff), *got) +} + +func TestApplicationOptions_AssetFileServerFS_Good(t *testing.T) { + assert.Nil(t, AssetFileServerFS(nil)) +} + +func TestApplicationOptions_AssetFileServerFS_Bad(t *testing.T) { + assert.Nil(t, AssetFileServerFS(fakeFS{})) +} + +func TestApplicationOptions_AssetFileServerFS_Ugly(t *testing.T) { + assert.Nil(t, BundledAssetFileServer(fakeFS{})) +} + +func TestApplicationOptions_BundledAssetFileServer_Good(t *testing.T) { + assert.Nil(t, BundledAssetFileServer(nil)) +} + +func TestApplicationOptions_BundledAssetFileServer_Bad(t *testing.T) { + assert.Nil(t, BundledAssetFileServer(fakeFS{})) +} + +func TestApplicationOptions_BundledAssetFileServer_Ugly(t *testing.T) { + assert.Nil(t, BundledAssetFileServer(fakeFS{})) +} diff --git a/stubs/wails/pkg/application/application_test.go b/stubs/wails/pkg/application/application_test.go new file mode 100644 index 00000000..4ec1061d --- /dev/null +++ b/stubs/wails/pkg/application/application_test.go @@ -0,0 +1,251 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var _ Window = (*WebviewWindow)(nil) +var _ Window = (*BrowserWindow)(nil) + +func TestApplication_NewRGBA_Good(t *testing.T) { + got := NewRGBA(1, 2, 3, 4) + + assert.Equal(t, RGBA{Red: 1, Green: 2, Blue: 3, Alpha: 4}, got) +} + +func TestApplication_NewRGBA_Bad(t *testing.T) { + got := NewRGBA(0, 0, 0, 0) + + assert.Equal(t, RGBA{}, got) +} + +func TestApplication_NewRGBA_Ugly(t *testing.T) { + got := NewRGBA(255, 255, 255, 255) + + assert.Equal(t, RGBA{Red: 255, Green: 255, Blue: 255, Alpha: 255}, got) +} + +func TestApplication_MenuRole_String_Good(t *testing.T) { + cases := []struct { + role MenuRole + want string + }{ + {AppMenu, "app"}, + {FileMenu, "file"}, + {EditMenu, "edit"}, + {ViewMenu, "view"}, + {WindowMenu, "window"}, + {HelpMenu, "help"}, + } + + for _, tc := range cases { + t.Run(tc.want, func(t *testing.T) { + assert.Equal(t, tc.want, tc.role.String()) + }) + } +} + +func TestApplication_MenuRole_String_Bad(t *testing.T) { + assert.Equal(t, "unknown", MenuRole(-1).String()) +} + +func TestApplication_MenuRole_String_Ugly(t *testing.T) { + assert.Equal(t, "unknown", MenuRole(999).String()) +} + +func TestApplication_Menu_Good(t *testing.T) { + menu := NewMenu() + menuItem := menu.Add("Open") + menu.AddSeparator() + submenu := menu.AddSubmenu("More") + menu.AddRole(FileMenu) + + require.NotNil(t, menuItem) + assert.Equal(t, "Open", menuItem.Label) + require.NotNil(t, submenu) + assert.Len(t, menu.Items, 4) + assert.Equal(t, "Open", menu.Items[0].Label) + assert.Equal(t, "---", menu.Items[1].Label) + assert.Equal(t, "More", menu.Items[2].Label) + assert.Equal(t, "file", menu.Items[3].Label) +} + +func TestApplication_Menu_Bad(t *testing.T) { + menu := NewMenu() + + assert.Empty(t, menu.Items) +} + +func TestApplication_Menu_Ugly(t *testing.T) { + menu := NewMenu() + submenu := menu.AddSubmenu("Nested") + submenu.Add("Child") + + assert.Len(t, menu.Items, 1) + assert.Len(t, submenu.Items, 1) + assert.Equal(t, "Nested", menu.Items[0].Label) +} + +func TestApplication_SystemTray_Good(t *testing.T) { + tray := (&SystemTrayManager{}).New() + menu := NewMenu() + window := (&WindowManager{}).NewWithOptions(WebviewWindowOptions{Name: "tray"}) + + tray.SetIcon([]byte{1, 2, 3}) + tray.SetTemplateIcon([]byte{4, 5, 6}) + tray.SetTooltip("tooltip") + tray.SetLabel("label") + tray.SetMenu(menu) + tray.AttachWindow(window) + + assert.Equal(t, []byte{1, 2, 3}, tray.icon) + assert.Equal(t, []byte{4, 5, 6}, tray.templateIcon) + assert.Equal(t, "tooltip", tray.tooltip) + assert.Equal(t, "label", tray.label) + assert.Same(t, menu, tray.menu) + assert.Same(t, window, tray.attachedWindow) +} + +func TestApplication_SystemTray_Bad(t *testing.T) { + tray := (&SystemTrayManager{}).New() + + assert.Empty(t, tray.icon) + assert.Empty(t, tray.templateIcon) + assert.Empty(t, tray.tooltip) + assert.Empty(t, tray.label) + assert.Nil(t, tray.menu) + assert.Nil(t, tray.attachedWindow) +} + +func TestApplication_SystemTray_Ugly(t *testing.T) { + tray := (&SystemTrayManager{}).New() + icon := []byte{9, 8, 7} + tray.SetIcon(icon) + icon[0] = 0 + + assert.Equal(t, []byte{9, 8, 7}, tray.icon) +} + +func TestApplication_WindowEventContext_Good(t *testing.T) { + ctx := &WindowEventContext{ + droppedFiles: []string{"a", "b"}, + dropDetails: &DropTargetDetails{ElementID: "drop"}, + } + + assert.Equal(t, []string{"a", "b"}, ctx.DroppedFiles()) + require.NotNil(t, ctx.DropTargetDetails()) + assert.Equal(t, "drop", ctx.DropTargetDetails().ElementID) +} + +func TestApplication_WindowEventContext_Bad(t *testing.T) { + ctx := &WindowEventContext{} + + assert.Empty(t, ctx.DroppedFiles()) + assert.Nil(t, ctx.DropTargetDetails()) +} + +func TestApplication_WindowEventContext_Ugly(t *testing.T) { + ctx := &WindowEventContext{droppedFiles: []string{"x"}} + files := ctx.DroppedFiles() + files[0] = "mutated" + + assert.Equal(t, []string{"x"}, ctx.DroppedFiles()) +} + +func TestApplication_WindowEvent_Good(t *testing.T) { + event := &WindowEvent{} + + require.NotNil(t, event.Context()) + require.Same(t, event.Context(), event.Context()) +} + +func TestApplication_WindowEvent_Bad(t *testing.T) { + event := &WindowEvent{ctx: &WindowEventContext{}} + + assert.Same(t, event.ctx, event.Context()) +} + +func TestApplication_WindowEvent_Ugly(t *testing.T) { + event := &WindowEvent{} + event.Context().droppedFiles = []string{"file"} + + assert.Equal(t, []string{"file"}, event.Context().DroppedFiles()) +} + +func TestApplication_WebviewWindow_Good(t *testing.T) { + manager := &WindowManager{} + window := manager.NewWithOptions(WebviewWindowOptions{ + Name: "main", + Title: "Main", + URL: "https://example.com", + HTML: "

Hello

", + X: 10, + Y: 20, + Width: 800, + Height: 600, + Hidden: false, + AlwaysOnTop: true, + }) + + assert.Equal(t, uint(1), window.ID()) + assert.Equal(t, "main", window.Name()) + assert.Equal(t, "Main", window.Title()) + assert.Equal(t, 10, window.Bounds().X) + assert.Equal(t, 20, window.Bounds().Y) + assert.Equal(t, 800, window.Width()) + assert.Equal(t, 600, window.Height()) + assert.True(t, window.IsVisible()) + assert.False(t, window.IsFullscreen()) + assert.False(t, window.IsMaximised()) + assert.True(t, window.GetOpacity() > 0) + assert.Equal(t, 1.0, window.GetZoom()) + assert.Same(t, window, window.SetAlwaysOnTop(false)) + assert.Same(t, window, window.SetOpacity(0.5)) + assert.Equal(t, 0.5, window.GetOpacity()) + assert.Same(t, window, window.SetURL("https://example.org")) + assert.Same(t, window, window.SetHTML("

Hi

")) + assert.Same(t, window, window.SetSize(1024, 768)) + assert.Equal(t, 1024, window.Width()) + assert.Equal(t, 768, window.Height()) +} + +func TestApplication_WebviewWindow_Bad(t *testing.T) { + manager := &WindowManager{} + window := manager.NewWithOptions(WebviewWindowOptions{Hidden: true}) + + assert.False(t, window.IsVisible()) + assert.Nil(t, manager.Get("missing")) + assert.Nil(t, manager.GetByID(99)) +} + +func TestApplication_WebviewWindow_Ugly(t *testing.T) { + manager := &WindowManager{} + first := manager.NewWithOptions(WebviewWindowOptions{Name: "first"}) + second := manager.NewWithOptions(WebviewWindowOptions{Name: "second"}) + + assert.Same(t, first, manager.Get("first")) + assert.Same(t, second, manager.GetByID(2)) + assert.Len(t, manager.GetAll(), 2) +} + +func TestApplication_App_Good(t *testing.T) { + app := &App{} + + assert.NotNil(t, app.NewMenu()) +} + +func TestApplication_App_Bad(t *testing.T) { + var app App + + assert.Zero(t, app.Logger) + assert.Zero(t, app.Window) + assert.Zero(t, app.Menu) +} + +func TestApplication_App_Ugly(t *testing.T) { + app := &App{} + app.Quit() +} diff --git a/stubs/wails/pkg/application/browser_manager_test.go b/stubs/wails/pkg/application/browser_manager_test.go new file mode 100644 index 00000000..914512a8 --- /dev/null +++ b/stubs/wails/pkg/application/browser_manager_test.go @@ -0,0 +1,61 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBrowserManager_OpenURL_Good(t *testing.T) { + manager := &BrowserManager{} + + err := manager.OpenURL("https://example.com") + + assert.NoError(t, err) + assert.Equal(t, "https://example.com", manager.LastURL) +} + +func TestBrowserManager_OpenURL_Bad(t *testing.T) { + manager := &BrowserManager{} + + err := manager.OpenURL("") + + assert.NoError(t, err) + assert.Empty(t, manager.LastURL) +} + +func TestBrowserManager_OpenURL_Ugly(t *testing.T) { + manager := &BrowserManager{} + + err := manager.OpenURL("file:///tmp/%00") + + assert.NoError(t, err) + assert.Equal(t, "file:///tmp/%00", manager.LastURL) +} + +func TestBrowserManager_OpenFile_Good(t *testing.T) { + manager := &BrowserManager{} + + err := manager.OpenFile("/tmp/report.txt") + + assert.NoError(t, err) + assert.Equal(t, "/tmp/report.txt", manager.LastFile) +} + +func TestBrowserManager_OpenFile_Bad(t *testing.T) { + manager := &BrowserManager{} + + err := manager.OpenFile("") + + assert.NoError(t, err) + assert.Empty(t, manager.LastFile) +} + +func TestBrowserManager_OpenFile_Ugly(t *testing.T) { + manager := &BrowserManager{} + + err := manager.OpenFile("/tmp/\x00report.txt") + + assert.NoError(t, err) + assert.Equal(t, "/tmp/\x00report.txt", manager.LastFile) +} diff --git a/stubs/wails/pkg/application/browser_window_test.go b/stubs/wails/pkg/application/browser_window_test.go new file mode 100644 index 00000000..e94dde2c --- /dev/null +++ b/stubs/wails/pkg/application/browser_window_test.go @@ -0,0 +1,61 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBrowserWindow_NewBrowserWindow_Good(t *testing.T) { + window := NewBrowserWindow(7, "client-abc") + + require.NotNil(t, window) + assert.Equal(t, uint(7), window.ID()) + assert.Equal(t, "browser-7", window.Name()) + assert.Equal(t, "client-abc", window.ClientID()) + assert.True(t, window.IsVisible()) + assert.False(t, window.IsFullscreen()) + assert.False(t, window.IsMaximised()) + assert.False(t, window.IsMinimised()) + assert.False(t, window.IsFocused()) + assert.False(t, window.IsIgnoreMouseEvents()) + assert.False(t, window.Resizable()) + assert.Equal(t, 1.0, window.GetZoom()) + assert.Nil(t, window.NativeWindow()) + assert.True(t, window.shouldUnconditionallyClose()) +} + +func TestBrowserWindow_NewBrowserWindow_Bad(t *testing.T) { + window := NewBrowserWindow(0, "") + + assert.Equal(t, uint(0), window.ID()) + assert.Equal(t, "browser-0", window.Name()) + assert.Empty(t, window.ClientID()) + assert.True(t, window.IsVisible()) +} + +func TestBrowserWindow_NewBrowserWindow_Ugly(t *testing.T) { + window := NewBrowserWindow(99, "client") + + assert.Same(t, window, window.Show()) + assert.Same(t, window, window.Hide()) + assert.Same(t, window, window.Fullscreen()) + assert.Same(t, window, window.Maximise()) + assert.Same(t, window, window.Minimise()) + assert.Same(t, window, window.SetAlwaysOnTop(true)) + assert.Same(t, window, window.SetBackgroundColour(NewRGBA(1, 2, 3, 4))) + assert.Same(t, window, window.SetFrameless(true)) + assert.Same(t, window, window.SetHTML("hi")) + assert.Same(t, window, window.SetMinSize(10, 20)) + assert.Same(t, window, window.SetMaxSize(30, 40)) + assert.Same(t, window, window.SetRelativePosition(1, 2)) + assert.Same(t, window, window.SetResizable(true)) + assert.Same(t, window, window.SetIgnoreMouseEvents(true)) + assert.Same(t, window, window.SetSize(100, 200)) + assert.Same(t, window, window.SetTitle("Title")) + assert.Same(t, window, window.SetURL("https://example.com")) + assert.Same(t, window, window.SetZoom(1.5)) + assert.Same(t, window, window.ZoomReset()) + assert.NoError(t, window.Print()) +} diff --git a/stubs/wails/pkg/application/clipboard_test.go b/stubs/wails/pkg/application/clipboard_test.go new file mode 100644 index 00000000..aecb358f --- /dev/null +++ b/stubs/wails/pkg/application/clipboard_test.go @@ -0,0 +1,73 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestClipboard_SetText_Good(t *testing.T) { + clipboard := &Clipboard{} + + ok := clipboard.SetText("hello") + + assert.True(t, ok) + text, present := clipboard.Text() + assert.True(t, present) + assert.Equal(t, "hello", text) +} + +func TestClipboard_SetText_Bad(t *testing.T) { + clipboard := &Clipboard{} + + ok := clipboard.SetText("") + + assert.True(t, ok) + text, present := clipboard.Text() + assert.True(t, present) + assert.Empty(t, text) +} + +func TestClipboard_SetText_Ugly(t *testing.T) { + clipboard := &Clipboard{} + + ok := clipboard.SetText("line1\nline2") + + assert.True(t, ok) + text, present := clipboard.Text() + require.True(t, present) + assert.Equal(t, "line1\nline2", text) +} + +func TestClipboardManager_Text_Good(t *testing.T) { + manager := &ClipboardManager{} + + ok := manager.SetText("copied") + + assert.True(t, ok) + text, present := manager.Text() + assert.True(t, present) + assert.Equal(t, "copied", text) +} + +func TestClipboardManager_Text_Bad(t *testing.T) { + manager := &ClipboardManager{} + + text, present := manager.Text() + + assert.False(t, present) + assert.Empty(t, text) +} + +func TestClipboardManager_Text_Ugly(t *testing.T) { + manager := &ClipboardManager{} + raw := "zero\x00byte" + + ok := manager.SetText(raw) + + assert.True(t, ok) + text, present := manager.Text() + assert.True(t, present) + assert.Equal(t, raw, text) +} diff --git a/stubs/wails/pkg/application/context_menu_test.go b/stubs/wails/pkg/application/context_menu_test.go new file mode 100644 index 00000000..197bb416 --- /dev/null +++ b/stubs/wails/pkg/application/context_menu_test.go @@ -0,0 +1,72 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestContextMenuManager_Add_Good(t *testing.T) { + manager := &ContextMenuManager{} + menu := manager.New() + menu.Add("Open") + + manager.Add("files", menu) + + got, ok := manager.Get("files") + require.True(t, ok) + require.Same(t, menu, got) + assert.Len(t, manager.GetAll(), 1) +} + +func TestContextMenuManager_Add_Bad(t *testing.T) { + manager := &ContextMenuManager{} + + manager.Add("empty", nil) + + got, ok := manager.Get("empty") + assert.True(t, ok) + assert.Nil(t, got) +} + +func TestContextMenuManager_Add_Ugly(t *testing.T) { + manager := &ContextMenuManager{} + first := manager.New() + second := manager.New() + + manager.Add("dup", first) + manager.Add("dup", second) + + got, ok := manager.Get("dup") + require.True(t, ok) + require.Same(t, second, got) + assert.Len(t, manager.GetAll(), 1) +} + +func TestContextMenuManager_Remove_Good(t *testing.T) { + manager := &ContextMenuManager{} + menu := manager.New() + manager.Add("files", menu) + + manager.Remove("files") + + _, ok := manager.Get("files") + assert.False(t, ok) + assert.Empty(t, manager.GetAll()) +} + +func TestContextMenuManager_Remove_Bad(t *testing.T) { + manager := &ContextMenuManager{} + + manager.Remove("missing") + + assert.Empty(t, manager.GetAll()) +} + +func TestContextMenuManager_Remove_Ugly(t *testing.T) { + manager := &ContextMenuManager{} + manager.Remove("") + + assert.Empty(t, manager.GetAll()) +} diff --git a/stubs/wails/pkg/application/dialog.go b/stubs/wails/pkg/application/dialog.go index 86139114..83e340a0 100644 --- a/stubs/wails/pkg/application/dialog.go +++ b/stubs/wails/pkg/application/dialog.go @@ -262,11 +262,11 @@ type MessageButton struct { // dialog.SetTitle("Done").SetMessage("File saved successfully.") // _ = dialog.Show() type MessageDialog struct { - mu sync.RWMutex - dialogType DialogType - title string - message string - buttons []MessageButton + mu sync.RWMutex + dialogType DialogType + title string + message string + buttons []MessageButton clickedButton string } diff --git a/stubs/wails/pkg/application/dialog_test.go b/stubs/wails/pkg/application/dialog_test.go new file mode 100644 index 00000000..5dc0cb22 --- /dev/null +++ b/stubs/wails/pkg/application/dialog_test.go @@ -0,0 +1,165 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestDialog_OpenFileDialogStruct_Good(t *testing.T) { + dialog := newOpenFileDialog() + dialog.SetOptions(&OpenFileDialogOptions{ + Title: "Pick", + Directory: "/tmp", + Filters: []FileFilter{{DisplayName: "Text", Pattern: "*.txt"}}, + AllowsMultipleSelection: true, + CanChooseDirectories: true, + CanChooseFiles: false, + ShowHiddenFiles: true, + }) + + dialog.SetSelectedFiles([]string{"/tmp/a.txt", "/tmp/b.txt"}) + got, err := dialog.PromptForSingleSelection() + + require.NoError(t, err) + assert.Equal(t, "/tmp/a.txt", got) + paths, err := dialog.PromptForMultipleSelection() + require.NoError(t, err) + assert.Equal(t, []string{"/tmp/a.txt", "/tmp/b.txt"}, paths) +} + +func TestDialog_OpenFileDialogStruct_Bad(t *testing.T) { + dialog := newOpenFileDialog() + dialog.SetOptions(nil) + + got, err := dialog.PromptForSingleSelection() + + require.NoError(t, err) + assert.Empty(t, got) + assert.True(t, dialog.canChooseFiles) +} + +func TestDialog_OpenFileDialogStruct_Ugly(t *testing.T) { + dialog := newOpenFileDialog() + selected := []string{"/tmp/input.txt"} + dialog.SetSelectedFiles(selected) + selected[0] = "/tmp/mutated.txt" + + paths, err := dialog.PromptForMultipleSelection() + + require.NoError(t, err) + assert.Equal(t, []string{"/tmp/input.txt"}, paths) +} + +func TestDialog_SaveFileDialogStruct_Good(t *testing.T) { + dialog := newSaveFileDialog() + dialog.SetOptions(&SaveFileDialogOptions{ + Title: "Export", + Directory: "/tmp", + Filename: "report.csv", + Filters: []FileFilter{{DisplayName: "CSV", Pattern: "*.csv"}}, + ShowHiddenFiles: true, + }) + dialog.SetSelectedPath("/tmp/report.csv") + + got, err := dialog.PromptForSingleSelection() + + require.NoError(t, err) + assert.Equal(t, "/tmp/report.csv", got) +} + +func TestDialog_SaveFileDialogStruct_Bad(t *testing.T) { + dialog := newSaveFileDialog() + dialog.SetOptions(nil) + + got, err := dialog.PromptForSingleSelection() + + require.NoError(t, err) + assert.Empty(t, got) +} + +func TestDialog_SaveFileDialogStruct_Ugly(t *testing.T) { + dialog := newSaveFileDialog() + selected := "/tmp/a.csv" + dialog.SetSelectedPath(selected) + selected = "/tmp/b.csv" + + got, err := dialog.PromptForSingleSelection() + + require.NoError(t, err) + assert.Equal(t, "/tmp/a.csv", got) +} + +func TestDialog_MessageDialog_Good(t *testing.T) { + dialog := newMessageDialog(QuestionDialogType) + dialog.SetTitle("Confirm"). + SetMessage("Proceed?"). + AddButton("Yes"). + AddButton("No"). + SetDefaultButton("Yes"). + SetCancelButton("No") + dialog.SetButtonClickedForStub("Yes") + + got, err := dialog.Show() + + require.NoError(t, err) + assert.Equal(t, "Yes", got) + assert.Equal(t, QuestionDialogType, dialog.dialogType) + assert.Equal(t, "Confirm", dialog.title) + assert.Equal(t, "Proceed?", dialog.message) + require.Len(t, dialog.buttons, 2) + assert.True(t, dialog.buttons[0].IsDefault) + assert.True(t, dialog.buttons[1].IsCancel) +} + +func TestDialog_MessageDialog_Bad(t *testing.T) { + dialog := newMessageDialog(InfoDialogType) + + got, err := dialog.Show() + + require.NoError(t, err) + assert.Empty(t, got) + assert.Equal(t, InfoDialogType, dialog.dialogType) +} + +func TestDialog_MessageDialog_Ugly(t *testing.T) { + dialog := newMessageDialog(ErrorDialogType) + dialog.AddButton("Retry").AddButton("Retry") + dialog.SetDefaultButton("Retry") + dialog.SetCancelButton("Retry") + + require.Len(t, dialog.buttons, 2) + assert.True(t, dialog.buttons[0].IsDefault) + assert.True(t, dialog.buttons[0].IsCancel) + assert.True(t, dialog.buttons[1].IsDefault) + assert.True(t, dialog.buttons[1].IsCancel) +} + +func TestDialog_DialogManager_Good(t *testing.T) { + manager := &DialogManager{} + + assert.Equal(t, InfoDialogType, manager.Info().dialogType) + assert.Equal(t, QuestionDialogType, manager.Question().dialogType) + assert.Equal(t, WarningDialogType, manager.Warning().dialogType) + assert.Equal(t, ErrorDialogType, manager.Error().dialogType) + assert.NotNil(t, manager.OpenFile()) + assert.NotNil(t, manager.SaveFile()) +} + +func TestDialog_DialogManager_Bad(t *testing.T) { + manager := &DialogManager{} + + assert.NotNil(t, manager.OpenFileWithOptions(nil)) + assert.NotNil(t, manager.SaveFileWithOptions(nil)) +} + +func TestDialog_DialogManager_Ugly(t *testing.T) { + manager := &DialogManager{} + + open := manager.OpenFileWithOptions(&OpenFileDialogOptions{AllowsMultipleSelection: true}) + save := manager.SaveFileWithOptions(&SaveFileDialogOptions{Filename: "out.csv"}) + + assert.True(t, open.multipleAllowed) + assert.Equal(t, "out.csv", save.filename) +} diff --git a/stubs/wails/pkg/application/environment.go b/stubs/wails/pkg/application/environment.go index 98651c97..fd3ab4b4 100644 --- a/stubs/wails/pkg/application/environment.go +++ b/stubs/wails/pkg/application/environment.go @@ -21,12 +21,12 @@ type EnvironmentInfo struct { // manager.SetDarkMode(true) // dark := manager.IsDarkMode() // true type EnvironmentManager struct { - mu sync.RWMutex - darkMode bool - accentColour string - operatingSystem string - architecture string - debugMode bool + mu sync.RWMutex + darkMode bool + accentColour string + operatingSystem string + architecture string + debugMode bool } // SetDarkMode sets the dark mode state used by IsDarkMode. diff --git a/stubs/wails/pkg/application/environment_test.go b/stubs/wails/pkg/application/environment_test.go new file mode 100644 index 00000000..9b190c93 --- /dev/null +++ b/stubs/wails/pkg/application/environment_test.go @@ -0,0 +1,92 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEnvironmentManager_IsDarkMode_Good(t *testing.T) { + manager := &EnvironmentManager{} + manager.SetDarkMode(true) + + assert.True(t, manager.IsDarkMode()) +} + +func TestEnvironmentManager_IsDarkMode_Bad(t *testing.T) { + manager := &EnvironmentManager{} + + assert.False(t, manager.IsDarkMode()) +} + +func TestEnvironmentManager_IsDarkMode_Ugly(t *testing.T) { + manager := &EnvironmentManager{} + manager.SetDarkMode(true) + manager.SetDarkMode(false) + + assert.False(t, manager.IsDarkMode()) +} + +func TestEnvironmentManager_GetAccentColor_Good(t *testing.T) { + manager := &EnvironmentManager{} + manager.SetAccentColour("rgb(1,2,3)") + + assert.Equal(t, "rgb(1,2,3)", manager.GetAccentColor()) +} + +func TestEnvironmentManager_GetAccentColor_Bad(t *testing.T) { + manager := &EnvironmentManager{} + + assert.Equal(t, "rgb(0,122,255)", manager.GetAccentColor()) +} + +func TestEnvironmentManager_GetAccentColor_Ugly(t *testing.T) { + manager := &EnvironmentManager{} + manager.SetAccentColour("") + + assert.Equal(t, "rgb(0,122,255)", manager.GetAccentColor()) +} + +func TestEnvironmentManager_Info_Good(t *testing.T) { + manager := &EnvironmentManager{} + manager.SetDarkMode(true) + manager.SetAccentColour("rgb(1,2,3)") + manager.operatingSystem = "linux" + manager.architecture = "amd64" + manager.debugMode = true + + got := manager.Info() + + assert.Equal(t, "linux", got.OS) + assert.Equal(t, "amd64", got.Arch) + assert.True(t, got.Debug) + assert.True(t, got.IsDarkMode) + assert.Equal(t, "rgb(1,2,3)", got.AccentColour) +} + +func TestEnvironmentManager_Info_Bad(t *testing.T) { + manager := &EnvironmentManager{} + + got := manager.Info() + + assert.Empty(t, got.OS) + assert.Empty(t, got.Arch) + assert.False(t, got.Debug) + assert.False(t, got.IsDarkMode) + assert.Empty(t, got.AccentColour) +} + +func TestEnvironmentManager_Info_Ugly(t *testing.T) { + manager := &EnvironmentManager{} + manager.operatingSystem = "plan9" + manager.architecture = "riscv64" + manager.debugMode = true + manager.SetDarkMode(true) + + got := manager.Info() + + assert.Equal(t, "plan9", got.OS) + assert.Equal(t, "riscv64", got.Arch) + assert.True(t, got.Debug) + assert.True(t, got.IsDarkMode) +} diff --git a/stubs/wails/pkg/application/events.go b/stubs/wails/pkg/application/events.go index 3b61f5bb..c7b24354 100644 --- a/stubs/wails/pkg/application/events.go +++ b/stubs/wails/pkg/application/events.go @@ -90,9 +90,9 @@ type applicationEventListener struct { // cancel := manager.On("data:ready", func(e *CustomEvent) { process(e.Data) }) // defer cancel() type EventManager struct { - mu sync.RWMutex - customListeners map[string][]*customEventListener - appListeners map[uint][]*applicationEventListener + mu sync.RWMutex + customListeners map[string][]*customEventListener + appListeners map[uint][]*applicationEventListener } func newEventManager() *EventManager { diff --git a/stubs/wails/pkg/application/events_test.go b/stubs/wails/pkg/application/events_test.go new file mode 100644 index 00000000..cbc44bee --- /dev/null +++ b/stubs/wails/pkg/application/events_test.go @@ -0,0 +1,137 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/wailsapp/wails/v3/pkg/events" +) + +func TestEvents_CustomEvent_Good(t *testing.T) { + event := &CustomEvent{Name: "ready", Data: "payload", Sender: "ui"} + + assert.False(t, event.IsCancelled()) + event.Cancel() + assert.True(t, event.IsCancelled()) +} + +func TestEvents_CustomEvent_Bad(t *testing.T) { + event := &CustomEvent{} + + assert.Empty(t, event.Name) + assert.Nil(t, event.Data) + assert.False(t, event.IsCancelled()) +} + +func TestEvents_CustomEvent_Ugly(t *testing.T) { + event := &CustomEvent{Name: "event", Data: []any{"a", 1}, Sender: "sender"} + + event.Cancel() + event.Cancel() + + assert.True(t, event.IsCancelled()) + assert.Equal(t, []any{"a", 1}, event.Data) +} + +func TestEvents_ApplicationEvent_Good(t *testing.T) { + event := &ApplicationEvent{Id: 7, ctx: newApplicationEventContext()} + + assert.False(t, event.IsCancelled()) + require.NotNil(t, event.Context()) + event.Cancel() + assert.True(t, event.IsCancelled()) +} + +func TestEvents_ApplicationEvent_Bad(t *testing.T) { + event := &ApplicationEvent{} + + assert.Nil(t, event.Context()) + assert.False(t, event.IsCancelled()) +} + +func TestEvents_ApplicationEvent_Ugly(t *testing.T) { + event := &ApplicationEvent{Id: 99} + + event.Cancel() + event.Cancel() + + assert.True(t, event.IsCancelled()) +} + +func TestEvents_EventManager_Emit_Good(t *testing.T) { + manager := newEventManager() + calls := 0 + manager.On("ready", func(event *CustomEvent) { + calls++ + assert.Equal(t, "ready", event.Name) + assert.Equal(t, "payload", event.Data) + event.Cancel() + }) + manager.On("ready", func(*CustomEvent) { + calls++ + }) + + cancelled := manager.Emit("ready", "payload") + + assert.True(t, cancelled) + assert.Equal(t, 1, calls) +} + +func TestEvents_EventManager_Emit_Bad(t *testing.T) { + manager := &EventManager{} + + assert.False(t, manager.Emit("missing")) +} + +func TestEvents_EventManager_Emit_Ugly(t *testing.T) { + manager := newEventManager() + calls := 0 + manager.OnMultiple("tick", func(event *CustomEvent) { + calls++ + assert.Equal(t, []any{1, 2}, event.Data) + }, 1) + + assert.False(t, manager.Emit("tick", 1, 2)) + assert.False(t, manager.Emit("tick", 1, 2)) + assert.Equal(t, 1, calls) +} + +func TestEvents_EventManager_OnApplicationEvent_Good(t *testing.T) { + manager := newEventManager() + eventType := events.ApplicationEventType(42) + calls := 0 + + cancel := manager.OnApplicationEvent(eventType, func(event *ApplicationEvent) { + calls++ + require.NotNil(t, event) + event.Cancel() + }) + + require.Len(t, manager.appListeners[uint(eventType)], 1) + cancel() + assert.Empty(t, manager.appListeners[uint(eventType)]) + assert.Equal(t, 0, calls) +} + +func TestEvents_EventManager_OnApplicationEvent_Bad(t *testing.T) { + manager := &EventManager{} + eventType := events.ApplicationEventType(7) + + cancel := manager.OnApplicationEvent(eventType, func(*ApplicationEvent) {}) + require.NotNil(t, cancel) + cancel() + + assert.Empty(t, manager.appListeners[uint(eventType)]) +} + +func TestEvents_EventManager_OnApplicationEvent_Ugly(t *testing.T) { + manager := newEventManager() + eventType := events.ApplicationEventType(1) + manager.OnApplicationEvent(eventType, func(*ApplicationEvent) {}) + + assert.Len(t, manager.appListeners[uint(eventType)], 1) + manager.Off("does-not-exist") + assert.Len(t, manager.appListeners[uint(eventType)], 1) +} diff --git a/stubs/wails/pkg/application/keybinding_test.go b/stubs/wails/pkg/application/keybinding_test.go new file mode 100644 index 00000000..1de1814b --- /dev/null +++ b/stubs/wails/pkg/application/keybinding_test.go @@ -0,0 +1,71 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestKeyBindingManager_Add_Good(t *testing.T) { + manager := &KeyBindingManager{} + calls := 0 + + manager.Add("CmdOrCtrl+K", func(window Window) { + calls++ + assert.Nil(t, window) + }) + + handled := manager.Process("CmdOrCtrl+K", nil) + + assert.True(t, handled) + assert.Equal(t, 1, calls) + assert.Len(t, manager.GetAll(), 1) +} + +func TestKeyBindingManager_Add_Bad(t *testing.T) { + manager := &KeyBindingManager{} + + handled := manager.Process("missing", nil) + + assert.False(t, handled) + assert.Empty(t, manager.GetAll()) +} + +func TestKeyBindingManager_Add_Ugly(t *testing.T) { + manager := &KeyBindingManager{} + calls := 0 + + manager.Add("CmdOrCtrl+K", func(Window) { calls++ }) + manager.Add("CmdOrCtrl+K", func(Window) { calls += 10 }) + + handled := manager.Process("CmdOrCtrl+K", nil) + + assert.True(t, handled) + assert.Equal(t, 10, calls) +} + +func TestKeyBindingManager_Remove_Good(t *testing.T) { + manager := &KeyBindingManager{} + manager.Add("CmdOrCtrl+K", func(Window) {}) + + manager.Remove("CmdOrCtrl+K") + + assert.False(t, manager.Process("CmdOrCtrl+K", nil)) + assert.Empty(t, manager.GetAll()) +} + +func TestKeyBindingManager_Remove_Bad(t *testing.T) { + manager := &KeyBindingManager{} + + manager.Remove("missing") + + assert.Empty(t, manager.GetAll()) +} + +func TestKeyBindingManager_Remove_Ugly(t *testing.T) { + manager := &KeyBindingManager{} + + manager.Remove("") + + assert.Empty(t, manager.GetAll()) +} diff --git a/stubs/wails/pkg/application/menuitem_test.go b/stubs/wails/pkg/application/menuitem_test.go new file mode 100644 index 00000000..9dfb0bdb --- /dev/null +++ b/stubs/wails/pkg/application/menuitem_test.go @@ -0,0 +1,50 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMenuItem_NewRole_Good(t *testing.T) { + cases := []struct { + role Role + want string + }{ + {AppMenu, "App"}, + {FileMenu, "File"}, + {EditMenu, "Edit"}, + {HelpMenu, "Help"}, + {Quit, "Quit"}, + } + + for _, tc := range cases { + t.Run(tc.want, func(t *testing.T) { + got := NewRole(tc.role) + assert.Equal(t, tc.want, got.Label) + assert.True(t, got.Enabled) + }) + } +} + +func TestMenuItem_NewRole_Bad(t *testing.T) { + got := NewRole(Role(-1)) + + assert.Empty(t, got.Label) + assert.True(t, got.Enabled) + assert.Equal(t, "unknown", MenuRole(999).String()) +} + +func TestMenuItem_NewRole_Ugly(t *testing.T) { + item := NewMenuItem("Open") + item.SetAccelerator("CmdOrCtrl+O") + item.SetTooltip("Open a file") + item.SetChecked(true) + item.SetEnabled(false) + + assert.Equal(t, "Open", item.Label) + assert.Equal(t, "CmdOrCtrl+O", item.GetAccelerator()) + assert.Equal(t, "Open a file", item.Tooltip) + assert.True(t, item.Checked) + assert.False(t, item.Enabled) +} diff --git a/stubs/wails/pkg/application/screen_test.go b/stubs/wails/pkg/application/screen_test.go new file mode 100644 index 00000000..4425e633 --- /dev/null +++ b/stubs/wails/pkg/application/screen_test.go @@ -0,0 +1,67 @@ +package application + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestScreen_Rect_Good(t *testing.T) { + rect := Rect{X: 10, Y: 20, Width: 300, Height: 200} + + assert.Equal(t, Point{X: 10, Y: 20}, rect.Origin()) + assert.Equal(t, Point{X: 310, Y: 220}, rect.Corner()) + assert.False(t, rect.IsEmpty()) + assert.True(t, rect.Contains(Point{X: 10, Y: 20})) + assert.False(t, rect.Contains(Point{X: 310, Y: 220})) + assert.Equal(t, Size{Width: 300, Height: 200}, rect.RectSize()) +} + +func TestScreen_Rect_Bad(t *testing.T) { + rect := Rect{} + + assert.True(t, rect.IsEmpty()) + assert.False(t, rect.Contains(Point{})) +} + +func TestScreen_Rect_Ugly(t *testing.T) { + rect := Rect{X: -10, Y: -5, Width: 10, Height: 5} + + assert.False(t, rect.IsEmpty()) + assert.True(t, rect.Contains(Point{X: -10, Y: -5})) +} + +func TestScreenManager_SetScreens_Good(t *testing.T) { + manager := &ScreenManager{} + primary := &Screen{ID: "1", IsPrimary: true} + secondary := &Screen{ID: "2"} + + manager.SetScreens([]*Screen{primary, secondary}) + + require.Same(t, primary, manager.GetPrimary()) + require.Same(t, primary, manager.GetCurrent()) + assert.Equal(t, []*Screen{primary, secondary}, manager.GetAll()) +} + +func TestScreenManager_SetScreens_Bad(t *testing.T) { + manager := &ScreenManager{} + + manager.SetScreens(nil) + + assert.Nil(t, manager.GetPrimary()) + assert.Nil(t, manager.GetCurrent()) + assert.Empty(t, manager.GetAll()) +} + +func TestScreenManager_SetScreens_Ugly(t *testing.T) { + manager := &ScreenManager{} + primary := &Screen{ID: "1", IsPrimary: true} + current := &Screen{ID: "current"} + + manager.SetCurrent(current) + manager.SetScreens([]*Screen{primary}) + + require.Same(t, primary, manager.GetPrimary()) + require.Same(t, current, manager.GetCurrent()) +} diff --git a/stubs/wails/pkg/application/services_test.go b/stubs/wails/pkg/application/services_test.go new file mode 100644 index 00000000..7e6b1465 --- /dev/null +++ b/stubs/wails/pkg/application/services_test.go @@ -0,0 +1,52 @@ +package application + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" +) + +type namedService struct{} + +func (namedService) ServiceName() string { return "named" } + +type plainService struct{} + +func TestServices_NewService_Good(t *testing.T) { + instance := &plainService{} + service := NewService(instance) + + assert.Same(t, instance, service.Instance()) + assert.Equal(t, DefaultServiceOptions, service.Options()) + assert.Equal(t, "application.plainService", getServiceName(service)) +} + +func TestServices_NewService_Bad(t *testing.T) { + instance := &namedService{} + service := NewServiceWithOptions(instance, ServiceOptions{Name: "explicit"}) + + assert.Same(t, instance, service.Instance()) + assert.Equal(t, "explicit", getServiceName(service)) +} + +func TestServices_NewService_Ugly(t *testing.T) { + instance := &namedService{} + service := NewService(instance) + + assert.Equal(t, "named", getServiceName(service)) +} + +func TestServices_ServiceInterfaces_Good(t *testing.T) { + var _ ServiceName = namedService{} + var _ ServiceStartup = (*startupService)(nil) + var _ ServiceShutdown = (*shutdownService)(nil) +} + +type startupService struct{} + +func (*startupService) ServiceStartup(context.Context, ServiceOptions) error { return nil } + +type shutdownService struct{} + +func (*shutdownService) ServiceShutdown() error { return nil }