/
/
/
1"""Tests that Collection folder renders audiobooks/podcasts sub-folders."""
2
3from __future__ import annotations
4
5import json
6from unittest.mock import Mock
7
8import pytest
9from music_assistant_models.enums import ProviderFeature
10from music_assistant_models.media_items import BrowseFolder
11
12from music_assistant.providers.yandex_music.provider import YandexMusicProvider
13
14from .conftest import provider_dir
15
16_STRINGS = json.loads((provider_dir() / "strings.json").read_text(encoding="utf-8"))
17
18
19def _make_provider_mock(features: set[ProviderFeature]) -> Mock:
20 provider = Mock(spec=YandexMusicProvider)
21 provider.instance_id = "yandex_music_instance"
22 provider.domain = "yandex_music"
23 provider.supported_features = features
24 provider.mass = Mock()
25 # Resolve authored names from the real strings.json, like the MA
26 # translations controller would for the English source.
27 provider.mass.translations.get_translation.side_effect = lambda key: _lookup_strings_key(key)
28 # real method so the strings.json lookup path runs
29 provider._media_label = YandexMusicProvider._media_label.__get__(provider, YandexMusicProvider)
30 provider.logger = Mock()
31 return provider
32
33
34def _lookup_strings_key(key: str) -> str | None:
35 """Resolve provider.yandex_music.media.<group>.<slug>.name against strings.json."""
36 parts = key.split(".")
37 node: object = _STRINGS
38 for part in parts[2:]: # skip "music_assistant.providers.yandex_music.yandex_music"
39 if not isinstance(node, dict) or part not in node:
40 return None
41 node = node[part]
42 return node if isinstance(node, str) else None
43
44
45@pytest.mark.asyncio
46async def test_collection_shows_audiobooks_folder_when_feature_enabled() -> None:
47 """LIBRARY_AUDIOBOOKS enabled â BrowseFolder for audiobooks is returned."""
48 features = {
49 ProviderFeature.LIBRARY_TRACKS,
50 ProviderFeature.LIBRARY_ALBUMS,
51 ProviderFeature.LIBRARY_AUDIOBOOKS,
52 }
53 provider = _make_provider_mock(features)
54
55 folders = await YandexMusicProvider._browse_collection(
56 provider, "yandex_music_instance://collection"
57 )
58
59 item_ids = [f.item_id for f in folders if isinstance(f, BrowseFolder)]
60 assert "audiobooks" in item_ids
61 audiobook_folder = next(
62 f for f in folders if isinstance(f, BrowseFolder) and f.item_id == "audiobooks"
63 )
64 assert audiobook_folder.is_playable is False
65 assert audiobook_folder.path.endswith("audiobooks")
66 assert audiobook_folder.name == _STRINGS["media"]["folder"]["my_audiobooks"]["name"]
67
68
69@pytest.mark.asyncio
70async def test_collection_shows_podcasts_folder_when_feature_enabled() -> None:
71 """LIBRARY_PODCASTS enabled â BrowseFolder for podcasts is returned."""
72 features = {
73 ProviderFeature.LIBRARY_TRACKS,
74 ProviderFeature.LIBRARY_PODCASTS,
75 }
76 provider = _make_provider_mock(features)
77
78 folders = await YandexMusicProvider._browse_collection(
79 provider, "yandex_music_instance://collection"
80 )
81
82 item_ids = [f.item_id for f in folders if isinstance(f, BrowseFolder)]
83 assert "podcasts" in item_ids
84
85
86@pytest.mark.asyncio
87async def test_collection_hides_audiobooks_folder_when_feature_disabled() -> None:
88 """Disabling LIBRARY_AUDIOBOOKS removes the folder from Collection."""
89 features = {
90 ProviderFeature.LIBRARY_TRACKS,
91 ProviderFeature.LIBRARY_ALBUMS,
92 }
93 provider = _make_provider_mock(features)
94
95 folders = await YandexMusicProvider._browse_collection(
96 provider, "yandex_music_instance://collection"
97 )
98
99 item_ids = [f.item_id for f in folders if isinstance(f, BrowseFolder)]
100 assert "audiobooks" not in item_ids
101 assert "podcasts" not in item_ids
102
103
104@pytest.mark.asyncio
105async def test_collection_folders_carry_authored_translation_keys() -> None:
106 """
107 Collection folders localize via translation keys authored in strings.json.
108
109 Localization happens at API serialization (per connection locale), so
110 the provider must emit an English fallback name plus a key that exists
111 under ``media.folder`` in strings.json.
112 """
113 features = {
114 ProviderFeature.LIBRARY_AUDIOBOOKS,
115 ProviderFeature.LIBRARY_PODCASTS,
116 }
117 provider = _make_provider_mock(features)
118
119 folders = await YandexMusicProvider._browse_collection(
120 provider, "yandex_music_instance://collection"
121 )
122
123 authored = _STRINGS["media"]["folder"]
124 for folder in folders:
125 assert isinstance(folder, BrowseFolder)
126 assert folder.translation_key is not None
127 assert folder.translation_key in authored
128