"""The tests for the LG webOS TV media player platform.""" from datetime import timedelta from http import HTTPStatus from aiowebostv import WebOsTvPairError from freezegun.api import FrozenDateTimeFactory import pytest from syrupy.assertion import SnapshotAssertion from syrupy.filters import props from homeassistant.components import automation from homeassistant.components.media_player import ( ATTR_INPUT_SOURCE, ATTR_INPUT_SOURCE_LIST, ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_CONTENT_TYPE, ATTR_MEDIA_TITLE, ATTR_MEDIA_VOLUME_LEVEL, ATTR_MEDIA_VOLUME_MUTED, DOMAIN as MP_DOMAIN, SERVICE_PLAY_MEDIA, SERVICE_SELECT_SOURCE, MediaPlayerEntityFeature, MediaPlayerState, MediaType, ) from homeassistant.components.webostv.const import ( ATTR_BUTTON, ATTR_PAYLOAD, ATTR_SOUND_OUTPUT, DOMAIN, LIVE_TV_APP_ID, SERVICE_BUTTON, SERVICE_COMMAND, SERVICE_SELECT_SOUND_OUTPUT, WebOsTvCommandError, ) from homeassistant.components.webostv.media_player import ( SUPPORT_WEBOSTV, SUPPORT_WEBOSTV_VOLUME, ) from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState from homeassistant.const import ( ATTR_COMMAND, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_CLIENT_SECRET, ENTITY_MATCH_NONE, SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF, SERVICE_VOLUME_DOWN, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_SET, SERVICE_VOLUME_UP, STATE_OFF, ) from homeassistant.core import HomeAssistant, State from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr from homeassistant.setup import async_setup_component from . import setup_webostv from .const import CHANNEL_2, ENTITY_ID, TV_NAME from tests.common import async_fire_time_changed, mock_restore_cache from tests.test_util.aiohttp import AiohttpClientMocker from tests.typing import ClientSessionGenerator @pytest.mark.parametrize( ("service", "attr_data", "client_call"), [ (SERVICE_VOLUME_MUTE, {ATTR_MEDIA_VOLUME_MUTED: True}, ("set_mute", True)), (SERVICE_VOLUME_MUTE, {ATTR_MEDIA_VOLUME_MUTED: False}, ("set_mute", False)), (SERVICE_VOLUME_SET, {ATTR_MEDIA_VOLUME_LEVEL: 1.00}, ("set_volume", 100)), (SERVICE_VOLUME_SET, {ATTR_MEDIA_VOLUME_LEVEL: 0.54}, ("set_volume", 54)), (SERVICE_VOLUME_SET, {ATTR_MEDIA_VOLUME_LEVEL: 0.0}, ("set_volume", 0)), ], ) async def test_services_with_parameters( hass: HomeAssistant, client, service, attr_data, client_call ) -> None: """Test services that has parameters in calls.""" await setup_webostv(hass) data = {ATTR_ENTITY_ID: ENTITY_ID, **attr_data} await hass.services.async_call(MP_DOMAIN, service, data, True) getattr(client, client_call[0]).assert_called_once_with(client_call[1]) @pytest.mark.parametrize( ("service", "client_call"), [ (SERVICE_TURN_OFF, "power_off"), (SERVICE_VOLUME_UP, "volume_up"), (SERVICE_VOLUME_DOWN, "volume_down"), (SERVICE_MEDIA_PLAY, "play"), (SERVICE_MEDIA_PAUSE, "pause"), (SERVICE_MEDIA_STOP, "stop"), ], ) async def test_services(hass: HomeAssistant, client, service, client_call) -> None: """Test simple services without parameters.""" await setup_webostv(hass) data = {ATTR_ENTITY_ID: ENTITY_ID} await hass.services.async_call(MP_DOMAIN, service, data, True) getattr(client, client_call).assert_called_once() async def test_media_play_pause(hass: HomeAssistant, client) -> None: """Test media play pause service.""" await setup_webostv(hass) data = {ATTR_ENTITY_ID: ENTITY_ID} # After init state is playing - check pause call await hass.services.async_call(MP_DOMAIN, SERVICE_MEDIA_PLAY_PAUSE, data, True) client.pause.assert_called_once() client.play.assert_not_called() # After pause state is paused - check play call await hass.services.async_call(MP_DOMAIN, SERVICE_MEDIA_PLAY_PAUSE, data, True) client.play.assert_called_once() client.pause.assert_called_once() @pytest.mark.parametrize( ("service", "client_call"), [ (SERVICE_MEDIA_NEXT_TRACK, ("fast_forward", "channel_up")), (SERVICE_MEDIA_PREVIOUS_TRACK, ("rewind", "channel_down")), ], ) async def test_media_next_previous_track( hass: HomeAssistant, client, service, client_call ) -> None: """Test media next/previous track services.""" await setup_webostv(hass) # check channel up/down for live TV channels data = {ATTR_ENTITY_ID: ENTITY_ID} await hass.services.async_call(MP_DOMAIN, service, data, True) getattr(client, client_call[0]).assert_not_called() getattr(client, client_call[1]).assert_called_once() # check next/previous for not Live TV channels client.tv_state.current_app_id = "in1" data = {ATTR_ENTITY_ID: ENTITY_ID} await hass.services.async_call(MP_DOMAIN, service, data, True) getattr(client, client_call[0]).assert_called_once() getattr(client, client_call[1]).assert_called_once() async def test_select_source_with_empty_source_list( hass: HomeAssistant, client ) -> None: """Ensure we don't call client methods when we don't have sources.""" await setup_webostv(hass) await client.mock_state_update() data = { ATTR_ENTITY_ID: ENTITY_ID, ATTR_INPUT_SOURCE: "nonexistent", } with pytest.raises( HomeAssistantError, match=f"Source nonexistent not found in the sources list for {TV_NAME}", ): await hass.services.async_call(MP_DOMAIN, SERVICE_SELECT_SOURCE, data, True) client.launch_app.assert_not_called() client.set_input.assert_not_called() async def test_select_app_source(hass: HomeAssistant, client) -> None: """Test select app source.""" await setup_webostv(hass) await client.mock_state_update() data = { ATTR_ENTITY_ID: ENTITY_ID, ATTR_INPUT_SOURCE: "Live TV", } await hass.services.async_call(MP_DOMAIN, SERVICE_SELECT_SOURCE, data, True) client.launch_app.assert_called_once_with(LIVE_TV_APP_ID) client.set_input.assert_not_called() async def test_select_input_source(hass: HomeAssistant, client) -> None: """Test select input source.""" await setup_webostv(hass) await client.mock_state_update() data = { ATTR_ENTITY_ID: ENTITY_ID, ATTR_INPUT_SOURCE: "Input01", } await hass.services.async_call(MP_DOMAIN, SERVICE_SELECT_SOURCE, data, True) client.launch_app.assert_not_called() client.set_input.assert_called_once_with("in1") async def test_button(hass: HomeAssistant, client) -> None: """Test generic button functionality.""" await setup_webostv(hass) data = { ATTR_ENTITY_ID: ENTITY_ID, ATTR_BUTTON: "test", } await hass.services.async_call(DOMAIN, SERVICE_BUTTON, data, True) await hass.async_block_till_done() client.button.assert_called_once() client.button.assert_called_with("test") async def test_command( hass: HomeAssistant, client, snapshot: SnapshotAssertion, ) -> None: """Test generic command functionality.""" await setup_webostv(hass) client.request.return_value = { "returnValue": True, "scenario": "mastervolume_tv_speaker_ext", "volume": 1, "muted": False, } data = { ATTR_ENTITY_ID: ENTITY_ID, ATTR_COMMAND: "audio/getVolume", } response = await hass.services.async_call( DOMAIN, SERVICE_COMMAND, data, True, return_response=True ) await hass.async_block_till_done() client.request.assert_called_with("audio/getVolume", payload=None) assert response == snapshot async def test_command_with_optional_arg(hass: HomeAssistant, client) -> None: """Test generic command functionality.""" await setup_webostv(hass) data = { ATTR_ENTITY_ID: ENTITY_ID, ATTR_COMMAND: "test", ATTR_PAYLOAD: {"target": "https://www.google.com"}, } await hass.services.async_call(DOMAIN, SERVICE_COMMAND, data, True) await hass.async_block_till_done() client.request.assert_called_with( "test", payload={"target": "https://www.google.com"} ) async def test_select_sound_output( hass: HomeAssistant, client, snapshot: SnapshotAssertion, ) -> None: """Test select sound output service.""" await setup_webostv(hass) client.change_sound_output.return_value = { "returnValue": True, "method": "setSystemSettings", } data = { ATTR_ENTITY_ID: ENTITY_ID, ATTR_SOUND_OUTPUT: "external_speaker", } response = await hass.services.async_call( DOMAIN, SERVICE_SELECT_SOUND_OUTPUT, data, True, return_response=True, ) await hass.async_block_till_done() client.change_sound_output.assert_called_once_with("external_speaker") assert response == snapshot async def test_device_info_startup_off( hass: HomeAssistant, client, device_registry: dr.DeviceRegistry ) -> None: """Test device info when device is off at startup.""" client.tv_info.system = {} client.tv_state.is_on = False entry = await setup_webostv(hass) await client.mock_state_update() assert hass.states.get(ENTITY_ID).state == STATE_OFF device = device_registry.async_get_device(identifiers={(DOMAIN, entry.unique_id)}) assert device assert device.identifiers == {(DOMAIN, entry.unique_id)} assert device.manufacturer == "LG" assert device.name == TV_NAME assert device.sw_version is None assert device.model is None async def test_entity_attributes( hass: HomeAssistant, client, device_registry: dr.DeviceRegistry, snapshot: SnapshotAssertion, ) -> None: """Test entity attributes.""" entry = await setup_webostv(hass) await client.mock_state_update() # Attributes when device is on state = hass.states.get(ENTITY_ID) assert state == snapshot(exclude=props("entity_picture")) # Volume level not available client.tv_state.volume = None await client.mock_state_update() attrs = hass.states.get(ENTITY_ID).attributes assert attrs.get(ATTR_MEDIA_VOLUME_LEVEL) is None # Channel change client.tv_state.current_channel = CHANNEL_2 await client.mock_state_update() attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_MEDIA_TITLE] == "Channel Name 2" # Device Info device = device_registry.async_get_device(identifiers={(DOMAIN, entry.unique_id)}) assert device == snapshot # Sound output when off client.tv_state.sound_output = None client.tv_state.is_on = False await client.mock_state_update() state = hass.states.get(ENTITY_ID) assert state.state == STATE_OFF assert state.attributes.get(ATTR_SOUND_OUTPUT) is None async def test_service_entity_id_none(hass: HomeAssistant, client) -> None: """Test service call with none as entity id.""" await setup_webostv(hass) data = { ATTR_ENTITY_ID: ENTITY_MATCH_NONE, ATTR_SOUND_OUTPUT: "external_speaker", } await hass.services.async_call(DOMAIN, SERVICE_SELECT_SOUND_OUTPUT, data, True) client.change_sound_output.assert_not_called() @pytest.mark.parametrize( ("media_id", "ch_id"), [ ("Channel 1", "ch1id"), # Perfect Match by channel name ("Name 2", "ch2id"), # Partial Match by channel name ("20", "ch2id"), # Perfect Match by channel number ], ) async def test_play_media(hass: HomeAssistant, client, media_id, ch_id) -> None: """Test play media service.""" await setup_webostv(hass) await client.mock_state_update() data = { ATTR_ENTITY_ID: ENTITY_ID, ATTR_MEDIA_CONTENT_TYPE: MediaType.CHANNEL, ATTR_MEDIA_CONTENT_ID: media_id, } await hass.services.async_call(MP_DOMAIN, SERVICE_PLAY_MEDIA, data, True) client.set_channel.assert_called_once_with(ch_id) async def test_update_sources_live_tv_find(hass: HomeAssistant, client) -> None: """Test finding live TV app id in update sources.""" await setup_webostv(hass) await client.mock_state_update() # Live TV found in app list sources = hass.states.get(ENTITY_ID).attributes[ATTR_INPUT_SOURCE_LIST] assert "Live TV" in sources assert len(sources) == 3 # Live TV is current app client.tv_state.apps = { LIVE_TV_APP_ID: { "title": "Live TV", "id": "some_id", }, } client.tv_state.current_app_id = "some_id" await client.mock_state_update() sources = hass.states.get(ENTITY_ID).attributes[ATTR_INPUT_SOURCE_LIST] assert "Live TV" in sources assert len(sources) == 3 # Live TV is is in inputs client.tv_state.inputs = { LIVE_TV_APP_ID: { "label": "Live TV", "id": "some_id", "appId": LIVE_TV_APP_ID, }, } await client.mock_state_update() sources = hass.states.get(ENTITY_ID).attributes[ATTR_INPUT_SOURCE_LIST] assert "Live TV" in sources assert len(sources) == 1 # Live TV is current input client.tv_state.inputs = { LIVE_TV_APP_ID: { "label": "Live TV", "id": "some_id", "appId": "some_id", }, } await client.mock_state_update() sources = hass.states.get(ENTITY_ID).attributes[ATTR_INPUT_SOURCE_LIST] assert "Live TV" in sources assert len(sources) == 1 # Live TV not found client.tv_state.current_app_id = "other_id" await client.mock_state_update() sources = hass.states.get(ENTITY_ID).attributes[ATTR_INPUT_SOURCE_LIST] assert "Live TV" in sources assert len(sources) == 1 # Live TV not found in sources/apps but is current app client.tv_state.apps = {} client.tv_state.current_app_id = LIVE_TV_APP_ID await client.mock_state_update() sources = hass.states.get(ENTITY_ID).attributes[ATTR_INPUT_SOURCE_LIST] assert "Live TV" in sources assert len(sources) == 1 # Bad update, keep old update client.tv_state.inputs = {} await client.mock_state_update() sources = hass.states.get(ENTITY_ID).attributes[ATTR_INPUT_SOURCE_LIST] assert "Live TV" in sources assert len(sources) == 1 async def test_client_disconnected( hass: HomeAssistant, client, caplog: pytest.LogCaptureFixture, freezer: FrozenDateTimeFactory, ) -> None: """Test error not raised when client is disconnected.""" await setup_webostv(hass) client.is_connected.return_value = False client.connect.side_effect = TimeoutError freezer.tick(timedelta(seconds=20)) async_fire_time_changed(hass) await hass.async_block_till_done() assert "TimeoutError" not in caplog.text async def test_client_key_update_on_connect( hass: HomeAssistant, client, freezer: FrozenDateTimeFactory ) -> None: """Test client key update upon connect.""" config_entry = await setup_webostv(hass) assert config_entry.data[CONF_CLIENT_SECRET] == client.client_key client.is_connected.return_value = False client.client_key = "new_key" freezer.tick(timedelta(seconds=20)) async_fire_time_changed(hass) await hass.async_block_till_done() assert config_entry.data[CONF_CLIENT_SECRET] == client.client_key @pytest.mark.parametrize( ("is_on", "exception", "error_message"), [ ( True, WebOsTvCommandError("Some error"), f"Communication error while calling async_media_play for device {TV_NAME}: Some error", ), ( True, WebOsTvCommandError("Some other error"), f"Communication error while calling async_media_play for device {TV_NAME}: Some other error", ), ( False, None, f"Error calling async_media_play for device {TV_NAME}: Device is off and cannot be controlled", ), ], ) async def test_control_error_handling( hass: HomeAssistant, client, is_on: bool, exception: Exception, error_message: str, ) -> None: """Test control errors handling.""" await setup_webostv(hass) client.play.side_effect = exception client.tv_state.is_on = is_on await client.mock_state_update() data = {ATTR_ENTITY_ID: ENTITY_ID} with pytest.raises(HomeAssistantError, match=error_message): await hass.services.async_call(MP_DOMAIN, SERVICE_MEDIA_PLAY, data, True) assert client.play.call_count == int(is_on) async def test_turn_off_when_device_is_off(hass: HomeAssistant, client) -> None: """Test no error when turning off device that is already off.""" await setup_webostv(hass) client.is_on = False await client.mock_state_update() data = {ATTR_ENTITY_ID: ENTITY_ID} await hass.services.async_call(MP_DOMAIN, SERVICE_TURN_OFF, data, True) assert client.power_off.call_count == 1 async def test_supported_features(hass: HomeAssistant, client) -> None: """Test test supported features.""" client.tv_state.sound_output = "lineout" await setup_webostv(hass) await client.mock_state_update() # No sound control support supported = SUPPORT_WEBOSTV attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported # Support volume mute, step client.tv_state.sound_output = "external_speaker" await client.mock_state_update() supported = supported | SUPPORT_WEBOSTV_VOLUME attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported # Support volume mute, step, set client.tv_state.sound_output = "speaker" await client.mock_state_update() supported = supported | SUPPORT_WEBOSTV_VOLUME | MediaPlayerEntityFeature.VOLUME_SET attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported # Support turn on assert await async_setup_component( hass, automation.DOMAIN, { automation.DOMAIN: [ { "trigger": { "platform": "webostv.turn_on", "entity_id": ENTITY_ID, }, "action": { "service": "test.automation", "data_template": { "some": ENTITY_ID, "id": "{{ trigger.id }}", }, }, }, ], }, ) supported |= MediaPlayerEntityFeature.TURN_ON await client.mock_state_update() attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported async def test_cached_supported_features(hass: HomeAssistant, client) -> None: """Test test supported features.""" client.tv_state.is_on = False client.tv_state.sound_output = None supported = ( SUPPORT_WEBOSTV | SUPPORT_WEBOSTV_VOLUME | MediaPlayerEntityFeature.TURN_ON ) mock_restore_cache( hass, [ State( ENTITY_ID, STATE_OFF, attributes={ ATTR_SUPPORTED_FEATURES: supported, }, ) ], ) await setup_webostv(hass) await client.mock_state_update() # TV off, restored state supports mute, step # validate MediaPlayerEntityFeature.TURN_ON is not cached attrs = hass.states.get(ENTITY_ID).attributes assert ( attrs[ATTR_SUPPORTED_FEATURES] == supported & ~MediaPlayerEntityFeature.TURN_ON ) # TV on, support volume mute, step client.tv_state.is_on = True client.tv_state.sound_output = "external_speaker" await client.mock_state_update() supported = SUPPORT_WEBOSTV | SUPPORT_WEBOSTV_VOLUME attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported # TV off, support volume mute, step client.tv_state.is_on = False client.tv_state.sound_output = None await client.mock_state_update() supported = SUPPORT_WEBOSTV | SUPPORT_WEBOSTV_VOLUME attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported # TV on, support volume mute, step, set client.tv_state.is_on = True client.tv_state.sound_output = "speaker" await client.mock_state_update() supported = ( SUPPORT_WEBOSTV | SUPPORT_WEBOSTV_VOLUME | MediaPlayerEntityFeature.VOLUME_SET ) attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported # TV off, support volume mute, step, set client.tv_state.is_on = False client.tv_state.sound_output = None await client.mock_state_update() supported = ( SUPPORT_WEBOSTV | SUPPORT_WEBOSTV_VOLUME | MediaPlayerEntityFeature.VOLUME_SET ) attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported # Test support turn on is updated on cached state assert await async_setup_component( hass, automation.DOMAIN, { automation.DOMAIN: [ { "trigger": { "platform": "webostv.turn_on", "entity_id": ENTITY_ID, }, "action": { "service": "test.automation", "data_template": { "some": ENTITY_ID, "id": "{{ trigger.id }}", }, }, }, ], }, ) await client.mock_state_update() attrs = hass.states.get(ENTITY_ID).attributes assert ( attrs[ATTR_SUPPORTED_FEATURES] == supported | MediaPlayerEntityFeature.TURN_ON ) async def test_supported_features_no_cache(hass: HomeAssistant, client) -> None: """Test supported features if device is off and no cache.""" client.tv_state.is_on = False client.tv_state.sound_output = None await setup_webostv(hass) supported = ( SUPPORT_WEBOSTV | SUPPORT_WEBOSTV_VOLUME | MediaPlayerEntityFeature.VOLUME_SET ) attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported async def test_supported_features_ignore_cache(hass: HomeAssistant, client) -> None: """Test ignore cached supported features if device is on at startup.""" mock_restore_cache( hass, [ State( ENTITY_ID, STATE_OFF, attributes={ ATTR_SUPPORTED_FEATURES: SUPPORT_WEBOSTV | SUPPORT_WEBOSTV_VOLUME, }, ) ], ) await setup_webostv(hass) supported = ( SUPPORT_WEBOSTV | SUPPORT_WEBOSTV_VOLUME | MediaPlayerEntityFeature.VOLUME_SET ) attrs = hass.states.get(ENTITY_ID).attributes assert attrs[ATTR_SUPPORTED_FEATURES] == supported async def test_get_image_http( hass: HomeAssistant, client, hass_client_no_auth: ClientSessionGenerator, aioclient_mock: AiohttpClientMocker, ) -> None: """Test get image via http.""" url = "http://something/valid_icon" client.tv_state.apps[LIVE_TV_APP_ID]["icon"] = url await setup_webostv(hass) await client.mock_state_update() attrs = hass.states.get(ENTITY_ID).attributes assert "entity_picture_local" not in attrs aioclient_mock.get(url, text="image") client = await hass_client_no_auth() resp = await client.get(attrs["entity_picture"]) content = await resp.read() assert content == b"image" async def test_get_image_http_error( hass: HomeAssistant, client, hass_client_no_auth: ClientSessionGenerator, aioclient_mock: AiohttpClientMocker, caplog: pytest.LogCaptureFixture, ) -> None: """Test get image via http error.""" url = "http://something/icon_error" client.tv_state.apps[LIVE_TV_APP_ID]["icon"] = url await setup_webostv(hass) await client.mock_state_update() attrs = hass.states.get(ENTITY_ID).attributes assert "entity_picture_local" not in attrs aioclient_mock.get(url, exc=TimeoutError()) client = await hass_client_no_auth() resp = await client.get(attrs["entity_picture"]) content = await resp.read() assert resp.status == HTTPStatus.INTERNAL_SERVER_ERROR assert f"Error retrieving proxied image from {url}" in caplog.text assert content == b"" async def test_get_image_https( hass: HomeAssistant, client, hass_client_no_auth: ClientSessionGenerator, aioclient_mock: AiohttpClientMocker, ) -> None: """Test get image via http.""" url = "https://something/valid_icon_https" client.tv_state.apps[LIVE_TV_APP_ID]["icon"] = url await setup_webostv(hass) await client.mock_state_update() attrs = hass.states.get(ENTITY_ID).attributes assert "entity_picture_local" not in attrs aioclient_mock.get(url, text="https_image") client = await hass_client_no_auth() resp = await client.get(attrs["entity_picture"]) content = await resp.read() assert content == b"https_image" async def test_reauth_reconnect( hass: HomeAssistant, client, freezer: FrozenDateTimeFactory ) -> None: """Test reauth flow triggered by reconnect.""" entry = await setup_webostv(hass) client.is_connected.return_value = False client.connect.side_effect = WebOsTvPairError assert entry.state is ConfigEntryState.LOADED freezer.tick(timedelta(seconds=20)) async_fire_time_changed(hass) await hass.async_block_till_done() assert entry.state is ConfigEntryState.LOADED flows = hass.config_entries.flow.async_progress() assert len(flows) == 1 flow = flows[0] assert flow.get("step_id") == "reauth_confirm" assert flow.get("handler") == DOMAIN assert "context" in flow assert flow["context"].get("source") == SOURCE_REAUTH assert flow["context"].get("entry_id") == entry.entry_id async def test_update_media_state(hass: HomeAssistant, client) -> None: """Test updating media state.""" await setup_webostv(hass) client.tv_state.media_state = [{"playState": "playing"}] await client.mock_state_update() assert hass.states.get(ENTITY_ID).state == MediaPlayerState.PLAYING client.tv_state.media_state = [{"playState": "paused"}] await client.mock_state_update() assert hass.states.get(ENTITY_ID).state == MediaPlayerState.PAUSED client.tv_state.media_state = [{"playState": "unloaded"}] await client.mock_state_update() assert hass.states.get(ENTITY_ID).state == MediaPlayerState.IDLE client.tv_state.is_on = False await client.mock_state_update() assert hass.states.get(ENTITY_ID).state == STATE_OFF