5 new test files covering the pure-function extractions from Phase 1: - test_search_controller.py (24): tag building, blacklist filtering, backfill - test_window_state.py (16): geometry parsing, splitter parsing, hyprctl cmds - test_media_controller.py (9): prefetch ring-expansion ordering - test_post_actions.py (10): batch message detection, library membership - test_popout_controller.py (3): video sync dict shape All import-pure (no PySide6, no mpv, no httpx). Total suite: 186 tests.
147 lines
4.3 KiB
Python
147 lines
4.3 KiB
Python
"""Tests for window_state -- geometry parsing, Hyprland command building.
|
|
|
|
Pure Python. No Qt, no subprocess, no Hyprland.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from booru_viewer.gui.window_state import (
|
|
build_hyprctl_restore_cmds,
|
|
format_geometry,
|
|
parse_geometry,
|
|
parse_splitter_sizes,
|
|
)
|
|
|
|
|
|
# ======================================================================
|
|
# parse_geometry
|
|
# ======================================================================
|
|
|
|
|
|
def test_parse_geometry_valid():
|
|
assert parse_geometry("100,200,800,600") == (100, 200, 800, 600)
|
|
|
|
|
|
def test_parse_geometry_wrong_count():
|
|
assert parse_geometry("100,200,800") is None
|
|
|
|
|
|
def test_parse_geometry_non_numeric():
|
|
assert parse_geometry("abc,200,800,600") is None
|
|
|
|
|
|
def test_parse_geometry_empty():
|
|
assert parse_geometry("") is None
|
|
|
|
|
|
# ======================================================================
|
|
# format_geometry
|
|
# ======================================================================
|
|
|
|
|
|
def test_format_geometry_basic():
|
|
assert format_geometry(10, 20, 1920, 1080) == "10,20,1920,1080"
|
|
|
|
|
|
def test_format_and_parse_round_trip():
|
|
geo = (100, 200, 800, 600)
|
|
assert parse_geometry(format_geometry(*geo)) == geo
|
|
|
|
|
|
# ======================================================================
|
|
# parse_splitter_sizes
|
|
# ======================================================================
|
|
|
|
|
|
def test_parse_splitter_sizes_valid_2():
|
|
assert parse_splitter_sizes("300,700", 2) == [300, 700]
|
|
|
|
|
|
def test_parse_splitter_sizes_valid_3():
|
|
assert parse_splitter_sizes("200,500,300", 3) == [200, 500, 300]
|
|
|
|
|
|
def test_parse_splitter_sizes_wrong_count():
|
|
assert parse_splitter_sizes("300,700", 3) is None
|
|
|
|
|
|
def test_parse_splitter_sizes_negative():
|
|
assert parse_splitter_sizes("300,-1", 2) is None
|
|
|
|
|
|
def test_parse_splitter_sizes_all_zero():
|
|
assert parse_splitter_sizes("0,0", 2) is None
|
|
|
|
|
|
def test_parse_splitter_sizes_non_numeric():
|
|
assert parse_splitter_sizes("abc,700", 2) is None
|
|
|
|
|
|
def test_parse_splitter_sizes_empty():
|
|
assert parse_splitter_sizes("", 2) is None
|
|
|
|
|
|
# ======================================================================
|
|
# build_hyprctl_restore_cmds
|
|
# ======================================================================
|
|
|
|
|
|
def test_floating_to_floating_no_toggle():
|
|
"""Already floating, want floating: no togglefloating needed."""
|
|
cmds = build_hyprctl_restore_cmds(
|
|
addr="0xdead", x=100, y=200, w=800, h=600,
|
|
want_floating=True, cur_floating=True,
|
|
)
|
|
assert not any("togglefloating" in c for c in cmds)
|
|
assert any("resizewindowpixel" in c for c in cmds)
|
|
assert any("movewindowpixel" in c for c in cmds)
|
|
|
|
|
|
def test_tiled_to_floating_has_toggle():
|
|
"""Currently tiled, want floating: one togglefloating to enter float."""
|
|
cmds = build_hyprctl_restore_cmds(
|
|
addr="0xdead", x=100, y=200, w=800, h=600,
|
|
want_floating=True, cur_floating=False,
|
|
)
|
|
toggle_cmds = [c for c in cmds if "togglefloating" in c]
|
|
assert len(toggle_cmds) == 1
|
|
|
|
|
|
def test_tiled_primes_floating_cache():
|
|
"""Want tiled: primes Hyprland's floating cache with 2 toggles + no_anim."""
|
|
cmds = build_hyprctl_restore_cmds(
|
|
addr="0xdead", x=100, y=200, w=800, h=600,
|
|
want_floating=False, cur_floating=False,
|
|
)
|
|
toggle_cmds = [c for c in cmds if "togglefloating" in c]
|
|
no_anim_on = [c for c in cmds if "no_anim 1" in c]
|
|
no_anim_off = [c for c in cmds if "no_anim 0" in c]
|
|
# Two toggles: tiled->float (to prime), float->tiled (to restore)
|
|
assert len(toggle_cmds) == 2
|
|
assert len(no_anim_on) == 1
|
|
assert len(no_anim_off) == 1
|
|
|
|
|
|
def test_floating_to_tiled_one_toggle():
|
|
"""Currently floating, want tiled: one toggle to tile."""
|
|
cmds = build_hyprctl_restore_cmds(
|
|
addr="0xdead", x=100, y=200, w=800, h=600,
|
|
want_floating=False, cur_floating=True,
|
|
)
|
|
toggle_cmds = [c for c in cmds if "togglefloating" in c]
|
|
# Only the final toggle at the end of the tiled branch
|
|
assert len(toggle_cmds) == 1
|
|
|
|
|
|
def test_correct_address_in_all_cmds():
|
|
"""Every command references the given address."""
|
|
addr = "0xbeef"
|
|
cmds = build_hyprctl_restore_cmds(
|
|
addr=addr, x=0, y=0, w=1920, h=1080,
|
|
want_floating=True, cur_floating=False,
|
|
)
|
|
for cmd in cmds:
|
|
assert addr in cmd
|