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 requireOpenWindow(t *testing.T, c *core.Core, window Window) WindowInfo { t.Helper() result, handled, err := c.PERFORM(TaskOpenWindow{Window: &window}) require.NoError(t, err) require.True(t, handled) return result.(WindowInfo) } func TestRegister_Good(t *testing.T) { svc, _ := newTestWindowService(t) assert.NotNil(t, svc) assert.NotNil(t, svc.manager) } func TestTaskOpenWindow_Good(t *testing.T) { _, c := newTestWindowService(t) result, handled, err := c.PERFORM(TaskOpenWindow{ Window: &Window{Name: "test", URL: "/"}, }) require.NoError(t, err) assert.True(t, handled) info := result.(WindowInfo) assert.Equal(t, "test", info.Name) } func TestTaskOpenWindow_Bad_MissingWindow(t *testing.T) { _, c := newTestWindowService(t) result, handled, err := c.PERFORM(TaskOpenWindow{}) assert.True(t, handled) assert.Error(t, err) assert.Nil(t, result) } 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) _ = requireOpenWindow(t, c, Window{Name: "a"}) _ = requireOpenWindow(t, c, Window{Name: "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) _ = requireOpenWindow(t, c, Window{Name: "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) } 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) _ = requireOpenWindow(t, c, Window{Name: "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) _ = requireOpenWindow(t, c, Window{Name: "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) _ = requireOpenWindow(t, c, Window{Name: "test"}) _, handled, err := c.PERFORM(TaskSetSize{Name: "test", Width: 800, Height: 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 TestTaskMaximise_Good(t *testing.T) { _, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "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 info := requireOpenWindow(t, c, Window{Name: "drop-test"}) 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() } // --- TaskMinimise --- func TestTaskMinimise_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "test"}) _, handled, err := c.PERFORM(TaskMinimise{Name: "test"}) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("test") require.True(t, ok) mw := pw.(*mockWindow) assert.True(t, mw.minimised) } func TestTaskMinimise_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskMinimise{Name: "nonexistent"}) assert.True(t, handled) assert.Error(t, err) } // --- TaskFocus --- func TestTaskFocus_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "test"}) _, handled, err := c.PERFORM(TaskFocus{Name: "test"}) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("test") require.True(t, ok) mw := pw.(*mockWindow) assert.True(t, mw.focused) } func TestTaskFocus_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskFocus{Name: "nonexistent"}) assert.True(t, handled) assert.Error(t, err) } // --- TaskRestore --- func TestTaskRestore_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "test"}) // First maximise, then restore _, _, _ = c.PERFORM(TaskMaximise{Name: "test"}) _, handled, err := c.PERFORM(TaskRestore{Name: "test"}) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("test") require.True(t, ok) mw := pw.(*mockWindow) assert.False(t, mw.maximised) // Verify state was updated state, ok := svc.Manager().State().GetState("test") assert.True(t, ok) assert.False(t, state.Maximized) } func TestTaskRestore_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskRestore{Name: "nonexistent"}) assert.True(t, handled) assert.Error(t, err) } // --- TaskSetTitle --- func TestTaskSetTitle_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "test"}) _, handled, err := c.PERFORM(TaskSetTitle{Name: "test", Title: "New Title"}) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("test") require.True(t, ok) assert.Equal(t, "New Title", pw.Title()) } func TestTaskSetTitle_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskSetTitle{Name: "nonexistent", Title: "Nope"}) assert.True(t, handled) assert.Error(t, err) } // --- TaskSetAlwaysOnTop --- func TestTaskSetAlwaysOnTop_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "test"}) _, handled, err := c.PERFORM(TaskSetAlwaysOnTop{Name: "test", AlwaysOnTop: true}) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("test") require.True(t, ok) mw := pw.(*mockWindow) assert.True(t, mw.alwaysOnTop) } func TestTaskSetAlwaysOnTop_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskSetAlwaysOnTop{Name: "nonexistent", AlwaysOnTop: true}) assert.True(t, handled) assert.Error(t, err) } // --- TaskSetBackgroundColour --- func TestTaskSetBackgroundColour_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "test"}) _, handled, err := c.PERFORM(TaskSetBackgroundColour{ Name: "test", Red: 10, Green: 20, Blue: 30, Alpha: 40, }) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("test") require.True(t, ok) mw := pw.(*mockWindow) assert.Equal(t, [4]uint8{10, 20, 30, 40}, mw.backgroundColour) } func TestTaskSetBackgroundColour_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskSetBackgroundColour{Name: "nonexistent", Red: 1, Green: 2, Blue: 3, Alpha: 4}) assert.True(t, handled) assert.Error(t, err) } // --- TaskSetVisibility --- func TestTaskSetVisibility_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "test"}) _, handled, err := c.PERFORM(TaskSetVisibility{Name: "test", Visible: true}) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("test") require.True(t, ok) mw := pw.(*mockWindow) assert.True(t, mw.visible) // Now hide it _, handled, err = c.PERFORM(TaskSetVisibility{Name: "test", Visible: false}) require.NoError(t, err) assert.True(t, handled) assert.False(t, mw.visible) } func TestTaskSetVisibility_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskSetVisibility{Name: "nonexistent", Visible: true}) assert.True(t, handled) assert.Error(t, err) } // --- TaskFullscreen --- func TestTaskFullscreen_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "test"}) // Enter fullscreen _, handled, err := c.PERFORM(TaskFullscreen{Name: "test", Fullscreen: true}) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("test") require.True(t, ok) mw := pw.(*mockWindow) assert.True(t, mw.fullscreened) // Exit fullscreen _, handled, err = c.PERFORM(TaskFullscreen{Name: "test", Fullscreen: false}) require.NoError(t, err) assert.True(t, handled) assert.False(t, mw.fullscreened) } func TestTaskFullscreen_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskFullscreen{Name: "nonexistent", Fullscreen: true}) assert.True(t, handled) assert.Error(t, err) } // --- TaskSaveLayout --- func TestTaskSaveLayout_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "editor", Width: 960, Height: 1080, X: 0, Y: 0}) _ = requireOpenWindow(t, c, Window{Name: "terminal", Width: 960, Height: 1080, X: 960, Y: 0}) _, handled, err := c.PERFORM(TaskSaveLayout{Name: "coding"}) require.NoError(t, err) assert.True(t, handled) // Verify layout was saved with correct window states layout, ok := svc.Manager().Layout().GetLayout("coding") assert.True(t, ok) assert.Equal(t, "coding", layout.Name) assert.Len(t, layout.Windows, 2) editorState, ok := layout.Windows["editor"] assert.True(t, ok) assert.Equal(t, 0, editorState.X) assert.Equal(t, 960, editorState.Width) termState, ok := layout.Windows["terminal"] assert.True(t, ok) assert.Equal(t, 960, termState.X) assert.Equal(t, 960, termState.Width) } func TestTaskSaveLayout_Bad(t *testing.T) { _, c := newTestWindowService(t) // Saving an empty layout with empty name returns an error from LayoutManager _, handled, err := c.PERFORM(TaskSaveLayout{Name: ""}) assert.True(t, handled) assert.Error(t, err) } // --- TaskRestoreLayout --- func TestTaskRestoreLayout_Good(t *testing.T) { svc, c := newTestWindowService(t) // Open windows _ = requireOpenWindow(t, c, Window{Name: "editor", Width: 800, Height: 600, X: 0, Y: 0}) _ = requireOpenWindow(t, c, Window{Name: "terminal", Width: 800, Height: 600, X: 0, Y: 0}) // Save a layout with specific positions _, _, _ = c.PERFORM(TaskSaveLayout{Name: "coding"}) // Move the windows to different positions _, _, _ = c.PERFORM(TaskSetPosition{Name: "editor", X: 500, Y: 500}) _, _, _ = c.PERFORM(TaskSetPosition{Name: "terminal", X: 600, Y: 600}) // Restore the layout _, handled, err := c.PERFORM(TaskRestoreLayout{Name: "coding"}) require.NoError(t, err) assert.True(t, handled) // Verify windows were moved back to saved positions pw, ok := svc.Manager().Get("editor") require.True(t, ok) x, y := pw.Position() assert.Equal(t, 0, x) assert.Equal(t, 0, y) pw2, ok := svc.Manager().Get("terminal") require.True(t, ok) x2, y2 := pw2.Position() assert.Equal(t, 0, x2) assert.Equal(t, 0, y2) editorState, ok := svc.Manager().State().GetState("editor") require.True(t, ok) assert.Equal(t, 0, editorState.X) assert.Equal(t, 0, editorState.Y) terminalState, ok := svc.Manager().State().GetState("terminal") require.True(t, ok) assert.Equal(t, 0, terminalState.X) assert.Equal(t, 0, terminalState.Y) } func TestTaskRestoreLayout_Bad(t *testing.T) { _, c := newTestWindowService(t) _, handled, err := c.PERFORM(TaskRestoreLayout{Name: "nonexistent"}) assert.True(t, handled) assert.Error(t, err) } // --- TaskStackWindows --- func TestTaskStackWindows_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "s1", Width: 800, Height: 600}) _ = requireOpenWindow(t, c, Window{Name: "s2", Width: 800, Height: 600}) _, handled, err := c.PERFORM(TaskStackWindows{Windows: []string{"s1", "s2"}, OffsetX: 25, OffsetY: 35}) require.NoError(t, err) assert.True(t, handled) pw, ok := svc.Manager().Get("s2") require.True(t, ok) x, y := pw.Position() assert.Equal(t, 25, x) assert.Equal(t, 35, y) } // --- TaskApplyWorkflow --- func TestTaskApplyWorkflow_Good(t *testing.T) { svc, c := newTestWindowService(t) _ = requireOpenWindow(t, c, Window{Name: "editor", Width: 800, Height: 600}) _ = requireOpenWindow(t, c, Window{Name: "terminal", Width: 800, Height: 600}) _, handled, err := c.PERFORM(TaskApplyWorkflow{Workflow: "side-by-side"}) require.NoError(t, err) assert.True(t, handled) editor, ok := svc.Manager().Get("editor") require.True(t, ok) x, y := editor.Position() assert.Equal(t, 0, x) assert.Equal(t, 0, y) terminal, ok := svc.Manager().Get("terminal") require.True(t, ok) x, y = terminal.Position() assert.Equal(t, 960, x) assert.Equal(t, 0, y) }