- 176 unit tests covering ConfigManager, FileClassifier, EpisodeRenamer, TVDBClient, MockTVDBClient, TVDBCache, and episode_matcher CLI - Tests organized in tests/ with conftest.py shared fixtures - pytest-cov configured with 90% coverage threshold in pyproject.toml - CI workflow updated with COVERAGE_CORE=sysmon for Python 3.13 compat - .gitignore updated for coverage artifacts and venv
111 lines
3.7 KiB
Python
111 lines
3.7 KiB
Python
"""Tests for episode_matcher.py - parse_disc_mapping and CLI."""
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
import pytest
|
|
from episode_matcher import parse_disc_mapping
|
|
|
|
|
|
class TestParseDiscMapping:
|
|
def test_single_disc_range(self):
|
|
result = parse_disc_mapping("1:1-3")
|
|
assert result == {1: [1, 2, 3]}
|
|
|
|
def test_single_disc_single_ep(self):
|
|
result = parse_disc_mapping("1:5")
|
|
assert result == {1: [5]}
|
|
|
|
def test_multi_disc(self):
|
|
result = parse_disc_mapping("1:1-3,2:4-6,3:7-9,4:10")
|
|
assert result == {1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9], 4: [10]}
|
|
|
|
def test_spaces(self):
|
|
result = parse_disc_mapping("1:1-3 , 2:4-6")
|
|
assert result == {1: [1, 2, 3], 2: [4, 5, 6]}
|
|
|
|
def test_empty_string(self):
|
|
result = parse_disc_mapping("")
|
|
assert result == {}
|
|
|
|
def test_none(self):
|
|
result = parse_disc_mapping(None)
|
|
assert result == {}
|
|
|
|
def test_single_ep_per_disc(self):
|
|
result = parse_disc_mapping("1:1,2:2,3:3")
|
|
assert result == {1: [1], 2: [2], 3: [3]}
|
|
|
|
def test_large_numbers(self):
|
|
result = parse_disc_mapping("1:1-22")
|
|
assert result == {1: list(range(1, 23))}
|
|
|
|
def test_invalid_format_exits(self, capsys):
|
|
with pytest.raises(SystemExit):
|
|
parse_disc_mapping("invalid")
|
|
|
|
def test_missing_colon_exits(self, capsys):
|
|
with pytest.raises(SystemExit):
|
|
parse_disc_mapping("1,2,3")
|
|
|
|
|
|
class TestArgParse:
|
|
def test_parser_basic_args(self):
|
|
import argparse
|
|
from episode_matcher import main
|
|
|
|
with patch("sys.argv", [
|
|
"episode_matcher.py",
|
|
"/tmp/episodes",
|
|
"Test Show",
|
|
"1",
|
|
]):
|
|
with patch("pathlib.Path.exists", return_value=True):
|
|
with patch("pathlib.Path.is_dir", return_value=True):
|
|
with patch("episode_matcher.TVDBClient") as mock_tvdb:
|
|
mock_instance = mock_tvdb.return_value
|
|
mock_instance.authenticate.return_value = False
|
|
with patch("episode_matcher.MockTVDBClient") as mock_mock:
|
|
m = mock_mock.return_value
|
|
m.authenticate.return_value = True
|
|
m.get_episode_durations.return_value = []
|
|
with patch("episode_matcher.FileClassifier") as mock_fc:
|
|
fc = mock_fc.return_value
|
|
fc.file_info = []
|
|
fc.classify_files.return_value = ([], [])
|
|
with pytest.raises(SystemExit):
|
|
main()
|
|
|
|
def test_parser_dry_run_flag(self):
|
|
import sys as real_sys
|
|
orig_argv = real_sys.argv
|
|
try:
|
|
real_sys.argv = [
|
|
"episode_matcher.py", "/tmp/e", "Show", "1", "--dry-run", "--verbose"
|
|
]
|
|
from importlib import reload
|
|
import episode_matcher
|
|
|
|
parser = episode_matcher.__dict__.get("_parser", None)
|
|
|
|
from episode_matcher import main
|
|
finally:
|
|
real_sys.argv = orig_argv
|
|
|
|
|
|
class TestParseDiscMappingEdgeCases:
|
|
def test_range_to_self(self):
|
|
result = parse_disc_mapping("1:5-5")
|
|
assert result == {1: [5]}
|
|
|
|
def test_multiple_ranges_same_ep(self):
|
|
result = parse_disc_mapping("1:1-3,2:3-5")
|
|
assert 3 in result[1]
|
|
assert 3 in result[2]
|
|
|
|
def test_disc_number_large(self):
|
|
result = parse_disc_mapping("99:1-3")
|
|
assert 99 in result
|