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

136 lines
4.5 KiB
Python

import asyncio
import logging
from unittest.mock import AsyncMock, MagicMock
import pytest
from services.audiodb_browse_queue import AudioDBBrowseQueue, BrowseQueueItem
@pytest.fixture
def queue():
return AudioDBBrowseQueue()
@pytest.fixture
def mock_audiodb_svc():
svc = AsyncMock()
svc.fetch_and_cache_artist_images = AsyncMock(return_value=None)
svc.fetch_and_cache_album_images = AsyncMock(return_value=None)
return svc
@pytest.fixture
def mock_prefs():
prefs = MagicMock()
settings = MagicMock()
settings.audiodb_enabled = True
prefs.get_advanced_settings.return_value = settings
return prefs
class TestEnqueue:
@pytest.mark.asyncio
async def test_enqueue_adds_item(self, queue: AudioDBBrowseQueue):
await queue.enqueue("artist", "abc-123", name="Coldplay")
assert queue._queue.qsize() == 1
@pytest.mark.asyncio
async def test_enqueue_dedup_same_mbid(self, queue: AudioDBBrowseQueue):
await queue.enqueue("artist", "abc-123")
await queue.enqueue("artist", "abc-123")
assert queue._queue.qsize() == 1
@pytest.mark.asyncio
async def test_enqueue_different_mbids(self, queue: AudioDBBrowseQueue):
await queue.enqueue("artist", "abc-123")
await queue.enqueue("album", "def-456")
assert queue._queue.qsize() == 2
@pytest.mark.asyncio
async def test_enqueue_full_queue_drops(self, queue: AudioDBBrowseQueue):
queue._queue = asyncio.Queue(maxsize=2)
await queue.enqueue("artist", "a")
await queue.enqueue("artist", "b")
await queue.enqueue("artist", "c")
assert queue._queue.qsize() == 2
@pytest.mark.asyncio
async def test_dedup_expires(self, queue: AudioDBBrowseQueue):
await queue.enqueue("artist", "abc-123")
queue._recent["abc-123"] -= 4000
await queue.enqueue("artist", "abc-123")
assert queue._queue.qsize() == 2
class TestConsumer:
@pytest.mark.asyncio
async def test_consumer_processes_artist(self, queue, mock_audiodb_svc, mock_prefs):
await queue.enqueue("artist", "abc-123", name="Coldplay")
task = queue.start_consumer(mock_audiodb_svc, mock_prefs)
await asyncio.sleep(0.05)
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
mock_audiodb_svc.fetch_and_cache_artist_images.assert_called_once_with(
"abc-123", "Coldplay", is_monitored=False,
)
@pytest.mark.asyncio
async def test_consumer_processes_album(self, queue, mock_audiodb_svc, mock_prefs):
await queue.enqueue("album", "def-456", name="Parachutes", artist_name="Coldplay")
task = queue.start_consumer(mock_audiodb_svc, mock_prefs)
await asyncio.sleep(0.05)
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
mock_audiodb_svc.fetch_and_cache_album_images.assert_called_once_with(
"def-456", artist_name="Coldplay", album_name="Parachutes", is_monitored=False,
)
@pytest.mark.asyncio
async def test_consumer_skips_when_disabled(self, queue, mock_audiodb_svc, mock_prefs):
mock_prefs.get_advanced_settings.return_value.audiodb_enabled = False
await queue.enqueue("artist", "abc-123", name="Coldplay")
task = queue.start_consumer(mock_audiodb_svc, mock_prefs)
await asyncio.sleep(0.05)
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
mock_audiodb_svc.fetch_and_cache_artist_images.assert_not_called()
@pytest.mark.asyncio
async def test_consumer_handles_item_error(self, queue, mock_audiodb_svc, mock_prefs, caplog):
mock_audiodb_svc.fetch_and_cache_artist_images.side_effect = RuntimeError("boom")
await queue.enqueue("artist", "abc-123", name="Coldplay")
caplog.set_level(logging.ERROR, logger="services.audiodb_browse_queue")
task = queue.start_consumer(mock_audiodb_svc, mock_prefs)
await asyncio.sleep(0.05)
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
assert queue._queue.qsize() == 0
assert any(
record.levelno == logging.ERROR
and "audiodb.browse_queue action=item_error" in record.message
and "entity_type=artist" in record.message
and "mbid=abc-123" in record.message
for record in caplog.records
)