"""Tests to push coverage toward 90%.""" import tempfile import os class TestSongUpload: def test_upload_unsupported(self, client): r = client.post( "/api/songs/upload", files={"file": ("test.txt", b"not audio", "text/plain")}, ) assert r.status_code == 400 assert "Unsupported format" in r.json()["detail"] class TestReleasesWithMock: pass def test_add_release_artist_not_found(self, client, db_module): from app.models.playlist import Playlist db = db_module.SessionLocal() p = Playlist(id="p1", name="Test") db.add(p) db.commit() db.close() r = client.post("/api/releases/add", params={ "artist": "UnknownXYZ", "album_id": "a1", "playlist_id": "p1" }) assert r.status_code == 200 assert r.json().get("error") == "Artist not found" class TestReleaseRouterWithMock: def test_check_artist_releases_mocked(self, client, db_module): import app.routers.releases as rel_mod original = rel_mod.search_artist rel_mod.search_artist = lambda x: {"id": "a1", "name": x, "releases": []} try: r = client.get("/api/releases/TestArtist") assert r.status_code == 200 finally: rel_mod.search_artist = original class TestImportBulk: def test_bulk_import_unsupported_formats(self, client): r = client.post( "/api/import/bulk", files=[("files", ("a.txt", b"x", "text/plain")), ("files", ("b.jpg", b"x", "image/jpeg"))], ) assert r.status_code == 200 data = r.json() assert data["scanned"] == 0 assert len(data["errors"]) == 2 class TestMoodAnalyzeAll: def test_analyze_all_empty(self, client): r = client.post("/api/mood/analyze") assert r.status_code == 200 assert r.json()["analyzed"] == 0 class TestRadioCurrent: def test_current_playing_defaults(self, client): r = client.get("/api/radio/current") assert r.status_code == 200 data = r.json() assert data["station"] is None assert data["song_name"] is None assert data["artist_name"] is None assert data["is_playing"] is False class TestSettingsAutoTranscode: def test_auto_transcode_false(self, client): client.put("/api/settings", json={"auto_transcode": False}) r = client.get("/api/settings") assert r.json()["auto_transcode"] is False class TestSongPagination: def test_songs_total_pages(self, client, db_module): from app.models.song import Song db = db_module.SessionLocal() for i in range(5): s = Song(id=f"s{i}", title=f"T{i}", artist="A", file_path=f"/tmp/{i}.mp3") db.add(s) db.commit() db.close() r = client.get("/api/songs?per_page=2") assert r.status_code == 200 data = r.json() assert data["total"] == 5 assert data["total_pages"] == 3 assert len(data["items"]) == 2 class TestPlaylistWithSongs: def test_playlist_songs_ordered(self, client, db_module): from app.models.song import Song from app.models.playlist import Playlist, PlaylistSong db = db_module.SessionLocal() p = Playlist(id="p1", name="Test") s1 = Song(id="s1", title="First", artist="A", file_path="/tmp/1.mp3") s2 = Song(id="s2", title="Second", artist="A", file_path="/tmp/2.mp3") ps1 = PlaylistSong(playlist_id="p1", song_id="s2", position=0) ps2 = PlaylistSong(playlist_id="p1", song_id="s1", position=1) db.add(p) db.add(s1) db.add(s2) db.add(ps1) db.add(ps2) db.commit() db.close() r = client.get("/api/playlists/p1") assert r.status_code == 200 data = r.json() assert len(data["songs"]) == 2 assert data["songs"][0]["title"] == "Second" # position 0 assert data["songs"][1]["title"] == "First" # position 1 assert data["song_count"] == 2 class TestSearchMultipleFields: def test_search_by_artist(self, client, db_module): from app.models.song import Song db = db_module.SessionLocal() s = Song(id="s1", title="Song", artist="UniqueArtist", file_path="/tmp/t.mp3") db.add(s) db.commit() db.close() r = client.get("/api/search?q=UniqueArtist") assert r.status_code == 200 assert len(r.json()["songs"]) == 1 def test_search_by_genre(self, client, db_module): from app.models.song import Song db = db_module.SessionLocal() s = Song(id="s1", title="Song", artist="A", genre="UniqueGenre", file_path="/tmp/t.mp3") db.add(s) db.commit() db.close() r = client.get("/api/search?q=UniqueGenre") assert r.status_code == 200 assert len(r.json()["songs"]) == 1 class TestReleaseCheckAllArtists: def test_check_releases_no_artists(self, client): r = client.get("/api/releases") assert r.status_code == 200 assert isinstance(r.json(), list) class TestLofiSeed: def test_seed_channels_called(self, client): # Default channels are seeded on startup r = client.get("/api/lofi/channels") assert r.status_code == 200 assert len(r.json()) >= 3 class TestSharePlayControlTypes: def test_control_volume(self, client, db_module): from app.routers.shareplay import manager db = db_module.SessionLocal() room = manager.create_room(db, creator="user") db.close() r = client.post("/api/shareplay/control", json={ "room_id": room["id"], "type": "unknown", "payload": None }) assert r.status_code == 200 class TestHealthEndpoint: def test_health_returns_ok(self, client): r = client.get("/health") assert r.status_code == 200 assert r.json() == {"status": "ok"} class TestNotFoundRoutes: def test_404_unknown_route(self, client): r = client.get("/api/nonexistent/route") assert r.status_code == 404 def test_405_wrong_method(self, client): r = client.post("/health") assert r.status_code == 405 class TestCORSHeaders: pass class TestAccountStatsWithGenres: def test_stats_empty(self, client): r = client.get("/api/account/stats") assert r.status_code == 200 data = r.json() assert data["total_listening_time"] == 0 assert data["top_artists"] == [] assert data["top_genres"] == [] assert data["top_moods"] == [] class TestMoodSetExistingSetting: def test_set_mood_updates_existing(self, client, db_module): from app.models.settings import UserSetting db = db_module.SessionLocal() s = UserSetting(key="default_mood", value="OldMood") db.add(s) db.commit() db.close() r = client.post("/api/mood/set", json={"mood": "NewMood"}) assert r.status_code == 200 db = db_module.SessionLocal() s = db.query(UserSetting).filter(UserSetting.key == "default_mood").first() assert s.value == "NewMood" db.close() class TestPlaylistUpdateFields: def test_update_description(self, client, db_module): from app.models.playlist import Playlist db = db_module.SessionLocal() p = Playlist(id="p1", name="Test") db.add(p) db.commit() db.close() r = client.put("/api/playlists/p1", json={ "name": "Test", "description": "New desc" }) assert r.status_code == 200 assert r.json()["description"] == "New desc" class TestRadioStationsParams: def test_stations_with_genre(self, client): r = client.get("/api/radio/stations?genre=jazz&limit=10") assert r.status_code == 200 def test_nearby_radius(self, client): r = client.get("/api/radio/nearby?lat=0&lon=0&radius=500") assert r.status_code == 200 class TestScanSongsWithDir: def test_scan_specific_dir(self, client): tmpdir = tempfile.mkdtemp() r = client.post("/api/songs/scan", params={"directory": tmpdir}) assert r.status_code == 200 assert r.json()["scanned"] == 0 os.rmdir(tmpdir) class TestDeleteSongCascade: def test_delete_song_removes_from_db(self, client, db_module): from app.models.song import Song db = db_module.SessionLocal() s = Song(id="s1", title="T", artist="A", file_path="/tmp/t.mp3") db.add(s) db.commit() db.close() r = client.delete("/api/songs/s1") assert r.status_code == 200 r = client.get("/api/songs/s1") assert r.status_code == 404 class TestServerConfig: def test_server_config_defaults(self): from app.schemas.settings import ServerConfigResponse sc = ServerConfigResponse(id="0", path="/music", name="Music") assert sc.last_scanned is None assert sc.song_count == 0 class TestReleaseTrackSchema: def test_release_track(self): from app.schemas.releases import ReleaseTrack t = ReleaseTrack(title="T", duration=0, duration_formatted="0:00") assert t.duration == 0 class TestSharePlayCommandSchema: def test_command_no_payload(self): from app.schemas.shareplay import SharePlayCommand cmd = SharePlayCommand(type="play") assert cmd.payload is None