music-app/backend/tests/test_edge_cases.py
Jarian Cottingham 24c03426f8 test: add comprehensive test suite with 94% coverage
- 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
2026-07-06 06:07:31 +00:00

168 lines
5.2 KiB
Python

"""Tests for uncovered routes: import, streaming, websocket."""
import tempfile
import os
class TestImportRouter:
def test_bulk_import_unsupported(self, client):
r = client.post(
"/api/import/bulk",
files=[("files", ("test.txt", b"content", "text/plain"))],
)
assert r.status_code == 200
data = r.json()
assert data["scanned"] == 0
assert len(data["errors"]) == 1
class TestSongStreaming:
def test_stream_not_found(self, client):
r = client.get("/api/songs/nonexistent/stream")
assert r.status_code == 404
def test_stream_file_not_found(self, client, db_module):
db = db_module.SessionLocal()
from app.models.song import Song
s = Song(id="s1", title="T", artist="A", file_path="/no/file.mp3")
db.add(s)
db.commit()
db.close()
r = client.get("/api/songs/s1/stream")
assert r.status_code == 404
class TestSongDelete:
def test_delete_song(self, client, db_module):
db = db_module.SessionLocal()
from app.models.song import Song
tmpdir = tempfile.mkdtemp()
fp = os.path.join(tmpdir, "test.mp3")
with open(fp, "w") as f:
f.write("test")
s = Song(id="s1", title="T", artist="A", file_path=fp)
db.add(s)
db.commit()
db.close()
r = client.delete("/api/songs/s1")
assert r.status_code == 200
assert not os.path.exists(fp)
os.unlink(fp) if os.path.exists(fp) else None
os.rmdir(tmpdir)
class TestPlaylistEdgeCases:
def test_add_song_playlist_not_found(self, client):
r = client.post("/api/playlists/nonexistent/songs", params={"song_id": "s1"})
assert r.status_code == 404
def test_add_song_song_not_found(self, client, db_module):
db = db_module.SessionLocal()
from app.models.playlist import Playlist
p = Playlist(id="p1", name="Test")
db.add(p)
db.commit()
db.close()
r = client.post("/api/playlists/p1/songs", params={"song_id": "nonexistent"})
assert r.status_code == 404
class TestMoodRouter:
def test_save_mood_playlist(self, client):
r = client.post("/api/mood/save", params={"mood": "Chill"})
assert r.status_code == 200
data = r.json()
assert data["name"] == "Chill Playlist"
class TestEventsAdd:
def test_add_event(self, client):
r = client.post("/api/events", json={
"id": "e99",
"name": "New Event",
"venue": "Venue",
"location_lat": 40.7,
"location_lon": -74.0,
"date": "2025-12-25",
"description": "Desc"
})
assert r.status_code == 200
class TestReleasesRouter:
def test_add_release_to_playlist_not_found(self, client):
r = client.post("/api/releases/add", params={
"artist": "A", "album_id": "b1", "playlist_id": "nonexistent"
})
assert r.status_code == 200
assert r.json().get("error") == "Playlist not found"
class TestSharePlayCue:
def test_add_to_cue_not_found(self, client):
r = client.post("/api/shareplay/cue", params={"room_id": "r1", "song_id": "nonexistent"})
assert r.status_code == 400
class TestSettingsRemoveServer:
def test_remove_server_bounds(self, client):
r = client.delete("/api/settings/servers/99")
# Should return 404 since no servers configured
assert r.status_code == 404
class TestRadioStream:
def test_stream_radio_not_found(self, client):
r = client.get("/api/radio/stream/nonexistent")
assert r.status_code == 200
class TestLofiChannels:
def test_list_after_add(self, client):
before = client.get("/api/lofi/channels").json()
client.post("/api/lofi/add", json={
"name": "Unique Lofi",
"stream_url": "https://unique.com/stream"
})
after = client.get("/api/lofi/channels").json()
assert len(after) == len(before) + 1
class TestSearchEdgeCases:
def test_search_special_chars(self, client):
r = client.get("/api/search?q=%25%27%22")
assert r.status_code == 200
class TestSongListEdgeCases:
def test_songs_per_page_max(self, client):
r = client.get("/api/songs?per_page=200")
assert r.status_code == 200
assert r.json()["per_page"] == 200
def test_songs_page_zero(self, client):
r = client.get("/api/songs?page=0")
assert r.status_code == 422
class TestMoodPlaylistLimit:
def test_mood_playlist_limit(self, client):
r = client.get("/api/mood/Happy/playlist?limit=5")
assert r.status_code == 200
def test_mood_playlist_limit_min(self, client):
r = client.get("/api/mood/Happy/playlist?limit=1")
assert r.status_code == 200
class TestSettingsUpdatePartial:
def test_update_partial_settings(self, client):
r = client.put("/api/settings", json={"theme": "light"})
assert r.status_code == 200
class TestAccountHistory:
def test_history_empty(self, client):
r = client.get("/api/account/history")
assert r.status_code == 200
assert r.json() == []