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

109 lines
3.4 KiB
Python

"""Tests for LibraryService._resolve_album_tracks and resolve_tracks_batch."""
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from api.v1.schemas.library import TrackResolveRequest, TrackResolveResponse, ResolvedTrack
from services.library_service import LibraryService
def _item(mbid: str, disc: int = 1, track: int = 1):
"""Shorthand to build a TrackResolveRequest.Item-like object."""
from api.v1.schemas.library import TrackResolveItem
return TrackResolveItem(release_group_mbid=mbid, disc_number=disc, track_number=track)
def _make_service(
*,
local_service=None,
jf_service=None,
nd_service=None,
preferences=None,
cache=None,
):
lidarr_repo = MagicMock()
library_db = MagicMock()
memory_cache = cache or MagicMock()
disk_cache = MagicMock()
prefs = preferences or MagicMock()
audiodb_image_service = MagicMock()
cover_repo = MagicMock()
service = LibraryService(
lidarr_repo=lidarr_repo,
library_db=library_db,
cover_repo=cover_repo,
preferences_service=prefs,
memory_cache=memory_cache,
disk_cache=disk_cache,
audiodb_image_service=audiodb_image_service,
local_files_service=local_service,
jellyfin_library_service=jf_service,
navidrome_library_service=nd_service,
)
return service
@pytest.mark.asyncio
async def test_resolve_tracks_batch_empty_items():
service = _make_service()
result = await service.resolve_tracks_batch([])
assert isinstance(result, TrackResolveResponse)
assert result.items == []
@pytest.mark.asyncio
async def test_resolve_tracks_batch_respects_max_items():
service = _make_service()
items = [_item(f"mbid-{i}", track=i) for i in range(60)]
cache = MagicMock()
cache.get = AsyncMock(return_value=None)
cache.set = AsyncMock()
service._memory_cache = cache
local_service = MagicMock()
local_match = MagicMock()
local_match.found = False
local_match.tracks = []
local_service.match_album_by_mbid = AsyncMock(return_value=local_match)
service._local_files_service = local_service
prefs = MagicMock()
prefs.get_navidrome_connection_raw = MagicMock(side_effect=Exception("unconfigured"))
prefs.get_jellyfin_connection = MagicMock(side_effect=Exception("unconfigured"))
service._preferences_service = prefs
result = await service.resolve_tracks_batch(items)
assert len(result.items) <= 50
@pytest.mark.asyncio
async def test_resolve_tracks_batch_missing_mbid_returns_base():
service = _make_service()
items = [_item("", disc=1, track=1)]
result = await service.resolve_tracks_batch(items)
assert len(result.items) == 1
assert result.items[0].source is None
assert result.items[0].stream_url is None
@pytest.mark.asyncio
async def test_resolve_tracks_batch_uses_cache_hit():
cache = MagicMock()
cached_map = {"1:1": ("local", "file-123", "flac", 240.0)}
cache.get = AsyncMock(return_value=cached_map)
cache.set = AsyncMock()
service = _make_service(cache=cache)
items = [_item("mbid-abc", disc=1, track=1)]
result = await service.resolve_tracks_batch(items)
assert len(result.items) == 1
assert result.items[0].source == "local"
assert result.items[0].stream_url == "/api/v1/stream/local/file-123"
assert result.items[0].format == "flac"
assert result.items[0].duration == 240.0