music-app/backend/tests/test_routers_songs.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

85 lines
2.5 KiB
Python

"""Router tests - Songs endpoints."""
from app.models.song import Song
class TestListSongs:
def test_empty_list(self, client):
r = client.get("/api/songs")
assert r.status_code == 200
data = r.json()
assert data["total"] == 0
assert data["items"] == []
assert data["page"] == 1
assert data["per_page"] == 50
def test_pagination_fields(self, client):
r = client.get("/api/songs?page=1&per_page=10")
assert r.status_code == 200
data = r.json()
assert "total_pages" in data
assert data["total_pages"] >= 1
def test_with_songs(self, client, db_module):
db = db_module.SessionLocal()
song = Song(id="s1", title="Test", artist="Artist", file_path="/tmp/test.mp3")
db.add(song)
db.commit()
db.close()
r = client.get("/api/songs")
assert r.status_code == 200
data = r.json()
assert data["total"] == 1
assert data["items"][0]["title"] == "Test"
class TestGetSong:
def test_found(self, client, db_module):
db = db_module.SessionLocal()
song = Song(id="s1", title="Test", artist="Artist", file_path="/tmp/test.mp3")
db.add(song)
db.commit()
db.close()
r = client.get("/api/songs/s1")
assert r.status_code == 200
assert r.json()["title"] == "Test"
def test_not_found(self, client):
r = client.get("/api/songs/nonexistent")
assert r.status_code == 404
class TestDeleteSong:
def test_delete_found(self, client, db_module):
db = db_module.SessionLocal()
song = Song(id="s1", title="Test", artist="Artist", file_path="/tmp/test.mp3")
db.add(song)
db.commit()
db.close()
r = client.delete("/api/songs/s1")
assert r.status_code == 200
assert r.json()["message"] == "Song deleted"
def test_delete_not_found(self, client):
r = client.delete("/api/songs/nonexistent")
assert r.status_code == 404
class TestScanSongs:
def test_scan_default_dir(self, client):
r = client.post("/api/songs/scan")
assert r.status_code == 200
data = r.json()
assert "scanned" in data
assert "added" in data
assert "skipped" in data
assert "errors" in data
class TestUploadSong:
def test_unsupported_format(self, client):
r = client.post(
"/api/songs/upload",
files={"file": ("test.txt", b"content", "text/plain")},
)
assert r.status_code == 400