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