/
/
/
1"""Tests for MetaDataController._select_description bio-selection policy."""
2
3from unittest.mock import MagicMock, patch
4
5from music_assistant.controllers.metadata import MetaDataController
6
7# candidate tuples are (language, text), in provider-priority order
8# (music providers first, then TADB, then Wikipedia)
9
10
11def _controller(language: str = "nl") -> MetaDataController:
12 """Create a bare MetaDataController whose preferred language is ``language``."""
13 with patch.object(MetaDataController, "__init__", lambda *_a, **_kw: None):
14 ctrl = MetaDataController.__new__(MetaDataController)
15 ctrl.mass = MagicMock()
16 ctrl.mass.config.get_raw_core_config_value = MagicMock(return_value=f"{language}_XX")
17 return ctrl
18
19
20class TestSelectDescription:
21 """First preferred-language bio in priority order wins, English as fallback."""
22
23 def test_preferred_language_highest_priority_wins(self) -> None:
24 """Both providers have the preferred language: the highest-priority wins."""
25 ctrl = _controller("nl")
26 candidates = [("nl", "TADB nl"), ("nl", "Wikipedia nl")]
27 assert ctrl._select_description(candidates, None, None) == ("TADB nl", "nl")
28
29 def test_preferred_language_beats_higher_priority_english(self) -> None:
30 """A lower-priority provider with the preferred language beats a higher-priority English one."""
31 ctrl = _controller("nl")
32 candidates = [("en", "TADB en"), ("nl", "Wikipedia nl")]
33 assert ctrl._select_description(candidates, None, None) == ("Wikipedia nl", "nl")
34
35 def test_higher_priority_preferred_beats_lower_english(self) -> None:
36 """Highest-priority provider already has the preferred language."""
37 ctrl = _controller("nl")
38 candidates = [("nl", "TADB nl"), ("en", "Wikipedia en")]
39 assert ctrl._select_description(candidates, None, None) == ("TADB nl", "nl")
40
41 def test_english_fallback_when_no_preferred(self) -> None:
42 """No provider has the preferred language: fall back to highest-priority English."""
43 ctrl = _controller("nl")
44 candidates = [("en", "TADB en"), ("en", "Wikipedia en")]
45 assert ctrl._select_description(candidates, None, None) == ("TADB en", "en")
46
47 def test_stored_preferred_not_downgraded_to_english(self) -> None:
48 """A stored preferred-language bio is kept rather than downgraded to English."""
49 ctrl = _controller("nl")
50 candidates = [("en", "TADB en")]
51 assert ctrl._select_description(candidates, "stored nl", "nl") == ("stored nl", "nl")
52
53 def test_fresh_preferred_replaces_stored_preferred(self) -> None:
54 """A fresh preferred-language bio replaces the stored one (content updates on refresh)."""
55 ctrl = _controller("nl")
56 candidates = [("nl", "fresh nl")]
57 assert ctrl._select_description(candidates, "old nl", "nl") == ("fresh nl", "nl")
58
59 def test_music_preferred_beats_metadata_preferred(self) -> None:
60 """A music-provider preferred-language bio outranks a metadata one (music is highest priority)."""
61 ctrl = _controller("nl")
62 candidates = [("nl", "qobuz nl"), ("nl", "TADB nl")]
63 assert ctrl._select_description(candidates, None, None) == ("qobuz nl", "nl")
64
65 def test_music_preferred_beats_english_metadata(self) -> None:
66 """A verified preferred-language music bio beats a higher-tier English metadata bio."""
67 ctrl = _controller("nl")
68 candidates = [("nl", "qobuz nl"), ("en", "TADB en")]
69 assert ctrl._select_description(candidates, None, None) == ("qobuz nl", "nl")
70
71 def test_music_english_beats_metadata_english(self) -> None:
72 """At equal (English) language, the music provider wins on priority."""
73 ctrl = _controller("nl")
74 candidates = [("en", "qobuz en"), ("en", "TADB en")]
75 assert ctrl._select_description(candidates, None, None) == ("qobuz en", "en")
76
77 def test_untagged_music_loses_to_english_metadata(self) -> None:
78 """An untagged (None-language) music bio cannot win the English fallback over tagged metadata."""
79 ctrl = _controller("nl")
80 candidates = [(None, "qobuz bio"), ("en", "TADB en")]
81 assert ctrl._select_description(candidates, None, None) == ("TADB en", "en")
82
83 def test_untagged_music_used_as_last_resort(self) -> None:
84 """With nothing in the preferred language or English, the untagged music bio is used."""
85 ctrl = _controller("nl")
86 candidates = [(None, "qobuz bio")]
87 assert ctrl._select_description(candidates, None, None) == ("qobuz bio", None)
88
89 def test_stored_preferred_beats_music(self) -> None:
90 """A stored preferred-language bio is not downgraded to a music-provider fallback."""
91 ctrl = _controller("nl")
92 candidates = [(None, "qobuz bio")]
93 assert ctrl._select_description(candidates, "stored nl", "nl") == ("stored nl", "nl")
94
95 def test_last_resort_follows_priority_order(self) -> None:
96 """No preferred/English match: the highest-priority bio wins regardless of language."""
97 ctrl = _controller("nl")
98 candidates = [(None, "qobuz bio"), ("de", "TADB de")]
99 assert ctrl._select_description(candidates, None, None) == ("qobuz bio", None)
100
101 def test_empty_pass_keeps_previous(self) -> None:
102 """No candidates this refresh: keep whatever was stored."""
103 ctrl = _controller("nl")
104 assert ctrl._select_description([], "old en", "en") == ("old en", "en")
105
106 def test_nothing_at_all_returns_none(self) -> None:
107 """No candidates and no stored bio: nothing to show."""
108 ctrl = _controller("nl")
109 assert ctrl._select_description([], None, None) == (None, None)
110
111 def test_english_user_gets_english_as_preferred(self) -> None:
112 """For an English user, English is the preferred language and wins by priority."""
113 ctrl = _controller("en")
114 candidates = [("en", "TADB en"), ("en", "Wikipedia en")]
115 assert ctrl._select_description(candidates, None, None) == ("TADB en", "en")
116
117 def test_non_english_metadata_used_as_last_resort(self) -> None:
118 """A non-preferred, non-English metadata bio is still used when nothing better exists."""
119 ctrl = _controller("nl")
120 candidates = [("de", "TADB de")]
121 assert ctrl._select_description(candidates, None, None) == ("TADB de", "de")
122