gui/pkg/window/service_test.go
Virgil 77e03060ac
Some checks failed
Security Scan / security (push) Failing after 31s
Test / test (push) Successful in 1m28s
feat(window): expose visibility and minimized state
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-02 14:30:42 +00:00

296 lines
8.5 KiB
Go

package window
import (
"context"
"sync"
"testing"
"forge.lthn.ai/core/go/pkg/core"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func newTestWindowService(t *testing.T) (*Service, *core.Core) {
t.Helper()
c, err := core.New(
core.WithService(Register(newMockPlatform())),
core.WithServiceLock(),
)
require.NoError(t, err)
require.NoError(t, c.ServiceStartup(context.Background(), nil))
svc := core.MustServiceFor[*Service](c, "window")
return svc, c
}
func TestRegister_Good(t *testing.T) {
svc, _ := newTestWindowService(t)
assert.NotNil(t, svc)
assert.NotNil(t, svc.manager)
}
func TestApplyConfig_Good(t *testing.T) {
svc, _ := newTestWindowService(t)
svc.applyConfig(map[string]any{
"default_width": 1500,
"default_height": 900,
})
pw, err := svc.manager.Open()
require.NoError(t, err)
w, h := pw.Size()
assert.Equal(t, 1500, w)
assert.Equal(t, 900, h)
}
func TestTaskOpenWindow_Good(t *testing.T) {
_, c := newTestWindowService(t)
result, handled, err := c.PERFORM(TaskOpenWindow{
Opts: []WindowOption{WithName("test"), WithURL("/")},
})
require.NoError(t, err)
assert.True(t, handled)
info := result.(WindowInfo)
assert.Equal(t, "test", info.Name)
}
func TestTaskOpenWindowDescriptor_Good(t *testing.T) {
_, c := newTestWindowService(t)
result, handled, err := c.PERFORM(TaskOpenWindow{
Window: &Window{Name: "descriptor", Title: "Descriptor", Width: 640, Height: 480},
})
require.NoError(t, err)
assert.True(t, handled)
info := result.(WindowInfo)
assert.Equal(t, "descriptor", info.Name)
assert.Equal(t, "Descriptor", info.Title)
}
func TestTaskOpenWindow_Bad(t *testing.T) {
// No window service registered — PERFORM returns handled=false
c, err := core.New(core.WithServiceLock())
require.NoError(t, err)
_, handled, _ := c.PERFORM(TaskOpenWindow{})
assert.False(t, handled)
}
func TestQueryWindowList_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("a")}})
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("b")}})
result, handled, err := c.QUERY(QueryWindowList{})
require.NoError(t, err)
assert.True(t, handled)
list := result.([]WindowInfo)
assert.Len(t, list, 2)
}
func TestQueryWindowByName_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
result, handled, err := c.QUERY(QueryWindowByName{Name: "test"})
require.NoError(t, err)
assert.True(t, handled)
info := result.(*WindowInfo)
assert.Equal(t, "test", info.Name)
assert.True(t, info.Visible)
assert.False(t, info.Minimized)
}
func TestQueryWindowByName_Bad(t *testing.T) {
_, c := newTestWindowService(t)
result, handled, err := c.QUERY(QueryWindowByName{Name: "nonexistent"})
require.NoError(t, err)
assert.True(t, handled) // handled=true, result is nil (not found)
assert.Nil(t, result)
}
func TestTaskCloseWindow_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
_, handled, err := c.PERFORM(TaskCloseWindow{Name: "test"})
require.NoError(t, err)
assert.True(t, handled)
// Verify window is removed
result, _, _ := c.QUERY(QueryWindowByName{Name: "test"})
assert.Nil(t, result)
}
func TestTaskCloseWindow_Bad(t *testing.T) {
_, c := newTestWindowService(t)
_, handled, err := c.PERFORM(TaskCloseWindow{Name: "nonexistent"})
assert.True(t, handled)
assert.Error(t, err)
}
func TestTaskSetPosition_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
_, handled, err := c.PERFORM(TaskSetPosition{Name: "test", X: 100, Y: 200})
require.NoError(t, err)
assert.True(t, handled)
result, _, _ := c.QUERY(QueryWindowByName{Name: "test"})
info := result.(*WindowInfo)
assert.Equal(t, 100, info.X)
assert.Equal(t, 200, info.Y)
}
func TestTaskSetSize_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
_, handled, err := c.PERFORM(TaskSetSize{Name: "test", W: 800, H: 600})
require.NoError(t, err)
assert.True(t, handled)
result, _, _ := c.QUERY(QueryWindowByName{Name: "test"})
info := result.(*WindowInfo)
assert.Equal(t, 800, info.Width)
assert.Equal(t, 600, info.Height)
}
func TestTaskMinimiseAndVisibility_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
_, handled, err := c.PERFORM(TaskMinimise{Name: "test"})
require.NoError(t, err)
assert.True(t, handled)
result, _, _ := c.QUERY(QueryWindowByName{Name: "test"})
info := result.(*WindowInfo)
assert.True(t, info.Minimized)
assert.False(t, info.Visible)
_, handled, err = c.PERFORM(TaskSetVisibility{Name: "test", Visible: true})
require.NoError(t, err)
assert.True(t, handled)
result, _, _ = c.QUERY(QueryWindowByName{Name: "test"})
info = result.(*WindowInfo)
assert.True(t, info.Visible)
}
func TestTaskSetAlwaysOnTop_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
_, handled, err := c.PERFORM(TaskSetAlwaysOnTop{Name: "test", AlwaysOnTop: true})
require.NoError(t, err)
assert.True(t, handled)
svc := core.MustServiceFor[*Service](c, "window")
pw, ok := svc.Manager().Get("test")
require.True(t, ok)
assert.True(t, pw.(*mockWindow).alwaysOnTop)
}
func TestTaskSetBackgroundColour_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
_, handled, err := c.PERFORM(TaskSetBackgroundColour{
Name: "test", Red: 10, Green: 20, Blue: 30, Alpha: 40,
})
require.NoError(t, err)
assert.True(t, handled)
svc := core.MustServiceFor[*Service](c, "window")
pw, ok := svc.Manager().Get("test")
require.True(t, ok)
assert.Equal(t, [4]uint8{10, 20, 30, 40}, pw.(*mockWindow).backgroundColor)
}
func TestTaskStackWindows_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("one")}})
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("two")}})
_, handled, err := c.PERFORM(TaskStackWindows{
Windows: []string{"one", "two"},
OffsetX: 20,
OffsetY: 30,
})
require.NoError(t, err)
assert.True(t, handled)
result, _, _ := c.QUERY(QueryWindowByName{Name: "two"})
info := result.(*WindowInfo)
assert.Equal(t, 20, info.X)
assert.Equal(t, 30, info.Y)
}
func TestTaskApplyWorkflow_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("editor")}})
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("assistant")}})
_, handled, err := c.PERFORM(TaskApplyWorkflow{
Workflow: WorkflowCoding,
Windows: []string{"editor", "assistant"},
})
require.NoError(t, err)
assert.True(t, handled)
editorResult, _, _ := c.QUERY(QueryWindowByName{Name: "editor"})
assistantResult, _, _ := c.QUERY(QueryWindowByName{Name: "assistant"})
editor := editorResult.(*WindowInfo)
assistant := assistantResult.(*WindowInfo)
assert.Greater(t, editor.Width, assistant.Width)
assert.Equal(t, editor.Width, assistant.X)
}
func TestTaskMaximise_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
_, handled, err := c.PERFORM(TaskMaximise{Name: "test"})
require.NoError(t, err)
assert.True(t, handled)
result, _, _ := c.QUERY(QueryWindowByName{Name: "test"})
info := result.(*WindowInfo)
assert.True(t, info.Maximized)
}
func TestFileDrop_Good(t *testing.T) {
_, c := newTestWindowService(t)
// Open a window
result, _, _ := c.PERFORM(TaskOpenWindow{
Opts: []WindowOption{WithName("drop-test")},
})
info := result.(WindowInfo)
assert.Equal(t, "drop-test", info.Name)
// Capture broadcast actions
var dropped ActionFilesDropped
var mu sync.Mutex
c.RegisterAction(func(_ *core.Core, msg core.Message) error {
if a, ok := msg.(ActionFilesDropped); ok {
mu.Lock()
dropped = a
mu.Unlock()
}
return nil
})
// Get the mock window and simulate file drop
svc := core.MustServiceFor[*Service](c, "window")
pw, ok := svc.Manager().Get("drop-test")
require.True(t, ok)
mw := pw.(*mockWindow)
mw.emitFileDrop([]string{"/tmp/file1.txt", "/tmp/file2.txt"}, "upload-zone")
mu.Lock()
assert.Equal(t, "drop-test", dropped.Name)
assert.Equal(t, []string{"/tmp/file1.txt", "/tmp/file2.txt"}, dropped.Paths)
assert.Equal(t, "upload-zone", dropped.TargetID)
mu.Unlock()
}