1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-02 08:26:41 +01:00

Bump spotifyaio to 2.0.2 (#164114)

Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
Joost Lekkerkerker
2026-03-06 20:28:04 +01:00
committed by GitHub
parent ffca43027f
commit 4bcea27151
17 changed files with 94 additions and 589 deletions

View File

@@ -118,7 +118,6 @@ class BrowsableMedia(StrEnum):
CURRENT_USER_RECENTLY_PLAYED = "current_user_recently_played"
CURRENT_USER_TOP_ARTISTS = "current_user_top_artists"
CURRENT_USER_TOP_TRACKS = "current_user_top_tracks"
NEW_RELEASES = "new_releases"
LIBRARY_MAP = {
@@ -130,7 +129,6 @@ LIBRARY_MAP = {
BrowsableMedia.CURRENT_USER_RECENTLY_PLAYED.value: "Recently played",
BrowsableMedia.CURRENT_USER_TOP_ARTISTS.value: "Top Artists",
BrowsableMedia.CURRENT_USER_TOP_TRACKS.value: "Top Tracks",
BrowsableMedia.NEW_RELEASES.value: "New Releases",
}
CONTENT_TYPE_MEDIA_CLASS: dict[str, Any] = {
@@ -166,10 +164,6 @@ CONTENT_TYPE_MEDIA_CLASS: dict[str, Any] = {
"parent": MediaClass.DIRECTORY,
"children": MediaClass.TRACK,
},
BrowsableMedia.NEW_RELEASES.value: {
"parent": MediaClass.DIRECTORY,
"children": MediaClass.ALBUM,
},
MediaType.PLAYLIST: {
"parent": MediaClass.PLAYLIST,
"children": MediaClass.TRACK,
@@ -356,14 +350,11 @@ async def build_item_response( # noqa: C901
elif media_content_type == BrowsableMedia.CURRENT_USER_TOP_TRACKS:
if top_tracks := await spotify.get_top_tracks():
items = [_get_track_item_payload(track) for track in top_tracks]
elif media_content_type == BrowsableMedia.NEW_RELEASES:
if new_releases := await spotify.get_new_releases():
items = [_get_album_item_payload(album) for album in new_releases]
elif media_content_type == MediaType.PLAYLIST:
if playlist := await spotify.get_playlist(media_content_id):
title = playlist.name
image = playlist.images[0].url if playlist.images else None
for playlist_item in playlist.tracks.items:
for playlist_item in playlist.items.items:
if playlist_item.track.type is ItemType.TRACK:
if TYPE_CHECKING:
assert isinstance(playlist_item.track, Track)

View File

@@ -6,7 +6,7 @@ from collections.abc import Mapping
import logging
from typing import Any
from spotifyaio import SpotifyClient
from spotifyaio import SpotifyClient, SpotifyForbiddenError
from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_NAME, CONF_TOKEN
@@ -41,6 +41,9 @@ class SpotifyFlowHandler(
try:
current_user = await spotify.get_current_user()
except SpotifyForbiddenError:
self.logger.exception("User is not subscribed to Spotify")
return self.async_abort(reason="user_not_premium")
except Exception:
self.logger.exception("Error while connecting to Spotify")
return self.async_abort(reason="connection_error")

View File

@@ -11,12 +11,15 @@ from spotifyaio import (
Playlist,
SpotifyClient,
SpotifyConnectionError,
SpotifyForbiddenError,
SpotifyNotFoundError,
UserProfile,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util import dt as dt_util
@@ -33,6 +36,11 @@ type SpotifyConfigEntry = ConfigEntry[SpotifyData]
UPDATE_INTERVAL = timedelta(seconds=30)
FREE_API_BLOGPOST = (
"https://developer.spotify.com/blog/"
"2026-02-06-update-on-developer-access-and-platform-security"
)
@dataclass
class SpotifyCoordinatorData:
@@ -78,6 +86,19 @@ class SpotifyCoordinator(DataUpdateCoordinator[SpotifyCoordinatorData]):
"""Set up the coordinator."""
try:
self.current_user = await self.client.get_current_user()
except SpotifyForbiddenError as err:
async_create_issue(
self.hass,
DOMAIN,
f"user_not_premium_{self.config_entry.unique_id}",
is_fixable=False,
issue_domain=DOMAIN,
severity=IssueSeverity.ERROR,
translation_key="user_not_premium",
translation_placeholders={"entry_title": self.config_entry.title},
learn_more_url=FREE_API_BLOGPOST,
)
raise ConfigEntryError("User is not subscribed to Spotify") from err
except SpotifyConnectionError as err:
raise UpdateFailed("Error communicating with Spotify API") from err

View File

@@ -8,5 +8,5 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"loggers": ["spotifyaio"],
"requirements": ["spotifyaio==1.0.0"]
"requirements": ["spotifyaio==2.0.2"]
}

View File

@@ -14,10 +14,10 @@ from spotifyaio import (
Item,
ItemType,
PlaybackState,
ProductType,
RepeatMode as SpotifyRepeatMode,
Track,
)
from spotifyaio.models import ProductType
from yarl import URL
from homeassistant.components.media_player import (
@@ -222,7 +222,7 @@ class SpotifyMediaPlayer(SpotifyEntity, MediaPlayerEntity):
if item.type == ItemType.EPISODE:
if TYPE_CHECKING:
assert isinstance(item, Episode)
return item.show.publisher
return item.show.name
if TYPE_CHECKING:
assert isinstance(item, Track)
@@ -230,12 +230,10 @@ class SpotifyMediaPlayer(SpotifyEntity, MediaPlayerEntity):
@property
@ensure_item
def media_album_name(self, item: Item) -> str: # noqa: PLR0206
def media_album_name(self, item: Item) -> str | None: # noqa: PLR0206
"""Return the media album."""
if item.type == ItemType.EPISODE:
if TYPE_CHECKING:
assert isinstance(item, Episode)
return item.show.name
return None
if TYPE_CHECKING:
assert isinstance(item, Track)

View File

@@ -12,7 +12,8 @@
"oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]",
"oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]",
"reauth_account_mismatch": "The Spotify account authenticated with does not match the account that needed re-authentication.",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
"user_not_premium": "The Spotify API has been changed and Developer applications created with a free account can no longer access the API. To continue using the Spotify integration, you should use an Spotify Developer application created with a Spotify Premium account, or upgrade to Spotify Premium."
},
"create_entry": {
"default": "Successfully authenticated with Spotify."
@@ -41,6 +42,12 @@
"message": "[%key:common::exceptions::oauth2_implementation_unavailable::message%]"
}
},
"issues": {
"user_not_premium": {
"description": "[%key:component::spotify::config::abort::user_not_premium%]",
"title": "Spotify integration requires a Spotify Premium account"
}
},
"system_health": {
"info": {
"api_endpoint_reachable": "Spotify API endpoint reachable"

2
requirements_all.txt generated
View File

@@ -2978,7 +2978,7 @@ speak2mary==1.4.0
speedtest-cli==2.1.3
# homeassistant.components.spotify
spotifyaio==1.0.0
spotifyaio==2.0.2
# homeassistant.components.sql
sqlparse==0.5.5

View File

@@ -2514,7 +2514,7 @@ speak2mary==1.4.0
speedtest-cli==2.1.3
# homeassistant.components.spotify
spotifyaio==1.0.0
spotifyaio==2.0.2
# homeassistant.components.sql
sqlparse==0.5.5

View File

@@ -10,7 +10,6 @@ from spotifyaio.models import (
Artist,
Devices,
FollowedArtistResponse,
NewReleasesResponse,
NewReleasesResponseInner,
PlaybackState,
PlayedTrackResponse,
@@ -142,9 +141,6 @@ def mock_spotify() -> Generator[AsyncMock]:
client.get_followed_artists.return_value = FollowedArtistResponse.from_json(
load_fixture("followed_artists.json", DOMAIN)
).artists.items
client.get_new_releases.return_value = NewReleasesResponse.from_json(
load_fixture("new_releases.json", DOMAIN)
).albums.items
client.get_devices.return_value = Devices.from_json(
load_fixture("devices.json", DOMAIN)
).devices

View File

@@ -1,469 +0,0 @@
{
"albums": {
"href": "https://api.spotify.com/v1/browse/new-releases?offset=0&limit=20&locale=en-US,en;q%3D0.5",
"items": [
{
"album_type": "album",
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/4gzpq5DPGxSnKTe4SA8HAU"
},
"href": "https://api.spotify.com/v1/artists/4gzpq5DPGxSnKTe4SA8HAU",
"id": "4gzpq5DPGxSnKTe4SA8HAU",
"name": "Coldplay",
"type": "artist",
"uri": "spotify:artist:4gzpq5DPGxSnKTe4SA8HAU"
}
],
"available_markets": [
"AR",
"AU",
"AT",
"BE",
"BO",
"BR",
"BG",
"CA",
"CL",
"CO",
"CR",
"CY",
"CZ",
"DK",
"DO",
"DE",
"EC",
"EE",
"SV",
"FI",
"FR",
"GR",
"GT",
"HN",
"HK",
"HU",
"IS",
"IE",
"IT",
"LV",
"LT",
"LU",
"MY",
"MT",
"MX",
"NL",
"NZ",
"NI",
"NO",
"PA",
"PY",
"PE",
"PH",
"PL",
"PT",
"SG",
"SK",
"ES",
"SE",
"CH",
"TW",
"TR",
"UY",
"US",
"GB",
"AD",
"LI",
"MC",
"ID",
"JP",
"TH",
"VN",
"RO",
"IL",
"ZA",
"SA",
"AE",
"BH",
"QA",
"OM",
"KW",
"EG",
"MA",
"DZ",
"TN",
"LB",
"JO",
"PS",
"IN",
"KZ",
"MD",
"UA",
"AL",
"BA",
"HR",
"ME",
"MK",
"RS",
"SI",
"KR",
"BD",
"PK",
"LK",
"GH",
"KE",
"NG",
"TZ",
"UG",
"AG",
"AM",
"BS",
"BB",
"BZ",
"BT",
"BW",
"BF",
"CV",
"CW",
"DM",
"FJ",
"GM",
"GE",
"GD",
"GW",
"GY",
"HT",
"JM",
"KI",
"LS",
"LR",
"MW",
"MV",
"ML",
"MH",
"FM",
"NA",
"NR",
"NE",
"PW",
"PG",
"PR",
"WS",
"SM",
"ST",
"SN",
"SC",
"SL",
"SB",
"KN",
"LC",
"VC",
"SR",
"TL",
"TO",
"TT",
"TV",
"VU",
"AZ",
"BN",
"BI",
"KH",
"CM",
"TD",
"KM",
"GQ",
"SZ",
"GA",
"GN",
"KG",
"LA",
"MO",
"MR",
"MN",
"NP",
"RW",
"TG",
"UZ",
"ZW",
"BJ",
"MG",
"MU",
"MZ",
"AO",
"CI",
"DJ",
"ZM",
"CD",
"CG",
"IQ",
"LY",
"TJ",
"VE",
"ET",
"XK"
],
"external_urls": {
"spotify": "https://open.spotify.com/album/5SGtrmYbIo0Dsg4kJ4qjM6"
},
"href": "https://api.spotify.com/v1/albums/5SGtrmYbIo0Dsg4kJ4qjM6",
"id": "5SGtrmYbIo0Dsg4kJ4qjM6",
"images": [
{
"height": 300,
"url": "https://i.scdn.co/image/ab67616d00001e0209ba52a5116e0c3e8461f58b",
"width": 300
},
{
"height": 64,
"url": "https://i.scdn.co/image/ab67616d0000485109ba52a5116e0c3e8461f58b",
"width": 64
},
{
"height": 640,
"url": "https://i.scdn.co/image/ab67616d0000b27309ba52a5116e0c3e8461f58b",
"width": 640
}
],
"name": "Moon Music",
"release_date": "2024-10-04",
"release_date_precision": "day",
"total_tracks": 10,
"type": "album",
"uri": "spotify:album:5SGtrmYbIo0Dsg4kJ4qjM6"
},
{
"album_type": "album",
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/4U9nsRTH2mr9L4UXEWqG5e"
},
"href": "https://api.spotify.com/v1/artists/4U9nsRTH2mr9L4UXEWqG5e",
"id": "4U9nsRTH2mr9L4UXEWqG5e",
"name": "Bente",
"type": "artist",
"uri": "spotify:artist:4U9nsRTH2mr9L4UXEWqG5e"
}
],
"available_markets": [
"AR",
"AU",
"AT",
"BE",
"BO",
"BR",
"BG",
"CA",
"CL",
"CO",
"CR",
"CY",
"CZ",
"DK",
"DO",
"DE",
"EC",
"EE",
"SV",
"FI",
"FR",
"GR",
"GT",
"HN",
"HK",
"HU",
"IS",
"IE",
"IT",
"LV",
"LT",
"LU",
"MY",
"MT",
"MX",
"NL",
"NZ",
"NI",
"NO",
"PA",
"PY",
"PE",
"PH",
"PL",
"PT",
"SG",
"SK",
"ES",
"SE",
"CH",
"TW",
"TR",
"UY",
"US",
"GB",
"AD",
"LI",
"MC",
"ID",
"JP",
"TH",
"VN",
"RO",
"IL",
"ZA",
"SA",
"AE",
"BH",
"QA",
"OM",
"KW",
"EG",
"MA",
"DZ",
"TN",
"LB",
"JO",
"PS",
"IN",
"KZ",
"MD",
"UA",
"AL",
"BA",
"HR",
"ME",
"MK",
"RS",
"SI",
"KR",
"BD",
"PK",
"LK",
"GH",
"KE",
"NG",
"TZ",
"UG",
"AG",
"AM",
"BS",
"BB",
"BZ",
"BT",
"BW",
"BF",
"CV",
"CW",
"DM",
"FJ",
"GM",
"GE",
"GD",
"GW",
"GY",
"HT",
"JM",
"KI",
"LS",
"LR",
"MW",
"MV",
"ML",
"MH",
"FM",
"NA",
"NR",
"NE",
"PW",
"PG",
"WS",
"SM",
"ST",
"SN",
"SC",
"SL",
"SB",
"KN",
"LC",
"VC",
"SR",
"TL",
"TO",
"TT",
"TV",
"VU",
"AZ",
"BN",
"BI",
"KH",
"CM",
"TD",
"KM",
"GQ",
"SZ",
"GA",
"GN",
"KG",
"LA",
"MO",
"MR",
"MN",
"NP",
"RW",
"TG",
"UZ",
"ZW",
"BJ",
"MG",
"MU",
"MZ",
"AO",
"CI",
"DJ",
"ZM",
"CD",
"CG",
"IQ",
"LY",
"TJ",
"VE",
"ET",
"XK"
],
"external_urls": {
"spotify": "https://open.spotify.com/album/713lZ7AF55fEFSQgcttj9y"
},
"href": "https://api.spotify.com/v1/albums/713lZ7AF55fEFSQgcttj9y",
"id": "713lZ7AF55fEFSQgcttj9y",
"images": [
{
"height": 300,
"url": "https://i.scdn.co/image/ab67616d00001e02ab9953b1d18f8233f6b26027",
"width": 300
},
{
"height": 64,
"url": "https://i.scdn.co/image/ab67616d00004851ab9953b1d18f8233f6b26027",
"width": 64
},
{
"height": 640,
"url": "https://i.scdn.co/image/ab67616d0000b273ab9953b1d18f8233f6b26027",
"width": 640
}
],
"name": "drift",
"release_date": "2024-10-03",
"release_date_precision": "day",
"total_tracks": 14,
"type": "album",
"uri": "spotify:album:713lZ7AF55fEFSQgcttj9y"
}
],
"limit": 20,
"next": "https://api.spotify.com/v1/browse/new-releases?offset=20&limit=20&locale=en-US,en;q%3D0.5",
"offset": 0,
"previous": null,
"total": 100
}
}

View File

@@ -108,21 +108,7 @@
'width': None,
}),
]),
'name': 'Spotify Web API Testing playlist',
'object_type': 'playlist',
'owner': dict({
'display_name': 'JMPerez²',
'external_urls': dict({
'spotify': 'https://open.spotify.com/user/jmperezperez',
}),
'href': 'https://api.spotify.com/v1/users/jmperezperez',
'object_type': 'user',
'owner_id': 'jmperezperez',
'uri': 'spotify:user:jmperezperez',
}),
'playlist_id': '3cEYpjA9oz9GiPac4AsH4n',
'public': True,
'tracks': dict({
'items': dict({
'items': list([
dict({
'added_at': '2015-01-15T12:39:22+00:00',
@@ -517,7 +503,6 @@
}),
]),
'name': 'Safety Third',
'publisher': 'Safety Third ',
'show_id': '1Y9ExMgMxoBVrgrfU7u0nD',
'total_episodes': 120,
'uri': 'spotify:show:1Y9ExMgMxoBVrgrfU7u0nD',
@@ -528,6 +513,20 @@
}),
]),
}),
'name': 'Spotify Web API Testing playlist',
'object_type': 'playlist',
'owner': dict({
'display_name': 'JMPerez²',
'external_urls': dict({
'spotify': 'https://open.spotify.com/user/jmperezperez',
}),
'href': 'https://api.spotify.com/v1/users/jmperezperez',
'object_type': 'user',
'owner_id': 'jmperezperez',
'uri': 'spotify:user:jmperezperez',
}),
'playlist_id': '3cEYpjA9oz9GiPac4AsH4n',
'public': True,
'uri': 'spotify:playlist:3cEYpjA9oz9GiPac4AsH4n',
}),
}),

