aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-23 13:02:47 -0500
committerCraig Jennings <c@cjennings.net>2026-05-23 13:02:47 -0500
commit3f802eb819bc9be572b230ac1bd142b7ce13d87f (patch)
tree60be68db7167d064669c608cfb8402812eeae5c2 /.ai/scripts/tests
parent7f2aea1e022c93f3eb463e5222bdb0d8ae6288b9 (diff)
downloadrulesets-3f802eb819bc9be572b230ac1bd142b7ce13d87f.tar.gz
rulesets-3f802eb819bc9be572b230ac1bd142b7ce13d87f.zip
chore(ai): resync workflow and script mirror with canonical
The .ai/ mirror lagged claude-templates/.ai/ for three workflows (task-audit, task-review, triage-intake) and two scripts (screenshot.py and its test) — earlier commits updated the canonical copies without resyncing the mirror in the same commit. The startup rsync caught it up; this commit tracks the result so the two stay identical.
Diffstat (limited to '.ai/scripts/tests')
-rw-r--r--.ai/scripts/tests/test_screenshot.py97
1 files changed, 97 insertions, 0 deletions
diff --git a/.ai/scripts/tests/test_screenshot.py b/.ai/scripts/tests/test_screenshot.py
new file mode 100644
index 0000000..357caec
--- /dev/null
+++ b/.ai/scripts/tests/test_screenshot.py
@@ -0,0 +1,97 @@
+"""Tests for screenshot.py — the pure helpers behind Wayland screenshot capture.
+
+The script is mostly thin wrappers around grim/hyprctl (I/O boundaries, verified
+functionally). The logic worth testing is pure: size parsing, grim geometry
+strings, window matching, the Hyprland exec-rule body, and floating-window
+centering. Those are imported and exercised directly here; the subprocess
+wrappers and the capture orchestration are not unit-tested.
+"""
+
+import sys
+from pathlib import Path
+
+import pytest
+
+sys.path.insert(0, str(Path(__file__).parent.parent))
+import screenshot # noqa: E402
+
+
+# ------------------------------- parse_size ----------------------------------
+
+def test_parse_size_normal():
+ assert screenshot.parse_size("1600x1000") == (1600, 1000)
+
+def test_parse_size_boundary_zero_and_one():
+ assert screenshot.parse_size("0x0") == (0, 0)
+ assert screenshot.parse_size("1x1") == (1, 1)
+
+@pytest.mark.parametrize("bad", ["", "bad", "100", "100x", "x100", "100X100", " 1x1"])
+def test_parse_size_error_malformed_dies(bad):
+ with pytest.raises(SystemExit):
+ screenshot.parse_size(bad)
+
+
+# ------------------------------ geometry_str ---------------------------------
+
+def test_geometry_str_normal():
+ assert screenshot.geometry_str({"at": [10, 20], "size": [800, 600]}) == "10,20 800x600"
+
+def test_geometry_str_boundary_origin_and_unit():
+ assert screenshot.geometry_str({"at": [0, 0], "size": [1, 1]}) == "0,0 1x1"
+
+
+# ------------------------------ match_windows --------------------------------
+
+CLIENTS = [
+ {"class": "Emacs", "title": "Emacs 30.2 : agent [.emacs.d]"},
+ {"class": "firefox", "title": "TrueNAS — Mozilla Firefox"},
+ {"class": "foot", "title": "foot"},
+]
+
+def test_match_windows_normal_by_class():
+ assert screenshot.match_windows(CLIENTS, "firefox") == [CLIENTS[1]]
+
+def test_match_windows_normal_by_title():
+ assert screenshot.match_windows(CLIENTS, "TrueNAS") == [CLIENTS[1]]
+
+def test_match_windows_case_insensitive():
+ assert screenshot.match_windows(CLIENTS, "EMACS") == [CLIENTS[0]]
+
+def test_match_windows_multiple():
+ # "o" appears in firefox and foot classes
+ assert len(screenshot.match_windows(CLIENTS, "foo")) == 1
+ assert len(screenshot.match_windows(CLIENTS, "e")) >= 2 # Emacs + firefox (title/class)
+
+def test_match_windows_boundary_empty_clients():
+ assert screenshot.match_windows([], "anything") == []
+
+def test_match_windows_boundary_missing_fields():
+ # client with no class/title keys must not raise
+ assert screenshot.match_windows([{"class": None, "title": None}], "x") == []
+
+def test_match_windows_error_no_match():
+ assert screenshot.match_windows(CLIENTS, "nonexistent-zzz") == []
+
+
+# ------------------------------- launch_rule ---------------------------------
+
+def test_launch_rule_tiled_default():
+ assert screenshot.launch_rule(2, "tiled") == "workspace 2 silent"
+
+def test_launch_rule_monocle_adds_fullscreen():
+ assert screenshot.launch_rule(2, "monocle") == "workspace 2 silent;fullscreen 1"
+
+def test_launch_rule_floating_adds_float():
+ assert screenshot.launch_rule(7, "floating") == "workspace 7 silent;float"
+
+
+# ------------------------------ center_offset --------------------------------
+
+def test_center_offset_normal():
+ assert screenshot.center_offset(1920, 1080, 800, 600) == (560, 240)
+
+def test_center_offset_boundary_exact_fit():
+ assert screenshot.center_offset(1920, 1080, 1920, 1080) == (0, 0)
+
+def test_center_offset_error_window_larger_than_output_clamps():
+ assert screenshot.center_offset(800, 600, 1000, 700) == (0, 0)