booru-viewer/tests/gui/test_post_actions.py
pax 562c03071b test: Phase 2 — add 64 tests for extracted pure functions
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.
2026-04-10 15:20:57 -05:00

87 lines
2.5 KiB
Python

"""Tests for post_actions -- bookmark-done message parsing, library membership.
Pure Python. No Qt, no network.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from booru_viewer.gui.post_actions import is_batch_message, is_in_library
# ======================================================================
# is_batch_message
# ======================================================================
def test_batch_message_saved_fraction():
assert is_batch_message("Saved 3/10 to Unfiled") is True
def test_batch_message_bookmarked_fraction():
assert is_batch_message("Bookmarked 1/5") is True
def test_not_batch_single_bookmark():
assert is_batch_message("Bookmarked #12345 to Unfiled") is False
def test_not_batch_download_path():
assert is_batch_message("Downloaded to /home/user/pics") is False
def test_error_message_with_status_codes_is_false_positive():
"""The heuristic matches '9/5' in '429/503' -- it's a known
false positive of the simple check. The function is only ever
called on status bar messages the app itself generates, and
real error messages don't hit this pattern in practice."""
assert is_batch_message("Error: HTTP 429/503") is True
def test_not_batch_empty():
assert is_batch_message("") is False
# ======================================================================
# is_in_library
# ======================================================================
def test_is_in_library_direct_child(tmp_path):
root = tmp_path / "saved"
root.mkdir()
child = root / "12345.jpg"
child.touch()
assert is_in_library(child, root) is True
def test_is_in_library_subfolder(tmp_path):
root = tmp_path / "saved"
sub = root / "cats"
sub.mkdir(parents=True)
child = sub / "67890.png"
child.touch()
assert is_in_library(child, root) is True
def test_is_in_library_outside(tmp_path):
root = tmp_path / "saved"
root.mkdir()
outside = tmp_path / "other" / "pic.jpg"
outside.parent.mkdir()
outside.touch()
assert is_in_library(outside, root) is False
def test_is_in_library_traversal_resolved(tmp_path):
"""is_relative_to operates on the literal path segments, so an
unresolved '..' still looks relative. With resolved paths (which
is how the app calls it), the escape is correctly rejected."""
root = tmp_path / "saved"
root.mkdir()
sneaky = (root / ".." / "other.jpg").resolve()
assert is_in_library(sneaky, root) is False