/
/
/
1"""Unit tests for AI Radio provider config entries."""
2
3from __future__ import annotations
4
5import asyncio
6from types import SimpleNamespace
7from typing import Any, cast
8
9from music_assistant.providers.ai_radio.config import get_config_entries
10from music_assistant.providers.ai_radio.provider import AIRadioProvider
11
12
13def _make_mass(base_url: str, locale: str = "en_US") -> Any:
14 """Build a minimal mass stub exposing webserver.base_url and metadata.locale."""
15 return cast(
16 "Any",
17 SimpleNamespace(
18 webserver=SimpleNamespace(base_url=base_url),
19 metadata=SimpleNamespace(locale=locale),
20 ),
21 )
22
23
24def test_optional_entries_use_the_advanced_flag_not_the_advanced_category() -> None:
25 """
26 Advanced options must set ``advanced``, not ``category="advanced"``.
27
28 The frontend drops the deprecated "advanced" category from its panel list, so entries
29 filed under it never render on the settings page.
30 """
31 mass = _make_mass("http://localhost:8095")
32
33 entries = asyncio.run(get_config_entries(mass))
34
35 assert entries, "provider must expose config entries"
36 for entry in entries:
37 assert entry.category != "advanced", f"{entry.key} uses the deprecated advanced category"
38 advanced = {entry.key for entry in entries if entry.advanced}
39 assert advanced == {"timezone"}
40
41
42def test_weather_country_is_a_dropdown_defaulting_to_the_server_region() -> None:
43 """The weather country is picked from a list and seeded from the server locale."""
44 entries = asyncio.run(get_config_entries(_make_mass("http://localhost:8095", "nl_NL")))
45
46 entry = next(entry for entry in entries if entry.key == "weather_country")
47 assert entry.default_value == "NL"
48 assert entry.options
49 assert any(option.value == "NL" for option in entry.options)
50
51
52def test_provider_instance_exposes_the_same_config_entries() -> None:
53 """
54 The options page reads the instance method, not the module-level setup hook.
55
56 Without the override the base class returns an empty tuple, so the provider's own
57 options silently vanish from the settings UI.
58 """
59 mass = _make_mass("http://localhost:8095")
60 provider = cast("Any", AIRadioProvider.__new__(AIRadioProvider))
61 provider.mass = mass
62 # instance_id is a read-only property backed by the provider config
63 provider.config = SimpleNamespace(instance_id="ai_radio")
64
65 entries = asyncio.run(provider.get_config_entries())
66
67 assert {entry.key for entry in entries} == {
68 entry.key for entry in asyncio.run(get_config_entries(mass, "ai_radio"))
69 }
70 assert "timezone" in {entry.key for entry in entries}
71