mirror of https://github.com/Nezreka/SoulSync.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.5 KiB
100 lines
3.5 KiB
"""Unit tests for api_search_tracks (fix 2.2).
|
|
|
|
The track search endpoint previously called search_tracks() then
|
|
api_get_tracks_by_ids() to re-hydrate the same rows. api_search_tracks
|
|
now returns the full dict rows in a single query.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from database.music_database import MusicDatabase
|
|
|
|
|
|
@pytest.fixture
|
|
def db(tmp_path):
|
|
return MusicDatabase(str(tmp_path / "music.db"))
|
|
|
|
|
|
def _insert_track(db, track_id, title, artist_id, artist_name, album_id, album_title):
|
|
with db._get_connection() as conn:
|
|
conn.execute(
|
|
"INSERT OR IGNORE INTO artists (id, name) VALUES (?, ?)",
|
|
(artist_id, artist_name),
|
|
)
|
|
conn.execute(
|
|
"INSERT OR IGNORE INTO albums (id, title, artist_id) VALUES (?, ?, ?)",
|
|
(album_id, album_title, artist_id),
|
|
)
|
|
conn.execute(
|
|
"""INSERT INTO tracks (id, album_id, artist_id, title, track_number, duration, file_path)
|
|
VALUES (?, ?, ?, ?, 1, 180, ?)""",
|
|
(track_id, album_id, artist_id, title, f"/music/{title}.mp3"),
|
|
)
|
|
conn.commit()
|
|
|
|
|
|
def test_api_search_tracks_returns_dict_rows_with_full_columns(db):
|
|
_insert_track(db, 100, "Great Song", 1, "Band One", 10, "Album X")
|
|
|
|
results = db.api_search_tracks(title="great")
|
|
|
|
assert len(results) == 1
|
|
row = results[0]
|
|
assert isinstance(row, dict)
|
|
assert str(row["id"]) == "100"
|
|
assert row["title"] == "Great Song"
|
|
assert row["artist_name"] == "Band One"
|
|
assert row["album_title"] == "Album X"
|
|
# file_path is a tracks.* column that must be present
|
|
assert row["file_path"] == "/music/Great Song.mp3"
|
|
|
|
|
|
def test_api_search_tracks_empty_query_returns_empty(db):
|
|
_insert_track(db, 1, "Track", 1, "Artist", 1, "Album")
|
|
assert db.api_search_tracks() == []
|
|
|
|
|
|
def test_api_search_tracks_no_matches_returns_empty(db):
|
|
_insert_track(db, 1, "Alpha", 1, "Artist A", 1, "Album A")
|
|
assert db.api_search_tracks(title="nonexistent") == []
|
|
|
|
|
|
def test_api_search_tracks_matches_by_artist(db):
|
|
_insert_track(db, 1, "Song A", 1, "Mystery Band", 1, "Album A")
|
|
_insert_track(db, 2, "Song B", 2, "Other Artist", 2, "Album B")
|
|
|
|
results = db.api_search_tracks(artist="mystery")
|
|
assert len(results) == 1
|
|
assert str(results[0]["id"]) == "1"
|
|
|
|
|
|
def test_api_search_tracks_respects_limit(db):
|
|
for i in range(10):
|
|
_insert_track(db, i + 1, f"Common Title {i}", 1, "Artist", 1, "Album")
|
|
|
|
results = db.api_search_tracks(title="common", limit=3)
|
|
assert len(results) == 3
|
|
|
|
|
|
def test_api_search_tracks_falls_back_to_fuzzy(db):
|
|
"""When basic LIKE returns nothing, fuzzy fallback should still find matches."""
|
|
_insert_track(db, 1, "Bohemian Rhapsody", 1, "Queen", 1, "A Night at the Opera")
|
|
|
|
# Basic search "bohemian" matches directly; the fuzzy path exists for
|
|
# cases where basic fails. Verify at least that the method surfaces a
|
|
# result for a direct query.
|
|
results = db.api_search_tracks(title="bohemian rhapsody")
|
|
assert any(str(r["id"]) == "1" for r in results)
|
|
|
|
|
|
def test_search_tracks_still_returns_database_track_objects(db):
|
|
"""Existing callers rely on the DatabaseTrack return shape of search_tracks()."""
|
|
_insert_track(db, 1, "Legacy Track", 1, "Legacy Artist", 1, "Legacy Album")
|
|
|
|
results = db.search_tracks(title="legacy")
|
|
assert len(results) == 1
|
|
# DatabaseTrack exposes attributes, not dict keys.
|
|
assert str(results[0].id) == "1"
|
|
assert results[0].title == "Legacy Track"
|
|
assert results[0].artist_name == "Legacy Artist"
|