gui/pkg/display/api_wrappers_test.go
Snider fb43e9a729
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run
Add display wrapper coverage
2026-04-17 19:47:15 +01:00

371 lines
9.8 KiB
Go

package display
import (
"context"
"testing"
core "dappco.re/go/core"
"forge.lthn.ai/core/gui/pkg/clipboard"
"forge.lthn.ai/core/gui/pkg/environment"
"forge.lthn.ai/core/gui/pkg/notification"
"forge.lthn.ai/core/gui/pkg/systray"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type errorOnlyWrapperCase struct {
name string
action string
call func(*Service) error
setupGood func(*testing.T, *core.Core)
}
func runErrorOnlyWrapperCase(t *testing.T, tc errorOnlyWrapperCase) {
t.Helper()
t.Run("good", func(t *testing.T) {
svc, c := newTestDisplayAPIService(t)
if tc.setupGood != nil {
tc.setupGood(t, c)
}
require.NoError(t, tc.call(svc))
})
t.Run("bad", func(t *testing.T) {
svc, c := newTestDisplayAPIService(t)
c.Action(tc.action, func(_ context.Context, _ core.Options) core.Result {
return core.Result{Value: assert.AnError, OK: false}
})
err := tc.call(svc)
require.Error(t, err)
assert.Equal(t, assert.AnError, err)
})
t.Run("ugly", func(t *testing.T) {
svc, c := newTestDisplayAPIService(t)
c.Action(tc.action, func(_ context.Context, _ core.Options) core.Result {
return core.Result{Value: "unexpected", OK: false}
})
err := tc.call(svc)
require.Error(t, err)
assert.Contains(t, err.Error(), tc.action)
})
}
func TestDisplayAPI_TrayWrappers(t *testing.T) {
cases := []errorOnlyWrapperCase{
{
name: "SetTrayTooltip",
action: "systray.setTooltip",
call: func(svc *Service) error {
return svc.SetTrayTooltip("Helper tooltip")
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("systray.setTooltip", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(systray.TaskSetTrayTooltip)
assert.Equal(t, "Helper tooltip", task.Tooltip)
return core.Result{OK: true}
})
},
},
{
name: "SetTrayLabel",
action: "systray.setLabel",
call: func(svc *Service) error {
return svc.SetTrayLabel("Launcher")
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("systray.setLabel", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(systray.TaskSetTrayLabel)
assert.Equal(t, "Launcher", task.Label)
return core.Result{OK: true}
})
},
},
{
name: "SetTrayMenu",
action: "systray.setMenu",
call: func(svc *Service) error {
return svc.SetTrayMenu([]TrayMenuItem{
{Label: "Open", ActionID: "open"},
{
Label: "More",
ActionID: "more",
Children: []TrayMenuItem{{Label: "Nested", ActionID: "nested"}},
},
})
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("systray.setMenu", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(systray.TaskSetTrayMenu)
require.Len(t, task.Items, 2)
assert.Equal(t, "Open", task.Items[0].Label)
require.Len(t, task.Items[1].Submenu, 1)
assert.Equal(t, "nested", task.Items[1].Submenu[0].ActionID)
return core.Result{OK: true}
})
},
},
{
name: "ShowTrayMessage",
action: "systray.showMessage",
call: func(svc *Service) error {
return svc.ShowTrayMessage("Status", "Task complete")
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("systray.showMessage", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(systray.TaskShowMessage)
assert.Equal(t, "Status", task.Title)
assert.Equal(t, "Task complete", task.Message)
return core.Result{OK: true}
})
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
runErrorOnlyWrapperCase(t, tc)
})
}
}
func TestDisplayAPI_ClipboardWrappers(t *testing.T) {
t.Run("ClearClipboard", func(t *testing.T) {
runErrorOnlyWrapperCase(t, errorOnlyWrapperCase{
name: "ClearClipboard",
action: "clipboard.clear",
call: func(svc *Service) error {
return svc.ClearClipboard()
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("clipboard.clear", func(_ context.Context, opts core.Options) core.Result {
assert.Equal(t, 0, opts.Len())
return core.Result{OK: true}
})
},
})
})
t.Run("HasClipboard", func(t *testing.T) {
svc, c := newTestDisplayAPIService(t)
c.RegisterQuery(func(_ *core.Core, q core.Query) core.Result {
switch q.(type) {
case clipboard.QueryText:
return core.Result{
Value: clipboard.ClipboardContent{
Text: "present",
HasContent: true,
},
OK: true,
}
default:
return core.Result{}
}
})
assert.True(t, svc.HasClipboard())
svc, c = newTestDisplayAPIService(t)
c.RegisterQuery(func(_ *core.Core, q core.Query) core.Result {
switch q.(type) {
case clipboard.QueryText:
return core.Result{
Value: clipboard.ClipboardContent{
Text: "",
HasContent: false,
},
OK: true,
}
default:
return core.Result{}
}
})
assert.False(t, svc.HasClipboard())
svc, c = newTestDisplayAPIService(t)
c.RegisterQuery(func(_ *core.Core, q core.Query) core.Result {
switch q.(type) {
case clipboard.QueryText:
return core.Result{OK: false}
default:
return core.Result{}
}
})
assert.False(t, svc.HasClipboard())
})
}
func TestDisplayAPI_NotificationWrappers(t *testing.T) {
cases := []errorOnlyWrapperCase{
{
name: "ShowNotification",
action: "notification.send",
call: func(svc *Service) error {
return svc.ShowNotification(NotificationOptions{
ID: "alert-1",
Title: "Deploy",
Message: "Done",
Subtitle: "CI",
})
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("notification.send", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(notification.TaskSend)
assert.Equal(t, notification.NotificationOptions{
ID: "alert-1",
Title: "Deploy",
Message: "Done",
Subtitle: "CI",
}, task.Options)
return core.Result{OK: true}
})
},
},
{
name: "ShowInfoNotification",
action: "notification.send",
call: func(svc *Service) error {
return svc.ShowInfoNotification("Info", "Ready")
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("notification.send", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(notification.TaskSend)
assert.Equal(t, notification.NotificationOptions{
Title: "Info",
Message: "Ready",
}, task.Options)
return core.Result{OK: true}
})
},
},
{
name: "ShowWarningNotification",
action: "notification.send",
call: func(svc *Service) error {
return svc.ShowWarningNotification("Warn", "Careful")
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("notification.send", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(notification.TaskSend)
assert.Equal(t, notification.NotificationOptions{
Title: "Warn",
Message: "Careful",
Severity: notification.SeverityWarning,
}, task.Options)
return core.Result{OK: true}
})
},
},
{
name: "ShowErrorNotification",
action: "notification.send",
call: func(svc *Service) error {
return svc.ShowErrorNotification("Error", "Failed")
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("notification.send", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(notification.TaskSend)
assert.Equal(t, notification.NotificationOptions{
Title: "Error",
Message: "Failed",
Severity: notification.SeverityError,
}, task.Options)
return core.Result{OK: true}
})
},
},
{
name: "ClearNotifications",
action: "notification.clear",
call: func(svc *Service) error {
return svc.ClearNotifications()
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("notification.clear", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(notification.TaskClear)
assert.Empty(t, task.ID)
return core.Result{OK: true}
})
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
runErrorOnlyWrapperCase(t, tc)
})
}
}
func TestDisplayAPI_ThemeWrapper(t *testing.T) {
runErrorOnlyWrapperCase(t, errorOnlyWrapperCase{
name: "SetTheme",
action: "environment.setTheme",
call: func(svc *Service) error {
return svc.SetTheme("system")
},
setupGood: func(t *testing.T, c *core.Core) {
t.Helper()
c.Action("environment.setTheme", func(_ context.Context, opts core.Options) core.Result {
task := opts.Get("task").Value.(environment.TaskSetTheme)
assert.Equal(t, "system", task.Theme)
return core.Result{OK: true}
})
},
})
}
func TestDisplayAPI_GetTrayInfo(t *testing.T) {
svc, c := newTestDisplayAPIService(t)
c.RegisterQuery(func(_ *core.Core, q core.Query) core.Result {
switch q.(type) {
case systray.QueryInfo:
return core.Result{
Value: map[string]any{
"tooltip": "Ready",
},
OK: true,
}
default:
return core.Result{}
}
})
info := svc.GetTrayInfo()
require.NotNil(t, info)
assert.Equal(t, "Ready", info["tooltip"])
svc, c = newTestDisplayAPIService(t)
c.RegisterQuery(func(_ *core.Core, q core.Query) core.Result {
switch q.(type) {
case systray.QueryInfo:
return core.Result{Value: "unexpected", OK: true}
default:
return core.Result{}
}
})
assert.Nil(t, svc.GetTrayInfo())
svc, c = newTestDisplayAPIService(t)
c.RegisterQuery(func(_ *core.Core, q core.Query) core.Result {
switch q.(type) {
case systray.QueryInfo:
return core.Result{OK: false}
default:
return core.Result{}
}
})
assert.Nil(t, svc.GetTrayInfo())
}