- Move src/core/ → src/server/ - Split SerieList.py (531 lines) and series.py (414 lines) into src/server/database/ - Add database/models.py for SQLAlchemy models - Update all test imports to reflect new structure - Remove deprecated test files (test_serie_class.py, test_serie_folder_with_year.py)
181 lines
6.7 KiB
Python
181 lines
6.7 KiB
Python
"""Tests for SerieList class - DB-only operations."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
|
|
from src.server.database.SerieList import SerieList
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_serie():
|
|
"""Create a sample AnimeSeries mock for testing."""
|
|
anime = MagicMock()
|
|
anime.key = "attack-on-titan"
|
|
anime.name = "Attack on Titan"
|
|
anime.site = "https://aniworld.to/anime/stream/attack-on-titan"
|
|
anime.folder = "Attack on Titan (2013)"
|
|
anime.year = 2013
|
|
anime.nfo_path = None
|
|
anime.episodeDict = {1: [1, 2, 3]}
|
|
return anime
|
|
|
|
|
|
class TestSerieListKeyBasedStorage:
|
|
"""Test SerieList uses key for internal storage."""
|
|
|
|
def test_init_creates_empty_keydict(self, tmp_path):
|
|
"""Test initialization creates keyDict."""
|
|
serie_list = SerieList(str(tmp_path))
|
|
assert hasattr(serie_list, 'keyDict')
|
|
assert isinstance(serie_list.keyDict, dict)
|
|
assert len(serie_list.keyDict) == 0
|
|
|
|
def test_contains_checks_by_key(self, tmp_path, sample_serie):
|
|
"""Test contains() checks by key."""
|
|
serie_list = SerieList(str(tmp_path))
|
|
serie_list.keyDict[sample_serie.key] = sample_serie
|
|
|
|
assert serie_list.contains(sample_serie.key)
|
|
assert not serie_list.contains("nonexistent-key")
|
|
|
|
def test_get_by_key_returns_correct_serie(self, tmp_path, sample_serie):
|
|
"""Test get_by_key() retrieves series correctly."""
|
|
serie_list = SerieList(str(tmp_path))
|
|
serie_list.keyDict[sample_serie.key] = sample_serie
|
|
|
|
result = serie_list.get_by_key(sample_serie.key)
|
|
assert result is not None
|
|
assert result.key == sample_serie.key
|
|
assert result.name == sample_serie.name
|
|
|
|
def test_get_by_key_returns_none_for_missing(self, tmp_path):
|
|
"""Test get_by_key() returns None for nonexistent key."""
|
|
serie_list = SerieList(str(tmp_path))
|
|
|
|
result = serie_list.get_by_key("nonexistent-key")
|
|
assert result is None
|
|
|
|
def test_get_by_folder_backward_compatibility(self, tmp_path, sample_serie):
|
|
"""Test get_by_folder() provides backward compatibility."""
|
|
import warnings
|
|
serie_list = SerieList(str(tmp_path))
|
|
serie_list.keyDict[sample_serie.key] = sample_serie
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
result = serie_list.get_by_folder(sample_serie.folder)
|
|
|
|
assert result is not None
|
|
assert result.key == sample_serie.key
|
|
assert result.folder == sample_serie.folder
|
|
|
|
def test_get_by_folder_returns_none_for_missing(self, tmp_path):
|
|
"""Test get_by_folder() returns None for nonexistent folder."""
|
|
import warnings
|
|
serie_list = SerieList(str(tmp_path))
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore", DeprecationWarning)
|
|
result = serie_list.get_by_folder("Nonexistent Folder")
|
|
assert result is None
|
|
|
|
def test_get_all_returns_all_series(self, tmp_path, sample_serie):
|
|
"""Test get_all() returns all series from keyDict."""
|
|
serie_list = SerieList(str(tmp_path))
|
|
|
|
serie2 = MagicMock()
|
|
serie2.key = "naruto"
|
|
serie2.name = "Naruto"
|
|
serie2.site = "https://aniworld.to/anime/stream/naruto"
|
|
serie2.folder = "Naruto (2002)"
|
|
serie2.episodeDict = {1: [1, 2]}
|
|
|
|
serie_list.keyDict[sample_serie.key] = sample_serie
|
|
serie_list.keyDict[serie2.key] = serie2
|
|
|
|
all_series = serie_list.get_all()
|
|
assert len(all_series) == 2
|
|
assert sample_serie in all_series
|
|
assert serie2 in all_series
|
|
|
|
def test_get_missing_episodes_filters_by_episode_dict(self, tmp_path):
|
|
"""Test get_missing_episodes() returns only series with episodes."""
|
|
serie_list = SerieList(str(tmp_path))
|
|
|
|
serie_with_episodes = MagicMock()
|
|
serie_with_episodes.key = "serie-with-episodes"
|
|
serie_with_episodes.name = "Serie With Episodes"
|
|
serie_with_episodes.episodeDict = {1: [1, 2, 3]}
|
|
|
|
serie_without_episodes = MagicMock()
|
|
serie_without_episodes.key = "serie-without-episodes"
|
|
serie_without_episodes.name = "Serie Without Episodes"
|
|
serie_without_episodes.episodeDict = {}
|
|
|
|
serie_list.keyDict[serie_with_episodes.key] = serie_with_episodes
|
|
serie_list.keyDict[serie_without_episodes.key] = serie_without_episodes
|
|
|
|
missing = serie_list.get_missing_episodes()
|
|
assert len(missing) == 1
|
|
assert serie_with_episodes in missing
|
|
assert serie_without_episodes not in missing
|
|
|
|
|
|
class TestSerieListPublicAPI:
|
|
"""Test that public API still works correctly."""
|
|
|
|
def test_public_methods_work(self, tmp_path, sample_serie):
|
|
"""Test that all public methods work correctly after refactoring."""
|
|
serie_list = SerieList(str(tmp_path))
|
|
|
|
# Add directly to keyDict (simulating DB load)
|
|
serie_list.keyDict[sample_serie.key] = sample_serie
|
|
|
|
# Test contains
|
|
assert serie_list.contains(sample_serie.key)
|
|
|
|
# Test GetList/get_all
|
|
assert len(serie_list.GetList()) == 1
|
|
assert len(serie_list.get_all()) == 1
|
|
|
|
# Test GetMissingEpisode/get_missing_episodes
|
|
assert len(serie_list.GetMissingEpisode()) == 1
|
|
assert len(serie_list.get_missing_episodes()) == 1
|
|
|
|
# Test get_by_key
|
|
assert serie_list.get_by_key(sample_serie.key) is not None
|
|
|
|
|
|
class TestSerieListDeprecationWarnings:
|
|
"""Test deprecation warnings are raised for deprecated methods."""
|
|
|
|
def test_get_by_folder_raises_deprecation_warning(self, tmp_path, sample_serie):
|
|
"""Test get_by_folder() raises deprecation warning."""
|
|
import warnings
|
|
serie_list = SerieList(str(tmp_path))
|
|
serie_list.keyDict[sample_serie.key] = sample_serie
|
|
|
|
with warnings.catch_warnings(record=True) as w:
|
|
warnings.simplefilter("always")
|
|
serie_list.get_by_folder(sample_serie.folder)
|
|
|
|
# Check deprecation warning was raised
|
|
assert len(w) == 1
|
|
assert issubclass(w[0].category, DeprecationWarning)
|
|
assert "get_by_key()" in str(w[0].message)
|
|
|
|
|
|
class TestInvalidateCache:
|
|
"""Test invalidate_cache method."""
|
|
|
|
def test_invalidate_cache_clears_keydict(self, tmp_path, sample_serie):
|
|
"""Verify invalidate_cache clears the in-memory cache."""
|
|
serie_list = SerieList(str(tmp_path))
|
|
serie_list.keyDict[sample_serie.key] = sample_serie
|
|
assert len(serie_list.keyDict) == 1
|
|
|
|
serie_list.invalidate_cache()
|
|
|
|
assert len(serie_list.keyDict) == 0
|