mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 17:27:52 +00:00
Add new mediatypes to Music Assistant integration (#139338)
* Bump Music Assistant client to 1.1.0 * Add some casts to help mypy * Add handling of the new media types in Music Assistant * mypy cleanup * lint * update snapshot * Adjust tests --------- Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
parent
d6f9040baf
commit
b79c6e772a
@ -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}")
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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)]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -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:
|
||||
|
@ -195,8 +195,11 @@
|
||||
"options": {
|
||||
"artist": "Artist",
|
||||
"album": "Album",
|
||||
"audiobook": "Audiobook",
|
||||
"folder": "Folder",
|
||||
"track": "Track",
|
||||
"playlist": "Playlist",
|
||||
"podcast": "Podcast",
|
||||
"radio": "Radio"
|
||||
}
|
||||
},
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
309
tests/components/music_assistant/fixtures/library_podcasts.json
Normal file
309
tests/components/music_assistant/fixtures/library_podcasts.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
@ -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': <MediaType.ARTIST: 'artist'>,
|
||||
'name': 'A Space Love Adventure',
|
||||
'uri': 'library://artist/289',
|
||||
'version': '',
|
||||
}),
|
||||
]),
|
||||
'image': None,
|
||||
'media_type': <MediaType.ALBUM: 'album'>,
|
||||
'name': 'Synth Punk EP',
|
||||
'uri': 'library://album/396',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'artists': list([
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.ARTIST: 'artist'>,
|
||||
'name': 'Various Artists',
|
||||
'uri': 'library://artist/96',
|
||||
'version': '',
|
||||
}),
|
||||
]),
|
||||
'image': None,
|
||||
'media_type': <MediaType.ALBUM: 'album'>,
|
||||
'name': 'Synthwave (The 80S Revival)',
|
||||
'uri': 'library://album/95',
|
||||
'version': 'The 80S Revival',
|
||||
}),
|
||||
]),
|
||||
'limit': 25,
|
||||
'media_type': <MediaType.ALBUM: 'album'>,
|
||||
'offset': 0,
|
||||
'order_by': 'name',
|
||||
})
|
||||
# ---
|
||||
# name: test_get_library_action[artist]
|
||||
dict({
|
||||
'items': list([
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.ARTIST: 'artist'>,
|
||||
'name': 'W O L F C L U B',
|
||||
'uri': 'library://artist/127',
|
||||
'version': '',
|
||||
}),
|
||||
]),
|
||||
'limit': 25,
|
||||
'media_type': <MediaType.ARTIST: 'artist'>,
|
||||
'offset': 0,
|
||||
'order_by': 'name',
|
||||
})
|
||||
# ---
|
||||
# name: test_get_library_action[audiobook]
|
||||
dict({
|
||||
'items': list([
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.AUDIOBOOK: 'audiobook'>,
|
||||
'name': 'Test Audiobook',
|
||||
'uri': 'library://audiobook/1',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.AUDIOBOOK: 'audiobook'>,
|
||||
'name': 'Test Audiobook 0',
|
||||
'uri': 'library://audiobook/11',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.AUDIOBOOK: 'audiobook'>,
|
||||
'name': 'Test Audiobook 1',
|
||||
'uri': 'library://audiobook/12',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.AUDIOBOOK: 'audiobook'>,
|
||||
'name': 'Test Audiobook 2',
|
||||
'uri': 'library://audiobook/13',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.AUDIOBOOK: 'audiobook'>,
|
||||
'name': 'Test Audiobook 3',
|
||||
'uri': 'library://audiobook/14',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.AUDIOBOOK: 'audiobook'>,
|
||||
'name': 'Test Audiobook 4',
|
||||
'uri': 'library://audiobook/15',
|
||||
'version': '',
|
||||
}),
|
||||
]),
|
||||
'limit': 25,
|
||||
'media_type': <MediaType.AUDIOBOOK: 'audiobook'>,
|
||||
'offset': 0,
|
||||
'order_by': 'name',
|
||||
})
|
||||
# ---
|
||||
# name: test_get_library_action[playlist]
|
||||
dict({
|
||||
'items': list([
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.PLAYLIST: 'playlist'>,
|
||||
'name': '1970s Rock Hits',
|
||||
'uri': 'library://playlist/40',
|
||||
'version': '',
|
||||
}),
|
||||
]),
|
||||
'limit': 25,
|
||||
'media_type': <MediaType.PLAYLIST: 'playlist'>,
|
||||
'offset': 0,
|
||||
'order_by': 'name',
|
||||
})
|
||||
# ---
|
||||
# name: test_get_library_action[podcast]
|
||||
dict({
|
||||
'items': list([
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.PODCAST: 'podcast'>,
|
||||
'name': 'Test Podcast 0',
|
||||
'uri': 'library://podcast/6',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.PODCAST: 'podcast'>,
|
||||
'name': 'Test Podcast 1',
|
||||
'uri': 'library://podcast/7',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.PODCAST: 'podcast'>,
|
||||
'name': 'Test Podcast 2',
|
||||
'uri': 'library://podcast/8',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.PODCAST: 'podcast'>,
|
||||
'name': 'Test Podcast 3',
|
||||
'uri': 'library://podcast/9',
|
||||
'version': '',
|
||||
}),
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.PODCAST: 'podcast'>,
|
||||
'name': 'Test Podcast 4',
|
||||
'uri': 'library://podcast/10',
|
||||
'version': '',
|
||||
}),
|
||||
]),
|
||||
'limit': 25,
|
||||
'media_type': <MediaType.PODCAST: 'podcast'>,
|
||||
'offset': 0,
|
||||
'order_by': 'name',
|
||||
})
|
||||
# ---
|
||||
# name: test_get_library_action[radio]
|
||||
dict({
|
||||
'items': list([
|
||||
dict({
|
||||
'image': None,
|
||||
'media_type': <MediaType.RADIO: 'radio'>,
|
||||
'name': 'fm4 | ORF | HQ',
|
||||
'uri': 'library://radio/1',
|
||||
'version': '',
|
||||
}),
|
||||
]),
|
||||
'limit': 25,
|
||||
'media_type': <MediaType.RADIO: 'radio'>,
|
||||
'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([
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user