Files
musicseerr/backend/tests/services/test_album_service.py
T
2026-04-03 15:53:00 +01:00

157 lines
5.6 KiB
Python

from unittest.mock import AsyncMock, MagicMock
import pytest
from api.v1.schemas.album import AlbumInfo
from services.album_service import AlbumService
def _make_service() -> tuple[AlbumService, MagicMock, MagicMock]:
lidarr_repo = MagicMock()
mb_repo = MagicMock()
library_db = MagicMock()
memory_cache = MagicMock()
disk_cache = MagicMock()
preferences_service = MagicMock()
audiodb_image_service = MagicMock()
service = AlbumService(
lidarr_repo=lidarr_repo,
mb_repo=mb_repo,
library_db=library_db,
memory_cache=memory_cache,
disk_cache=disk_cache,
preferences_service=preferences_service,
audiodb_image_service=audiodb_image_service,
)
return service, lidarr_repo, library_db
@pytest.mark.asyncio
async def test_revalidate_library_status_keeps_value_when_lidarr_details_unavailable():
service, lidarr_repo, _ = _make_service()
lidarr_repo.get_album_details = AsyncMock(return_value=None)
lidarr_repo.get_library_mbids = AsyncMock(return_value={"should-not-be-used"})
service._save_album_to_cache = AsyncMock()
album_info = AlbumInfo(
title="Test",
musicbrainz_id="4549a80c-efe6-4386-b3a2-4b4a918eb31f",
artist_name="Artist",
artist_id="artist-id",
in_library=True,
)
result = await service._revalidate_library_status(album_info.musicbrainz_id, album_info)
assert result.in_library is True
service._save_album_to_cache.assert_not_called()
lidarr_repo.get_library_mbids.assert_not_called()
@pytest.mark.asyncio
async def test_revalidate_library_status_uses_lidarr_details_and_updates_cache_on_change():
service, lidarr_repo, _ = _make_service()
lidarr_repo.get_album_details = AsyncMock(
return_value={"monitored": False, "statistics": {"trackFileCount": 0}}
)
service._save_album_to_cache = AsyncMock()
album_info = AlbumInfo(
title="Test",
musicbrainz_id="8e1e9e51-38dc-4df3-8027-a0ada37d4674",
artist_name="Artist",
artist_id="artist-id",
in_library=True,
)
result = await service._revalidate_library_status(album_info.musicbrainz_id, album_info)
assert result.in_library is False
service._save_album_to_cache.assert_awaited_once()
@pytest.mark.asyncio
async def test_get_album_basic_info_does_not_use_library_cache_when_lidarr_payload_exists():
service, lidarr_repo, library_db = _make_service()
service._get_cached_album_info = AsyncMock(return_value=None)
service._fetch_release_group = AsyncMock(
return_value={
"title": "Album",
"first-release-date": "2024-01-01",
"primary-type": "Album",
"disambiguation": "",
"artist-credit": [],
}
)
lidarr_repo.get_requested_mbids = AsyncMock(return_value=set())
lidarr_repo.get_album_details = AsyncMock(
return_value={"monitored": False, "statistics": {"trackFileCount": 20}}
)
library_db.get_album_by_mbid = AsyncMock(return_value={"mbid": "from-cache"})
result = await service.get_album_basic_info("8e1e9e51-38dc-4df3-8027-a0ada37d4674")
assert result.in_library is False
library_db.get_album_by_mbid.assert_not_awaited()
@pytest.mark.asyncio
async def test_get_album_tracks_info_preserves_disc_numbers_from_lidarr():
service, lidarr_repo, _ = _make_service()
service._get_cached_album_info = AsyncMock(return_value=None)
lidarr_repo.is_configured.return_value = True
lidarr_repo.get_album_details = AsyncMock(return_value={"id": 42, "monitored": True})
lidarr_repo.get_album_tracks = AsyncMock(
return_value=[
{
"track_number": 1,
"disc_number": 1,
"title": "Disc One",
"duration_ms": 1000,
},
{
"track_number": 1,
"disc_number": 2,
"title": "Disc Two",
"duration_ms": 2000,
},
]
)
result = await service.get_album_tracks_info("8e1e9e51-38dc-4df3-8027-a0ada37d4674")
assert [(track.disc_number, track.position, track.title) for track in result.tracks] == [
(1, 1, "Disc One"),
(2, 1, "Disc Two"),
]
assert result.total_length == 3000
@pytest.mark.asyncio
async def test_get_album_tracks_info_multi_disc_same_track_numbers():
"""Verify tracks with same track_number but different disc_number are kept distinct."""
service, lidarr_repo, _ = _make_service()
service._get_cached_album_info = AsyncMock(return_value=None)
lidarr_repo.is_configured.return_value = True
lidarr_repo.get_album_details = AsyncMock(return_value={"id": 42, "monitored": True})
lidarr_repo.get_album_tracks = AsyncMock(
return_value=[
{"track_number": 1, "disc_number": 1, "title": "Intro", "duration_ms": 1000},
{"track_number": 2, "disc_number": 1, "title": "Main", "duration_ms": 2000},
{"track_number": 1, "disc_number": 2, "title": "Intro II", "duration_ms": 1500},
{"track_number": 2, "disc_number": 2, "title": "Finale", "duration_ms": 3000},
]
)
result = await service.get_album_tracks_info("8e1e9e51-38dc-4df3-8027-a0ada37d4674")
assert len(result.tracks) == 4
disc_track_pairs = [(track.disc_number, track.position, track.title) for track in result.tracks]
assert (1, 1, "Intro") in disc_track_pairs
assert (1, 2, "Main") in disc_track_pairs
assert (2, 1, "Intro II") in disc_track_pairs
assert (2, 2, "Finale") in disc_track_pairs
assert result.total_length == 7500