181 lines
6.0 KiB
Python
181 lines
6.0 KiB
Python
"""Tests for SettingsService.verify_navidrome / verify_youtube / verify_lastfm."""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from services.settings_service import (
|
|
SettingsService,
|
|
NavidromeVerifyResult,
|
|
YouTubeVerifyResult,
|
|
LastFmVerifyResult,
|
|
)
|
|
|
|
|
|
def _make_service(*, preferences=None):
|
|
prefs = preferences or MagicMock()
|
|
cache = MagicMock()
|
|
cache.clear_by_prefix = AsyncMock(return_value=0)
|
|
service = SettingsService(
|
|
preferences_service=prefs,
|
|
cache=cache,
|
|
)
|
|
return service
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verify_navidrome_success():
|
|
prefs = MagicMock()
|
|
raw = MagicMock()
|
|
raw.password = "real-password"
|
|
prefs.get_navidrome_connection_raw = MagicMock(return_value=raw)
|
|
|
|
service = _make_service(preferences=prefs)
|
|
|
|
from api.v1.schemas.settings import NavidromeConnectionSettings
|
|
settings = NavidromeConnectionSettings(
|
|
enabled=True,
|
|
navidrome_url="http://navidrome.local",
|
|
username="admin",
|
|
password="••••••••",
|
|
)
|
|
|
|
mock_repo_instance = MagicMock()
|
|
mock_repo_instance.ping = AsyncMock(return_value=True)
|
|
|
|
with patch("infrastructure.validators.validate_service_url"), \
|
|
patch("services.settings_service.get_settings", return_value=MagicMock()), \
|
|
patch("services.settings_service.get_http_client", return_value=MagicMock()), \
|
|
patch("repositories.navidrome_repository.NavidromeRepository") as MockRepo:
|
|
MockRepo.return_value = mock_repo_instance
|
|
MockRepo.reset_circuit_breaker = MagicMock()
|
|
|
|
result = await service.verify_navidrome(settings)
|
|
|
|
assert isinstance(result, NavidromeVerifyResult)
|
|
assert result.valid is True
|
|
assert "success" in result.message.lower()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verify_navidrome_ping_fail():
|
|
prefs = MagicMock()
|
|
raw = MagicMock()
|
|
raw.password = "real-password"
|
|
prefs.get_navidrome_connection_raw = MagicMock(return_value=raw)
|
|
|
|
service = _make_service(preferences=prefs)
|
|
|
|
from api.v1.schemas.settings import NavidromeConnectionSettings
|
|
settings = NavidromeConnectionSettings(
|
|
enabled=True,
|
|
navidrome_url="http://navidrome.local",
|
|
username="admin",
|
|
password="real-password",
|
|
)
|
|
|
|
mock_repo_instance = MagicMock()
|
|
mock_repo_instance.ping = AsyncMock(return_value=False)
|
|
|
|
with patch("infrastructure.validators.validate_service_url"), \
|
|
patch("services.settings_service.get_settings", return_value=MagicMock()), \
|
|
patch("services.settings_service.get_http_client", return_value=MagicMock()), \
|
|
patch("repositories.navidrome_repository.NavidromeRepository") as MockRepo:
|
|
MockRepo.return_value = mock_repo_instance
|
|
MockRepo.reset_circuit_breaker = MagicMock()
|
|
|
|
result = await service.verify_navidrome(settings)
|
|
|
|
assert result.valid is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verify_youtube_success():
|
|
service = _make_service()
|
|
|
|
from api.v1.schemas.settings import YouTubeConnectionSettings
|
|
settings = YouTubeConnectionSettings(
|
|
enabled=True,
|
|
api_key="test-key",
|
|
daily_quota_limit=100,
|
|
)
|
|
|
|
mock_repo_instance = MagicMock()
|
|
mock_repo_instance.verify_api_key = AsyncMock(return_value=(True, "Valid"))
|
|
|
|
with patch("services.settings_service.get_settings", return_value=MagicMock()), \
|
|
patch("services.settings_service.get_http_client", return_value=MagicMock()), \
|
|
patch("repositories.youtube.YouTubeRepository") as MockRepo:
|
|
MockRepo.return_value = mock_repo_instance
|
|
|
|
result = await service.verify_youtube(settings)
|
|
|
|
assert isinstance(result, YouTubeVerifyResult)
|
|
assert result.valid is True
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verify_lastfm_api_key_invalid():
|
|
prefs = MagicMock()
|
|
current = MagicMock()
|
|
current.shared_secret = "real-secret"
|
|
current.session_key = ""
|
|
prefs.get_lastfm_connection = MagicMock(return_value=current)
|
|
|
|
service = _make_service(preferences=prefs)
|
|
|
|
from api.v1.schemas.settings import LastFmConnectionSettings
|
|
settings = LastFmConnectionSettings(
|
|
enabled=True,
|
|
api_key="bad-key",
|
|
shared_secret="real-secret",
|
|
session_key="",
|
|
)
|
|
|
|
mock_repo_instance = MagicMock()
|
|
mock_repo_instance.validate_api_key = AsyncMock(return_value=(False, "Invalid API key"))
|
|
|
|
with patch("services.settings_service.get_settings", return_value=MagicMock()), \
|
|
patch("services.settings_service.get_http_client", return_value=MagicMock()), \
|
|
patch("repositories.lastfm_repository.LastFmRepository") as MockRepo:
|
|
MockRepo.return_value = mock_repo_instance
|
|
|
|
result = await service.verify_lastfm(settings)
|
|
|
|
assert isinstance(result, LastFmVerifyResult)
|
|
assert result.valid is False
|
|
assert "invalid" in result.message.lower()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_verify_lastfm_with_session_key():
|
|
prefs = MagicMock()
|
|
current = MagicMock()
|
|
current.shared_secret = "real-secret"
|
|
current.session_key = "real-session-key"
|
|
prefs.get_lastfm_connection = MagicMock(return_value=current)
|
|
|
|
service = _make_service(preferences=prefs)
|
|
|
|
from api.v1.schemas.settings import LastFmConnectionSettings, LASTFM_SECRET_MASK
|
|
settings = LastFmConnectionSettings(
|
|
enabled=True,
|
|
api_key="good-key",
|
|
shared_secret=LASTFM_SECRET_MASK,
|
|
session_key=LASTFM_SECRET_MASK,
|
|
)
|
|
|
|
mock_repo_instance = MagicMock()
|
|
mock_repo_instance.validate_api_key = AsyncMock(return_value=(True, "OK"))
|
|
mock_repo_instance.validate_session = AsyncMock(return_value=(True, "Session valid"))
|
|
|
|
with patch("services.settings_service.get_settings", return_value=MagicMock()), \
|
|
patch("services.settings_service.get_http_client", return_value=MagicMock()), \
|
|
patch("repositories.lastfm_repository.LastFmRepository") as MockRepo:
|
|
MockRepo.return_value = mock_repo_instance
|
|
|
|
result = await service.verify_lastfm(settings)
|
|
|
|
assert result.valid is True
|
|
assert "session" in result.message.lower()
|