Add even more tests to Spotify (#128298)

This commit is contained in:
Joost Lekkerkerker 2024-10-16 13:20:57 +02:00 committed by GitHub
parent dddc1906c2
commit ed445d0ab8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 248 additions and 2 deletions

View file

@ -74,7 +74,7 @@
"images": [
{
"height": 640,
"url": "https://i.scdn.co/image/ab6765630000ba8ac7bedd27a4413b1abf926d8a",
"url": "https://i.scdn.co/image/ab6765630000ba8ac7bedd27a4413b1abf926d8b",
"width": 640
},
{

View file

@ -0,0 +1,65 @@
"""Tests for the Spotify initialization."""
from unittest.mock import MagicMock
import pytest
from spotipy import SpotifyException
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from . import setup_integration
from tests.common import MockConfigEntry
@pytest.mark.usefixtures("setup_credentials")
async def test_setup(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify setup."""
await setup_integration(hass, mock_config_entry)
assert mock_config_entry.state is ConfigEntryState.LOADED
await hass.config_entries.async_unload(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
@pytest.mark.usefixtures("setup_credentials")
@pytest.mark.parametrize(
"method",
[
"me",
"devices",
],
)
async def test_setup_with_required_calls_failing(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
method: str,
) -> None:
"""Test the Spotify setup with required calls failing."""
getattr(mock_spotify.return_value, method).side_effect = SpotifyException(
400, "Bad Request", "Bad Request"
)
mock_config_entry.add_to_hass(hass)
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
@pytest.mark.usefixtures("setup_credentials")
async def test_no_current_user(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify setup with required calls failing."""
mock_spotify.return_value.me.return_value = None
mock_config_entry.add_to_hass(hass)
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)

View file

@ -5,6 +5,7 @@ from unittest.mock import MagicMock
import pytest
from syrupy import SnapshotAssertion
from homeassistant.components.media_player import BrowseError
from homeassistant.components.spotify import DOMAIN
from homeassistant.components.spotify.browse_media import async_browse_media
from homeassistant.const import CONF_ID
@ -138,3 +139,42 @@ async def test_browsing(
f"spotify://{mock_config_entry.entry_id}/{media_content_id}",
)
assert response.as_dict() == snapshot
@pytest.mark.parametrize(
("media_content_id"),
[
"artist",
None,
],
)
@pytest.mark.usefixtures("setup_credentials")
async def test_invalid_spotify_url(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
media_content_id: str | None,
) -> None:
"""Test browsing with an invalid Spotify URL."""
await setup_integration(hass, mock_config_entry)
with pytest.raises(BrowseError, match="Invalid Spotify URL specified"):
await async_browse_media(
hass,
"spotify://artist",
media_content_id,
)
@pytest.mark.usefixtures("setup_credentials")
async def test_browsing_not_loaded_entry(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test browsing with an unloaded config entry."""
with pytest.raises(BrowseError, match="Invalid Spotify account specified"):
await async_browse_media(
hass,
"spotify://artist",
f"spotify://{mock_config_entry.entry_id}/spotify:artist:0TnOYISbd1XYRBk9myaseg",
)

View file

@ -1,13 +1,16 @@
"""Tests for the Spotify media player platform."""
from datetime import timedelta
from unittest.mock import MagicMock, patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from spotipy import SpotifyException
from syrupy import SnapshotAssertion
from homeassistant.components.media_player import (
ATTR_INPUT_SOURCE,
ATTR_INPUT_SOURCE_LIST,
ATTR_MEDIA_CONTENT_ID,
ATTR_MEDIA_CONTENT_TYPE,
ATTR_MEDIA_ENQUEUE,
@ -27,6 +30,7 @@ from homeassistant.components.media_player import (
from homeassistant.components.spotify import DOMAIN
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_ENTITY_PICTURE,
SERVICE_MEDIA_NEXT_TRACK,
SERVICE_MEDIA_PAUSE,
SERVICE_MEDIA_PLAY,
@ -35,13 +39,19 @@ from homeassistant.const import (
SERVICE_REPEAT_SET,
SERVICE_SHUFFLE_SET,
SERVICE_VOLUME_SET,
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import setup_integration
from tests.common import MockConfigEntry, load_json_value_fixture, snapshot_platform
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
load_json_value_fixture,
snapshot_platform,
)
@pytest.mark.freeze_time("2023-10-21")
@ -373,6 +383,30 @@ async def test_play_media(
mock_spotify.return_value.start_playback.assert_called_with(**called_with)
@pytest.mark.usefixtures("setup_credentials")
async def test_add_unsupported_media_to_queue(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify media player add unsupported media to queue."""
await setup_integration(hass, mock_config_entry)
with pytest.raises(
ValueError, match="Media type playlist is not supported when enqueue is ADD"
):
await hass.services.async_call(
MEDIA_PLAYER_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: "media_player.spotify_spotify_1",
ATTR_MEDIA_CONTENT_TYPE: "spotify://playlist",
ATTR_MEDIA_CONTENT_ID: "spotify:playlist:74Yus6IHfa3tWZzXXAYtS2",
ATTR_MEDIA_ENQUEUE: MediaPlayerEnqueue.ADD,
},
blocking=True,
)
@pytest.mark.usefixtures("setup_credentials")
async def test_play_unsupported_media(
hass: HomeAssistant,
@ -415,3 +449,110 @@ async def test_select_source(
mock_spotify.return_value.transfer_playback.assert_called_with(
"21dac6b0e0a1f181870fdc9749b2656466557666", True
)
@pytest.mark.usefixtures("setup_credentials")
async def test_source_devices(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test the Spotify media player available source devices."""
await setup_integration(hass, mock_config_entry)
state = hass.states.get("media_player.spotify_spotify_1")
assert state.attributes[ATTR_INPUT_SOURCE_LIST] == ["DESKTOP-BKC5SIK"]
mock_spotify.return_value.devices.side_effect = SpotifyException(
404, "Not Found", "msg"
)
freezer.tick(timedelta(minutes=5))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("media_player.spotify_spotify_1")
assert state
assert state.state != STATE_UNAVAILABLE
assert state.attributes[ATTR_INPUT_SOURCE_LIST] == ["DESKTOP-BKC5SIK"]
@pytest.mark.usefixtures("setup_credentials")
async def test_no_source_devices(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify media player with no source devices."""
mock_spotify.return_value.devices.return_value = None
await setup_integration(hass, mock_config_entry)
state = hass.states.get("media_player.spotify_spotify_1")
assert ATTR_INPUT_SOURCE_LIST not in state.attributes
@pytest.mark.usefixtures("setup_credentials")
async def test_paused_playback(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify media player with paused playback."""
mock_spotify.return_value.current_playback.return_value["is_playing"] = False
await setup_integration(hass, mock_config_entry)
state = hass.states.get("media_player.spotify_spotify_1")
assert state
assert state.state == MediaPlayerState.PAUSED
@pytest.mark.usefixtures("setup_credentials")
async def test_fallback_show_image(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify media player with a fallback image."""
playback = load_json_value_fixture("playback_episode.json", DOMAIN)
playback["item"]["images"] = []
mock_spotify.return_value.current_playback.return_value = playback
with patch("secrets.token_hex", return_value="mock-token"):
await setup_integration(hass, mock_config_entry)
state = hass.states.get("media_player.spotify_spotify_1")
assert state
assert (
state.attributes[ATTR_ENTITY_PICTURE]
== "/api/media_player_proxy/media_player.spotify_spotify_1?token=mock-token&cache=16ff384dbae94fea"
)
@pytest.mark.usefixtures("setup_credentials")
async def test_no_episode_images(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify media player with no episode images."""
playback = load_json_value_fixture("playback_episode.json", DOMAIN)
playback["item"]["images"] = []
playback["item"]["show"]["images"] = []
mock_spotify.return_value.current_playback.return_value = playback
await setup_integration(hass, mock_config_entry)
state = hass.states.get("media_player.spotify_spotify_1")
assert state
assert ATTR_ENTITY_PICTURE not in state.attributes
@pytest.mark.usefixtures("setup_credentials")
async def test_no_album_images(
hass: HomeAssistant,
mock_spotify: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Spotify media player with no album images."""
mock_spotify.return_value.current_playback.return_value["item"]["album"][
"images"
] = []
await setup_integration(hass, mock_config_entry)
state = hass.states.get("media_player.spotify_spotify_1")
assert state
assert ATTR_ENTITY_PICTURE not in state.attributes