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

143 lines
4.5 KiB
Python

import pytest
from unittest.mock import AsyncMock, MagicMock
from fastapi import FastAPI
from fastapi.testclient import TestClient
from api.v1.schemas.settings import (
LastFmConnectionSettings,
LastFmConnectionSettingsResponse,
LastFmVerifyResponse,
LASTFM_SECRET_MASK,
_mask_secret,
)
from api.v1.routes.settings import router
from core.dependencies import get_preferences_service, get_settings_service
def _saved_settings() -> LastFmConnectionSettings:
return LastFmConnectionSettings(
api_key="real-key",
shared_secret="real-secret-value",
session_key="sk-real-session",
username="testuser",
enabled=True,
)
@pytest.fixture
def mock_prefs():
mock = MagicMock()
mock.get_lastfm_connection.return_value = _saved_settings()
mock.save_lastfm_connection = MagicMock()
return mock
@pytest.fixture
def mock_settings_service():
mock = MagicMock()
mock.clear_home_cache = AsyncMock()
mock.on_lastfm_settings_changed = AsyncMock()
return mock
@pytest.fixture
def client(mock_prefs, mock_settings_service):
app = FastAPI()
app.include_router(router)
app.dependency_overrides[get_preferences_service] = lambda: mock_prefs
app.dependency_overrides[get_settings_service] = lambda: mock_settings_service
yield TestClient(app)
class TestGetLastFmSettings:
def test_returns_masked_secrets(self, client, mock_prefs):
response = client.get("/settings/lastfm")
assert response.status_code == 200
data = response.json()
assert data["api_key"] == "real-key"
assert data["shared_secret"] == _mask_secret("real-secret-value")
assert data["session_key"] == _mask_secret("sk-real-session")
assert data["username"] == "testuser"
assert data["enabled"] is True
def test_returns_empty_when_no_secret(self, client, mock_prefs):
mock_prefs.get_lastfm_connection.return_value = LastFmConnectionSettings()
response = client.get("/settings/lastfm")
assert response.status_code == 200
data = response.json()
assert data["shared_secret"] == ""
assert data["session_key"] == ""
class TestPutLastFmSettings:
def test_save_returns_masked_response(self, client, mock_prefs):
response = client.put(
"/settings/lastfm",
json={
"api_key": "new-key",
"shared_secret": "new-secret",
"session_key": "",
"username": "",
"enabled": True,
},
)
assert response.status_code == 200
mock_prefs.save_lastfm_connection.assert_called_once()
data = response.json()
assert data["shared_secret"] == _mask_secret("real-secret-value")
def test_save_with_empty_creds_still_succeeds(self, client, mock_prefs):
mock_prefs.get_lastfm_connection.return_value = LastFmConnectionSettings(
api_key="",
shared_secret="",
session_key="",
username="",
enabled=False,
)
response = client.put(
"/settings/lastfm",
json={
"api_key": "",
"shared_secret": "",
"session_key": "",
"username": "",
"enabled": False,
},
)
assert response.status_code == 200
def test_save_preserves_masked_session_key(self, client, mock_prefs):
masked = _mask_secret("sk-real-session")
response = client.put(
"/settings/lastfm",
json={
"api_key": "real-key",
"shared_secret": LASTFM_SECRET_MASK,
"session_key": masked,
"username": "testuser",
"enabled": True,
},
)
assert response.status_code == 200
saved = mock_prefs.save_lastfm_connection.call_args[0][0]
assert saved.shared_secret == LASTFM_SECRET_MASK
assert saved.session_key == masked
class TestMaskSecretConsistency:
def test_mask_secret_starts_with_mask_constant(self):
masked = _mask_secret("secret123")
assert masked.startswith(LASTFM_SECRET_MASK)
def test_mask_secret_short_value_equals_mask(self):
masked = _mask_secret("ab")
assert masked == LASTFM_SECRET_MASK
def test_mask_secret_empty_returns_empty(self):
assert _mask_secret("") == ""
def test_mask_secret_suffix_preserved(self):
masked = _mask_secret("my-long-secret")
assert masked == LASTFM_SECRET_MASK + "cret"