- Remove db_session parameter from SeriesApp, SerieList, SerieScanner - Move all database operations to AnimeService (service layer) - Add add_series_to_db, contains_in_db methods to AnimeService - Update sync_series_from_data_files to use inline DB operations - Remove obsolete test classes for removed DB methods - Fix pylint issues: add broad-except comments, fix line lengths - Core layer (src/core/) now has zero database imports 722 unit tests pass
137 lines
4.7 KiB
Python
137 lines
4.7 KiB
Python
"""Tests for SerieScanner class - file-based operations."""
|
|
|
|
import os
|
|
import tempfile
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from src.core.entities.series import Serie
|
|
from src.core.SerieScanner import SerieScanner
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_directory():
|
|
"""Create a temporary directory with subdirectories for testing."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
# Create an anime folder with an mp4 file
|
|
anime_folder = os.path.join(tmpdir, "Attack on Titan (2013)")
|
|
os.makedirs(anime_folder, exist_ok=True)
|
|
|
|
# Create a dummy mp4 file
|
|
mp4_path = os.path.join(
|
|
anime_folder, "Attack on Titan - S01E001 - (German Dub).mp4"
|
|
)
|
|
with open(mp4_path, "w") as f:
|
|
f.write("dummy mp4")
|
|
|
|
yield tmpdir
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_loader():
|
|
"""Create a mock Loader instance."""
|
|
loader = MagicMock()
|
|
loader.get_season_episode_count = MagicMock(return_value={1: 25})
|
|
loader.is_language = MagicMock(return_value=True)
|
|
return loader
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_serie():
|
|
"""Create a sample Serie for testing."""
|
|
return Serie(
|
|
key="attack-on-titan",
|
|
name="Attack on Titan",
|
|
site="aniworld.to",
|
|
folder="Attack on Titan (2013)",
|
|
episodeDict={1: [2, 3, 4]}
|
|
)
|
|
|
|
|
|
class TestSerieScannerInitialization:
|
|
"""Test SerieScanner initialization."""
|
|
|
|
def test_init_success(self, temp_directory, mock_loader):
|
|
"""Test successful initialization."""
|
|
scanner = SerieScanner(temp_directory, mock_loader)
|
|
|
|
assert scanner.directory == os.path.abspath(temp_directory)
|
|
assert scanner.loader == mock_loader
|
|
assert scanner.keyDict == {}
|
|
|
|
def test_init_empty_path_raises_error(self, mock_loader):
|
|
"""Test initialization with empty path raises ValueError."""
|
|
with pytest.raises(ValueError, match="empty"):
|
|
SerieScanner("", mock_loader)
|
|
|
|
def test_init_nonexistent_path_raises_error(self, mock_loader):
|
|
"""Test initialization with non-existent path raises ValueError."""
|
|
with pytest.raises(ValueError, match="does not exist"):
|
|
SerieScanner("/nonexistent/path", mock_loader)
|
|
|
|
|
|
class TestSerieScannerScan:
|
|
"""Test file-based scan operations."""
|
|
|
|
def test_file_based_scan_works(
|
|
self, temp_directory, mock_loader, sample_serie
|
|
):
|
|
"""Test file-based scan works properly."""
|
|
scanner = SerieScanner(temp_directory, mock_loader)
|
|
|
|
with patch.object(scanner, 'get_total_to_scan', return_value=1):
|
|
with patch.object(
|
|
scanner,
|
|
'_SerieScanner__find_mp4_files',
|
|
return_value=iter([
|
|
("Attack on Titan (2013)", ["S01E001.mp4"])
|
|
])
|
|
):
|
|
with patch.object(
|
|
scanner,
|
|
'_SerieScanner__read_data_from_file',
|
|
return_value=sample_serie
|
|
):
|
|
with patch.object(
|
|
scanner,
|
|
'_SerieScanner__get_missing_episodes_and_season',
|
|
return_value=({1: [2, 3]}, "aniworld.to")
|
|
):
|
|
with patch.object(
|
|
sample_serie, 'save_to_file'
|
|
) as mock_save:
|
|
scanner.scan()
|
|
|
|
# Verify file was saved
|
|
mock_save.assert_called_once()
|
|
|
|
def test_keydict_populated_after_scan(
|
|
self, temp_directory, mock_loader, sample_serie
|
|
):
|
|
"""Test keyDict is populated after scan."""
|
|
scanner = SerieScanner(temp_directory, mock_loader)
|
|
|
|
with patch.object(scanner, 'get_total_to_scan', return_value=1):
|
|
with patch.object(
|
|
scanner,
|
|
'_SerieScanner__find_mp4_files',
|
|
return_value=iter([
|
|
("Attack on Titan (2013)", ["S01E001.mp4"])
|
|
])
|
|
):
|
|
with patch.object(
|
|
scanner,
|
|
'_SerieScanner__read_data_from_file',
|
|
return_value=sample_serie
|
|
):
|
|
with patch.object(
|
|
scanner,
|
|
'_SerieScanner__get_missing_episodes_and_season',
|
|
return_value=({1: [2, 3]}, "aniworld.to")
|
|
):
|
|
with patch.object(sample_serie, 'save_to_file'):
|
|
scanner.scan()
|
|
|
|
assert sample_serie.key in scanner.keyDict
|