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