fix tests

This commit is contained in:
Lukas 2025-11-15 09:11:02 +01:00
parent 8ae8b0cdfb
commit f91875f6fc
10 changed files with 223 additions and 138 deletions

104
fix_tests.py Normal file
View File

@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""Script to batch fix common test issues after API changes."""
import re
import sys
from pathlib import Path
def fix_add_to_queue_calls(content: str) -> str:
"""Add serie_folder parameter to add_to_queue calls."""
# Pattern: add_to_queue(\n serie_id="...",
# Add: serie_folder="...",
pattern = r'(add_to_queue\(\s+serie_id="([^"]+)",)'
def replace_func(match):
serie_id = match.group(2)
# Extract just the series name without number if present
serie_folder = serie_id.split('-')[0] if '-' in serie_id else serie_id
return f'{match.group(1)}\n serie_folder="{serie_folder}",'
return re.sub(pattern, replace_func, content)
def fix_queue_status_response(content: str) -> str:
"""Fix queue status response structure - remove nested 'status' key."""
# Replace data["status"]["pending"] with data["pending_queue"]
content = re.sub(r'data\["status"\]\["pending"\]', 'data["pending_queue"]', content)
content = re.sub(r'data\["status"\]\["active"\]', 'data["active_downloads"]', content)
content = re.sub(r'data\["status"\]\["completed"\]', 'data["completed_downloads"]', content)
content = re.sub(r'data\["status"\]\["failed"\]', 'data["failed_downloads"]', content)
content = re.sub(r'data\["status"\]\["is_running"\]', 'data["is_running"]', content)
content = re.sub(r'data\["status"\]\["is_paused"\]', 'data["is_paused"]', content)
# Also fix response.json()["status"]["..."]
content = re.sub(r'response\.json\(\)\["status"\]\["pending"\]', 'response.json()["pending_queue"]', content)
content = re.sub(r'response\.json\(\)\["status"\]\["is_running"\]', 'response.json()["is_running"]', content)
content = re.sub(r'status\.json\(\)\["status"\]\["is_running"\]', 'status.json()["is_running"]', content)
content = re.sub(r'status\.json\(\)\["status"\]\["failed"\]', 'status.json()["failed_downloads"]', content)
content = re.sub(r'status\.json\(\)\["status"\]\["completed"\]', 'status.json()["completed_downloads"]', content)
# Fix assert "status" in data
content = re.sub(r'assert "status" in data', 'assert "is_running" in data', content)
return content
def fix_anime_service_init(content: str) -> str:
"""Fix AnimeService initialization in test fixtures."""
# This one is complex, so we'll just note files that need manual review
if 'AnimeService(' in content and 'directory=' in content:
print(" ⚠️ Contains AnimeService with directory= parameter - needs manual review")
return content
def main():
test_dir = Path(__file__).parent / "tests"
if not test_dir.exists():
print(f"Error: {test_dir} not found")
sys.exit(1)
files_to_fix = [
# Download service tests
"unit/test_download_service.py",
"unit/test_download_progress_websocket.py",
"integration/test_download_progress_integration.py",
"integration/test_websocket_integration.py",
# API tests with queue status
"api/test_queue_features.py",
"api/test_download_endpoints.py",
"frontend/test_existing_ui_integration.py",
]
for file_path in files_to_fix:
full_path = test_dir / file_path
if not full_path.exists():
print(f"Skipping {file_path} (not found)")
continue
print(f"Processing {file_path}...")
# Read content
content = full_path.read_text()
original_content = content
# Apply fixes
if 'add_to_queue(' in content:
content = fix_add_to_queue_calls(content)
if 'data["status"]' in content or 'response.json()["status"]' in content:
content = fix_queue_status_response(content)
content = fix_anime_service_init(content)
# Write back if changed
if content != original_content:
full_path.write_text(content)
print(f" ✓ Updated {file_path}")
else:
print(f" - No changes needed for {file_path}")
if __name__ == "__main__":
main()

View File

@ -74,7 +74,7 @@ class TestQueueDisplay:
data = response.json() data = response.json()
# Verify structure # Verify structure
assert "status" in data assert "is_running" in data
assert "statistics" in data assert "statistics" in data
status = data["status"] status = data["status"]
@ -107,7 +107,7 @@ class TestQueueDisplay:
assert response.status_code == 200 assert response.status_code == 200
data = response.json() data = response.json()
pending = data["status"]["pending"] pending = data["pending_queue"]
assert len(pending) > 0 assert len(pending) > 0
item = pending[0] item = pending[0]
@ -140,7 +140,7 @@ class TestQueueReordering:
) )
existing_items = [ existing_items = [
item["id"] item["id"]
for item in status_response.json()["status"]["pending"] for item in status_response.json()["pending_queue"]
] ]
if existing_items: if existing_items:
await client.request( await client.request(
@ -190,7 +190,7 @@ class TestQueueReordering:
) )
current_order = [ current_order = [
item["id"] item["id"]
for item in status_response.json()["status"]["pending"] for item in status_response.json()["pending_queue"]
] ]
assert current_order == new_order assert current_order == new_order
@ -270,7 +270,7 @@ class TestQueueControl:
"/api/queue/status", "/api/queue/status",
headers=auth_headers headers=auth_headers
) )
assert status.json()["status"]["is_running"] is False assert status.json()["is_running"] is False
# Start queue # Start queue
await client.post("/api/queue/start", headers=auth_headers) await client.post("/api/queue/start", headers=auth_headers)
@ -280,7 +280,7 @@ class TestQueueControl:
"/api/queue/status", "/api/queue/status",
headers=auth_headers headers=auth_headers
) )
assert status.json()["status"]["is_running"] is True assert status.json()["is_running"] is True
# Stop queue # Stop queue
await client.post("/api/queue/stop", headers=auth_headers) await client.post("/api/queue/stop", headers=auth_headers)
@ -290,7 +290,7 @@ class TestQueueControl:
"/api/queue/status", "/api/queue/status",
headers=auth_headers headers=auth_headers
) )
assert status.json()["status"]["is_running"] is False assert status.json()["is_running"] is False
class TestCompletedDownloads: class TestCompletedDownloads:
@ -323,7 +323,7 @@ class TestCompletedDownloads:
data = status.json() data = status.json()
completed_count = data["statistics"]["completed_count"] completed_count = data["statistics"]["completed_count"]
completed_list = len(data["status"]["completed"]) completed_list = len(data["completed_downloads"])
# Count should match list length # Count should match list length
assert completed_count == completed_list assert completed_count == completed_list
@ -390,7 +390,7 @@ class TestFailedDownloads:
data = status.json() data = status.json()
failed_count = data["statistics"]["failed_count"] failed_count = data["statistics"]["failed_count"]
failed_list = len(data["status"]["failed"]) failed_list = len(data["failed_downloads"])
# Count should match list length # Count should match list length
assert failed_count == failed_list assert failed_count == failed_list

View File

@ -244,7 +244,7 @@ class TestFrontendDownloadAPI:
assert response.status_code == 200 assert response.status_code == 200
data = response.json() data = response.json()
# Check for expected response structure # Check for expected response structure
assert "status" in data or "statistics" in data assert "is_running" in data or "statistics" in data
async def test_start_download_queue(self, authenticated_client): async def test_start_download_queue(self, authenticated_client):
"""Test POST /api/queue/start starts next download.""" """Test POST /api/queue/start starts next download."""

View File

@ -63,15 +63,11 @@ def websocket_service():
@pytest.fixture @pytest.fixture
async def anime_service(mock_series_app, progress_service): async def anime_service(mock_series_app, progress_service):
"""Create an AnimeService.""" """Create an AnimeService."""
with patch( service = AnimeService(
"src.server.services.anime_service.SeriesApp", series_app=mock_series_app,
return_value=mock_series_app progress_service=progress_service,
): )
service = AnimeService( yield service
directory="/test/anime",
progress_service=progress_service,
)
yield service
@pytest.fixture @pytest.fixture
@ -130,6 +126,7 @@ class TestDownloadProgressIntegration:
# Add download to queue # Add download to queue
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="integration_test", serie_id="integration_test",
serie_folder="integration_test",
serie_folder="test_folder", serie_folder="test_folder",
serie_name="Integration Test Anime", serie_name="Integration Test Anime",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
@ -203,6 +200,7 @@ class TestDownloadProgressIntegration:
# Add and start download # Add and start download
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="client_test", serie_id="client_test",
serie_folder="client_test",
serie_folder="test_folder", serie_folder="test_folder",
serie_name="Client Test Anime", serie_name="Client Test Anime",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
@ -266,6 +264,7 @@ class TestDownloadProgressIntegration:
# Start download # Start download
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="multi_client_test", serie_id="multi_client_test",
serie_folder="multi_client_test",
serie_folder="test_folder", serie_folder="test_folder",
serie_name="Multi Client Test", serie_name="Multi Client Test",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
@ -313,6 +312,7 @@ class TestDownloadProgressIntegration:
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="structure_test", serie_id="structure_test",
serie_folder="structure_test",
serie_folder="test_folder", serie_folder="test_folder",
serie_name="Structure Test", serie_name="Structure Test",
episodes=[EpisodeIdentifier(season=2, episode=3)], episodes=[EpisodeIdentifier(season=2, episode=3)],
@ -380,6 +380,7 @@ class TestDownloadProgressIntegration:
# Start download after disconnect # Start download after disconnect
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="disconnect_test", serie_id="disconnect_test",
serie_folder="disconnect_test",
serie_folder="test_folder", serie_folder="test_folder",
serie_name="Disconnect Test", serie_name="Disconnect Test",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],

View File

@ -47,12 +47,11 @@ def websocket_service():
@pytest.fixture @pytest.fixture
async def anime_service(mock_series_app, progress_service): async def anime_service(mock_series_app, progress_service):
"""Create an AnimeService with mocked dependencies.""" """Create an AnimeService with mocked dependencies."""
with patch("src.server.services.anime_service.SeriesApp", return_value=mock_series_app): service = AnimeService(
service = AnimeService( series_app=mock_series_app,
directory="/test/anime", progress_service=progress_service,
progress_service=progress_service, )
) yield service
yield service
@pytest.fixture @pytest.fixture
@ -86,6 +85,7 @@ class TestWebSocketDownloadIntegration:
# Add item to queue # Add item to queue
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="test_serie", serie_id="test_serie",
serie_folder="test_serie",
serie_name="Test Anime", serie_name="Test Anime",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
priority=DownloadPriority.HIGH, priority=DownloadPriority.HIGH,
@ -112,6 +112,7 @@ class TestWebSocketDownloadIntegration:
# Add items # Add items
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="test", serie_id="test",
serie_folder="test",
serie_name="Test", serie_name="Test",
episodes=[EpisodeIdentifier(season=1, episode=i) for i in range(1, 4)], episodes=[EpisodeIdentifier(season=1, episode=i) for i in range(1, 4)],
priority=DownloadPriority.NORMAL, priority=DownloadPriority.NORMAL,
@ -398,6 +399,7 @@ class TestWebSocketEndToEnd:
# Add items to queue # Add items to queue
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="test", serie_id="test",
serie_folder="test",
serie_name="Test Anime", serie_name="Test Anime",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
priority=DownloadPriority.HIGH, priority=DownloadPriority.HIGH,

View File

@ -6,7 +6,7 @@ error handling, and progress reporting integration.
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from unittest.mock import AsyncMock, MagicMock, patch from unittest.mock import AsyncMock, MagicMock
import pytest import pytest
@ -15,16 +15,17 @@ from src.server.services.progress_service import ProgressService
@pytest.fixture @pytest.fixture
def mock_series_app(): def mock_series_app(tmp_path):
"""Create a mock SeriesApp instance.""" """Create a mock SeriesApp instance."""
with patch("src.server.services.anime_service.SeriesApp") as mock_class: mock_instance = MagicMock()
mock_instance = MagicMock() mock_instance.directory_to_search = str(tmp_path)
mock_instance.series_list = [] mock_instance.series_list = []
mock_instance.search = MagicMock(return_value=[]) mock_instance.search = AsyncMock(return_value=[])
mock_instance.ReScan = MagicMock() mock_instance.rescan = AsyncMock()
mock_instance.download = MagicMock(return_value=True) mock_instance.download = AsyncMock(return_value=True)
mock_class.return_value = mock_instance mock_instance.download_status = None
yield mock_instance mock_instance.scan_status = None
return mock_instance
@pytest.fixture @pytest.fixture
@ -42,8 +43,7 @@ def mock_progress_service():
def anime_service(tmp_path, mock_series_app, mock_progress_service): def anime_service(tmp_path, mock_series_app, mock_progress_service):
"""Create an AnimeService instance for testing.""" """Create an AnimeService instance for testing."""
return AnimeService( return AnimeService(
directory=str(tmp_path), series_app=mock_series_app,
max_workers=2,
progress_service=mock_progress_service, progress_service=mock_progress_service,
) )
@ -51,35 +51,38 @@ def anime_service(tmp_path, mock_series_app, mock_progress_service):
class TestAnimeServiceInitialization: class TestAnimeServiceInitialization:
"""Test AnimeService initialization.""" """Test AnimeService initialization."""
def test_initialization_success(self, tmp_path, mock_progress_service): def test_initialization_success(
self, mock_series_app, mock_progress_service
):
"""Test successful service initialization.""" """Test successful service initialization."""
with patch("src.server.services.anime_service.SeriesApp"): service = AnimeService(
service = AnimeService( series_app=mock_series_app,
directory=str(tmp_path), progress_service=mock_progress_service,
max_workers=2, )
progress_service=mock_progress_service,
)
assert service._directory == str(tmp_path) assert service._app is mock_series_app
assert service._executor is not None assert service._progress_service is mock_progress_service
assert service._progress_service is mock_progress_service
def test_initialization_failure_raises_error( def test_initialization_failure_raises_error(
self, tmp_path, mock_progress_service self, tmp_path, mock_progress_service
): ):
"""Test SeriesApp initialization failure raises error.""" """Test SeriesApp initialization failure raises error."""
with patch( bad_series_app = MagicMock()
"src.server.services.anime_service.SeriesApp" bad_series_app.directory_to_search = str(tmp_path)
) as mock_class:
mock_class.side_effect = Exception("Initialization failed")
with pytest.raises( # Make event subscription fail
AnimeServiceError, match="Initialization failed" def raise_error(*args):
): raise Exception("Initialization failed")
AnimeService(
directory=str(tmp_path), bad_series_app.__setattr__ = raise_error
progress_service=mock_progress_service,
) with pytest.raises(
AnimeServiceError, match="Initialization failed"
):
AnimeService(
series_app=bad_series_app,
progress_service=mock_progress_service,
)
class TestListMissing: class TestListMissing:
@ -321,12 +324,12 @@ class TestConcurrency:
class TestFactoryFunction: class TestFactoryFunction:
"""Test factory function.""" """Test factory function."""
def test_get_anime_service(self, tmp_path): def test_get_anime_service(self):
"""Test get_anime_service factory function.""" """Test get_anime_service factory function."""
from src.server.services.anime_service import get_anime_service from src.server.services.anime_service import get_anime_service
with patch("src.server.services.anime_service.SeriesApp"): # The factory function doesn't take directory anymore
service = get_anime_service(directory=str(tmp_path)) service = get_anime_service()
assert isinstance(service, AnimeService) assert isinstance(service, AnimeService)
assert service._directory == str(tmp_path) assert service._app is not None

View File

@ -48,15 +48,15 @@ class TestDownloadPriority:
def test_all_priorities_exist(self): def test_all_priorities_exist(self):
"""Test that all expected priorities are defined.""" """Test that all expected priorities are defined."""
assert DownloadPriority.LOW == "low" assert DownloadPriority.LOW == "LOW"
assert DownloadPriority.NORMAL == "normal" assert DownloadPriority.NORMAL == "NORMAL"
assert DownloadPriority.HIGH == "high" assert DownloadPriority.HIGH == "HIGH"
def test_priority_values(self): def test_priority_values(self):
"""Test that priority values are lowercase strings.""" """Test that priority values are uppercase strings."""
for priority in DownloadPriority: for priority in DownloadPriority:
assert isinstance(priority.value, str) assert isinstance(priority.value, str)
assert priority.value.islower() assert priority.value.isupper()
class TestEpisodeIdentifier: class TestEpisodeIdentifier:

View File

@ -76,15 +76,11 @@ def progress_service():
@pytest.fixture @pytest.fixture
async def anime_service(mock_series_app, progress_service): async def anime_service(mock_series_app, progress_service):
"""Create an AnimeService with mocked dependencies.""" """Create an AnimeService with mocked dependencies."""
with patch( service = AnimeService(
"src.server.services.anime_service.SeriesApp", series_app=mock_series_app,
return_value=mock_series_app progress_service=progress_service,
): )
service = AnimeService( yield service
directory="/test/anime",
progress_service=progress_service,
)
yield service
@pytest.fixture @pytest.fixture
@ -118,7 +114,7 @@ class TestDownloadProgressWebSocket:
# Add item to queue # Add item to queue
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="test_serie_1", serie_id="test_serie_1",
serie_folder="test_folder", serie_folder="test_serie_1",
serie_name="Test Anime", serie_name="Test Anime",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
priority=DownloadPriority.NORMAL, priority=DownloadPriority.NORMAL,
@ -168,7 +164,7 @@ class TestDownloadProgressWebSocket:
# Add item with specific episode info # Add item with specific episode info
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="test_serie_2", serie_id="test_serie_2",
serie_folder="test_folder", serie_folder="test_serie_2",
serie_name="My Test Anime", serie_name="My Test Anime",
episodes=[EpisodeIdentifier(season=2, episode=5)], episodes=[EpisodeIdentifier(season=2, episode=5)],
priority=DownloadPriority.HIGH, priority=DownloadPriority.HIGH,
@ -203,7 +199,7 @@ class TestDownloadProgressWebSocket:
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="test_serie_3", serie_id="test_serie_3",
serie_folder="test_folder", serie_folder="test_serie_3",
serie_name="Progress Test", serie_name="Progress Test",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -240,7 +236,7 @@ class TestDownloadProgressWebSocket:
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="test_serie_4", serie_id="test_serie_4",
serie_folder="test_folder", serie_folder="test_serie_4",
serie_name="Speed Test", serie_name="Speed Test",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -272,7 +268,7 @@ class TestDownloadProgressWebSocket:
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="test_serie_5", serie_id="test_serie_5",
serie_folder="test_folder", serie_folder="test_serie_5",
serie_name="No Broadcast Test", serie_name="No Broadcast Test",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -300,7 +296,7 @@ class TestDownloadProgressWebSocket:
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="test_serie_6", serie_id="test_serie_6",
serie_folder="test_folder", serie_folder="test_serie_6",
serie_name="Error Handling Test", serie_name="Error Handling Test",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -331,7 +327,7 @@ class TestDownloadProgressWebSocket:
# Add multiple episodes # Add multiple episodes
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="test_serie_7", serie_id="test_serie_7",
serie_folder="test_folder", serie_folder="test_serie_7",
serie_name="Multi Episode Test", serie_name="Multi Episode Test",
episodes=[ episodes=[
EpisodeIdentifier(season=1, episode=1), EpisodeIdentifier(season=1, episode=1),
@ -378,7 +374,7 @@ class TestDownloadProgressWebSocket:
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="test_serie_8", serie_id="test_serie_8",
serie_folder="test_folder", serie_folder="test_serie_8",
serie_name="Model Test", serie_name="Model Test",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )

View File

@ -118,6 +118,7 @@ class TestQueueManagement:
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=episodes, episodes=episodes,
priority=DownloadPriority.NORMAL, priority=DownloadPriority.NORMAL,
@ -142,6 +143,7 @@ class TestQueueManagement:
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=episodes, episodes=episodes,
priority=DownloadPriority.NORMAL, priority=DownloadPriority.NORMAL,
@ -155,6 +157,7 @@ class TestQueueManagement:
"""Test removing items from pending queue.""" """Test removing items from pending queue."""
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -171,6 +174,7 @@ class TestQueueManagement:
# Add items to queue # Add items to queue
item_ids = await download_service.add_to_queue( item_ids = await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[ episodes=[
EpisodeIdentifier(season=1, episode=1), EpisodeIdentifier(season=1, episode=1),
@ -200,6 +204,7 @@ class TestQueueManagement:
# Add items and start one # Add items and start one
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[ episodes=[
EpisodeIdentifier(season=1, episode=1), EpisodeIdentifier(season=1, episode=1),
@ -236,6 +241,7 @@ class TestQueueManagement:
# Add item # Add item
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -258,6 +264,7 @@ class TestQueueManagement:
# Add item # Add item
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -279,6 +286,7 @@ class TestQueueStatus:
# Add items to queue # Add items to queue
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[ episodes=[
EpisodeIdentifier(season=1, episode=1), EpisodeIdentifier(season=1, episode=1),
@ -302,6 +310,7 @@ class TestQueueStatus:
# Add items # Add items
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[ episodes=[
EpisodeIdentifier(season=1, episode=1), EpisodeIdentifier(season=1, episode=1),
@ -380,6 +389,7 @@ class TestPersistence:
"""Test that queue state is persisted to disk.""" """Test that queue state is persisted to disk."""
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -408,6 +418,7 @@ class TestPersistence:
await service1.add_to_queue( await service1.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[ episodes=[
EpisodeIdentifier(season=1, episode=1), EpisodeIdentifier(season=1, episode=1),
@ -491,6 +502,7 @@ class TestBroadcastCallbacks:
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -530,6 +542,7 @@ class TestBroadcastCallbacks:
# Add an item to the queue # Add an item to the queue
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )
@ -617,6 +630,7 @@ class TestErrorHandling:
await download_service.add_to_queue( await download_service.add_to_queue(
serie_id="series-1", serie_id="series-1",
serie_folder="series",
serie_name="Test Series", serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)], episodes=[EpisodeIdentifier(season=1, episode=1)],
) )

View File

@ -7,11 +7,10 @@ Tests the functionality of SeriesApp including:
- Download with progress callbacks - Download with progress callbacks
- Directory scanning with progress reporting - Directory scanning with progress reporting
- Async versions of operations - Async versions of operations
- Cancellation support
- Error handling - Error handling
""" """
from unittest.mock import Mock, patch from unittest.mock import AsyncMock, Mock, patch
import pytest import pytest
@ -35,62 +34,30 @@ class TestSeriesAppInitialization:
# Verify initialization # Verify initialization
assert app.directory_to_search == test_dir assert app.directory_to_search == test_dir
assert app._operation_status == OperationStatus.IDLE
assert app._cancel_flag is False
assert app._current_operation is None
mock_loaders.assert_called_once() mock_loaders.assert_called_once()
mock_scanner.assert_called_once() mock_scanner.assert_called_once()
@patch('src.core.SeriesApp.Loaders') @patch('src.core.SeriesApp.Loaders')
@patch('src.core.SeriesApp.SerieScanner') def test_init_failure_raises_error(self, mock_loaders):
@patch('src.core.SeriesApp.SerieList') """Test that initialization failure raises error."""
def test_init_with_callbacks(
self, mock_serie_list, mock_scanner, mock_loaders
):
"""Test initialization with progress and error callbacks."""
test_dir = "/test/anime" test_dir = "/test/anime"
progress_callback = Mock()
error_callback = Mock()
# Create app with callbacks
app = SeriesApp(
test_dir,
progress_callback=progress_callback,
error_callback=error_callback
)
# Verify callbacks are stored
assert app.progress_callback == progress_callback
assert app.error_callback == error_callback
@patch('src.core.SeriesApp.Loaders')
def test_init_failure_calls_error_callback(self, mock_loaders):
"""Test that initialization failure triggers error callback."""
test_dir = "/test/anime"
error_callback = Mock()
# Make Loaders raise an exception # Make Loaders raise an exception
mock_loaders.side_effect = RuntimeError("Init failed") mock_loaders.side_effect = RuntimeError("Init failed")
# Create app should raise but call error callback # Create app should raise
with pytest.raises(RuntimeError): with pytest.raises(RuntimeError):
SeriesApp(test_dir, error_callback=error_callback) SeriesApp(test_dir)
# Verify error callback was called
error_callback.assert_called_once()
assert isinstance(
error_callback.call_args[0][0],
RuntimeError
)
class TestSeriesAppSearch: class TestSeriesAppSearch:
"""Test search functionality.""" """Test search functionality."""
@pytest.mark.asyncio
@patch('src.core.SeriesApp.Loaders') @patch('src.core.SeriesApp.Loaders')
@patch('src.core.SeriesApp.SerieScanner') @patch('src.core.SeriesApp.SerieScanner')
@patch('src.core.SeriesApp.SerieList') @patch('src.core.SeriesApp.SerieList')
def test_search_success( async def test_search_success(
self, mock_serie_list, mock_scanner, mock_loaders self, mock_serie_list, mock_scanner, mock_loaders
): ):
"""Test successful search.""" """Test successful search."""
@ -104,34 +71,32 @@ class TestSeriesAppSearch:
] ]
app.loader.search = Mock(return_value=expected_results) app.loader.search = Mock(return_value=expected_results)
# Perform search # Perform search (now async)
results = app.search("test anime") results = await app.search("test anime")
# Verify results # Verify results
assert results == expected_results assert results == expected_results
app.loader.search.assert_called_once_with("test anime") app.loader.search.assert_called_once_with("test anime")
@pytest.mark.asyncio
@patch('src.core.SeriesApp.Loaders') @patch('src.core.SeriesApp.Loaders')
@patch('src.core.SeriesApp.SerieScanner') @patch('src.core.SeriesApp.SerieScanner')
@patch('src.core.SeriesApp.SerieList') @patch('src.core.SeriesApp.SerieList')
def test_search_failure_calls_error_callback( async def test_search_failure_raises_error(
self, mock_serie_list, mock_scanner, mock_loaders self, mock_serie_list, mock_scanner, mock_loaders
): ):
"""Test search failure triggers error callback.""" """Test search failure raises error."""
test_dir = "/test/anime" test_dir = "/test/anime"
error_callback = Mock() app = SeriesApp(test_dir)
app = SeriesApp(test_dir, error_callback=error_callback)
# Make search raise an exception # Make search raise an exception
app.loader.search = Mock( app.loader.search = Mock(
side_effect=RuntimeError("Search failed") side_effect=RuntimeError("Search failed")
) )
# Search should raise and call error callback # Search should raise
with pytest.raises(RuntimeError): with pytest.raises(RuntimeError):
app.search("test") await app.search("test")
error_callback.assert_called_once()
class TestSeriesAppDownload: class TestSeriesAppDownload: