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
|
"""Tests for dotfiles/hyprland/.local/bin/waybar-touchpad.
The script emits one JSON line for waybar's custom/touchpad module, derived
from the touchpad state file that toggle-touchpad / touchpad-auto maintain
at $XDG_RUNTIME_DIR/touchpad-state. Tests point XDG_RUNTIME_DIR at a temp
dir and assert on the emitted JSON for each state — enabled, disabled, and
the missing-file default. No mocking: the real script runs against a real
state file.
Run from repo root:
python3 -m unittest tests.waybar-touchpad.test_waybar_touchpad
"""
import json
import os
import shutil
import subprocess
import tempfile
import unittest
REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
SCRIPT = os.path.join(REPO_ROOT, "dotfiles/hyprland/.local/bin/waybar-touchpad")
class WaybarTouchpadHarness(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.mkdtemp(prefix="waybar-touchpad-test-")
self.state_file = os.path.join(self.tmp, "touchpad-state")
def tearDown(self):
shutil.rmtree(self.tmp, ignore_errors=True)
def set_state(self, value):
with open(self.state_file, "w") as f:
f.write(value)
def run_script(self):
env = os.environ.copy()
env["XDG_RUNTIME_DIR"] = self.tmp
return subprocess.run(
[SCRIPT], env=env, capture_output=True, text=True, timeout=10,
)
def emitted_json(self):
result = self.run_script()
self.assertEqual(result.returncode, 0, msg=result.stderr)
return json.loads(result.stdout)
# -----------------------------------------------------------------------------
# Normal cases
# -----------------------------------------------------------------------------
class TestWaybarTouchpadNormal(WaybarTouchpadHarness):
def test_enabled_state_emits_enabled_class_and_mouse_icon(self):
self.set_state("enabled")
data = self.emitted_json()
self.assertEqual(data["class"], "enabled")
self.assertIn("\U000f037d", data["text"]) # mouse
self.assertIn("enabled", data["tooltip"].lower())
def test_disabled_state_emits_disabled_class_and_mouse_off_icon(self):
self.set_state("disabled")
data = self.emitted_json()
self.assertEqual(data["class"], "disabled")
self.assertIn("\U000f037e", data["text"]) # mouse-off
self.assertIn("disabled", data["tooltip"].lower())
# -----------------------------------------------------------------------------
# Boundary cases
# -----------------------------------------------------------------------------
class TestWaybarTouchpadBoundary(WaybarTouchpadHarness):
def test_missing_state_file_defaults_to_enabled(self):
# No state file written → script should treat the touchpad as enabled.
data = self.emitted_json()
self.assertEqual(data["class"], "enabled")
def test_state_with_trailing_newline_is_handled(self):
self.set_state("disabled\n")
data = self.emitted_json()
self.assertEqual(data["class"], "disabled")
def test_unknown_state_value_treated_as_enabled(self):
# Anything that isn't "disabled" reads as enabled (fail-safe: the
# pointer is usable rather than hidden).
self.set_state("garbage")
data = self.emitted_json()
self.assertEqual(data["class"], "enabled")
def test_output_is_a_single_json_object(self):
self.set_state("enabled")
result = self.run_script()
lines = [ln for ln in result.stdout.splitlines() if ln.strip()]
self.assertEqual(len(lines), 1, msg=f"expected one line, got {lines!r}")
if __name__ == "__main__":
unittest.main()
|