Improve cast integration tests (#42229)
* Improve cast tests * Address review comments * Further cleanup of tests
This commit is contained in:
parent
7618fe6111
commit
b626df1316
2 changed files with 488 additions and 88 deletions
|
@ -119,7 +119,6 @@ omit =
|
|||
homeassistant/components/buienradar/weather.py
|
||||
homeassistant/components/caldav/calendar.py
|
||||
homeassistant/components/canary/camera.py
|
||||
homeassistant/components/cast/*
|
||||
homeassistant/components/cert_expiry/helper.py
|
||||
homeassistant/components/channels/*
|
||||
homeassistant/components/circuit/*
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""The tests for the Cast Media player platform."""
|
||||
# pylint: disable=protected-access
|
||||
import json
|
||||
from typing import Optional
|
||||
from uuid import UUID
|
||||
|
||||
|
@ -15,12 +16,25 @@ from homeassistant.exceptions import PlatformNotReady
|
|||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.async_mock import AsyncMock, MagicMock, Mock, patch
|
||||
from tests.async_mock import ANY, AsyncMock, MagicMock, Mock, patch
|
||||
from tests.common import MockConfigEntry, assert_setup_component
|
||||
from tests.components.media_player import common
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def mz_mock():
|
||||
"""Mock pychromecast MultizoneManager."""
|
||||
return MagicMock()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def quick_play_mock():
|
||||
"""Mock pychromecast quick_play."""
|
||||
return MagicMock()
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def cast_mock():
|
||||
def cast_mock(mz_mock, quick_play_mock):
|
||||
"""Mock pychromecast."""
|
||||
pycast_mock = MagicMock()
|
||||
pycast_mock.start_discovery.return_value = (None, Mock())
|
||||
|
@ -35,10 +49,14 @@ def cast_mock():
|
|||
), patch(
|
||||
"homeassistant.components.cast.discovery.pychromecast", pycast_mock
|
||||
), patch(
|
||||
"homeassistant.components.cast.media_player.MultizoneManager", MagicMock()
|
||||
"homeassistant.components.cast.media_player.MultizoneManager",
|
||||
return_value=mz_mock,
|
||||
), patch(
|
||||
"homeassistant.components.cast.media_player.zeroconf.async_get_instance",
|
||||
AsyncMock(),
|
||||
), patch(
|
||||
"homeassistant.components.cast.media_player.quick_play",
|
||||
quick_play_mock,
|
||||
):
|
||||
yield
|
||||
|
||||
|
@ -133,8 +151,6 @@ async def async_setup_media_player_cast(hass: HomeAssistantType, info: Chromecas
|
|||
chromecast = get_fake_chromecast(info)
|
||||
zconf = get_fake_zconf(host=info.host, port=info.port)
|
||||
|
||||
cast.CastStatusListener = MagicMock()
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.cast.discovery.pychromecast.get_chromecast_from_service",
|
||||
return_value=chromecast,
|
||||
|
@ -153,27 +169,40 @@ async def async_setup_media_player_cast(hass: HomeAssistantType, info: Chromecas
|
|||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await cast.async_setup_entry(hass, MockConfigEntry(), None)
|
||||
|
||||
discovery_callback = cast_listener.call_args[0][0]
|
||||
|
||||
def discover_chromecast(service_name: str, info: ChromecastInfo) -> None:
|
||||
"""Discover a chromecast device."""
|
||||
listener.services[info.uuid] = (
|
||||
{service_name},
|
||||
info.uuid,
|
||||
info.model_name,
|
||||
info.friendly_name,
|
||||
)
|
||||
discovery_callback(info.uuid, service_name)
|
||||
service_name = "the-service"
|
||||
listener.services[info.uuid] = (
|
||||
{service_name},
|
||||
info.uuid,
|
||||
info.model_name,
|
||||
info.friendly_name,
|
||||
)
|
||||
discovery_callback(info.uuid, service_name)
|
||||
|
||||
discover_chromecast("the-service", info)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
assert get_chromecast.call_count == 1
|
||||
assert cast.CastStatusListener.call_count == 1
|
||||
entity = cast.CastStatusListener.call_args[0][0]
|
||||
return chromecast, entity
|
||||
return chromecast
|
||||
|
||||
|
||||
def get_status_callbacks(chromecast_mock, mz_mock=None):
|
||||
"""Get registered status callbacks from the chromecast mock."""
|
||||
status_listener = chromecast_mock.register_status_listener.call_args[0][0]
|
||||
cast_status_cb = status_listener.new_cast_status
|
||||
|
||||
connection_listener = chromecast_mock.register_connection_listener.call_args[0][0]
|
||||
conn_status_cb = connection_listener.new_connection_status
|
||||
|
||||
mc = chromecast_mock.socket_client.media_controller
|
||||
media_status_cb = mc.register_status_listener.call_args[0][0].new_media_status
|
||||
|
||||
if not mz_mock:
|
||||
return cast_status_cb, conn_status_cb, media_status_cb
|
||||
|
||||
mz_listener = mz_mock.register_listener.call_args[0][1]
|
||||
group_media_status_cb = mz_listener.multizone_new_media_status
|
||||
return cast_status_cb, conn_status_cb, media_status_cb, group_media_status_cb
|
||||
|
||||
|
||||
async def test_start_discovery_called_once(hass):
|
||||
|
@ -358,78 +387,429 @@ async def test_update_cast_chromecasts(hass):
|
|||
assert add_dev1.call_count == 1
|
||||
|
||||
|
||||
async def test_entity_media_states(hass: HomeAssistantType):
|
||||
"""Test various entity media states."""
|
||||
async def test_entity_availability(hass: HomeAssistantType):
|
||||
"""Test handling of connection status."""
|
||||
entity_id = "media_player.speaker"
|
||||
info = get_fake_chromecast_info()
|
||||
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, _ = get_status_callbacks(chromecast)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "unavailable"
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "unknown"
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "DISCONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "unavailable"
|
||||
|
||||
|
||||
async def test_entity_cast_status(hass: HomeAssistantType):
|
||||
"""Test handling of cast status."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
cast_status_cb, conn_status_cb, _ = get_status_callbacks(chromecast)
|
||||
|
||||
entity._available = True
|
||||
entity.schedule_update_ha_state()
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity.unique_id == full_info.uuid
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
cast_status = MagicMock()
|
||||
cast_status.volume_level = 0.5
|
||||
cast_status.volume_muted = False
|
||||
cast_status_cb(cast_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get("volume_level") == 0.5
|
||||
assert not state.attributes.get("is_volume_muted")
|
||||
|
||||
cast_status = MagicMock()
|
||||
cast_status.volume_level = 0.2
|
||||
cast_status.volume_muted = True
|
||||
cast_status_cb(cast_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get("volume_level") == 0.2
|
||||
assert state.attributes.get("is_volume_muted")
|
||||
|
||||
|
||||
async def test_entity_play_media(hass: HomeAssistantType):
|
||||
"""Test playing media."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, _ = get_status_callbacks(chromecast)
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
# Play_media
|
||||
await common.async_play_media(hass, "audio", "best.mp3", entity_id)
|
||||
chromecast.media_controller.play_media.assert_called_once_with("best.mp3", "audio")
|
||||
|
||||
|
||||
async def test_entity_play_media_cast(hass: HomeAssistantType, quick_play_mock):
|
||||
"""Test playing media with cast special features."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, _ = get_status_callbacks(chromecast)
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
# Play_media - cast with app ID
|
||||
await common.async_play_media(hass, "cast", '{"app_id": "abc123"}', entity_id)
|
||||
chromecast.start_app.assert_called_once_with("abc123")
|
||||
|
||||
# Play_media - cast with app name (quick play)
|
||||
await common.async_play_media(hass, "cast", '{"app_name": "youtube"}', entity_id)
|
||||
quick_play_mock.assert_called_once_with(ANY, "youtube", {})
|
||||
|
||||
|
||||
async def test_entity_play_media_cast_invalid(hass, caplog, quick_play_mock):
|
||||
"""Test playing media."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, _ = get_status_callbacks(chromecast)
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
# play_media - media_type cast with invalid JSON
|
||||
with pytest.raises(json.decoder.JSONDecodeError):
|
||||
await common.async_play_media(hass, "cast", '{"app_id": "abc123"', entity_id)
|
||||
assert "Invalid JSON in media_content_id" in caplog.text
|
||||
chromecast.start_app.assert_not_called()
|
||||
quick_play_mock.assert_not_called()
|
||||
|
||||
# Play_media - media_type cast with extra keys
|
||||
await common.async_play_media(
|
||||
hass, "cast", '{"app_id": "abc123", "extra": "data"}', entity_id
|
||||
)
|
||||
assert "Extra keys dict_keys(['extra']) were ignored" in caplog.text
|
||||
chromecast.start_app.assert_called_once_with("abc123")
|
||||
quick_play_mock.assert_not_called()
|
||||
|
||||
# Play_media - media_type cast with unsupported app
|
||||
quick_play_mock.side_effect = NotImplementedError()
|
||||
await common.async_play_media(hass, "cast", '{"app_name": "unknown"}', entity_id)
|
||||
quick_play_mock.assert_called_once_with(ANY, "unknown", {})
|
||||
assert "App unknown not supported" in caplog.text
|
||||
|
||||
|
||||
async def test_entity_play_media_sign_URL(hass: HomeAssistantType):
|
||||
"""Test playing media."""
|
||||
entity_id = "media_player.speaker"
|
||||
|
||||
await async_process_ha_core_config(
|
||||
hass,
|
||||
{"external_url": "http://example.com:8123"},
|
||||
)
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, _ = get_status_callbacks(chromecast)
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Play_media
|
||||
await common.async_play_media(hass, "audio", "/best.mp3", entity_id)
|
||||
chromecast.media_controller.play_media.assert_called_once_with(ANY, "audio")
|
||||
assert chromecast.media_controller.play_media.call_args[0][0].startswith(
|
||||
"http://example.com:8123/best.mp3?authSig="
|
||||
)
|
||||
|
||||
|
||||
async def test_entity_media_content_type(hass: HomeAssistantType):
|
||||
"""Test various content types."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.media_is_movie = False
|
||||
media_status.media_is_musictrack = False
|
||||
media_status.media_is_tvshow = False
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get("media_content_type") is None
|
||||
|
||||
media_status.media_is_tvshow = True
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get("media_content_type") == "tvshow"
|
||||
|
||||
media_status.media_is_tvshow = False
|
||||
media_status.media_is_musictrack = True
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get("media_content_type") == "music"
|
||||
|
||||
media_status.media_is_musictrack = True
|
||||
media_status.media_is_movie = True
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get("media_content_type") == "movie"
|
||||
|
||||
|
||||
async def test_entity_control(hass: HomeAssistantType):
|
||||
"""Test various device and media controls."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
# Turn on
|
||||
await common.async_turn_on(hass, entity_id)
|
||||
chromecast.play_media.assert_called_once_with(
|
||||
"https://www.home-assistant.io/images/cast/splash.png", ANY
|
||||
)
|
||||
chromecast.quit_app.reset_mock()
|
||||
|
||||
# Turn off
|
||||
await common.async_turn_off(hass, entity_id)
|
||||
chromecast.quit_app.assert_called_once_with()
|
||||
|
||||
# Mute
|
||||
await common.async_mute_volume(hass, True, entity_id)
|
||||
chromecast.set_volume_muted.assert_called_once_with(True)
|
||||
|
||||
# Volume
|
||||
await common.async_set_volume_level(hass, 0.33, entity_id)
|
||||
chromecast.set_volume.assert_called_once_with(0.33)
|
||||
|
||||
# Media play
|
||||
await common.async_media_play(hass, entity_id)
|
||||
chromecast.media_controller.play.assert_called_once_with()
|
||||
|
||||
# Media pause
|
||||
await common.async_media_pause(hass, entity_id)
|
||||
chromecast.media_controller.pause.assert_called_once_with()
|
||||
|
||||
# Media previous
|
||||
await common.async_media_previous_track(hass, entity_id)
|
||||
chromecast.media_controller.queue_prev.assert_not_called()
|
||||
|
||||
# Media next
|
||||
await common.async_media_next_track(hass, entity_id)
|
||||
chromecast.media_controller.queue_next.assert_not_called()
|
||||
|
||||
# Media seek
|
||||
await common.async_media_seek(hass, 123, entity_id)
|
||||
chromecast.media_controller.seek.assert_not_called()
|
||||
|
||||
# Enable support for queue and seek
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.supports_queue_next = True
|
||||
media_status.supports_seek = True
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Media previous
|
||||
await common.async_media_previous_track(hass, entity_id)
|
||||
chromecast.media_controller.queue_prev.assert_called_once_with()
|
||||
|
||||
# Media next
|
||||
await common.async_media_next_track(hass, entity_id)
|
||||
chromecast.media_controller.queue_next.assert_called_once_with()
|
||||
|
||||
# Media seek
|
||||
await common.async_media_seek(hass, 123, entity_id)
|
||||
chromecast.media_controller.seek.assert_called_once_with(123)
|
||||
|
||||
|
||||
async def test_entity_media_states(hass: HomeAssistantType):
|
||||
"""Test various entity media states."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.player_is_playing = True
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "playing"
|
||||
|
||||
media_status.player_is_playing = False
|
||||
media_status.player_is_paused = True
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "paused"
|
||||
|
||||
media_status.player_is_paused = False
|
||||
media_status.player_is_idle = True
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "idle"
|
||||
|
||||
media_status.player_is_idle = False
|
||||
chromecast.is_idle = True
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "off"
|
||||
|
||||
chromecast.is_idle = False
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "unknown"
|
||||
|
||||
|
||||
async def test_url_replace(hass: HomeAssistantType):
|
||||
"""Test functionality of replacing URL for HTTPS."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
entity._available = True
|
||||
entity.schedule_update_ha_state()
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity.unique_id == full_info.uuid
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
class FakeHTTPImage:
|
||||
url = "http://example.com/test.png"
|
||||
|
@ -439,112 +819,128 @@ async def test_url_replace(hass: HomeAssistantType):
|
|||
|
||||
media_status = MagicMock(images=[FakeHTTPImage()])
|
||||
media_status.player_is_playing = True
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get("entity_picture") == "//example.com/test.png"
|
||||
|
||||
media_status.images = [FakeHTTPSImage()]
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get("entity_picture") == "https://example.com/test.png"
|
||||
|
||||
|
||||
async def test_group_media_states(hass: HomeAssistantType):
|
||||
async def test_group_media_states(hass, mz_mock):
|
||||
"""Test media states are read from group if entity has no state."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, conn_status_cb, media_status_cb, group_media_status_cb = get_status_callbacks(
|
||||
chromecast, mz_mock
|
||||
)
|
||||
|
||||
entity._available = True
|
||||
entity.schedule_update_ha_state()
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity.unique_id == full_info.uuid
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
group_media_status = MagicMock(images=None)
|
||||
player_media_status = MagicMock(images=None)
|
||||
|
||||
# Player has no state, group is playing -> Should report 'playing'
|
||||
group_media_status.player_is_playing = True
|
||||
entity.multizone_new_media_status(str(FakeGroupUUID), group_media_status)
|
||||
group_media_status_cb(str(FakeGroupUUID), group_media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "playing"
|
||||
|
||||
# Player is paused, group is playing -> Should report 'paused'
|
||||
player_media_status.player_is_playing = False
|
||||
player_media_status.player_is_paused = True
|
||||
entity.new_media_status(player_media_status)
|
||||
media_status_cb(player_media_status)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "paused"
|
||||
|
||||
# Player is in unknown state, group is playing -> Should report 'playing'
|
||||
player_media_status.player_state = "UNKNOWN"
|
||||
entity.new_media_status(player_media_status)
|
||||
media_status_cb(player_media_status)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("media_player.speaker")
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "playing"
|
||||
|
||||
|
||||
async def test_group_media_control(hass: HomeAssistantType):
|
||||
async def test_group_media_control(hass, mz_mock):
|
||||
"""Test media states are read from group if entity has no state."""
|
||||
entity_id = "media_player.speaker"
|
||||
reg = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
full_info = attr.evolve(
|
||||
info, model_name="google home", friendly_name="Speaker", uuid=FakeUUID
|
||||
)
|
||||
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
|
||||
entity._available = True
|
||||
entity.async_write_ha_state()
|
||||
_, conn_status_cb, media_status_cb, group_media_status_cb = get_status_callbacks(
|
||||
chromecast, mz_mock
|
||||
)
|
||||
|
||||
state = hass.states.get("media_player.speaker")
|
||||
connection_status = MagicMock()
|
||||
connection_status.status = "CONNECTED"
|
||||
conn_status_cb(connection_status)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state is not None
|
||||
assert state.name == "Speaker"
|
||||
assert state.state == "unknown"
|
||||
assert entity.unique_id == full_info.uuid
|
||||
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
|
||||
|
||||
group_media_status = MagicMock(images=None)
|
||||
player_media_status = MagicMock(images=None)
|
||||
|
||||
# Player has no state, group is playing -> Should forward calls to group
|
||||
group_media_status.player_is_playing = True
|
||||
entity.multizone_new_media_status(str(FakeGroupUUID), group_media_status)
|
||||
entity.media_play()
|
||||
grp_media = entity.mz_mgr.get_multizone_mediacontroller(str(FakeGroupUUID))
|
||||
group_media_status_cb(str(FakeGroupUUID), group_media_status)
|
||||
await common.async_media_play(hass, entity_id)
|
||||
grp_media = mz_mock.get_multizone_mediacontroller(str(FakeGroupUUID))
|
||||
assert grp_media.play.called
|
||||
assert not chromecast.media_controller.play.called
|
||||
|
||||
# Player is paused, group is playing -> Should not forward
|
||||
player_media_status.player_is_playing = False
|
||||
player_media_status.player_is_paused = True
|
||||
entity.new_media_status(player_media_status)
|
||||
entity.media_pause()
|
||||
grp_media = entity.mz_mgr.get_multizone_mediacontroller(str(FakeGroupUUID))
|
||||
media_status_cb(player_media_status)
|
||||
await common.async_media_pause(hass, entity_id)
|
||||
grp_media = mz_mock.get_multizone_mediacontroller(str(FakeGroupUUID))
|
||||
assert not grp_media.pause.called
|
||||
assert chromecast.media_controller.pause.called
|
||||
|
||||
# Player is in unknown state, group is playing -> Should forward to group
|
||||
player_media_status.player_state = "UNKNOWN"
|
||||
entity.new_media_status(player_media_status)
|
||||
entity.media_stop()
|
||||
grp_media = entity.mz_mgr.get_multizone_mediacontroller(str(FakeGroupUUID))
|
||||
media_status_cb(player_media_status)
|
||||
await common.async_media_stop(hass, entity_id)
|
||||
grp_media = mz_mock.get_multizone_mediacontroller(str(FakeGroupUUID))
|
||||
assert grp_media.stop.called
|
||||
assert not chromecast.media_controller.stop.called
|
||||
|
||||
# Verify play_media is not forwarded
|
||||
entity.play_media(None, None)
|
||||
await common.async_play_media(hass, "music", "best.mp3", entity_id)
|
||||
assert not grp_media.play_media.called
|
||||
assert chromecast.media_controller.play_media.called
|
||||
|
||||
|
@ -552,27 +948,28 @@ async def test_group_media_control(hass: HomeAssistantType):
|
|||
async def test_failed_cast_on_idle(hass, caplog):
|
||||
"""Test no warning when unless player went idle with reason "ERROR"."""
|
||||
info = get_fake_chromecast_info()
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, _, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.player_is_idle = False
|
||||
media_status.idle_reason = "ERROR"
|
||||
media_status.content_id = "http://example.com:8123/tts.mp3"
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
assert "Failed to cast media" not in caplog.text
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.player_is_idle = True
|
||||
media_status.idle_reason = "Other"
|
||||
media_status.content_id = "http://example.com:8123/tts.mp3"
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
assert "Failed to cast media" not in caplog.text
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.player_is_idle = True
|
||||
media_status.idle_reason = "ERROR"
|
||||
media_status.content_id = "http://example.com:8123/tts.mp3"
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
assert "Failed to cast media http://example.com:8123/tts.mp3." in caplog.text
|
||||
|
||||
|
||||
|
@ -586,13 +983,14 @@ async def test_failed_cast_other_url(hass, caplog):
|
|||
)
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, _, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.player_is_idle = True
|
||||
media_status.idle_reason = "ERROR"
|
||||
media_status.content_id = "http://example.com:8123/tts.mp3"
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
assert "Failed to cast media http://example.com:8123/tts.mp3." in caplog.text
|
||||
|
||||
|
||||
|
@ -608,13 +1006,14 @@ async def test_failed_cast_internal_url(hass, caplog):
|
|||
)
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, _, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.player_is_idle = True
|
||||
media_status.idle_reason = "ERROR"
|
||||
media_status.content_id = "http://example.local:8123/tts.mp3"
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
assert (
|
||||
"Failed to cast media http://example.local:8123/tts.mp3 from internal_url"
|
||||
in caplog.text
|
||||
|
@ -635,13 +1034,14 @@ async def test_failed_cast_external_url(hass, caplog):
|
|||
)
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, _, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.player_is_idle = True
|
||||
media_status.idle_reason = "ERROR"
|
||||
media_status.content_id = "http://example.com:8123/tts.mp3"
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
assert (
|
||||
"Failed to cast media http://example.com:8123/tts.mp3 from external_url"
|
||||
in caplog.text
|
||||
|
@ -658,13 +1058,14 @@ async def test_failed_cast_tts_base_url(hass, caplog):
|
|||
)
|
||||
|
||||
info = get_fake_chromecast_info()
|
||||
chromecast, entity = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
_, _, media_status_cb = get_status_callbacks(chromecast)
|
||||
|
||||
media_status = MagicMock(images=None)
|
||||
media_status.player_is_idle = True
|
||||
media_status.idle_reason = "ERROR"
|
||||
media_status.content_id = "http://example.local:8123/tts.mp3"
|
||||
entity.new_media_status(media_status)
|
||||
media_status_cb(media_status)
|
||||
assert (
|
||||
"Failed to cast media http://example.local:8123/tts.mp3 from tts.base_url"
|
||||
in caplog.text
|
||||
|
@ -675,7 +1076,7 @@ async def test_disconnect_on_stop(hass: HomeAssistantType):
|
|||
"""Test cast device disconnects socket on stop."""
|
||||
info = get_fake_chromecast_info()
|
||||
|
||||
chromecast, _ = await async_setup_media_player_cast(hass, info)
|
||||
chromecast = await async_setup_media_player_cast(hass, info)
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
|
|
Loading…
Add table
Reference in a new issue