From 46bf2086273d52049d9b8c6ee528a3d5aeb16ee2 Mon Sep 17 00:00:00 2001 From: shyguyCreate <107062289+shyguyCreate@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:20:13 +0000 Subject: [PATCH] feat(hook): complete test for all hooks --- test/test_hook.py | 384 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 362 insertions(+), 22 deletions(-) diff --git a/test/test_hook.py b/test/test_hook.py index effd70a959..e005ac68c7 100644 --- a/test/test_hook.py +++ b/test/test_hook.py @@ -27,14 +27,12 @@ import libqtile.log_utils import libqtile.utils -from libqtile import hook +from libqtile import config, hook, layout +from libqtile.config import Match from libqtile.resources import default_config -from test.conftest import BareConfig +from test.conftest import BareConfig, dualmonitor from test.helpers import Retry -# TODO: more tests required. -# 1. Check all hooks that can be fired - class Call: def __init__(self, val): @@ -199,6 +197,14 @@ def test_resume_hook(manager): assert test.val == 1 +@pytest.mark.usefixtures("hook_fixture") +def test_suspend_hook(manager): + test = NoArgCall(0) + hook.subscribe.suspend(test) + hook.fire("suspend") + assert test.val == 1 + + @pytest.mark.usefixtures("hook_fixture") def test_custom_hook_registry(): """Tests ability to create custom hook registries""" @@ -260,6 +266,52 @@ def defined_text(text): assert manager.custom_text.value == "C" +def test_shutdown(manager_nospawn): + def inc_shutdown_calls(): + manager_nospawn.shutdown_calls.value += 1 + + manager_nospawn.shutdown_calls = Value("i", 0) + hook.subscribe.shutdown(inc_shutdown_calls) + + manager_nospawn.start(BareConfig) + manager_nospawn.c.shutdown() + assert manager_nospawn.shutdown_calls.value == 1 + + +@dualmonitor +def test_setgroup(manager_nospawn): + @Retry(ignore_exceptions=(AssertionError)) + def assert_inc_calls(num: int): + assert manager_nospawn.setgroup_calls.value == num + + def inc_setgroup_calls(): + manager_nospawn.setgroup_calls.value += 1 + + manager_nospawn.setgroup_calls = Value("i", 0) + hook.subscribe.setgroup(inc_setgroup_calls) + + # Starts with two because of the dual screen + manager_nospawn.start(BareConfig) + assert_inc_calls(2) + + manager_nospawn.c.switch_groups("a", "b") + assert_inc_calls(3) + + manager_nospawn.c.to_screen(1) + assert_inc_calls(4) + manager_nospawn.c.to_screen(1) + assert_inc_calls(4) + + manager_nospawn.c.next_screen() + assert_inc_calls(5) + + manager_nospawn.c.prev_screen() + assert_inc_calls(6) + + manager_nospawn.c.group.switch_groups("b") + assert_inc_calls(7) + + class CallGroupname: def __init__(self): self.groupname = "" @@ -282,6 +334,8 @@ class AddgroupConfig(BareConfig): manager_nospawn.start(AddgroupConfig) assert_groupname(manager_nospawn, "d") + manager_nospawn.c.addgroup("e") + assert_groupname(manager_nospawn, "e") @pytest.mark.usefixtures("hook_fixture") @@ -291,10 +345,128 @@ class DelgroupConfig(BareConfig): hook.subscribe.delgroup(test) manager_nospawn.start(DelgroupConfig) + manager_nospawn.c.delgroup("e") + assert_groupname(manager_nospawn, "") manager_nospawn.c.delgroup("d") assert_groupname(manager_nospawn, "d") +def test_changegroup(manager_nospawn): + @Retry(ignore_exceptions=(AssertionError)) + def assert_inc_calls(num: int): + assert manager_nospawn.changegroup_calls.value == num + + def inc_changegroup_calls(): + manager_nospawn.changegroup_calls.value += 1 + + manager_nospawn.changegroup_calls = Value("i", 0) + hook.subscribe.changegroup(inc_changegroup_calls) + + # Starts with four beacuase of four groups in BareConfig + manager_nospawn.start(BareConfig) + assert_inc_calls(4) + + manager_nospawn.c.group.set_label("Test") + assert_inc_calls(5) + + manager_nospawn.c.addgroup("e") + assert_inc_calls(6) + manager_nospawn.c.addgroup("e") + assert_inc_calls(6) + + manager_nospawn.c.delgroup("e") + assert_inc_calls(7) + manager_nospawn.c.delgroup("e") + assert_inc_calls(7) + + +def test_focus_change(manager_nospawn): + @Retry(ignore_exceptions=(AssertionError)) + def assert_inc_calls(num: int): + assert manager_nospawn.focus_change_calls.value == num + + def inc_focus_change_calls(): + manager_nospawn.focus_change_calls.value += 1 + + manager_nospawn.focus_change_calls = Value("i", 0) + hook.subscribe.focus_change(inc_focus_change_calls) + + manager_nospawn.start(BareConfig) + assert_inc_calls(1) + + manager_nospawn.test_window("Test Window") + assert_inc_calls(2) + + manager_nospawn.c.group.focus_by_index(0) + assert_inc_calls(3) + manager_nospawn.c.group.focus_by_index(1) + assert_inc_calls(3) + + manager_nospawn.test_window("Test Focus Change") + assert_inc_calls(4) + + manager_nospawn.c.group.focus_back() + assert_inc_calls(5) + + manager_nospawn.c.group.focus_by_name("Test Focus Change") + assert_inc_calls(6) + manager_nospawn.c.group.focus_by_name("Test Focus") + assert_inc_calls(6) + + manager_nospawn.c.group.next_window() + assert_inc_calls(7) + + manager_nospawn.c.group.prev_window() + assert_inc_calls(8) + + manager_nospawn.c.window.kill() + assert_inc_calls(9) + + +def test_float_change(manager_nospawn): + @Retry(ignore_exceptions=(AssertionError)) + def assert_inc_calls(num: int): + assert manager_nospawn.float_change_calls.value == num + + def inc_float_change_calls(): + manager_nospawn.float_change_calls.value += 1 + + manager_nospawn.float_change_calls = Value("i", 0) + hook.subscribe.float_change(inc_float_change_calls) + + manager_nospawn.start(BareConfig) + manager_nospawn.test_window("Test Window") + + manager_nospawn.c.window.enable_floating() + assert_inc_calls(1) + manager_nospawn.c.window.enable_floating() + assert_inc_calls(1) + + manager_nospawn.c.window.disable_floating() + assert_inc_calls(2) + manager_nospawn.c.window.disable_floating() + assert_inc_calls(2) + + manager_nospawn.c.window.toggle_floating() + assert_inc_calls(3) + + manager_nospawn.c.window.toggle_floating() + manager_nospawn.c.window.move_floating(0, 0) + assert_inc_calls(5) + + manager_nospawn.c.window.toggle_floating() + manager_nospawn.c.window.resize_floating(10, 10) + assert_inc_calls(7) + + manager_nospawn.c.window.toggle_floating() + manager_nospawn.c.window.set_position_floating(0, 0) + assert_inc_calls(9) + + manager_nospawn.c.window.toggle_floating() + manager_nospawn.c.window.set_size_floating(100, 100) + assert_inc_calls(11) + + class CallGroupWindow: def __init__(self): self.window = "" @@ -336,67 +508,235 @@ class RemoveGroupWindowConfig(BareConfig): assert_group_window(manager_nospawn, "a", "Test Window") -class CallClient: +class CallWindow: def __init__(self): - self.client = "" + self.window = "" - def __call__(self, client): - self.client = client.name + def __call__(self, window): + self.window = window.name @Retry(ignore_exceptions=(AssertionError)) -def assert_client(mgr_nospawn, client): - _, _client = mgr_nospawn.c.eval("self.config.test.client") - assert _client == client +def assert_window(mgr_nospawn, window): + _, _window = mgr_nospawn.c.eval("self.config.test.window") + assert _window == window @pytest.mark.usefixtures("hook_fixture") def test_client_new(manager_nospawn): class ClientNewConfig(BareConfig): - test = CallClient() + test = CallWindow() hook.subscribe.client_new(test) manager_nospawn.start(ClientNewConfig) manager_nospawn.test_window("Test Client") - assert_client(manager_nospawn, "Test Client") + assert_window(manager_nospawn, "Test Client") @pytest.mark.usefixtures("hook_fixture") def test_client_managed(manager_nospawn): class ClientManagedConfig(BareConfig): - test = CallClient() + test = CallWindow() hook.subscribe.client_managed(test) manager_nospawn.start(ClientManagedConfig) manager_nospawn.test_window("Test Client") - assert_client(manager_nospawn, "Test Client") + assert_window(manager_nospawn, "Test Client") + manager_nospawn.test_window("Test Static") manager_nospawn.c.group.focus_back() manager_nospawn.c.window.static() - assert_client(manager_nospawn, "Test Client") + assert_window(manager_nospawn, "Test Client") @pytest.mark.usefixtures("hook_fixture") def test_client_killed(manager_nospawn): class ClientKilledConfig(BareConfig): - test = CallClient() + test = CallWindow() hook.subscribe.client_killed(test) manager_nospawn.start(ClientKilledConfig) manager_nospawn.test_window("Test Client") manager_nospawn.c.window.kill() - assert_client(manager_nospawn, "Test Client") + assert_window(manager_nospawn, "Test Client") @pytest.mark.usefixtures("hook_fixture") def test_client_focus(manager_nospawn): class ClientFocusConfig(BareConfig): - test = CallClient() + test = CallWindow() hook.subscribe.client_focus(test) manager_nospawn.start(ClientFocusConfig) manager_nospawn.test_window("Test Client") - assert_client(manager_nospawn, "Test Client") + assert_window(manager_nospawn, "Test Client") + manager_nospawn.test_window("Test Focus") manager_nospawn.c.group.focus_back() - assert_client(manager_nospawn, "Test Client") + assert_window(manager_nospawn, "Test Client") + + +@pytest.mark.usefixtures("hook_fixture") +def test_client_mouse_enter(manager_nospawn): + class ClientMouseEnterConfig(BareConfig): + cursor_warp = True # wayland backend + test = CallWindow() + hook.subscribe.client_mouse_enter(test) + + manager_nospawn.start(ClientMouseEnterConfig) + manager_nospawn.test_window("Test Client") + manager_nospawn.test_window("Test MouseEnter") # wayland backend + manager_nospawn.c.next_layout() # wayland backend + manager_nospawn.backend.fake_click(0, 0) # x11 backend + assert_window(manager_nospawn, "Test Client") + + +@pytest.mark.usefixtures("hook_fixture") +def test_client_name_updated(manager_nospawn): + class ClientNameUpdatedConfig(BareConfig): + test = CallWindow() + hook.subscribe.client_name_updated(test) + + manager_nospawn.start(ClientNameUpdatedConfig) + manager_nospawn.test_window("Test Client", new_title="Test NameUpdated") + assert_window(manager_nospawn, "Test NameUpdated") + + +@pytest.mark.usefixtures("hook_fixture") +def test_client_urgent_hint_changed(manager_nospawn, backend_name): + if backend_name == "wayland": + pytest.skip("Core not listening to XDG request_activate_event ?") + + class ClientUrgentHintChangedConfig(BareConfig): + groups = [ + config.Group("a"), + config.Group("b", matches=[Match(title="Test Client")]), + ] + focus_on_window_activation = "urgent" + test = CallWindow() + hook.subscribe.client_urgent_hint_changed(test) + + manager_nospawn.start(ClientUrgentHintChangedConfig) + manager_nospawn.test_window("Test Client", urgent_hint=True) + assert_window(manager_nospawn, "Test Client") + + +class CallLayoutGroup: + def __init__(self): + self.layout = "" + self.group = "" + + def __call__(self, layout, group): + self.layout = layout.name + self.group = group.name + + +@Retry(ignore_exceptions=(AssertionError)) +def assert_layout_group(mgr_nospawn, layout, group): + _, _layout = mgr_nospawn.c.eval("self.config.test.layout") + assert _layout == layout + _, _group = mgr_nospawn.c.eval("self.config.test.group") + assert _group == group + + +@pytest.mark.usefixtures("hook_fixture") +def test_layout_change(manager_nospawn): + class ClientLayoutChange(BareConfig): + layouts = [layout.stack.Stack(), layout.columns.Columns()] + test = CallLayoutGroup() + hook.subscribe.layout_change(test) + + manager_nospawn.start(ClientLayoutChange) + assert_layout_group(manager_nospawn, "stack", "a") + + manager_nospawn.c.group.setlayout("columns") + assert_layout_group(manager_nospawn, "columns", "a") + + manager_nospawn.c.screen.next_group() + assert_layout_group(manager_nospawn, "stack", "b") + + manager_nospawn.c.screen.prev_group() + assert_layout_group(manager_nospawn, "columns", "a") + + manager_nospawn.c.screen.toggle_group() + assert_layout_group(manager_nospawn, "stack", "b") + + manager_nospawn.c.next_layout() + assert_layout_group(manager_nospawn, "columns", "b") + + manager_nospawn.c.prev_layout() + assert_layout_group(manager_nospawn, "stack", "b") + + +@pytest.mark.usefixtures("hook_fixture") +def test_net_wm_icon_change(manager_nospawn, backend_name): + if backend_name == "wayland": + pytest.skip("X11 only.") + + class ClientNewConfig(BareConfig): + test = CallWindow() + hook.subscribe.net_wm_icon_change(test) + + manager_nospawn.start(ClientNewConfig) + manager_nospawn.test_window("Test Client") + assert_window(manager_nospawn, "Test Client") + + +@pytest.mark.usefixtures("hook_fixture") +def test_screen_change(manager_nospawn): + @Retry(ignore_exceptions=(AssertionError)) + def assert_inc_calls(num: int): + assert manager_nospawn.screen_change_calls.value == num + + def inc_screen_change_calls(event): + manager_nospawn.screen_change_calls.value += 1 + + manager_nospawn.screen_change_calls = Value("i", 0) + hook.subscribe.screen_change(inc_screen_change_calls) + + manager_nospawn.start(BareConfig) + assert_inc_calls(1) + + +@pytest.mark.usefixtures("hook_fixture") +def test_screens_reconfigured(manager_nospawn): + @Retry(ignore_exceptions=(AssertionError)) + def assert_inc_calls(num: int): + assert manager_nospawn.screens_reconfigured_calls.value == num + + def inc_screens_reconfigured_calls(): + manager_nospawn.screens_reconfigured_calls.value += 1 + + manager_nospawn.screens_reconfigured_calls = Value("i", 0) + hook.subscribe.screens_reconfigured(inc_screens_reconfigured_calls) + + manager_nospawn.start(BareConfig) + manager_nospawn.c.reconfigure_screens() + assert_inc_calls(1) + + +@dualmonitor +@pytest.mark.usefixtures("hook_fixture") +def test_current_screen_change(manager_nospawn): + @Retry(ignore_exceptions=(AssertionError)) + def assert_inc_calls(num: int): + assert manager_nospawn.current_screen_change_calls.value == num + + def inc_current_screen_change_calls(): + manager_nospawn.current_screen_change_calls.value += 1 + + manager_nospawn.current_screen_change_calls = Value("i", 0) + hook.subscribe.current_screen_change(inc_current_screen_change_calls) + + manager_nospawn.start(BareConfig) + + manager_nospawn.c.to_screen(1) + assert_inc_calls(1) + manager_nospawn.c.to_screen(1) + assert_inc_calls(1) + + manager_nospawn.c.next_screen() + assert_inc_calls(2) + + manager_nospawn.c.prev_screen() + assert_inc_calls(3)