Complete Task 8: Database Support for NFO Status
- Added 5 NFO tracking fields to AnimeSeries model - Fields: has_nfo, nfo_created_at, nfo_updated_at, tmdb_id, tvdb_id - Added 3 service methods to AnimeService for NFO operations - Methods: update_nfo_status, get_series_without_nfo, get_nfo_statistics - SQLAlchemy auto-migration (no manual migration needed) - Backward compatible with existing data - 15 new tests added (19/19 passing) - Tests: database models, service methods, integration queries
This commit is contained in:
@@ -341,6 +341,139 @@ class TestConcurrency:
|
||||
assert all(len(r) == 1 for r in results)
|
||||
|
||||
|
||||
class TestNFOTracking:
|
||||
"""Test NFO status tracking methods."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_nfo_status_success(self, anime_service):
|
||||
"""Test successful NFO status update."""
|
||||
mock_series = MagicMock()
|
||||
mock_series.key = "test-series"
|
||||
mock_series.has_nfo = False
|
||||
mock_series.nfo_created_at = None
|
||||
mock_series.nfo_updated_at = None
|
||||
mock_series.tmdb_id = None
|
||||
|
||||
mock_query = MagicMock()
|
||||
mock_query.filter.return_value.first.return_value = mock_series
|
||||
|
||||
mock_db = MagicMock()
|
||||
mock_db.query.return_value = mock_query
|
||||
|
||||
# Update NFO status
|
||||
await anime_service.update_nfo_status(
|
||||
key="test-series",
|
||||
has_nfo=True,
|
||||
tmdb_id=12345,
|
||||
db=mock_db
|
||||
)
|
||||
|
||||
# Verify series was updated
|
||||
assert mock_series.has_nfo is True
|
||||
assert mock_series.tmdb_id == 12345
|
||||
assert mock_series.nfo_created_at is not None
|
||||
assert mock_series.nfo_updated_at is not None
|
||||
mock_db.commit.assert_called_once()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_nfo_status_not_found(self, anime_service):
|
||||
"""Test NFO status update when series not found."""
|
||||
mock_query = MagicMock()
|
||||
mock_query.filter.return_value.first.return_value = None
|
||||
|
||||
mock_db = MagicMock()
|
||||
mock_db.query.return_value = mock_query
|
||||
|
||||
# Should not raise, just log warning
|
||||
await anime_service.update_nfo_status(
|
||||
key="nonexistent",
|
||||
has_nfo=True,
|
||||
db=mock_db
|
||||
)
|
||||
|
||||
# Should not commit if series not found
|
||||
mock_db.commit.assert_not_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_series_without_nfo(self, anime_service):
|
||||
"""Test getting series without NFO files."""
|
||||
mock_series1 = MagicMock()
|
||||
mock_series1.key = "series-1"
|
||||
mock_series1.name = "Series 1"
|
||||
mock_series1.folder = "Series 1 (2020)"
|
||||
mock_series1.tmdb_id = 123
|
||||
mock_series1.tvdb_id = None
|
||||
|
||||
mock_series2 = MagicMock()
|
||||
mock_series2.key = "series-2"
|
||||
mock_series2.name = "Series 2"
|
||||
mock_series2.folder = "Series 2 (2021)"
|
||||
mock_series2.tmdb_id = None
|
||||
mock_series2.tvdb_id = 456
|
||||
|
||||
mock_query = MagicMock()
|
||||
mock_query.filter.return_value.all.return_value = [
|
||||
mock_series1,
|
||||
mock_series2
|
||||
]
|
||||
|
||||
mock_db = MagicMock()
|
||||
mock_db.query.return_value = mock_query
|
||||
|
||||
result = await anime_service.get_series_without_nfo(db=mock_db)
|
||||
|
||||
assert len(result) == 2
|
||||
assert result[0]["key"] == "series-1"
|
||||
assert result[0]["has_nfo"] is False
|
||||
assert result[0]["tmdb_id"] == 123
|
||||
assert result[1]["key"] == "series-2"
|
||||
assert result[1]["tvdb_id"] == 456
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_nfo_statistics(self, anime_service):
|
||||
"""Test getting NFO statistics."""
|
||||
mock_db = MagicMock()
|
||||
|
||||
# Mock total count
|
||||
mock_total_query = MagicMock()
|
||||
mock_total_query.count.return_value = 100
|
||||
|
||||
# Mock with_nfo count
|
||||
mock_with_nfo_query = MagicMock()
|
||||
mock_with_nfo_filter = MagicMock()
|
||||
mock_with_nfo_filter.count.return_value = 75
|
||||
mock_with_nfo_query.filter.return_value = mock_with_nfo_filter
|
||||
|
||||
# Mock with_tmdb count
|
||||
mock_with_tmdb_query = MagicMock()
|
||||
mock_with_tmdb_filter = MagicMock()
|
||||
mock_with_tmdb_filter.count.return_value = 80
|
||||
mock_with_tmdb_query.filter.return_value = mock_with_tmdb_filter
|
||||
|
||||
# Mock with_tvdb count
|
||||
mock_with_tvdb_query = MagicMock()
|
||||
mock_with_tvdb_filter = MagicMock()
|
||||
mock_with_tvdb_filter.count.return_value = 60
|
||||
mock_with_tvdb_query.filter.return_value = mock_with_tvdb_filter
|
||||
|
||||
# Configure mock to return different queries for each call
|
||||
query_returns = [
|
||||
mock_total_query,
|
||||
mock_with_nfo_query,
|
||||
mock_with_tmdb_query,
|
||||
mock_with_tvdb_query
|
||||
]
|
||||
mock_db.query.side_effect = query_returns
|
||||
|
||||
result = await anime_service.get_nfo_statistics(db=mock_db)
|
||||
|
||||
assert result["total"] == 100
|
||||
assert result["with_nfo"] == 75
|
||||
assert result["without_nfo"] == 25
|
||||
assert result["with_tmdb_id"] == 80
|
||||
assert result["with_tvdb_id"] == 60
|
||||
|
||||
|
||||
class TestFactoryFunction:
|
||||
"""Test factory function."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user