777 lines
30 KiB
Python
777 lines
30 KiB
Python
import sqlite3
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from music_server.app import create_app
|
|
from tests.support import auth_headers
|
|
|
|
|
|
class MfCatalogRouteTests(unittest.TestCase):
|
|
def _prepare_playlist_toplist_catalog_db(self, db_path: Path) -> None:
|
|
conn = sqlite3.connect(db_path)
|
|
conn.executescript(
|
|
"""
|
|
create table catalog_playlists (
|
|
playlist_id integer primary key,
|
|
platform text not null,
|
|
remote_playlist_id text not null,
|
|
name text not null,
|
|
description text,
|
|
cover_url text,
|
|
play_count integer not null,
|
|
song_count integer not null,
|
|
playable_song_count integer not null
|
|
);
|
|
create table catalog_toplists (
|
|
toplist_id text primary key,
|
|
platform text not null,
|
|
name text not null,
|
|
description text,
|
|
cover_url text,
|
|
play_count integer not null,
|
|
song_count integer not null,
|
|
playable_song_count integer not null,
|
|
group_name text not null
|
|
);
|
|
create table catalog_tracks (
|
|
song_id integer primary key,
|
|
platform text not null,
|
|
remote_song_id text not null,
|
|
name text not null,
|
|
singers text,
|
|
album text,
|
|
cover_url text,
|
|
duration_ms integer,
|
|
metadata_json text
|
|
);
|
|
create table catalog_track_files (
|
|
song_id integer not null,
|
|
quality_label text not null,
|
|
ext text not null,
|
|
file_size_bytes integer,
|
|
backend_type text not null,
|
|
backend_name text not null,
|
|
locator text not null,
|
|
public_url text,
|
|
status text not null,
|
|
is_primary integer not null
|
|
);
|
|
create table catalog_playlist_tracks (
|
|
playlist_id integer not null,
|
|
song_id integer not null,
|
|
position integer not null
|
|
);
|
|
create table catalog_toplist_tracks (
|
|
toplist_id text not null,
|
|
song_id integer not null,
|
|
position integer not null
|
|
);
|
|
create table catalog_artists (
|
|
artist_id integer primary key,
|
|
artist_key text not null unique,
|
|
platform text not null,
|
|
remote_artist_id text,
|
|
name text not null,
|
|
normalized_name text not null,
|
|
avatar_url text,
|
|
description text,
|
|
playable_song_count integer not null
|
|
);
|
|
create table catalog_artist_tracks (
|
|
artist_id integer not null,
|
|
song_id integer not null,
|
|
position integer not null
|
|
);
|
|
"""
|
|
)
|
|
conn.execute(
|
|
"""
|
|
insert into catalog_playlists (
|
|
playlist_id, platform, remote_playlist_id, name, description, cover_url, play_count, song_count, playable_song_count
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
(1, "netease", "rid-1", "playlist-1", "desc", "https://img/1.jpg", 100, 2, 1),
|
|
)
|
|
conn.execute(
|
|
"""
|
|
insert into catalog_toplists (
|
|
toplist_id, platform, name, description, cover_url, play_count, song_count, playable_song_count, group_name
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
("tl-1", "netease", "toplist-1", "desc", "https://img/top.jpg", 88, 2, 1, "official"),
|
|
)
|
|
conn.executemany(
|
|
"""
|
|
insert into catalog_tracks (
|
|
song_id, platform, remote_song_id, name, singers, album, cover_url, duration_ms, metadata_json
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
[
|
|
(
|
|
1,
|
|
"netease",
|
|
"n1",
|
|
"Playable Song",
|
|
"Singer A",
|
|
"Album A",
|
|
"https://img/song1.jpg",
|
|
200000,
|
|
"{}",
|
|
),
|
|
(
|
|
2,
|
|
"netease",
|
|
"n2",
|
|
"Blocked Song",
|
|
"Singer B",
|
|
"Album B",
|
|
"https://img/song2.jpg",
|
|
180000,
|
|
"{}",
|
|
),
|
|
],
|
|
)
|
|
conn.executemany(
|
|
"""
|
|
insert into catalog_track_files (
|
|
song_id, quality_label, ext, file_size_bytes, backend_type, backend_name, locator, public_url, status, is_primary
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
[
|
|
(
|
|
1,
|
|
"super",
|
|
"flac",
|
|
100,
|
|
"object_storage",
|
|
"cdn",
|
|
"song-1.flac",
|
|
"https://cdn/1.flac",
|
|
"active",
|
|
1,
|
|
),
|
|
(
|
|
2,
|
|
"standard",
|
|
"mp3",
|
|
90,
|
|
"object_storage",
|
|
"cdn",
|
|
"song-2.mp3",
|
|
"https://cdn/2.mp3",
|
|
"inactive",
|
|
1,
|
|
),
|
|
],
|
|
)
|
|
conn.executemany(
|
|
"""
|
|
insert into catalog_playlist_tracks (playlist_id, song_id, position) values (?, ?, ?)
|
|
""",
|
|
[(1, 1, 1), (1, 2, 2)],
|
|
)
|
|
conn.executemany(
|
|
"""
|
|
insert into catalog_toplist_tracks (toplist_id, song_id, position) values (?, ?, ?)
|
|
""",
|
|
[("tl-1", 1, 1), ("tl-1", 2, 2)],
|
|
)
|
|
conn.execute(
|
|
"""
|
|
insert into catalog_artists (
|
|
artist_id, artist_key, platform, remote_artist_id, name, normalized_name, avatar_url, description, playable_song_count
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
(
|
|
1,
|
|
"netease:artist-a",
|
|
"netease",
|
|
"artist-a",
|
|
"Singer A",
|
|
"singer a",
|
|
"https://img/artist-a.jpg",
|
|
"artist-desc",
|
|
1,
|
|
),
|
|
)
|
|
conn.execute(
|
|
"""
|
|
insert into catalog_artist_tracks (artist_id, song_id, position) values (?, ?, ?)
|
|
""",
|
|
(1, 1, 1),
|
|
)
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def test_recommend_tags_returns_musicfree_shape(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
with patch.dict("os.environ", {"PLAYER_DB_PATH": str(player_db_path)}, clear=False):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/recommend/tags",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertIn("pinned", payload)
|
|
self.assertIn("data", payload)
|
|
self.assertEqual(["all", "netease", "qq", "kuwo"], [item["id"] for item in payload["pinned"]])
|
|
self.assertEqual(
|
|
["playlist_square", "toplist"],
|
|
[item["id"] for item in payload["data"][0]["data"]],
|
|
)
|
|
|
|
def test_recommend_routes_requires_token_when_missing(self):
|
|
client = TestClient(create_app())
|
|
response = client.get("/mf/v1/recommend/tags")
|
|
|
|
self.assertEqual(401, response.status_code)
|
|
|
|
def test_recommend_routes_requires_token_when_wrong(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
with patch.dict("os.environ", {"PLAYER_DB_PATH": str(player_db_path)}, clear=False):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/recommend/tags",
|
|
headers=auth_headers(player_db_path, token="wrong-token"),
|
|
)
|
|
|
|
self.assertEqual(401, response.status_code)
|
|
|
|
def test_recommend_routes_allow_anonymous_when_auth_disabled(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
"MUSIC_SERVER_DISABLE_AUTH": "1",
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get("/mf/v1/recommend/tags")
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
|
|
def test_recommend_sheets_returns_musicfree_shape(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
conn = sqlite3.connect(db_path)
|
|
conn.executescript(
|
|
"""
|
|
create table catalog_playlists (
|
|
playlist_id integer primary key,
|
|
platform text not null,
|
|
remote_playlist_id text not null,
|
|
name text not null,
|
|
description text,
|
|
cover_url text,
|
|
play_count integer not null,
|
|
song_count integer not null,
|
|
playable_song_count integer not null
|
|
);
|
|
"""
|
|
)
|
|
rows = [
|
|
(
|
|
1,
|
|
"netease",
|
|
"rid-1",
|
|
"测试歌单",
|
|
"desc",
|
|
"https://img/1.jpg",
|
|
999,
|
|
9,
|
|
5,
|
|
)
|
|
]
|
|
for idx in range(2, 21):
|
|
rows.append(
|
|
(
|
|
idx,
|
|
"netease",
|
|
f"rid-{idx}",
|
|
f"playlist-{idx}",
|
|
"desc",
|
|
f"https://img/{idx}.jpg",
|
|
200 - idx,
|
|
5,
|
|
5,
|
|
)
|
|
)
|
|
conn.executemany(
|
|
"""
|
|
insert into catalog_playlists (
|
|
playlist_id, platform, remote_playlist_id, name, description, cover_url, play_count, song_count, playable_song_count
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
rows,
|
|
)
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/recommend/sheets?page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
response_large_page = client.get(
|
|
"/mf/v1/recommend/sheets?page=1&page_size=21",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertFalse(payload["isEnd"])
|
|
self.assertEqual("catalogsync:playlist:1", payload["data"][0]["id"])
|
|
self.assertEqual("测试歌单", payload["data"][0]["title"])
|
|
self.assertEqual(9, payload["data"][0]["worksNum"])
|
|
self.assertEqual(5, payload["data"][0]["playableSongCount"])
|
|
self.assertEqual(999, payload["data"][0]["play_count"])
|
|
self.assertNotIn("playCount", payload["data"][0])
|
|
self.assertEqual(200, response_large_page.status_code)
|
|
self.assertTrue(response_large_page.json()["isEnd"])
|
|
|
|
def test_recommend_sheets_filters_by_platform_tag(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
conn = sqlite3.connect(db_path)
|
|
conn.executescript(
|
|
"""
|
|
create table catalog_playlists (
|
|
playlist_id integer primary key,
|
|
platform text not null,
|
|
remote_playlist_id text not null,
|
|
name text not null,
|
|
description text,
|
|
cover_url text,
|
|
play_count integer not null,
|
|
song_count integer not null,
|
|
playable_song_count integer not null
|
|
);
|
|
"""
|
|
)
|
|
conn.executemany(
|
|
"""
|
|
insert into catalog_playlists (
|
|
playlist_id, platform, remote_playlist_id, name, description, cover_url, play_count, song_count, playable_song_count
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
[
|
|
(1, "netease", "n-1", "Netease List", "desc", "https://img/1.jpg", 300, 10, 10),
|
|
(2, "qq", "q-1", "QQ List", "desc", "https://img/2.jpg", 200, 10, 10),
|
|
(3, "kuwo", "k-1", "Kuwo List", "desc", "https://img/3.jpg", 100, 10, 10),
|
|
],
|
|
)
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/recommend/sheets?tag=qq&page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertTrue(payload["isEnd"])
|
|
self.assertEqual(["catalogsync:playlist:2"], [item["id"] for item in payload["data"]])
|
|
self.assertEqual(["QQ List"], [item["title"] for item in payload["data"]])
|
|
|
|
def test_recommend_sheets_returns_toplists_when_tag_toplist(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
conn = sqlite3.connect(db_path)
|
|
conn.execute(
|
|
"""
|
|
insert into catalog_toplists (
|
|
toplist_id, platform, name, description, cover_url, play_count, song_count, playable_song_count, group_name
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
("tl-2", "netease", "toplist-2", "desc", "https://img/top2.jpg", 77, 1, 1, "official"),
|
|
)
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response_page_1 = client.get(
|
|
"/mf/v1/recommend/sheets?tag=toplist&page=1&page_size=1",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
response_page_2 = client.get(
|
|
"/mf/v1/recommend/sheets?tag=toplist&page=2&page_size=1",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response_page_1.status_code)
|
|
self.assertEqual(200, response_page_2.status_code)
|
|
|
|
payload_page_1 = response_page_1.json()
|
|
payload_page_2 = response_page_2.json()
|
|
|
|
self.assertEqual(["catalogsync:toplist:tl-1"], [item["id"] for item in payload_page_1["data"]])
|
|
self.assertTrue(payload_page_1["data"][0]["id"].startswith("catalogsync:toplist:"))
|
|
self.assertFalse(payload_page_1["isEnd"])
|
|
|
|
self.assertEqual(["catalogsync:toplist:tl-2"], [item["id"] for item in payload_page_2["data"]])
|
|
self.assertTrue(payload_page_2["data"][0]["id"].startswith("catalogsync:toplist:"))
|
|
self.assertTrue(payload_page_2["isEnd"])
|
|
|
|
def test_search_songs_returns_musicfree_shape(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{"CATALOG_DB_PATH": str(db_path), "PLAYER_DB_PATH": str(player_db_path)},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/search/songs?q=Playable&page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertTrue(payload["isEnd"])
|
|
self.assertEqual(["catalogsync:song:1"], [item["id"] for item in payload["data"]])
|
|
|
|
def test_search_songs_includes_raw_lrc_when_local_lyrics_exist(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
library_root = Path(tmpdir) / "library"
|
|
library_root.mkdir()
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
conn = sqlite3.connect(db_path)
|
|
conn.execute(
|
|
"""
|
|
insert into catalog_track_files (
|
|
song_id, quality_label, ext, file_size_bytes, backend_type, backend_name, locator, public_url, status, is_primary
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
(
|
|
1,
|
|
"standard",
|
|
"mp3",
|
|
80,
|
|
"local_fs",
|
|
"library",
|
|
"Singer A/Playable Song.mp3",
|
|
None,
|
|
"active",
|
|
0,
|
|
),
|
|
)
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
song_dir = library_root / "Singer A"
|
|
song_dir.mkdir()
|
|
(song_dir / "Playable Song.mp3").write_bytes(b"audio")
|
|
(song_dir / "Playable Song.lrc").write_text("[00:00.00]hello lyric\n", encoding="utf-8")
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
"LOCAL_LIBRARY_ROOT": str(library_root),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/search/songs?q=Playable&page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertEqual("[00:00.00]hello lyric\n", payload["data"][0]["rawLrc"])
|
|
|
|
def test_song_lyric_route_returns_raw_lrc_when_local_lyrics_exist(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
library_root = Path(tmpdir) / "library"
|
|
library_root.mkdir()
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
conn = sqlite3.connect(db_path)
|
|
conn.execute(
|
|
"""
|
|
insert into catalog_track_files (
|
|
song_id, quality_label, ext, file_size_bytes, backend_type, backend_name, locator, public_url, status, is_primary
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
(
|
|
1,
|
|
"standard",
|
|
"mp3",
|
|
80,
|
|
"local_fs",
|
|
"library",
|
|
"Singer A/Playable Song.mp3",
|
|
None,
|
|
"active",
|
|
0,
|
|
),
|
|
)
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
song_dir = library_root / "Singer A"
|
|
song_dir.mkdir()
|
|
(song_dir / "Playable Song.mp3").write_bytes(b"audio")
|
|
(song_dir / "Playable Song.lrc").write_text("[00:00.00]hello lyric\n", encoding="utf-8")
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
"LOCAL_LIBRARY_ROOT": str(library_root),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/songs/1/lyric",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertEqual("[00:00.00]hello lyric\n", payload["rawLrc"])
|
|
self.assertEqual("[00:00.00]hello lyric\n", payload["lyric"])
|
|
|
|
def test_playlist_tracks_omit_raw_lrc_when_local_library_root_missing(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
conn = sqlite3.connect(db_path)
|
|
conn.execute(
|
|
"""
|
|
insert into catalog_track_files (
|
|
song_id, quality_label, ext, file_size_bytes, backend_type, backend_name, locator, public_url, status, is_primary
|
|
) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""",
|
|
(
|
|
1,
|
|
"standard",
|
|
"mp3",
|
|
80,
|
|
"local_fs",
|
|
"library",
|
|
"Singer A/Playable Song.mp3",
|
|
None,
|
|
"active",
|
|
0,
|
|
),
|
|
)
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/playlists/1/tracks?page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertNotIn("rawLrc", payload["musicList"][0])
|
|
|
|
def test_search_artists_and_artist_detail_routes_return_musicfree_shape(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{"CATALOG_DB_PATH": str(db_path), "PLAYER_DB_PATH": str(player_db_path)},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
search_response = client.get(
|
|
"/mf/v1/search/artists?q=Singer&page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
detail_response = client.get(
|
|
"/mf/v1/artists/1",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
tracks_response = client.get(
|
|
"/mf/v1/artists/1/tracks?page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, search_response.status_code)
|
|
self.assertEqual(200, detail_response.status_code)
|
|
self.assertEqual(200, tracks_response.status_code)
|
|
self.assertEqual("catalogsync:artist:1", search_response.json()["data"][0]["id"])
|
|
self.assertEqual(["music"], search_response.json()["data"][0]["supportedArtistTabs"])
|
|
self.assertEqual("Singer A", detail_response.json()["name"])
|
|
self.assertEqual("catalogsync:song:1", tracks_response.json()["musicList"][0]["id"])
|
|
|
|
def test_search_sheets_returns_playlists_and_toplists(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{"CATALOG_DB_PATH": str(db_path), "PLAYER_DB_PATH": str(player_db_path)},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/search/sheets?q=1&page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertEqual(
|
|
["catalogsync:playlist:1", "catalogsync:toplist:tl-1"],
|
|
[item["id"] for item in payload["data"]],
|
|
)
|
|
|
|
def test_playlist_tracks_only_returns_playable_rows(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/playlists/1/tracks?page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertEqual(1, len(payload["musicList"]))
|
|
self.assertEqual("catalogsync:song:1", payload["musicList"][0]["id"])
|
|
self.assertEqual("Playable Song", payload["musicList"][0]["title"])
|
|
|
|
def test_toplists_returns_playable_song_count(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/toplists",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertEqual(1, len(payload))
|
|
self.assertEqual(1, len(payload[0]["data"]))
|
|
toplist = payload[0]["data"][0]
|
|
self.assertEqual("catalogsync:toplist:tl-1", toplist["id"])
|
|
self.assertEqual(2, toplist["worksNum"])
|
|
self.assertEqual(1, toplist["playableSongCount"])
|
|
|
|
def test_toplist_tracks_only_returns_playable_rows(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
db_path = Path(tmpdir) / "catalog_read.db"
|
|
player_db_path = Path(tmpdir) / "player.db"
|
|
self._prepare_playlist_toplist_catalog_db(db_path)
|
|
|
|
with patch.dict(
|
|
"os.environ",
|
|
{
|
|
"CATALOG_DB_PATH": str(db_path),
|
|
"PLAYER_DB_PATH": str(player_db_path),
|
|
},
|
|
clear=False,
|
|
):
|
|
client = TestClient(create_app())
|
|
response = client.get(
|
|
"/mf/v1/toplists/tl-1/tracks?page=1&page_size=20",
|
|
headers=auth_headers(player_db_path),
|
|
)
|
|
|
|
self.assertEqual(200, response.status_code)
|
|
payload = response.json()
|
|
self.assertEqual(1, len(payload["musicList"]))
|
|
self.assertEqual("catalogsync:song:1", payload["musicList"][0]["id"])
|
|
self.assertEqual("Playable Song", payload["musicList"][0]["title"])
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|