Files
beets/test/plugins/test_deezer.py
2026-09-06 14:04:15 +08:00

189 lines
5.7 KiB
Python

from typing import Any
import pytest
from beets.library import Item
from beetsplug.deezer import DeezerPlugin
JSONDict = dict[str, Any]
@pytest.fixture
def plugin():
return DeezerPlugin()
class TestSearchQuery:
def test_track_query_is_free_text(self, plugin):
query, filters = plugin.get_search_query_with_filters(
"track", [Item()], "Artist", "Title", False
)
assert query == "Title Artist"
assert filters == {}
def test_track_query_tolerates_missing_artist(self, plugin):
query, _ = plugin.get_search_query_with_filters(
"track", [Item()], "", "Title", False
)
assert query == "Title"
def test_album_query_filters_on_album_and_artist(self, plugin):
query, filters = plugin.get_search_query_with_filters(
"album", [Item()], "Artist", "Album", False
)
assert query == 'album:"Album" artist:"Artist"'
assert filters == {}
def test_album_query_omits_artist_for_various_artists(self, plugin):
query, _ = plugin.get_search_query_with_filters(
"album", [Item()], "Various Artists", "Album", True
)
assert query == 'album:"Album"'
def make_track(artist_id: int, position: int) -> JSONDict:
"""Build a minimal Deezer track payload credited to ``artist_id``."""
return {
"title": f"Track {position}",
"id": 1000 + position,
"link": f"https://www.deezer.com/track/{1000 + position}",
"duration": 200,
"track_position": position,
"disk_number": 1,
"artist": {"id": artist_id, "name": f"Artist {artist_id}"},
}
class TestGetTrack:
def track_data(self, **fields):
return {
"id": 1,
"title": "Title",
"duration": 100,
"link": "https://www.deezer.com/track/1",
**fields,
}
def test_uses_contributors_when_artist_is_missing(self, plugin):
track = plugin._get_track(
self.track_data(contributors=[{"id": 2, "name": "Artist"}])
)
assert track.artist == "Artist"
assert track.artist_id == "2"
def test_falls_back_to_artist_without_contributors(self, plugin):
track = plugin._get_track(
self.track_data(artist={"id": 2, "name": "Artist"})
)
assert track.artist == "Artist"
assert track.artist_id == "2"
def test_tolerates_missing_artist_and_contributors(self, plugin):
track = plugin._get_track(self.track_data())
assert track.artist is None
assert track.artist_id is None
class TestVariousArtistsDetection:
def make_album(
self, album_artist_id: int, contributor_ids: list[int]
) -> JSONDict:
"""Build a minimal Deezer album payload."""
return {
"title": "Some Album",
"link": "https://www.deezer.com/album/1",
"record_type": "album",
"label": "Some Label",
"release_date": "2017-01-01",
"artist": {
"id": album_artist_id,
"name": f"Artist {album_artist_id}",
},
"contributors": [
{"id": aid, "name": f"Artist {aid}"} for aid in contributor_ids
],
"cover_xl": None,
}
def mock_album(
self,
requests_mock,
album_artist_id,
track_artist_ids,
contributor_ids=None,
):
"""Mock the album and album-tracks endpoints for album id 1.
``contributor_ids`` overrides the album-level contributors, which
otherwise cover every artist involved.
"""
if contributor_ids is None:
contributor_ids = list(
dict.fromkeys([album_artist_id, *track_artist_ids])
)
requests_mock.get(
f"{DeezerPlugin.album_url}1",
json=self.make_album(album_artist_id, contributor_ids),
)
requests_mock.get(
f"{DeezerPlugin.album_url}1/tracks",
json={
"data": [
make_track(aid, i)
for i, aid in enumerate(track_artist_ids, start=1)
]
},
)
def test_compilation_with_non_va_album_artist(self, plugin, requests_mock):
# Album credited to a single "main" artist that performs on only one
# of many tracks: this is a compilation and should be flagged as VA.
self.mock_album(
requests_mock,
album_artist_id=100,
track_artist_ids=[100, 200, 300, 400, 500, 600],
)
album_info = plugin.album_for_id("1")
assert album_info is not None
assert album_info.va is True
assert album_info.artist == "Various Artists"
def test_plurality_artist_album_not_va(self, plugin, requests_mock):
# Album whose main artist performs on 2 of 5 tracks (40%) is above
# the importer's single-artist threshold and stays single-artist.
self.mock_album(
requests_mock,
album_artist_id=100,
track_artist_ids=[100, 100, 200, 300, 400],
contributor_ids=[100],
)
album_info = plugin.album_for_id("1")
assert album_info is not None
assert album_info.va is False
assert album_info.artist == "Artist 100"
def test_single_artist_album_not_va(self, plugin, requests_mock):
# Album whose main artist performs on every track is not a compilation.
self.mock_album(
requests_mock,
album_artist_id=100,
track_artist_ids=[100, 100, 100, 100],
)
album_info = plugin.album_for_id("1")
assert album_info is not None
assert album_info.va is False
assert album_info.artist == "Artist 100"