- Renamed folderDict to keyDict for clarity - Updated internal storage to use serie.key instead of serie.folder - Optimized contains() from O(n) to O(1) with direct key lookup - Added get_by_key() as primary lookup method - Added get_by_folder() for backward compatibility - Enhanced docstrings to clarify key vs folder usage - Created comprehensive test suite (12 tests, all passing) - Verified no breaking changes (16 SeriesApp tests pass) This establishes key as the single source of truth for series identification while maintaining folder as metadata for filesystem operations only.
204 lines
7.1 KiB
Python
204 lines
7.1 KiB
Python
"""Tests for SerieList class - identifier standardization."""
|
|
|
|
import os
|
|
import tempfile
|
|
|
|
import pytest
|
|
|
|
from src.core.entities.SerieList import SerieList
|
|
from src.core.entities.series import Serie
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_directory():
|
|
"""Create a temporary directory for testing."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
yield tmpdir
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_serie():
|
|
"""Create a sample Serie for testing."""
|
|
return Serie(
|
|
key="attack-on-titan",
|
|
name="Attack on Titan",
|
|
site="https://aniworld.to/anime/stream/attack-on-titan",
|
|
folder="Attack on Titan (2013)",
|
|
episodeDict={1: [1, 2, 3]}
|
|
)
|
|
|
|
|
|
class TestSerieListKeyBasedStorage:
|
|
"""Test SerieList uses key for internal storage."""
|
|
|
|
def test_init_creates_empty_keydict(self, temp_directory):
|
|
"""Test initialization creates keyDict."""
|
|
serie_list = SerieList(temp_directory)
|
|
assert hasattr(serie_list, 'keyDict')
|
|
assert isinstance(serie_list.keyDict, dict)
|
|
|
|
def test_add_stores_by_key(self, temp_directory, sample_serie):
|
|
"""Test add() stores series by key."""
|
|
serie_list = SerieList(temp_directory)
|
|
serie_list.add(sample_serie)
|
|
|
|
# Verify stored by key, not folder
|
|
assert sample_serie.key in serie_list.keyDict
|
|
assert serie_list.keyDict[sample_serie.key] == sample_serie
|
|
|
|
def test_contains_checks_by_key(self, temp_directory, sample_serie):
|
|
"""Test contains() checks by key."""
|
|
serie_list = SerieList(temp_directory)
|
|
serie_list.add(sample_serie)
|
|
|
|
assert serie_list.contains(sample_serie.key)
|
|
assert not serie_list.contains("nonexistent-key")
|
|
|
|
def test_add_prevents_duplicates_by_key(
|
|
self, temp_directory, sample_serie
|
|
):
|
|
"""Test add() prevents duplicates based on key."""
|
|
serie_list = SerieList(temp_directory)
|
|
|
|
# Add same serie twice
|
|
serie_list.add(sample_serie)
|
|
initial_count = len(serie_list.keyDict)
|
|
|
|
serie_list.add(sample_serie)
|
|
|
|
# Should still have only one entry
|
|
assert len(serie_list.keyDict) == initial_count
|
|
assert len(serie_list.keyDict) == 1
|
|
|
|
def test_get_by_key_returns_correct_serie(
|
|
self, temp_directory, sample_serie
|
|
):
|
|
"""Test get_by_key() retrieves series correctly."""
|
|
serie_list = SerieList(temp_directory)
|
|
serie_list.add(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, temp_directory):
|
|
"""Test get_by_key() returns None for nonexistent key."""
|
|
serie_list = SerieList(temp_directory)
|
|
|
|
result = serie_list.get_by_key("nonexistent-key")
|
|
assert result is None
|
|
|
|
def test_get_by_folder_backward_compatibility(
|
|
self, temp_directory, sample_serie
|
|
):
|
|
"""Test get_by_folder() provides backward compatibility."""
|
|
serie_list = SerieList(temp_directory)
|
|
serie_list.add(sample_serie)
|
|
|
|
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, temp_directory):
|
|
"""Test get_by_folder() returns None for nonexistent folder."""
|
|
serie_list = SerieList(temp_directory)
|
|
|
|
result = serie_list.get_by_folder("Nonexistent Folder")
|
|
assert result is None
|
|
|
|
def test_get_all_returns_all_series(self, temp_directory, sample_serie):
|
|
"""Test get_all() returns all series from keyDict."""
|
|
serie_list = SerieList(temp_directory)
|
|
serie_list.add(sample_serie)
|
|
|
|
serie2 = Serie(
|
|
key="naruto",
|
|
name="Naruto",
|
|
site="https://aniworld.to/anime/stream/naruto",
|
|
folder="Naruto (2002)",
|
|
episodeDict={1: [1, 2]}
|
|
)
|
|
serie_list.add(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, temp_directory
|
|
):
|
|
"""Test get_missing_episodes() returns only series with episodes."""
|
|
serie_list = SerieList(temp_directory)
|
|
|
|
# Serie with missing episodes
|
|
serie_with_episodes = Serie(
|
|
key="serie-with-episodes",
|
|
name="Serie With Episodes",
|
|
site="https://aniworld.to/anime/stream/serie-with-episodes",
|
|
folder="Serie With Episodes (2020)",
|
|
episodeDict={1: [1, 2, 3]}
|
|
)
|
|
|
|
# Serie without missing episodes
|
|
serie_without_episodes = Serie(
|
|
key="serie-without-episodes",
|
|
name="Serie Without Episodes",
|
|
site="https://aniworld.to/anime/stream/serie-without-episodes",
|
|
folder="Serie Without Episodes (2021)",
|
|
episodeDict={}
|
|
)
|
|
|
|
serie_list.add(serie_with_episodes)
|
|
serie_list.add(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
|
|
|
|
def test_load_series_stores_by_key(self, temp_directory, sample_serie):
|
|
"""Test load_series() stores series by key when loading from disk."""
|
|
# Create directory structure and save serie
|
|
folder_path = os.path.join(temp_directory, sample_serie.folder)
|
|
os.makedirs(folder_path, exist_ok=True)
|
|
data_path = os.path.join(folder_path, "data")
|
|
sample_serie.save_to_file(data_path)
|
|
|
|
# Create new SerieList (triggers load_series in __init__)
|
|
serie_list = SerieList(temp_directory)
|
|
|
|
# Verify loaded by key
|
|
assert sample_serie.key in serie_list.keyDict
|
|
loaded_serie = serie_list.keyDict[sample_serie.key]
|
|
assert loaded_serie.key == sample_serie.key
|
|
assert loaded_serie.name == sample_serie.name
|
|
|
|
|
|
class TestSerieListPublicAPI:
|
|
"""Test that public API still works correctly."""
|
|
|
|
def test_public_methods_work(self, temp_directory, sample_serie):
|
|
"""Test that all public methods work correctly after refactoring."""
|
|
serie_list = SerieList(temp_directory)
|
|
|
|
# Test add
|
|
serie_list.add(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 new helper methods
|
|
assert serie_list.get_by_key(sample_serie.key) is not None
|
|
assert serie_list.get_by_folder(sample_serie.folder) is not None
|