aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_windows.py
blob: e63240625eb1428838567c4f3b0740824048b184 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# deck-it - tests for windows
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

import unittest
from unittest import mock

import deckit.modules.windows as windows


class DesktopIcons(unittest.TestCase):
    def test_maps_class_and_wmclass(self):
        import tempfile
        from pathlib import Path
        base = Path(tempfile.mkdtemp())
        (base / "com.obsproject.Studio.desktop").write_text(
            "[Desktop Entry]\nName=OBS Studio\nIcon=com.obsproject.Studio\nStartupWMClass=obs\n"
            "[Desktop Action x]\nName=Other\n")
        mapping = windows._desktop_icons(windows._desktop_entries([base]))
        self.assertEqual(mapping["com.obsproject.studio"], ["com.obsproject.Studio", "obs"])
        self.assertEqual(mapping["obs"], ["com.obsproject.Studio", "obs"])
        self.assertEqual(windows._desktop_entries([base])["com.obsproject.Studio"]["name"], "OBS Studio")


class Move(unittest.TestCase):
    def test_lua_focuses_then_moves(self):
        calls = []
        m = windows.make({"hyprland": "lua", "run": lambda cmd: "[]"})
        with mock.patch.object(windows, "_dispatch", lambda cmd: calls.append(cmd)):
            m.actions["move"]({"address": "0x1", "n": 3})
        self.assertIn("focus", calls[0][2])
        self.assertIn("window.move", calls[1][2])

    def test_classic_uses_movetoworkspacesilent(self):
        calls = []
        m = windows.make({"hyprland": "classic", "run": lambda cmd: "[]"})
        with mock.patch.object(windows, "_dispatch", lambda cmd: calls.append(cmd)):
            m.actions["move"]({"address": "0x1", "n": 3})
        self.assertEqual(calls[0], ["hyprctl", "dispatch", "movetoworkspacesilent", "3,address:0x1"])


class Commands(unittest.TestCase):
    def test_lua_and_classic(self):
        self.assertEqual(windows.workspace_cmd(3, lua=False),
                         ["hyprctl", "dispatch", "workspace", "3"])
        self.assertEqual(windows.workspace_cmd(3, lua=True)[:2], ["hyprctl", "eval"])

    def test_window_commands_are_dispatched(self):
        self.assertEqual(windows.window_cmd("focus", "0x1", lua=True),
                         ["hyprctl", "eval", 'hl.dispatch(hl.dsp.focus({window = "address:0x1"}))'])
        self.assertEqual(windows.window_cmd("close", "0x1", lua=True),
                         ["hyprctl", "eval", 'hl.dispatch(hl.dsp.window.close({window = "address:0x1"}))'])

    def test_address_guard(self):
        self.assertIsNone(windows.ADDR.fullmatch("0x1;rm"))
        self.assertTrue(windows.ADDR.fullmatch("0x55897e5c0800"))

    def test_state_lists_all_workspaces(self):
        responses = {
            ("hyprctl", "clients", "-j"): "[]",
            ("hyprctl", "activewindow", "-j"): "{}",
            ("hyprctl", "monitors", "-j"): "[]",
            ("hyprctl", "workspaces", "-j"): '[{"id": 1}, {"id": 2}, {"id": 5}]',
        }
        st = windows._state(lambda cmd: responses[tuple(cmd)])
        self.assertEqual(st["workspaces"], [1, 2, 5])

    def test_state_includes_empty_workspaces_and_launch_icons(self):
        responses = {
            ("hyprctl", "clients", "-j"): "[]",
            ("hyprctl", "activewindow", "-j"): "{}",
            ("hyprctl", "workspaces", "-j"): '[{"id": 3}]',
        }
        entries = {"com.obsproject.Studio": {"name": "OBS Studio", "icon": "obs", "wmclass": None}}
        with mock.patch.object(windows, "_desktop_entries", lambda: entries):
            m = windows.make({
                "windows": {"workspaces": [1, 2, 3, 4]},
                "launch": {"apps": ["com.obsproject.Studio", "not-installed"]},
                "run": lambda cmd: responses[tuple(cmd)],
            })
        st = m.state()
        self.assertEqual(st["workspaces"], [1, 2, 3, 4])
        self.assertEqual(st["launches"],
                         [{"key": "com.obsproject.Studio", "icon": "obs", "label": "OBS Studio"}])

    def test_launch_runs_only_listed_installed_apps(self):
        entries = {"kitty": {"name": "kitty", "icon": "kitty", "wmclass": None},
                   "other": {"name": "Other", "icon": None, "wmclass": None}}
        calls = []
        with mock.patch.object(windows, "_desktop_entries", lambda: entries):
            m = windows.make({"launch": {"apps": ["kitty", "gone"]}, "run": lambda cmd: "[]"})
        with mock.patch.object(windows, "_popen", calls.append):
            m.actions["launch"]({"key": "kitty"})
            for bad in ("other", "gone", "kitty; rm"):
                with self.assertRaises(windows.ModuleError):
                    m.actions["launch"]({"key": bad})
        self.assertEqual(calls, [["gtk-launch", "kitty"]])


if __name__ == "__main__":
    unittest.main()