diff --git a/homeassistant/components/music_assistant/actions.py b/homeassistant/components/music_assistant/actions.py index bf9a1260362..031229d1544 100644 --- a/homeassistant/components/music_assistant/actions.py +++ b/homeassistant/components/music_assistant/actions.py @@ -23,6 +23,7 @@ from .const import ( ATTR_ALBUM_TYPE, ATTR_ALBUMS, ATTR_ARTISTS, + ATTR_AUDIOBOOKS, ATTR_CONFIG_ENTRY_ID, ATTR_FAVORITE, ATTR_ITEMS, @@ -32,6 +33,7 @@ from .const import ( ATTR_OFFSET, ATTR_ORDER_BY, ATTR_PLAYLISTS, + ATTR_PODCASTS, ATTR_RADIO, ATTR_SEARCH, ATTR_SEARCH_ALBUM, @@ -48,7 +50,15 @@ from .schemas import ( if TYPE_CHECKING: from music_assistant_client import MusicAssistantClient - from music_assistant_models.media_items import Album, Artist, Playlist, Radio, Track + from music_assistant_models.media_items import ( + Album, + Artist, + Audiobook, + Playlist, + Podcast, + Radio, + Track, + ) from . import MusicAssistantConfigEntry @@ -155,6 +165,14 @@ async def handle_search(call: ServiceCall) -> ServiceResponse: media_item_dict_from_mass_item(mass, item) for item in search_results.radio ], + ATTR_AUDIOBOOKS: [ + media_item_dict_from_mass_item(mass, item) + for item in search_results.audiobooks + ], + ATTR_PODCASTS: [ + media_item_dict_from_mass_item(mass, item) + for item in search_results.podcasts + ], } ) return response @@ -175,7 +193,13 @@ async def handle_get_library(call: ServiceCall) -> ServiceResponse: "order_by": order_by, } library_result: ( - list[Album] | list[Artist] | list[Track] | list[Radio] | list[Playlist] + list[Album] + | list[Artist] + | list[Track] + | list[Radio] + | list[Playlist] + | list[Audiobook] + | list[Podcast] ) if media_type == MediaType.ALBUM: library_result = await mass.music.get_library_albums( @@ -199,6 +223,14 @@ async def handle_get_library(call: ServiceCall) -> ServiceResponse: library_result = await mass.music.get_library_playlists( **base_params, ) + elif media_type == MediaType.AUDIOBOOK: + library_result = await mass.music.get_library_audiobooks( + **base_params, + ) + elif media_type == MediaType.PODCAST: + library_result = await mass.music.get_library_podcasts( + **base_params, + ) else: raise ServiceValidationError(f"Unsupported media type {media_type}") diff --git a/homeassistant/components/music_assistant/const.py b/homeassistant/components/music_assistant/const.py index 1980c495278..d2ee1f75028 100644 --- a/homeassistant/components/music_assistant/const.py +++ b/homeassistant/components/music_assistant/const.py @@ -34,6 +34,8 @@ ATTR_ARTISTS = "artists" ATTR_ALBUMS = "albums" ATTR_TRACKS = "tracks" ATTR_PLAYLISTS = "playlists" +ATTR_AUDIOBOOKS = "audiobooks" +ATTR_PODCASTS = "podcasts" ATTR_RADIO = "radio" ATTR_ITEMS = "items" ATTR_RADIO_MODE = "radio_mode" diff --git a/homeassistant/components/music_assistant/schemas.py b/homeassistant/components/music_assistant/schemas.py index 0954d1573e7..7501d3d2038 100644 --- a/homeassistant/components/music_assistant/schemas.py +++ b/homeassistant/components/music_assistant/schemas.py @@ -15,6 +15,7 @@ from .const import ( ATTR_ALBUM, ATTR_ALBUMS, ATTR_ARTISTS, + ATTR_AUDIOBOOKS, ATTR_BIT_DEPTH, ATTR_CONTENT_TYPE, ATTR_CURRENT_INDEX, @@ -31,6 +32,7 @@ from .const import ( ATTR_OFFSET, ATTR_ORDER_BY, ATTR_PLAYLISTS, + ATTR_PODCASTS, ATTR_PROVIDER, ATTR_QUEUE_ID, ATTR_QUEUE_ITEM_ID, @@ -101,6 +103,12 @@ SEARCH_RESULT_SCHEMA = vol.Schema( vol.Required(ATTR_RADIO): vol.All( cv.ensure_list, [vol.Schema(MEDIA_ITEM_SCHEMA)] ), + vol.Required(ATTR_AUDIOBOOKS): vol.All( + cv.ensure_list, [vol.Schema(MEDIA_ITEM_SCHEMA)] + ), + vol.Required(ATTR_PODCASTS): vol.All( + cv.ensure_list, [vol.Schema(MEDIA_ITEM_SCHEMA)] + ), }, ) diff --git a/homeassistant/components/music_assistant/services.yaml b/homeassistant/components/music_assistant/services.yaml index 73e8e2d7521..a3715ea2580 100644 --- a/homeassistant/components/music_assistant/services.yaml +++ b/homeassistant/components/music_assistant/services.yaml @@ -21,7 +21,10 @@ play_media: options: - artist - album + - audiobook + - folder - playlist + - podcast - track - radio artist: @@ -118,7 +121,9 @@ search: options: - artist - album + - audiobook - playlist + - podcast - track - radio artist: @@ -160,7 +165,9 @@ get_library: options: - artist - album + - audiobook - playlist + - podcast - track - radio favorite: diff --git a/homeassistant/components/music_assistant/strings.json b/homeassistant/components/music_assistant/strings.json index 32b72088518..7338af7cb65 100644 --- a/homeassistant/components/music_assistant/strings.json +++ b/homeassistant/components/music_assistant/strings.json @@ -195,8 +195,11 @@ "options": { "artist": "Artist", "album": "Album", + "audiobook": "Audiobook", + "folder": "Folder", "track": "Track", "playlist": "Playlist", + "podcast": "Podcast", "radio": "Radio" } }, diff --git a/tests/components/music_assistant/common.py b/tests/components/music_assistant/common.py index 863d945ccd1..6d7ef927c6e 100644 --- a/tests/components/music_assistant/common.py +++ b/tests/components/music_assistant/common.py @@ -8,7 +8,15 @@ from unittest.mock import AsyncMock, MagicMock from music_assistant_models.api import MassEvent from music_assistant_models.enums import EventType -from music_assistant_models.media_items import Album, Artist, Playlist, Radio, Track +from music_assistant_models.media_items import ( + Album, + Artist, + Audiobook, + Playlist, + Podcast, + Radio, + Track, +) from music_assistant_models.player import Player from music_assistant_models.player_queue import PlayerQueue from syrupy import SnapshotAssertion @@ -62,6 +70,10 @@ async def setup_integration_from_fixtures( music.get_playlist_tracks = AsyncMock(return_value=library_playlist_tracks) library_radios = create_library_radios_from_fixture() music.get_library_radios = AsyncMock(return_value=library_radios) + library_audiobooks = create_library_audiobooks_from_fixture() + music.get_library_audiobooks = AsyncMock(return_value=library_audiobooks) + library_podcasts = create_library_podcasts_from_fixture() + music.get_library_podcasts = AsyncMock(return_value=library_podcasts) music.get_item_by_uri = AsyncMock() config_entry.add_to_hass(hass) @@ -132,6 +144,18 @@ def create_library_radios_from_fixture() -> list[Radio]: return [Radio.from_dict(radio_data) for radio_data in fixture_data] +def create_library_audiobooks_from_fixture() -> list[Audiobook]: + """Create MA Audiobooks from fixture.""" + fixture_data = load_and_parse_fixture("library_audiobooks") + return [Audiobook.from_dict(radio_data) for radio_data in fixture_data] + + +def create_library_podcasts_from_fixture() -> list[Podcast]: + """Create MA Podcasts from fixture.""" + fixture_data = load_and_parse_fixture("library_podcasts") + return [Podcast.from_dict(radio_data) for radio_data in fixture_data] + + async def trigger_subscription_callback( hass: HomeAssistant, client: MagicMock, diff --git a/tests/components/music_assistant/fixtures/library_audiobooks.json b/tests/components/music_assistant/fixtures/library_audiobooks.json new file mode 100644 index 00000000000..1994ee68e14 --- /dev/null +++ b/tests/components/music_assistant/fixtures/library_audiobooks.json @@ -0,0 +1,489 @@ +{ + "library_audiobooks": [ + { + "item_id": "1", + "provider": "library", + "name": "Test Audiobook", + "version": "", + "sort_name": "test audiobook", + "uri": "library://audiobook/1", + "external_ids": [], + "is_playable": true, + "media_type": "audiobook", + "provider_mappings": [ + { + "item_id": "test-audiobook.mp3", + "provider_domain": "filesystem_smb", + "provider_instance": "filesystem_smb--7Kf8QySu", + "available": true, + "audio_format": { + "content_type": "mp3", + "codec_type": "?", + "sample_rate": 48000, + "bit_depth": 16, + "channels": 1, + "output_format_str": "mp3", + "bit_rate": 90304 + }, + "url": null, + "details": "1738502411" + } + ], + "metadata": { + "description": "Cover (front)", + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "test-audiobook.mp3", + "provider": "filesystem_smb--7Kf8QySu", + "remotely_accessible": false + } + ], + "genres": [], + "mood": null, + "style": null, + "copyright": null, + "lyrics": "", + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": [], + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": null, + "authors": ["TestWriter"], + "narrators": [], + "duration": 9, + "fully_played": true, + "resume_position_ms": 9000 + }, + { + "item_id": "11", + "provider": "library", + "name": "Test Audiobook 0", + "version": "", + "sort_name": "test audiobook 0", + "uri": "library://audiobook/11", + "external_ids": [], + "is_playable": true, + "media_type": "audiobook", + "provider_mappings": [ + { + "item_id": "0", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": "This is a description for Test Audiobook", + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": [ + { + "position": 1, + "name": "Chapter 1", + "start": 10.0, + "end": 20.0 + }, + { + "position": 2, + "name": "Chapter 2", + "start": 20.0, + "end": 40.0 + }, + { + "position": 2, + "name": "Chapter 3", + "start": 40.0, + "end": null + } + ], + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "authors": ["AudioBook Author"], + "narrators": ["AudioBook Narrator"], + "duration": 60, + "fully_played": null, + "resume_position_ms": null + }, + { + "item_id": "12", + "provider": "library", + "name": "Test Audiobook 1", + "version": "", + "sort_name": "test audiobook 1", + "uri": "library://audiobook/12", + "external_ids": [], + "is_playable": true, + "media_type": "audiobook", + "provider_mappings": [ + { + "item_id": "1", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": "This is a description for Test Audiobook", + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": [ + { + "position": 1, + "name": "Chapter 1", + "start": 10.0, + "end": 20.0 + }, + { + "position": 2, + "name": "Chapter 2", + "start": 20.0, + "end": 40.0 + }, + { + "position": 2, + "name": "Chapter 3", + "start": 40.0, + "end": null + } + ], + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "authors": ["AudioBook Author"], + "narrators": ["AudioBook Narrator"], + "duration": 60, + "fully_played": null, + "resume_position_ms": null + }, + { + "item_id": "13", + "provider": "library", + "name": "Test Audiobook 2", + "version": "", + "sort_name": "test audiobook 2", + "uri": "library://audiobook/13", + "external_ids": [], + "is_playable": true, + "media_type": "audiobook", + "provider_mappings": [ + { + "item_id": "2", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": "This is a description for Test Audiobook", + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": [ + { + "position": 1, + "name": "Chapter 1", + "start": 10.0, + "end": 20.0 + }, + { + "position": 2, + "name": "Chapter 2", + "start": 20.0, + "end": 40.0 + }, + { + "position": 2, + "name": "Chapter 3", + "start": 40.0, + "end": null + } + ], + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "authors": ["AudioBook Author"], + "narrators": ["AudioBook Narrator"], + "duration": 60, + "fully_played": null, + "resume_position_ms": null + }, + { + "item_id": "14", + "provider": "library", + "name": "Test Audiobook 3", + "version": "", + "sort_name": "test audiobook 3", + "uri": "library://audiobook/14", + "external_ids": [], + "is_playable": true, + "media_type": "audiobook", + "provider_mappings": [ + { + "item_id": "3", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": "This is a description for Test Audiobook", + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": [ + { + "position": 1, + "name": "Chapter 1", + "start": 10.0, + "end": 20.0 + }, + { + "position": 2, + "name": "Chapter 2", + "start": 20.0, + "end": 40.0 + }, + { + "position": 2, + "name": "Chapter 3", + "start": 40.0, + "end": null + } + ], + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "authors": ["AudioBook Author"], + "narrators": ["AudioBook Narrator"], + "duration": 60, + "fully_played": null, + "resume_position_ms": null + }, + { + "item_id": "15", + "provider": "library", + "name": "Test Audiobook 4", + "version": "", + "sort_name": "test audiobook 4", + "uri": "library://audiobook/15", + "external_ids": [], + "is_playable": true, + "media_type": "audiobook", + "provider_mappings": [ + { + "item_id": "4", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": "This is a description for Test Audiobook", + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": [ + { + "position": 1, + "name": "Chapter 1", + "start": 10.0, + "end": 20.0 + }, + { + "position": 2, + "name": "Chapter 2", + "start": 20.0, + "end": 40.0 + }, + { + "position": 2, + "name": "Chapter 3", + "start": 40.0, + "end": null + } + ], + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "authors": ["AudioBook Author"], + "narrators": ["AudioBook Narrator"], + "duration": 60, + "fully_played": null, + "resume_position_ms": null + } + ] +} diff --git a/tests/components/music_assistant/fixtures/library_podcasts.json b/tests/components/music_assistant/fixtures/library_podcasts.json new file mode 100644 index 00000000000..2c6a9c62f65 --- /dev/null +++ b/tests/components/music_assistant/fixtures/library_podcasts.json @@ -0,0 +1,309 @@ +{ + "library_podcasts": [ + { + "item_id": "6", + "provider": "library", + "name": "Test Podcast 0", + "version": "", + "sort_name": "test podcast 0", + "uri": "library://podcast/6", + "external_ids": [], + "is_playable": true, + "media_type": "podcast", + "provider_mappings": [ + { + "item_id": "0", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": null, + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": null, + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "total_episodes": null + }, + { + "item_id": "7", + "provider": "library", + "name": "Test Podcast 1", + "version": "", + "sort_name": "test podcast 1", + "uri": "library://podcast/7", + "external_ids": [], + "is_playable": true, + "media_type": "podcast", + "provider_mappings": [ + { + "item_id": "1", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": null, + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": null, + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "total_episodes": null + }, + { + "item_id": "8", + "provider": "library", + "name": "Test Podcast 2", + "version": "", + "sort_name": "test podcast 2", + "uri": "library://podcast/8", + "external_ids": [], + "is_playable": true, + "media_type": "podcast", + "provider_mappings": [ + { + "item_id": "2", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": null, + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": null, + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "total_episodes": null + }, + { + "item_id": "9", + "provider": "library", + "name": "Test Podcast 3", + "version": "", + "sort_name": "test podcast 3", + "uri": "library://podcast/9", + "external_ids": [], + "is_playable": true, + "media_type": "podcast", + "provider_mappings": [ + { + "item_id": "3", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": null, + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": null, + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "total_episodes": null + }, + { + "item_id": "10", + "provider": "library", + "name": "Test Podcast 4", + "version": "", + "sort_name": "test podcast 4", + "uri": "library://podcast/10", + "external_ids": [], + "is_playable": true, + "media_type": "podcast", + "provider_mappings": [ + { + "item_id": "4", + "provider_domain": "test", + "provider_instance": "test", + "available": true, + "audio_format": { + "content_type": "?", + "codec_type": "?", + "sample_rate": 44100, + "bit_depth": 16, + "channels": 2, + "output_format_str": "?", + "bit_rate": 0 + }, + "url": null, + "details": null + } + ], + "metadata": { + "description": null, + "review": null, + "explicit": null, + "images": [ + { + "type": "thumb", + "path": "logo.png", + "provider": "builtin", + "remotely_accessible": false + } + ], + "genres": null, + "mood": null, + "style": null, + "copyright": null, + "lyrics": null, + "label": null, + "links": null, + "performers": null, + "preview": null, + "popularity": null, + "release_date": null, + "languages": null, + "chapters": null, + "last_refresh": null + }, + "favorite": false, + "position": null, + "publisher": "Test Publisher", + "total_episodes": null + } + ] +} diff --git a/tests/components/music_assistant/snapshots/test_actions.ambr b/tests/components/music_assistant/snapshots/test_actions.ambr index 6c30ffc512c..32c8776c953 100644 --- a/tests/components/music_assistant/snapshots/test_actions.ambr +++ b/tests/components/music_assistant/snapshots/test_actions.ambr @@ -1,5 +1,195 @@ # serializer version: 1 -# name: test_get_library_action +# name: test_get_library_action[album] + dict({ + 'items': list([ + dict({ + 'artists': list([ + dict({ + 'image': None, + 'media_type': , + 'name': 'A Space Love Adventure', + 'uri': 'library://artist/289', + 'version': '', + }), + ]), + 'image': None, + 'media_type': , + 'name': 'Synth Punk EP', + 'uri': 'library://album/396', + 'version': '', + }), + dict({ + 'artists': list([ + dict({ + 'image': None, + 'media_type': , + 'name': 'Various Artists', + 'uri': 'library://artist/96', + 'version': '', + }), + ]), + 'image': None, + 'media_type': , + 'name': 'Synthwave (The 80S Revival)', + 'uri': 'library://album/95', + 'version': 'The 80S Revival', + }), + ]), + 'limit': 25, + 'media_type': , + 'offset': 0, + 'order_by': 'name', + }) +# --- +# name: test_get_library_action[artist] + dict({ + 'items': list([ + dict({ + 'image': None, + 'media_type': , + 'name': 'W O L F C L U B', + 'uri': 'library://artist/127', + 'version': '', + }), + ]), + 'limit': 25, + 'media_type': , + 'offset': 0, + 'order_by': 'name', + }) +# --- +# name: test_get_library_action[audiobook] + dict({ + 'items': list([ + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Audiobook', + 'uri': 'library://audiobook/1', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Audiobook 0', + 'uri': 'library://audiobook/11', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Audiobook 1', + 'uri': 'library://audiobook/12', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Audiobook 2', + 'uri': 'library://audiobook/13', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Audiobook 3', + 'uri': 'library://audiobook/14', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Audiobook 4', + 'uri': 'library://audiobook/15', + 'version': '', + }), + ]), + 'limit': 25, + 'media_type': , + 'offset': 0, + 'order_by': 'name', + }) +# --- +# name: test_get_library_action[playlist] + dict({ + 'items': list([ + dict({ + 'image': None, + 'media_type': , + 'name': '1970s Rock Hits', + 'uri': 'library://playlist/40', + 'version': '', + }), + ]), + 'limit': 25, + 'media_type': , + 'offset': 0, + 'order_by': 'name', + }) +# --- +# name: test_get_library_action[podcast] + dict({ + 'items': list([ + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Podcast 0', + 'uri': 'library://podcast/6', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Podcast 1', + 'uri': 'library://podcast/7', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Podcast 2', + 'uri': 'library://podcast/8', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Podcast 3', + 'uri': 'library://podcast/9', + 'version': '', + }), + dict({ + 'image': None, + 'media_type': , + 'name': 'Test Podcast 4', + 'uri': 'library://podcast/10', + 'version': '', + }), + ]), + 'limit': 25, + 'media_type': , + 'offset': 0, + 'order_by': 'name', + }) +# --- +# name: test_get_library_action[radio] + dict({ + 'items': list([ + dict({ + 'image': None, + 'media_type': , + 'name': 'fm4 | ORF | HQ', + 'uri': 'library://radio/1', + 'version': '', + }), + ]), + 'limit': 25, + 'media_type': , + 'offset': 0, + 'order_by': 'name', + }) +# --- +# name: test_get_library_action[track] dict({ 'items': list([ dict({ @@ -192,8 +382,12 @@ ]), 'artists': list([ ]), + 'audiobooks': list([ + ]), 'playlists': list([ ]), + 'podcasts': list([ + ]), 'radio': list([ ]), 'tracks': list([ diff --git a/tests/components/music_assistant/test_actions.py b/tests/components/music_assistant/test_actions.py index 4d3917091c1..ba8b1acdeac 100644 --- a/tests/components/music_assistant/test_actions.py +++ b/tests/components/music_assistant/test_actions.py @@ -3,6 +3,7 @@ from unittest.mock import AsyncMock, MagicMock from music_assistant_models.media_items import SearchResults +import pytest from syrupy import SnapshotAssertion from homeassistant.components.music_assistant.actions import ( @@ -47,9 +48,22 @@ async def test_search_action( assert response == snapshot +@pytest.mark.parametrize( + "media_type", + [ + "artist", + "album", + "track", + "playlist", + "audiobook", + "podcast", + "radio", + ], +) async def test_get_library_action( hass: HomeAssistant, music_assistant_client: MagicMock, + media_type: str, snapshot: SnapshotAssertion, ) -> None: """Test music assistant get_library action.""" @@ -60,7 +74,7 @@ async def test_get_library_action( { ATTR_CONFIG_ENTRY_ID: entry.entry_id, ATTR_FAVORITE: False, - ATTR_MEDIA_TYPE: "track", + ATTR_MEDIA_TYPE: media_type, }, blocking=True, return_response=True,