94 lines
4.3 KiB
Python
94 lines
4.3 KiB
Python
"""Contrats du modèle scratchpad Sway, sans toucher au bureau réel."""
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
|
|
BACKEND = (Path(__file__).resolve().parents[2] / "quickshell/.config/quickshell"
|
|
/ "labfy-sway/scratchpad/backend.py")
|
|
spec = importlib.util.spec_from_file_location("drawer_backend", BACKEND)
|
|
drawer = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(drawer)
|
|
|
|
|
|
def app(cid, name="Application", app_id="demo", state="none"):
|
|
return {"id": cid, "type": "con", "name": name, "app_id": app_id,
|
|
"scratchpad_state": state, "nodes": [], "floating_nodes": []}
|
|
|
|
|
|
def tree(*nodes):
|
|
return {"id": 1, "type": "root", "nodes": [
|
|
{"id": 2, "type": "output", "name": "__i3", "nodes": [
|
|
{"id": 3, "type": "workspace", "name": "__i3_scratch",
|
|
"nodes": [], "floating_nodes": [n for n in nodes if n.get("hidden")]}]},
|
|
{"id": 4, "type": "output", "name": "DP-2", "nodes": [
|
|
{"id": 5, "type": "workspace", "name": 'Travail ; "A"',
|
|
"nodes": [], "floating_nodes": [n for n in nodes if not n.get("hidden")]}]}]}
|
|
|
|
|
|
class DrawerModelTest(unittest.TestCase):
|
|
def test_empty_and_duplicate_app_identity(self):
|
|
self.assertEqual(drawer.members(tree()), [])
|
|
a, b = app(20, "Premier", state="fresh"), app(21, "Second", state="fresh")
|
|
a["hidden"] = True
|
|
result = drawer.members(tree(a, b))
|
|
self.assertEqual([(x["id"], x["shown"]) for x in result], [(20, False), (21, True)])
|
|
|
|
def test_group_is_blocked_even_when_apps_are_nested(self):
|
|
group = {"id": 10, "type": "floating_con", "scratchpad_state": "fresh",
|
|
"nodes": [{"id": 11, "type": "con", "nodes": [app(20)],
|
|
"floating_nodes": [app(21)]}], "floating_nodes": []}
|
|
group["hidden"] = True
|
|
self.assertTrue(all(x["group"] for x in drawer.members(tree(group))))
|
|
|
|
def test_workspace_quoting_and_missing_target(self):
|
|
self.assertEqual(drawer.quoted_workspace('Travail ; "A"'), "'Travail ; \"A\"'")
|
|
with self.assertRaises(drawer.DrawerError):
|
|
drawer.quoted_workspace("A 'B' and \"C\"")
|
|
with self.assertRaises(drawer.DrawerError):
|
|
drawer.valid_app(tree(), 99)
|
|
with patch.object(drawer, "sway", return_value=[{"name": "A", "output": "DP-2", "visible": True}]):
|
|
with self.assertRaises(drawer.DrawerError):
|
|
drawer.target_workspace("HDMI-A-1")
|
|
|
|
def test_non_app_container_is_rejected(self):
|
|
group = {"id": 30, "type": "con", "nodes": [app(31)], "floating_nodes": []}
|
|
with self.assertRaises(drawer.DrawerError):
|
|
drawer.valid_app(tree(group), 30)
|
|
|
|
def test_store_rejects_multi_app_parent(self):
|
|
group = {"id": 30, "type": "floating_con", "nodes": [app(31), app(32)],
|
|
"floating_nodes": []}
|
|
with self.assertRaises(drawer.DrawerError):
|
|
drawer.valid_app(tree(group), 31)
|
|
|
|
def test_repeated_show_only_focuses_and_repeated_hide_sends_nothing(self):
|
|
displayed = tree(app(20, state="fresh"))
|
|
hidden = app(20, state="fresh")
|
|
hidden["hidden"] = True
|
|
hidden_tree = tree(hidden)
|
|
workspaces = [{"name": 'Travail ; "A"', "output": "DP-2", "visible": True}]
|
|
|
|
def answer(kind, current):
|
|
return current if kind == "get_tree" else workspaces
|
|
|
|
with patch.object(drawer, "sway", side_effect=lambda kind: answer(kind, displayed)), \
|
|
patch.object(drawer, "safe_command") as sent:
|
|
self.assertTrue(drawer.operate("show", 20, "DP-2")["shown"])
|
|
sent.assert_called_once_with("[con_id=20] focus")
|
|
with patch.object(drawer, "sway", side_effect=lambda kind: answer(kind, hidden_tree)), \
|
|
patch.object(drawer, "safe_command") as sent:
|
|
self.assertFalse(drawer.operate("hide", 20, "DP-2")["shown"])
|
|
sent.assert_not_called()
|
|
|
|
def test_rejected_command_does_not_report_success(self):
|
|
with patch.object(drawer, "sway", return_value=tree(app(20))), \
|
|
patch.object(drawer, "safe_command", side_effect=drawer.DrawerError("refusée")):
|
|
with self.assertRaisesRegex(drawer.DrawerError, "refusée"):
|
|
drawer.operate("store", 20, "DP-2")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|