Add filter for series with no downloaded episodes

- Added get_series_with_no_episodes() method to AnimeSeriesService
- Updated list_anime endpoint to support filter='no_episodes' parameter
- Added comprehensive unit tests for the new filtering functionality
- All tests passing successfully
This commit is contained in:
2026-01-23 18:55:04 +01:00
parent 2b904fd01e
commit c7bf232fe1
4 changed files with 977 additions and 661 deletions

View File

@@ -0,0 +1,191 @@
"""Tests for series filtering functionality."""
import pytest
from sqlalchemy.ext.asyncio import (
AsyncSession,
async_sessionmaker,
create_async_engine,
)
from src.server.database.models import Base
from src.server.database.service import AnimeSeriesService, EpisodeService
@pytest.fixture
async def db_engine():
"""Create test database engine."""
engine = create_async_engine(
"sqlite+aiosqlite:///:memory:",
echo=False,
)
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield engine
await engine.dispose()
@pytest.fixture
async def session_factory(db_engine):
"""Create session factory for testing."""
return async_sessionmaker(
db_engine,
class_=AsyncSession,
expire_on_commit=False,
autoflush=False,
autocommit=False,
)
@pytest.fixture
async def async_session(session_factory):
"""Create database session for testing."""
async with session_factory() as session:
yield session
await session.rollback()
@pytest.mark.asyncio
async def test_get_series_with_no_episodes_empty_database(
async_session: AsyncSession
):
"""Test that empty database returns empty list."""
result = await AnimeSeriesService.get_series_with_no_episodes(
async_session
)
assert result == []
@pytest.mark.asyncio
async def test_get_series_with_no_episodes_no_downloaded_episodes(
async_session: AsyncSession
):
"""Test that series with no downloaded episodes are returned."""
# Create a series with no episodes
series1 = await AnimeSeriesService.create(
async_session,
key="test-series-1",
name="Test Series 1",
folder="Test Series 1 (2024)",
site="https://example.com/test1",
)
# Create a series with undownloaded episodes
series2 = await AnimeSeriesService.create(
async_session,
key="test-series-2",
name="Test Series 2",
folder="Test Series 2 (2024)",
site="https://example.com/test2",
)
await EpisodeService.create(
async_session,
series_id=series2.id,
season=1,
episode_number=1,
is_downloaded=False,
)
# Create a series with downloaded episodes (should not be in result)
series3 = await AnimeSeriesService.create(
async_session,
key="test-series-3",
name="Test Series 3",
folder="Test Series 3 (2024)",
site="https://example.com/test3",
)
await EpisodeService.create(
async_session,
series_id=series3.id,
season=1,
episode_number=1,
is_downloaded=True,
)
await async_session.commit()
# Query for series with no downloaded episodes
result = await AnimeSeriesService.get_series_with_no_episodes(
async_session
)
# Should return series1 and series2 but not series3
result_ids = {s.id for s in result}
assert series1.id in result_ids
assert series2.id in result_ids
assert series3.id not in result_ids
@pytest.mark.asyncio
async def test_get_series_with_no_episodes_mixed_downloads(
async_session: AsyncSession
):
"""Test series with mixed downloaded/undownloaded episodes."""
# Create series with some downloaded and some undownloaded episodes
series = await AnimeSeriesService.create(
async_session,
key="test-series-mixed",
name="Test Series Mixed",
folder="Test Series Mixed (2024)",
site="https://example.com/testmixed",
)
# Add downloaded episode
await EpisodeService.create(
async_session,
series_id=series.id,
season=1,
episode_number=1,
is_downloaded=True,
)
# Add undownloaded episode
await EpisodeService.create(
async_session,
series_id=series.id,
season=1,
episode_number=2,
is_downloaded=False,
)
await async_session.commit()
# Query for series with no downloaded episodes
result = await AnimeSeriesService.get_series_with_no_episodes(
async_session
)
# Should NOT include series with at least one downloaded episode
result_ids = {s.id for s in result}
assert series.id not in result_ids
@pytest.mark.asyncio
async def test_get_series_with_no_episodes_pagination(
async_session: AsyncSession
):
"""Test pagination works correctly."""
# Create multiple series without downloaded episodes
for i in range(5):
await AnimeSeriesService.create(
async_session,
key=f"test-series-{i}",
name=f"Test Series {i}",
folder=f"Test Series {i} (2024)",
site=f"https://example.com/test{i}",
)
await async_session.commit()
# Test limit
result = await AnimeSeriesService.get_series_with_no_episodes(
async_session, limit=3
)
assert len(result) == 3
# Test offset
result = await AnimeSeriesService.get_series_with_no_episodes(
async_session, offset=2, limit=2
)
assert len(result) == 2