"""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()