image_server/tests/test_navigation.py
Timothy Farrell f856c92394 Clean up tests for query param conversion and remove auth
- Deleted test_auth.py (auth no longer exists)
- Rewrote TestOrderDelayRoute -> TestRootRedirectWithOrderDelay using query params
- Updated TestHashPageWithRefresh to use ?order=...&delay=... URLs
- Added play button query param assertion in TestHashPage
- Removed password=None from test_navigation.py seeded_indexers fixture
- Formatted with black, all 59 tests passing
2026-04-25 05:35:27 -05:00

125 lines
4.8 KiB
Python

"""Tests for navigation helper functions."""
import argparse
from pathlib import Path
import pytest
import main
@pytest.fixture
def seeded_indexers(sample_files: dict[str, Path], tmp_path: Path) -> None:
"""Initialize with a fixed salt so hashes are predictable."""
args = argparse.Namespace(
source=str(tmp_path),
host="127.0.0.1",
port=0,
salt="nav-test-salt",
)
main.initialize_server(args)
class TestGetNavigationData:
"""Tests for _get_navigation_data."""
def test_returns_all_keys(self, seeded_indexers: None) -> None:
"""Navigation data contains all required keys."""
file_hash = list(main.file_mapping.keys())[0]
data = main._get_navigation_data(file_hash, order=None)
assert "file_hash" in data
assert "next_hash" in data
assert "prev_hash" in data
assert "filename" in data
def test_file_hash_matches_input(self, seeded_indexers: None) -> None:
"""Returned file_hash matches the input."""
file_hash = list(main.file_mapping.keys())[0]
data = main._get_navigation_data(file_hash, order=None)
assert data["file_hash"] == file_hash
def test_sequential_next_and_prev(self, seeded_indexers: None) -> None:
"""In sequential mode, next and prev are adjacent in the list."""
keys = list(main.file_mapping.keys())
if len(keys) < 2:
pytest.skip("Need at least 2 files for sequential navigation")
file_hash = keys[0]
data = main._get_navigation_data(file_hash, order=None)
assert data["next_hash"] == keys[1]
# First item's prev wraps to last
assert data["prev_hash"] == keys[-1]
def test_middle_item_navigation(self, seeded_indexers: None) -> None:
"""Middle item has correct prev and next."""
keys = list(main.file_mapping.keys())
if len(keys) < 3:
pytest.skip("Need at least 3 files for middle-item test")
mid_idx = len(keys) // 2
file_hash = keys[mid_idx]
data = main._get_navigation_data(file_hash, order=None)
assert data["next_hash"] == keys[mid_idx + 1]
assert data["prev_hash"] == keys[mid_idx - 1]
def test_last_item_wraps_next(self, seeded_indexers: None) -> None:
"""Last item's next wraps to the first item."""
keys = list(main.file_mapping.keys())
if len(keys) < 2:
pytest.skip("Need at least 2 files for wrap test")
file_hash = keys[-1]
data = main._get_navigation_data(file_hash, order=None)
assert data["next_hash"] == keys[0]
def test_random_order_returns_different_hashes(self, seeded_indexers: None) -> None:
"""Random order returns hashes that may differ from current."""
keys = list(main.file_mapping.keys())
if len(keys) < 3:
pytest.skip("Need at least 3 files for random test")
file_hash = keys[0]
data = main._get_navigation_data(file_hash, order="random")
# next and prev should be random (not necessarily adjacent)
assert data["next_hash"] in keys
assert data["prev_hash"] in keys
def test_filename_is_returned(self, seeded_indexers: None) -> None:
"""Filename is populated from the indexer."""
file_hash = list(main.file_mapping.keys())[0]
data = main._get_navigation_data(file_hash, order=None)
assert data["filename"] is not None
assert isinstance(data["filename"], str)
class TestGetRandomHash:
"""Tests for _get_random_hash."""
def test_returns_valid_hash(self, seeded_indexers: None) -> None:
"""Returns a hash that exists in the mapping."""
random_hash = main._get_random_hash()
assert random_hash in main.file_mapping
def test_raises_when_empty(self) -> None:
"""Raises HTTPException when no files are indexed."""
main.file_mapping.clear()
with pytest.raises(main.HTTPException) as exc_info:
main._get_random_hash()
assert exc_info.value.status_code == 404
class TestFindIndexerForHash:
"""Tests for _find_indexer_for_hash."""
def test_finds_correct_indexer(self, seeded_indexers: None) -> None:
"""Returns the indexer containing the given hash."""
file_hash = list(main.file_mapping.keys())[0]
indexer = main._find_indexer_for_hash(file_hash)
assert indexer is not None
assert file_hash in indexer._file_mapping
def test_returns_none_for_unknown_hash(self, seeded_indexers: None) -> None:
"""Returns None for a hash not in any indexer."""
assert main._find_indexer_for_hash("nonexistent") is None
def test_returns_none_when_no_indexers(self) -> None:
"""Returns None when no indexers are registered."""
main.indexers.clear()
assert main._find_indexer_for_hash("any-hash") is None