View File

@@ -93,17 +93,6 @@
'thumbnail': None,
'title': 'Top Tracks',
}),
dict({
'can_expand': True,
'can_play': False,
'can_search': False,
'children_media_class': <MediaClass.ALBUM: 'album'>,
'media_class': <MediaClass.DIRECTORY: 'directory'>,
'media_content_id': 'spotify://01j5tx5a0ff6g5v0qjx6hbc94t/new_releases',
'media_content_type': 'spotify://new_releases',
'thumbnail': None,
'title': 'New Releases',
}),
]),
'children_media_class': <MediaClass.DIRECTORY: 'directory'>,
'media_class': <MediaClass.DIRECTORY: 'directory'>,
@@ -608,44 +597,6 @@
'title': 'Top Tracks',
})
# ---
# name: test_browsing[new_releases-new_releases]
dict({
'can_expand': True,
'can_play': False,
'can_search': False,
'children': list([
dict({
'can_expand': True,
'can_play': True,
'can_search': False,
'children_media_class': <MediaClass.TRACK: 'track'>,
'media_class': <MediaClass.ALBUM: 'album'>,
'media_content_id': 'spotify://01j5tx5a0ff6g5v0qjx6hbc94t/spotify:album:5SGtrmYbIo0Dsg4kJ4qjM6',
'media_content_type': 'spotify://album',
'thumbnail': 'https://i.scdn.co/image/ab67616d00001e0209ba52a5116e0c3e8461f58b',
'title': 'Moon Music',
}),
dict({
'can_expand': True,
'can_play': True,
'can_search': False,
'children_media_class': <MediaClass.TRACK: 'track'>,
'media_class': <MediaClass.ALBUM: 'album'>,
'media_content_id': 'spotify://01j5tx5a0ff6g5v0qjx6hbc94t/spotify:album:713lZ7AF55fEFSQgcttj9y',
'media_content_type': 'spotify://album',
'thumbnail': 'https://i.scdn.co/image/ab67616d00001e02ab9953b1d18f8233f6b26027',
'title': 'drift',
}),
]),
'children_media_class': <MediaClass.ALBUM: 'album'>,
'media_class': <MediaClass.DIRECTORY: 'directory'>,
'media_content_id': 'spotify://01j5tx5a0ff6g5v0qjx6hbc94t/new_releases',
'media_content_type': 'spotify://new_releases',
'not_shown': 0,
'thumbnail': None,
'title': 'New Releases',
})
# ---
# name: test_browsing[playlist-spotify:playlist:3cEYpjA9oz9GiPac4AsH4n]
dict({
'can_expand': True,

View File

@@ -116,8 +116,7 @@
'attributes': ReadOnlyDict({
'entity_picture': '/api/media_player_proxy/media_player.spotify_spotify_1?token=mock-token&cache=cf1e6e1e830f08d3',
'friendly_name': 'Spotify spotify_1',
'media_album_name': 'Safety Third',
'media_artist': 'Safety Third ',
'media_artist': 'Safety Third',
'media_content_id': 'spotify:episode:3o0RYoo5iOMKSmEbunsbvW',
'media_content_type': <MediaType.PODCAST: 'podcast'>,
'media_duration': 3690,

View File

@@ -4,7 +4,7 @@ from http import HTTPStatus
from unittest.mock import MagicMock, patch
import pytest
from spotifyaio import SpotifyConnectionError
from spotifyaio import SpotifyConnectionError, SpotifyForbiddenError
from homeassistant.components.spotify.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
@@ -95,6 +95,13 @@ async def test_full_flow(
assert result["result"].unique_id == "1112264111"
@pytest.mark.parametrize(
("exception", "reason"),
[
(SpotifyConnectionError, "connection_error"),
(SpotifyForbiddenError, "user_not_premium"),
],
)
@pytest.mark.usefixtures("current_request_with_host")
@pytest.mark.usefixtures("setup_credentials")
async def test_abort_if_spotify_error(
@@ -102,6 +109,8 @@ async def test_abort_if_spotify_error(
hass_client_no_auth: ClientSessionGenerator,
aioclient_mock: AiohttpClientMocker,
mock_spotify: MagicMock,
exception: Exception,
reason: str,
) -> None:
"""Check Spotify errors causes flow to abort."""
result = await hass.config_entries.flow.async_init(
@@ -128,12 +137,12 @@ async def test_abort_if_spotify_error(
},
)
mock_spotify.return_value.get_current_user.side_effect = SpotifyConnectionError
mock_spotify.return_value.get_current_user.side_effect = exception
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "connection_error"
assert result["reason"] == reason
@pytest.mark.usefixtures("current_request_with_host")

View File

@@ -3,10 +3,12 @@
from unittest.mock import MagicMock, patch
import pytest
from spotifyaio import SpotifyConnectionError
from spotifyaio import SpotifyConnectionError, SpotifyForbiddenError
from homeassistant.components.spotify.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.config_entry_oauth2_flow import (
ImplementationUnavailableError,
)
@@ -53,6 +55,26 @@ async def test_setup_with_required_calls_failing(
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
@pytest.mark.usefixtures("setup_credentials")
async def test_setup_free_account_is_failing(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
issue_registry: ir.IssueRegistry,
) -> None:
"""Test the Spotify setup with a free account is failing."""
mock_spotify.return_value.get_current_user.side_effect = SpotifyForbiddenError(
"Check settings on developer.spotify.com/dashboard, the user may not be registered."
)
mock_config_entry.add_to_hass(hass)
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
issue = issue_registry.issues.get(
(DOMAIN, f"user_not_premium_{mock_config_entry.unique_id}")
)
assert issue, "Repair issue not created"
@pytest.mark.usefixtures("setup_credentials")
async def test_oauth_implementation_not_available(
hass: HomeAssistant,

View File

@@ -66,7 +66,7 @@ async def test_browse_media_categories(
@pytest.mark.parametrize(
("config_entry_id"), [("01J5TX5A0FF6G5V0QJX6HBC94T"), ("32oesphrnacjcf7vw5bf6odx3")]
"config_entry_id", ["01J5TX5A0FF6G5V0QJX6HBC94T", "32oesphrnacjcf7vw5bf6odx3"]
)
@pytest.mark.usefixtures("setup_credentials")
async def test_browse_media_playlists(
@@ -112,7 +112,6 @@ async def test_browse_media_playlists(
("current_user_recently_played", "current_user_recently_played"),
("current_user_top_artists", "current_user_top_artists"),
("current_user_top_tracks", "current_user_top_tracks"),
("new_releases", "new_releases"),
("playlist", "spotify:playlist:3cEYpjA9oz9GiPac4AsH4n"),
("album", "spotify:album:3IqzqH6ShrRtie9Yd2ODyG"),
("artist", "spotify:artist:0TnOYISbd1XYRBk9myaseg"),
@@ -138,13 +137,7 @@ async def test_browsing(
assert response.as_dict() == snapshot
@pytest.mark.parametrize(
("media_content_id"),
[
"artist",
None,
],
)
@pytest.mark.parametrize("media_content_id", ["artist", None])
@pytest.mark.usefixtures("setup_credentials")
async def test_invalid_spotify_url(
hass: HomeAssistant,

View File

@@ -7,7 +7,6 @@ from freezegun.api import FrozenDateTimeFactory
import pytest
from spotifyaio import (
PlaybackState,
ProductType,
RepeatMode as SpotifyRepeatMode,
SpotifyConnectionError,
SpotifyNotFoundError,
@@ -108,20 +107,6 @@ async def test_podcast(
)
@pytest.mark.usefixtures("setup_credentials")
async def test_free_account(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify entities with a free account."""
mock_spotify.return_value.get_current_user.return_value.product = ProductType.FREE
await setup_integration(hass, mock_config_entry)
state = hass.states.get("media_player.spotify_spotify_1")
assert state
assert state.attributes["supported_features"] == 0
@pytest.mark.usefixtures("setup_credentials")
async def test_restricted_device(
hass: HomeAssistant,