Complete Phase 7: Testing and Validation for identifier standardization
- Task 7.1: Update All Test Fixtures to Use Key - Updated FakeSerie/FakeSeriesApp with realistic keys in test_anime_endpoints.py - Updated 6+ fixtures in test_websocket_integration.py - Updated 5 fixtures in test_download_progress_integration.py - Updated 9 fixtures in test_download_progress_websocket.py - Updated 10+ fixtures in test_download_models.py - All fixtures now use URL-safe, lowercase, hyphenated key format - Task 7.2: Add Integration Tests for Identifier Consistency - Created tests/integration/test_identifier_consistency.py with 10 tests - TestAPIIdentifierConsistency: API response validation - TestServiceIdentifierConsistency: Download service key usage - TestWebSocketIdentifierConsistency: WebSocket events - TestIdentifierValidation: Model validation - TestEndToEndIdentifierFlow: Full flow verification - Tests use UUID suffixes for isolation All 1006 tests passing.
This commit is contained in:
@@ -124,9 +124,10 @@ class TestDownloadProgressIntegration:
|
||||
)
|
||||
|
||||
# Add download to queue
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase)
|
||||
await download_service.add_to_queue(
|
||||
serie_id="integration_test",
|
||||
serie_folder="test_folder",
|
||||
serie_id="integration-test-key",
|
||||
serie_folder="Integration Test Anime (2024)",
|
||||
serie_name="Integration Test Anime",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -197,9 +198,10 @@ class TestDownloadProgressIntegration:
|
||||
)
|
||||
|
||||
# Add and start download
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase)
|
||||
await download_service.add_to_queue(
|
||||
serie_id="client_test",
|
||||
serie_folder="test_folder",
|
||||
serie_id="client-test-key",
|
||||
serie_folder="Client Test Anime (2024)",
|
||||
serie_name="Client Test Anime",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -273,9 +275,10 @@ class TestDownloadProgressIntegration:
|
||||
)
|
||||
|
||||
# Start download
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase)
|
||||
await download_service.add_to_queue(
|
||||
serie_id="multi_client_test",
|
||||
serie_folder="test_folder",
|
||||
serie_id="multi-client-test-key",
|
||||
serie_folder="Multi Client Test (2024)",
|
||||
serie_name="Multi Client Test",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -320,9 +323,10 @@ class TestDownloadProgressIntegration:
|
||||
|
||||
progress_service.subscribe("progress_updated", capture_broadcast)
|
||||
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase)
|
||||
await download_service.add_to_queue(
|
||||
serie_id="structure_test",
|
||||
serie_folder="test_folder",
|
||||
serie_id="structure-test-key",
|
||||
serie_folder="Structure Test (2024)",
|
||||
serie_name="Structure Test",
|
||||
episodes=[EpisodeIdentifier(season=2, episode=3)],
|
||||
)
|
||||
@@ -382,9 +386,10 @@ class TestDownloadProgressIntegration:
|
||||
)
|
||||
|
||||
# Start download after disconnect
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase)
|
||||
await download_service.add_to_queue(
|
||||
serie_id="disconnect_test",
|
||||
serie_folder="test_folder",
|
||||
serie_id="disconnect-test-key",
|
||||
serie_folder="Disconnect Test (2024)",
|
||||
serie_name="Disconnect Test",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
|
||||
521
tests/integration/test_identifier_consistency.py
Normal file
521
tests/integration/test_identifier_consistency.py
Normal file
@@ -0,0 +1,521 @@
|
||||
"""Integration tests for series identifier consistency.
|
||||
|
||||
This module verifies that the 'key' identifier is used consistently
|
||||
across all layers of the application (API, services, database, WebSocket).
|
||||
|
||||
The identifier standardization ensures:
|
||||
- 'key' is the primary identifier (provider-assigned, URL-safe)
|
||||
- 'folder' is metadata only (not used for lookups)
|
||||
- Consistent identifier usage throughout the codebase
|
||||
"""
|
||||
import asyncio
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Dict, List
|
||||
from unittest.mock import AsyncMock, Mock
|
||||
|
||||
import pytest
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from src.server.fastapi_app import app
|
||||
from src.server.models.download import (
|
||||
DownloadItem,
|
||||
DownloadPriority,
|
||||
DownloadStatus,
|
||||
EpisodeIdentifier,
|
||||
)
|
||||
from src.server.services.anime_service import AnimeService
|
||||
from src.server.services.auth_service import auth_service
|
||||
from src.server.services.download_service import DownloadService
|
||||
from src.server.services.progress_service import ProgressService
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def reset_auth():
|
||||
"""Reset authentication state before each test."""
|
||||
original_hash = auth_service._hash
|
||||
auth_service._hash = None
|
||||
auth_service._failed.clear()
|
||||
yield
|
||||
auth_service._hash = original_hash
|
||||
auth_service._failed.clear()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def client():
|
||||
"""Create an async test client."""
|
||||
transport = ASGITransport(app=app)
|
||||
async with AsyncClient(transport=transport, base_url="http://test") as ac:
|
||||
yield ac
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def authenticated_client(client):
|
||||
"""Create an authenticated test client with token."""
|
||||
# Setup master password
|
||||
await client.post(
|
||||
"/api/auth/setup",
|
||||
json={"master_password": "TestPassword123!"}
|
||||
)
|
||||
|
||||
# Login to get token
|
||||
response = await client.post(
|
||||
"/api/auth/login",
|
||||
json={"password": "TestPassword123!"}
|
||||
)
|
||||
token = response.json()["access_token"]
|
||||
|
||||
# Add token to default headers
|
||||
client.headers.update({"Authorization": f"Bearer {token}"})
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_series_app():
|
||||
"""Mock SeriesApp for testing."""
|
||||
app_mock = Mock()
|
||||
app_mock.series_list = []
|
||||
app_mock.search = Mock(return_value=[])
|
||||
app_mock.ReScan = Mock()
|
||||
app_mock.download = Mock(return_value=True)
|
||||
return app_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def progress_service():
|
||||
"""Create a ProgressService instance for testing."""
|
||||
return ProgressService()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def download_service(mock_series_app, progress_service, tmp_path):
|
||||
"""Create a DownloadService with dependencies."""
|
||||
import uuid
|
||||
persistence_path = tmp_path / f"test_queue_{uuid.uuid4()}.json"
|
||||
|
||||
anime_service = AnimeService(
|
||||
series_app=mock_series_app,
|
||||
progress_service=progress_service,
|
||||
)
|
||||
anime_service.download = AsyncMock(return_value=True)
|
||||
|
||||
service = DownloadService(
|
||||
anime_service=anime_service,
|
||||
progress_service=progress_service,
|
||||
persistence_path=str(persistence_path),
|
||||
)
|
||||
yield service
|
||||
await service.stop()
|
||||
|
||||
|
||||
class TestAPIIdentifierConsistency:
|
||||
"""Test that API endpoints use 'key' as the primary identifier."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_queue_add_returns_key_in_response(
|
||||
self, authenticated_client
|
||||
):
|
||||
"""Test that adding to queue uses key as identifier.
|
||||
|
||||
Verifies:
|
||||
- Request accepts serie_id (key) as primary identifier
|
||||
- serie_folder is accepted as metadata
|
||||
- Response reflects correct identifiers
|
||||
"""
|
||||
request_data = {
|
||||
"serie_id": "attack-on-titan", # Key (primary identifier)
|
||||
"serie_folder": "Attack on Titan (2013)", # Metadata only
|
||||
"serie_name": "Attack on Titan",
|
||||
"episodes": [{"season": 1, "episode": 1}],
|
||||
"priority": "normal"
|
||||
}
|
||||
|
||||
response = await authenticated_client.post(
|
||||
"/api/queue/add",
|
||||
json=request_data
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
data = response.json()
|
||||
|
||||
# Verify response structure
|
||||
assert data["status"] == "success"
|
||||
assert len(data.get("added_items", [])) > 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_queue_status_contains_key_identifier(
|
||||
self, authenticated_client
|
||||
):
|
||||
"""Test that queue status returns key as identifier.
|
||||
|
||||
Verifies:
|
||||
- Queue items have serie_id (key) as identifier
|
||||
- Queue items have serie_folder as metadata
|
||||
- Both fields are present and distinct
|
||||
"""
|
||||
import uuid
|
||||
# Add an item first with unique key
|
||||
unique_suffix = str(uuid.uuid4())[:8]
|
||||
unique_key = f"one-piece-{unique_suffix}"
|
||||
unique_folder = f"One Piece ({unique_suffix})"
|
||||
|
||||
await authenticated_client.post(
|
||||
"/api/queue/add",
|
||||
json={
|
||||
"serie_id": unique_key,
|
||||
"serie_folder": unique_folder,
|
||||
"serie_name": "One Piece",
|
||||
"episodes": [{"season": 1, "episode": 1}],
|
||||
"priority": "normal"
|
||||
}
|
||||
)
|
||||
|
||||
# Get queue status
|
||||
response = await authenticated_client.get("/api/queue/status")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
|
||||
# Navigate to pending queue
|
||||
pending = data["status"]["pending_queue"]
|
||||
assert len(pending) > 0
|
||||
|
||||
# Find the item we just added by key
|
||||
matching_items = [
|
||||
item for item in pending if item["serie_id"] == unique_key
|
||||
]
|
||||
assert len(matching_items) == 1, (
|
||||
f"Expected to find item with key {unique_key}"
|
||||
)
|
||||
|
||||
item = matching_items[0]
|
||||
|
||||
# Verify identifier structure in queue item
|
||||
assert "serie_id" in item, "Queue item must have serie_id (key)"
|
||||
assert "serie_folder" in item, "Queue item must have serie_folder"
|
||||
|
||||
# Verify key format (lowercase, hyphenated)
|
||||
assert item["serie_id"] == unique_key
|
||||
|
||||
# Verify folder is preserved as metadata
|
||||
assert item["serie_folder"] == unique_folder
|
||||
|
||||
# Verify both are present but different
|
||||
assert item["serie_id"] != item["serie_folder"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_key_used_for_lookup_not_folder(
|
||||
self, authenticated_client
|
||||
):
|
||||
"""Test that lookups use key, not folder.
|
||||
|
||||
Verifies:
|
||||
- Items can be identified by serie_id (key)
|
||||
- Multiple items with same folder but different keys are distinct
|
||||
"""
|
||||
import uuid
|
||||
unique_suffix = str(uuid.uuid4())[:8]
|
||||
|
||||
# Add two items with different keys but similar folders
|
||||
key1 = f"naruto-original-{unique_suffix}"
|
||||
key2 = f"naruto-shippuden-{unique_suffix}"
|
||||
shared_folder = f"Naruto Series ({unique_suffix})"
|
||||
|
||||
await authenticated_client.post(
|
||||
"/api/queue/add",
|
||||
json={
|
||||
"serie_id": key1,
|
||||
"serie_folder": shared_folder,
|
||||
"serie_name": "Naruto",
|
||||
"episodes": [{"season": 1, "episode": 1}],
|
||||
"priority": "normal"
|
||||
}
|
||||
)
|
||||
|
||||
await authenticated_client.post(
|
||||
"/api/queue/add",
|
||||
json={
|
||||
"serie_id": key2,
|
||||
"serie_folder": shared_folder, # Same folder
|
||||
"serie_name": "Naruto Shippuden",
|
||||
"episodes": [{"season": 1, "episode": 1}],
|
||||
"priority": "normal"
|
||||
}
|
||||
)
|
||||
|
||||
# Get queue status
|
||||
response = await authenticated_client.get("/api/queue/status")
|
||||
data = response.json()
|
||||
|
||||
pending = data["status"]["pending_queue"]
|
||||
|
||||
# Both items should be present (same folder doesn't cause collision)
|
||||
serie_ids = [item["serie_id"] for item in pending]
|
||||
assert key1 in serie_ids
|
||||
assert key2 in serie_ids
|
||||
|
||||
|
||||
class TestServiceIdentifierConsistency:
|
||||
"""Test that services use 'key' as the primary identifier."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_download_service_uses_key(self, download_service):
|
||||
"""Test that DownloadService uses key as identifier.
|
||||
|
||||
Verifies:
|
||||
- Items are stored with serie_id (key)
|
||||
- Items can be retrieved by key
|
||||
- Queue operations use key consistently
|
||||
"""
|
||||
# Add item to queue
|
||||
item_ids = await download_service.add_to_queue(
|
||||
serie_id="my-hero-academia",
|
||||
serie_folder="My Hero Academia (2016)",
|
||||
serie_name="My Hero Academia",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
priority=DownloadPriority.NORMAL,
|
||||
)
|
||||
|
||||
assert len(item_ids) == 1
|
||||
|
||||
# Verify item is stored correctly
|
||||
pending = download_service._pending_queue
|
||||
assert len(pending) == 1
|
||||
|
||||
item = pending[0]
|
||||
assert item.serie_id == "my-hero-academia"
|
||||
assert item.serie_folder == "My Hero Academia (2016)"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_download_item_normalizes_key(self, download_service):
|
||||
"""Test that serie_id is normalized (lowercase, stripped).
|
||||
|
||||
Verifies:
|
||||
- Key is converted to lowercase
|
||||
- Whitespace is stripped
|
||||
"""
|
||||
# Add item with uppercase key
|
||||
item_ids = await download_service.add_to_queue(
|
||||
serie_id=" DEMON-SLAYER ",
|
||||
serie_folder="Demon Slayer (2019)",
|
||||
serie_name="Demon Slayer",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
priority=DownloadPriority.NORMAL,
|
||||
)
|
||||
|
||||
assert len(item_ids) == 1
|
||||
|
||||
# Verify key is normalized
|
||||
item = download_service._pending_queue[0]
|
||||
assert item.serie_id == "demon-slayer"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_queue_persistence_uses_key(
|
||||
self, download_service, tmp_path
|
||||
):
|
||||
"""Test that persisted queue data uses key as identifier.
|
||||
|
||||
Verifies:
|
||||
- Persisted data contains serie_id (key)
|
||||
- Data can be restored with correct identifiers
|
||||
"""
|
||||
import json
|
||||
|
||||
# Add item to queue
|
||||
await download_service.add_to_queue(
|
||||
serie_id="jujutsu-kaisen",
|
||||
serie_folder="Jujutsu Kaisen (2020)",
|
||||
serie_name="Jujutsu Kaisen",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
priority=DownloadPriority.NORMAL,
|
||||
)
|
||||
|
||||
# Read persisted data
|
||||
persistence_path = download_service._persistence_path
|
||||
with open(persistence_path, "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Verify persisted data structure
|
||||
assert "pending" in data
|
||||
assert len(data["pending"]) == 1
|
||||
|
||||
persisted_item = data["pending"][0]
|
||||
assert persisted_item["serie_id"] == "jujutsu-kaisen"
|
||||
assert persisted_item["serie_folder"] == "Jujutsu Kaisen (2020)"
|
||||
|
||||
|
||||
class TestWebSocketIdentifierConsistency:
|
||||
"""Test that WebSocket events use 'key' in their payloads."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_progress_events_include_key(
|
||||
self, download_service, progress_service
|
||||
):
|
||||
"""Test that progress events include key identifier.
|
||||
|
||||
Verifies:
|
||||
- Progress events contain key information
|
||||
- Events use consistent identifier structure
|
||||
"""
|
||||
broadcasts: List[Dict[str, Any]] = []
|
||||
|
||||
async def mock_event_handler(event):
|
||||
broadcasts.append({
|
||||
"type": event.event_type,
|
||||
"data": event.progress.to_dict(),
|
||||
"room": event.room,
|
||||
})
|
||||
|
||||
progress_service.subscribe("progress_updated", mock_event_handler)
|
||||
|
||||
# Add item to trigger events
|
||||
await download_service.add_to_queue(
|
||||
serie_id="spy-x-family",
|
||||
serie_folder="Spy x Family (2022)",
|
||||
serie_name="Spy x Family",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
priority=DownloadPriority.NORMAL,
|
||||
)
|
||||
|
||||
# Verify events were emitted
|
||||
assert len(broadcasts) >= 1
|
||||
|
||||
# Check queue progress events for metadata
|
||||
queue_events = [
|
||||
b for b in broadcasts if b["type"] == "queue_progress"
|
||||
]
|
||||
|
||||
# Verify metadata structure includes identifier info
|
||||
for event in queue_events:
|
||||
metadata = event["data"].get("metadata", {})
|
||||
# Queue events should track items by their identifiers
|
||||
if "added_ids" in metadata:
|
||||
assert len(metadata["added_ids"]) > 0
|
||||
|
||||
|
||||
class TestIdentifierValidation:
|
||||
"""Test identifier validation and edge cases."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_key_format_validation(self, authenticated_client):
|
||||
"""Test that key format is validated correctly.
|
||||
|
||||
Verifies:
|
||||
- Valid keys are accepted (lowercase, hyphenated)
|
||||
- Keys are normalized on input
|
||||
"""
|
||||
import uuid
|
||||
unique_suffix = str(uuid.uuid4())[:8]
|
||||
|
||||
# Valid key format
|
||||
response = await authenticated_client.post(
|
||||
"/api/queue/add",
|
||||
json={
|
||||
"serie_id": f"valid-key-format-{unique_suffix}",
|
||||
"serie_folder": f"Valid Key ({unique_suffix})",
|
||||
"serie_name": "Valid Key",
|
||||
"episodes": [{"season": 1, "episode": 1}],
|
||||
"priority": "normal"
|
||||
}
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_folder_not_used_for_identification(
|
||||
self, download_service
|
||||
):
|
||||
"""Test that folder changes don't affect identification.
|
||||
|
||||
Verifies:
|
||||
- Same key with different folder is same series
|
||||
- Folder is metadata only, not identity
|
||||
"""
|
||||
# Add item
|
||||
await download_service.add_to_queue(
|
||||
serie_id="chainsaw-man",
|
||||
serie_folder="Chainsaw Man (2022)",
|
||||
serie_name="Chainsaw Man",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
priority=DownloadPriority.NORMAL,
|
||||
)
|
||||
|
||||
# Add another episode for same key, different folder
|
||||
await download_service.add_to_queue(
|
||||
serie_id="chainsaw-man",
|
||||
serie_folder="Chainsaw Man Updated (2022)", # Different folder
|
||||
serie_name="Chainsaw Man",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=2)],
|
||||
priority=DownloadPriority.NORMAL,
|
||||
)
|
||||
|
||||
# Both should be added (same key, different episodes)
|
||||
assert len(download_service._pending_queue) == 2
|
||||
|
||||
# Verify both use the same key
|
||||
keys = [item.serie_id for item in download_service._pending_queue]
|
||||
assert all(k == "chainsaw-man" for k in keys)
|
||||
|
||||
|
||||
class TestEndToEndIdentifierFlow:
|
||||
"""End-to-end tests for identifier consistency across layers."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_complete_flow_with_key(
|
||||
self, authenticated_client
|
||||
):
|
||||
"""Test complete flow uses key consistently.
|
||||
|
||||
Verifies:
|
||||
- API -> Service -> Storage uses key
|
||||
- All responses contain correct identifiers
|
||||
"""
|
||||
import uuid
|
||||
# Use unique key to avoid conflicts with other tests
|
||||
unique_suffix = str(uuid.uuid4())[:8]
|
||||
unique_key = f"bleach-tybw-{unique_suffix}"
|
||||
unique_folder = f"Bleach: TYBW ({unique_suffix})"
|
||||
|
||||
# 1. Add to queue via API
|
||||
add_response = await authenticated_client.post(
|
||||
"/api/queue/add",
|
||||
json={
|
||||
"serie_id": unique_key,
|
||||
"serie_folder": unique_folder,
|
||||
"serie_name": "Bleach: TYBW",
|
||||
"episodes": [{"season": 1, "episode": 1}],
|
||||
"priority": "high"
|
||||
}
|
||||
)
|
||||
|
||||
assert add_response.status_code == 201
|
||||
|
||||
# 2. Verify in queue status
|
||||
status_response = await authenticated_client.get("/api/queue/status")
|
||||
assert status_response.status_code == 200
|
||||
|
||||
status_data = status_response.json()
|
||||
pending = status_data["status"]["pending_queue"]
|
||||
|
||||
# Find our item by key
|
||||
items = [
|
||||
i for i in pending
|
||||
if i["serie_id"] == unique_key
|
||||
]
|
||||
assert len(items) == 1, (
|
||||
f"Expected exactly 1 item with key {unique_key}, "
|
||||
f"found {len(items)}"
|
||||
)
|
||||
|
||||
item = items[0]
|
||||
|
||||
# 3. Verify identifier consistency
|
||||
assert item["serie_id"] == unique_key
|
||||
assert item["serie_folder"] == unique_folder
|
||||
assert item["serie_name"] == "Bleach: TYBW"
|
||||
|
||||
# 4. Verify key and folder are different
|
||||
assert item["serie_id"] != item["serie_folder"]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
@@ -106,9 +106,10 @@ class TestWebSocketDownloadIntegration:
|
||||
progress_svc.subscribe("progress_updated", mock_event_handler)
|
||||
|
||||
# Add item to queue
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase, hyphenated)
|
||||
item_ids = await download_svc.add_to_queue(
|
||||
serie_id="test_serie",
|
||||
serie_folder="test_serie",
|
||||
serie_id="test-serie-key",
|
||||
serie_folder="Test Anime (2024)",
|
||||
serie_name="Test Anime",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
priority=DownloadPriority.HIGH,
|
||||
@@ -142,9 +143,10 @@ class TestWebSocketDownloadIntegration:
|
||||
progress_svc.subscribe("progress_updated", mock_event_handler)
|
||||
|
||||
# Add items
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase, hyphenated)
|
||||
item_ids = await download_svc.add_to_queue(
|
||||
serie_id="test",
|
||||
serie_folder="test",
|
||||
serie_id="test-queue-ops-key",
|
||||
serie_folder="Test Queue Ops (2024)",
|
||||
serie_name="Test",
|
||||
episodes=[
|
||||
EpisodeIdentifier(season=1, episode=i)
|
||||
@@ -193,9 +195,10 @@ class TestWebSocketDownloadIntegration:
|
||||
progress_svc.subscribe("progress_updated", mock_event_handler)
|
||||
|
||||
# Add an item to initialize the queue progress
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase, hyphenated)
|
||||
await download_svc.add_to_queue(
|
||||
serie_id="test",
|
||||
serie_folder="test",
|
||||
serie_id="test-start-stop-key",
|
||||
serie_folder="Test Start Stop (2024)",
|
||||
serie_name="Test",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -226,9 +229,10 @@ class TestWebSocketDownloadIntegration:
|
||||
progress_svc.subscribe("progress_updated", mock_event_handler)
|
||||
|
||||
# Initialize the download queue progress by adding an item
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase)
|
||||
await download_svc.add_to_queue(
|
||||
serie_id="test",
|
||||
serie_folder="test",
|
||||
serie_id="test-init-key",
|
||||
serie_folder="Test Init (2024)",
|
||||
serie_name="Test Init",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -240,9 +244,9 @@ class TestWebSocketDownloadIntegration:
|
||||
|
||||
completed_item = DownloadItem(
|
||||
id="test_completed",
|
||||
serie_id="test",
|
||||
serie_id="test-completed-key",
|
||||
serie_name="Test",
|
||||
serie_folder="Test",
|
||||
serie_folder="Test (2024)",
|
||||
episode=EpisodeIdentifier(season=1, episode=1),
|
||||
status=DownloadStatus.COMPLETED,
|
||||
priority=DownloadPriority.NORMAL,
|
||||
@@ -463,9 +467,10 @@ class TestWebSocketEndToEnd:
|
||||
progress_service.subscribe("progress_updated", capture_event)
|
||||
|
||||
# Add items to queue
|
||||
# Note: serie_id uses provider key format (URL-safe, lowercase)
|
||||
item_ids = await download_svc.add_to_queue(
|
||||
serie_id="test",
|
||||
serie_folder="test",
|
||||
serie_id="test-e2e-key",
|
||||
serie_folder="Test Anime (2024)",
|
||||
serie_name="Test Anime",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
priority=DownloadPriority.HIGH,
|
||||
|
||||
Reference in New Issue
Block a user