- Add pytest config with 90% coverage threshold - 15 test files covering all routers, services, schemas, models - 300 tests: unit tests, integration tests, edge cases, mocked external APIs - Update CI workflow to run pytest with coverage enforcement - Mock external services (Genius, MusicBrainz, RadioBrowser) - In-memory SQLite DB per test via conftest fixtures
217 lines
7.3 KiB
Python
217 lines
7.3 KiB
Python
"""Schema validation tests."""
|
|
from datetime import datetime
|
|
|
|
|
|
class TestSongSchemas:
|
|
def test_song_base(self):
|
|
from app.schemas.song import SongBase
|
|
s = SongBase(title="T", artist="A")
|
|
assert s.title == "T"
|
|
assert s.album is None
|
|
|
|
def test_song_response(self):
|
|
from app.schemas.song import SongResponse
|
|
s = SongResponse(
|
|
id="1", title="T", artist="A", file_path="/tmp/t.mp3",
|
|
added_at=datetime.now()
|
|
)
|
|
assert s.duration_sec == 0
|
|
assert s.file_size_bytes == 0
|
|
|
|
def test_scan_result(self):
|
|
from app.schemas.song import ScanResult
|
|
sr = ScanResult(scanned=10, added=5, skipped=3, errors=["err"])
|
|
assert sr.scanned == 10
|
|
assert sr.errors == ["err"]
|
|
|
|
def test_song_create(self):
|
|
from app.schemas.song import SongCreate
|
|
s = SongCreate(title="T", artist="A", album="Album", genre="Rock")
|
|
assert s.genre == "Rock"
|
|
|
|
|
|
class TestPlaylistSchemas:
|
|
def test_playlist_base(self):
|
|
from app.schemas.playlist import PlaylistBase
|
|
p = PlaylistBase(name="Test")
|
|
assert p.description == ""
|
|
|
|
def test_playlist_create(self):
|
|
from app.schemas.playlist import PlaylistCreate
|
|
p = PlaylistCreate(name="T", song_ids=["s1", "s2"], mood_category="happy")
|
|
assert len(p.song_ids) == 2
|
|
|
|
def test_playlist_response(self):
|
|
from app.schemas.playlist import PlaylistResponse
|
|
p = PlaylistResponse(
|
|
id="1", name="T", created_at=datetime.now(), updated_at=datetime.now()
|
|
)
|
|
assert p.is_shared is False
|
|
assert p.song_count == 0
|
|
|
|
def test_playlist_with_songs(self):
|
|
from app.schemas.playlist import PlaylistWithSongs
|
|
p = PlaylistWithSongs(
|
|
id="1", name="T", created_at=datetime.now(), updated_at=datetime.now(),
|
|
songs=[]
|
|
)
|
|
assert p.songs == []
|
|
|
|
|
|
class TestMoodSchemas:
|
|
def test_mood_category(self):
|
|
from app.schemas.mood import MoodCategoryResponse
|
|
m = MoodCategoryResponse(
|
|
id="sad", name="Sad", color_hex="#1a2a4a",
|
|
description="D", background_image="/s.jpg", icon_path="/i.svg"
|
|
)
|
|
assert m.color_hex == "#1a2a4a"
|
|
|
|
def test_mood_score(self):
|
|
from app.schemas.mood import MoodScore
|
|
ms = MoodScore(mood="Happy", score=0.9, keywords=["joy"])
|
|
assert ms.score == 0.9
|
|
|
|
def test_mood_analysis(self):
|
|
from app.schemas.mood import MoodAnalysisResponse
|
|
ma = MoodAnalysisResponse(
|
|
song_id="s1", scores=[], top_mood="Happy", confidence=0.9,
|
|
analyzed_at=datetime.now()
|
|
)
|
|
assert ma.top_mood == "Happy"
|
|
|
|
def test_mood_playlist_response(self):
|
|
from app.schemas.mood import MoodPlaylistResponse
|
|
mp = MoodPlaylistResponse(mood="Chill", songs=[], total_songs=0)
|
|
assert mp.total_songs == 0
|
|
|
|
|
|
class TestLofiSchemas:
|
|
def test_lofi_channel(self):
|
|
from app.schemas.lofi import LofiChannelResponse
|
|
lc = LofiChannelResponse(
|
|
id="1", name="Lofi Girl", stream_url="https://y.com",
|
|
image_path=None, description="D", source_platform="youtube", is_active=True
|
|
)
|
|
assert lc.is_active is True
|
|
|
|
|
|
class TestRadioSchemas:
|
|
def test_station_response(self):
|
|
from app.schemas.radio import RadioStationResponse
|
|
rs = RadioStationResponse(
|
|
id="1", name="Test", stream_url="https://s.com",
|
|
frequency=None, location_lat=None, location_lon=None,
|
|
genre=None, country=None, language=None,
|
|
bitrate=None, tags=None, votes=None, is_favorite=False
|
|
)
|
|
assert rs.is_favorite is False
|
|
|
|
def test_current_response(self):
|
|
from app.schemas.radio import RadioCurrentResponse
|
|
rc = RadioCurrentResponse(station=None, is_playing=False)
|
|
assert rc.is_playing is False
|
|
|
|
|
|
class TestShareplaySchemas:
|
|
def test_room_response(self):
|
|
from app.schemas.shareplay import SharePlayRoomResponse
|
|
sr = SharePlayRoomResponse(
|
|
id="1", creator_user="u1", created_at=datetime.now(),
|
|
current_song_id=None, position_sec=0, is_playing=False,
|
|
shuffle_mode=False, active_connections=1
|
|
)
|
|
assert sr.active_connections == 1
|
|
|
|
def test_command(self):
|
|
from app.schemas.shareplay import SharePlayCommand
|
|
cmd = SharePlayCommand(type="play", payload={"position": 10})
|
|
assert cmd.type == "play"
|
|
|
|
def test_cue_response(self):
|
|
from app.schemas.shareplay import SharePlayCueResponse
|
|
cr = SharePlayCueResponse(items=[], next_song=None)
|
|
assert cr.items == []
|
|
|
|
|
|
class TestSettingsSchemas:
|
|
def test_user_settings(self):
|
|
from app.schemas.settings import UserSettingsResponse
|
|
us = UserSettingsResponse()
|
|
assert us.audio_quality == "high"
|
|
assert us.theme == "dark"
|
|
assert us.auto_transcode is True
|
|
|
|
def test_server_config(self):
|
|
from app.schemas.settings import ServerConfigResponse
|
|
sc = ServerConfigResponse(id="0", path="/music", name="Music")
|
|
assert sc.song_count == 0
|
|
|
|
|
|
class TestSearchSchemas:
|
|
def test_search_result(self):
|
|
from app.schemas.search import SearchResultResponse
|
|
sr = SearchResultResponse(query="test")
|
|
assert sr.songs == []
|
|
assert sr.playlists == []
|
|
assert sr.total_results == 0
|
|
|
|
|
|
class TestCommonSchemas:
|
|
def test_paginated(self):
|
|
from app.schemas.common import PaginatedResponse
|
|
from app.schemas.song import SongResponse
|
|
p = PaginatedResponse[SongResponse](
|
|
items=[], total=0, page=1, per_page=50, total_pages=1
|
|
)
|
|
assert p.total == 0
|
|
|
|
|
|
class TestAccountSchemas:
|
|
def test_artist_stat(self):
|
|
from app.schemas.account import ArtistStat
|
|
a = ArtistStat(name="Artist", count=5)
|
|
assert a.count == 5
|
|
|
|
def test_account_stats(self):
|
|
from app.schemas.account import AccountStatsResponse
|
|
s = AccountStatsResponse()
|
|
assert s.total_songs == 0
|
|
assert s.top_artists == []
|
|
|
|
def test_history_item(self):
|
|
from app.schemas.account import ListeningHistoryItem
|
|
h = ListeningHistoryItem(
|
|
song_id="s1", title="T", artist="A",
|
|
played_at=datetime.now(), duration_played=100
|
|
)
|
|
assert h.duration_played == 100
|
|
|
|
|
|
class TestEventsSchemas:
|
|
def test_event_response(self):
|
|
from app.schemas.events import ConcertEventResponse
|
|
e = ConcertEventResponse(
|
|
id="1", name="Concert", date="2025-01-01",
|
|
venue=None, location_lat=None, location_lon=None,
|
|
description=None
|
|
)
|
|
assert e.venue is None
|
|
|
|
|
|
class TestReleasesSchemas:
|
|
def test_release_track(self):
|
|
from app.schemas.releases import ReleaseTrack
|
|
t = ReleaseTrack(title="Song", duration=245, duration_formatted="4:05")
|
|
assert t.duration == 245
|
|
|
|
def test_album_response(self):
|
|
from app.schemas.releases import ReleaseAlbumResponse
|
|
a = ReleaseAlbumResponse(id="1", title="Album", release_date="2025-01-01")
|
|
assert a.tracks == []
|
|
|
|
def test_new_release(self):
|
|
from app.schemas.releases import NewReleaseResponse
|
|
nr = NewReleaseResponse(artist_name="Artist")
|
|
assert nr.albums == []
|