Add tests for Roku (#34380)
parent
3b12fd22a4
commit
b3eba49a2f
|
@ -596,8 +596,6 @@ omit =
|
|||
homeassistant/components/ring/camera.py
|
||||
homeassistant/components/ripple/sensor.py
|
||||
homeassistant/components/rocketchat/notify.py
|
||||
homeassistant/components/roku/__init__.py
|
||||
homeassistant/components/roku/media_player.py
|
||||
homeassistant/components/roku/remote.py
|
||||
homeassistant/components/roomba/vacuum.py
|
||||
homeassistant/components/route53/*
|
||||
|
|
|
@ -1,49 +1,59 @@
|
|||
"""Tests for the Roku component."""
|
||||
from requests_mock import Mocker
|
||||
|
||||
from homeassistant.components.roku.const import DOMAIN
|
||||
from homeassistant.const import CONF_HOST
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.common import MockConfigEntry, load_fixture
|
||||
|
||||
HOST = "1.2.3.4"
|
||||
HOST = "192.168.1.160"
|
||||
NAME = "Roku 3"
|
||||
SSDP_LOCATION = "http://1.2.3.4/"
|
||||
SSDP_LOCATION = "http://192.168.1.160/"
|
||||
UPNP_FRIENDLY_NAME = "My Roku 3"
|
||||
UPNP_SERIAL = "1GU48T017973"
|
||||
|
||||
|
||||
class MockDeviceInfo:
|
||||
"""Mock DeviceInfo for Roku."""
|
||||
def mock_connection(
|
||||
requests_mocker: Mocker, device: str = "roku3", app: str = "roku", host: str = HOST,
|
||||
) -> None:
|
||||
"""Mock the Roku connection."""
|
||||
roku_url = f"http://{host}:8060"
|
||||
|
||||
model_name = NAME
|
||||
model_num = "4200X"
|
||||
software_version = "7.5.0.09021"
|
||||
serial_num = UPNP_SERIAL
|
||||
user_device_name = UPNP_FRIENDLY_NAME
|
||||
roku_type = "Box"
|
||||
requests_mocker.get(
|
||||
f"{roku_url}/query/device-info",
|
||||
text=load_fixture(f"roku/{device}-device-info.xml"),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
"""Return the object representation of DeviceInfo."""
|
||||
return "<DeviceInfo: {}-{}, SW v{}, Ser# {} ({})>".format(
|
||||
self.model_name,
|
||||
self.model_num,
|
||||
self.software_version,
|
||||
self.serial_num,
|
||||
self.roku_type,
|
||||
)
|
||||
apps_fixture = "roku/apps.xml"
|
||||
if device == "rokutv":
|
||||
apps_fixture = "roku/apps-tv.xml"
|
||||
|
||||
requests_mocker.get(
|
||||
f"{roku_url}/query/apps", text=load_fixture(apps_fixture),
|
||||
)
|
||||
|
||||
requests_mocker.get(
|
||||
f"{roku_url}/query/active-app", text=load_fixture(f"roku/active-app-{app}.xml"),
|
||||
)
|
||||
|
||||
|
||||
async def setup_integration(
|
||||
hass: HomeAssistantType, skip_entry_setup: bool = False
|
||||
hass: HomeAssistantType,
|
||||
requests_mocker: Mocker,
|
||||
device: str = "roku3",
|
||||
app: str = "roku",
|
||||
host: str = HOST,
|
||||
unique_id: str = UPNP_SERIAL,
|
||||
skip_entry_setup: bool = False,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the Roku integration in Home Assistant."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN, unique_id=UPNP_SERIAL, data={CONF_HOST: HOST}
|
||||
)
|
||||
entry = MockConfigEntry(domain=DOMAIN, unique_id=unique_id, data={CONF_HOST: host})
|
||||
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
if not skip_entry_setup:
|
||||
mock_connection(requests_mocker, device, app=app, host=host)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
"""Test the Roku config flow."""
|
||||
from socket import gaierror as SocketGIAError
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from asynctest import patch
|
||||
from requests.exceptions import RequestException
|
||||
from requests_mock import Mocker
|
||||
from roku import RokuException
|
||||
|
||||
from homeassistant.components.roku.const import DOMAIN
|
||||
|
@ -27,91 +27,74 @@ from tests.components.roku import (
|
|||
SSDP_LOCATION,
|
||||
UPNP_FRIENDLY_NAME,
|
||||
UPNP_SERIAL,
|
||||
MockDeviceInfo,
|
||||
mock_connection,
|
||||
setup_integration,
|
||||
)
|
||||
|
||||
|
||||
async def async_configure_flow(
|
||||
hass: HomeAssistantType, flow_id: str, user_input: Optional[Dict] = None
|
||||
) -> Any:
|
||||
"""Set up mock Roku integration flow."""
|
||||
with patch(
|
||||
"homeassistant.components.roku.config_flow.Roku.device_info",
|
||||
new=MockDeviceInfo,
|
||||
):
|
||||
return await hass.config_entries.flow.async_configure(
|
||||
flow_id=flow_id, user_input=user_input
|
||||
)
|
||||
|
||||
|
||||
async def async_init_flow(
|
||||
hass: HomeAssistantType,
|
||||
handler: str = DOMAIN,
|
||||
context: Optional[Dict] = None,
|
||||
data: Any = None,
|
||||
) -> Any:
|
||||
"""Set up mock Roku integration flow."""
|
||||
with patch(
|
||||
"homeassistant.components.roku.config_flow.Roku.device_info",
|
||||
new=MockDeviceInfo,
|
||||
):
|
||||
return await hass.config_entries.flow.async_init(
|
||||
handler=handler, context=context, data=data
|
||||
)
|
||||
|
||||
|
||||
async def test_duplicate_error(hass: HomeAssistantType) -> None:
|
||||
async def test_duplicate_error(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test that errors are shown when duplicates are added."""
|
||||
await setup_integration(hass, skip_entry_setup=True)
|
||||
await setup_integration(hass, requests_mock, skip_entry_setup=True)
|
||||
|
||||
result = await async_init_flow(
|
||||
hass, context={CONF_SOURCE: SOURCE_IMPORT}, data={CONF_HOST: HOST}
|
||||
mock_connection(requests_mock)
|
||||
|
||||
user_input = {CONF_HOST: HOST}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={CONF_SOURCE: SOURCE_IMPORT}, data=user_input
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
result = await async_init_flow(
|
||||
hass, context={CONF_SOURCE: SOURCE_USER}, data={CONF_HOST: HOST}
|
||||
user_input = {CONF_HOST: HOST}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={CONF_SOURCE: SOURCE_USER}, data=user_input
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
result = await async_init_flow(
|
||||
hass,
|
||||
context={CONF_SOURCE: SOURCE_SSDP},
|
||||
data={
|
||||
ATTR_UPNP_FRIENDLY_NAME: UPNP_FRIENDLY_NAME,
|
||||
ATTR_SSDP_LOCATION: SSDP_LOCATION,
|
||||
ATTR_UPNP_SERIAL: UPNP_SERIAL,
|
||||
},
|
||||
discovery_info = {
|
||||
ATTR_UPNP_FRIENDLY_NAME: UPNP_FRIENDLY_NAME,
|
||||
ATTR_SSDP_LOCATION: SSDP_LOCATION,
|
||||
ATTR_UPNP_SERIAL: UPNP_SERIAL,
|
||||
}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={CONF_SOURCE: SOURCE_SSDP}, data=discovery_info
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_form(hass: HomeAssistantType) -> None:
|
||||
async def test_form(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test the user step."""
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
mock_connection(requests_mock)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={CONF_SOURCE: SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["errors"] == {}
|
||||
|
||||
user_input = {CONF_HOST: HOST}
|
||||
with patch(
|
||||
"homeassistant.components.roku.async_setup", return_value=True
|
||||
) as mock_setup, patch(
|
||||
"homeassistant.components.roku.async_setup_entry", return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await async_configure_flow(hass, result["flow_id"], {CONF_HOST: HOST})
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
flow_id=result["flow_id"], user_input=user_input
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == HOST
|
||||
assert result["data"] == {CONF_HOST: HOST}
|
||||
|
||||
assert result["data"]
|
||||
assert result["data"][CONF_HOST] == HOST
|
||||
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
@ -144,12 +127,13 @@ async def test_form_cannot_connect_request(hass: HomeAssistantType) -> None:
|
|||
DOMAIN, context={CONF_SOURCE: SOURCE_USER}
|
||||
)
|
||||
|
||||
user_input = {CONF_HOST: HOST}
|
||||
with patch(
|
||||
"homeassistant.components.roku.config_flow.Roku._call",
|
||||
side_effect=RequestException,
|
||||
) as mock_validate_input:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
flow_id=result["flow_id"], user_input={CONF_HOST: HOST}
|
||||
flow_id=result["flow_id"], user_input=user_input
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
|
@ -165,12 +149,13 @@ async def test_form_cannot_connect_socket(hass: HomeAssistantType) -> None:
|
|||
DOMAIN, context={CONF_SOURCE: SOURCE_USER}
|
||||
)
|
||||
|
||||
user_input = {CONF_HOST: HOST}
|
||||
with patch(
|
||||
"homeassistant.components.roku.config_flow.Roku._call",
|
||||
side_effect=SocketGIAError,
|
||||
) as mock_validate_input:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
flow_id=result["flow_id"], user_input={CONF_HOST: HOST}
|
||||
flow_id=result["flow_id"], user_input=user_input
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
|
@ -186,11 +171,12 @@ async def test_form_unknown_error(hass: HomeAssistantType) -> None:
|
|||
DOMAIN, context={CONF_SOURCE: SOURCE_USER}
|
||||
)
|
||||
|
||||
user_input = {CONF_HOST: HOST}
|
||||
with patch(
|
||||
"homeassistant.components.roku.config_flow.Roku._call", side_effect=Exception,
|
||||
) as mock_validate_input:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
flow_id=result["flow_id"], user_input={CONF_HOST: HOST}
|
||||
flow_id=result["flow_id"], user_input=user_input
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
|
@ -200,36 +186,42 @@ async def test_form_unknown_error(hass: HomeAssistantType) -> None:
|
|||
assert len(mock_validate_input.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_import(hass: HomeAssistantType) -> None:
|
||||
async def test_import(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test the import step."""
|
||||
mock_connection(requests_mock)
|
||||
|
||||
user_input = {CONF_HOST: HOST}
|
||||
with patch(
|
||||
"homeassistant.components.roku.async_setup", return_value=True
|
||||
) as mock_setup, patch(
|
||||
"homeassistant.components.roku.async_setup_entry", return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await async_init_flow(
|
||||
hass, context={CONF_SOURCE: SOURCE_IMPORT}, data={CONF_HOST: HOST}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={CONF_SOURCE: SOURCE_IMPORT}, data=user_input
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == HOST
|
||||
assert result["data"] == {CONF_HOST: HOST}
|
||||
|
||||
assert result["data"]
|
||||
assert result["data"][CONF_HOST] == HOST
|
||||
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_ssdp_discovery(hass: HomeAssistantType) -> None:
|
||||
async def test_ssdp_discovery(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test the ssdp discovery step."""
|
||||
mock_connection(requests_mock)
|
||||
|
||||
discovery_info = {
|
||||
ATTR_SSDP_LOCATION: SSDP_LOCATION,
|
||||
ATTR_UPNP_FRIENDLY_NAME: UPNP_FRIENDLY_NAME,
|
||||
ATTR_UPNP_SERIAL: UPNP_SERIAL,
|
||||
}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={CONF_SOURCE: SOURCE_SSDP},
|
||||
data={
|
||||
ATTR_SSDP_LOCATION: SSDP_LOCATION,
|
||||
ATTR_UPNP_FRIENDLY_NAME: UPNP_FRIENDLY_NAME,
|
||||
ATTR_UPNP_SERIAL: UPNP_SERIAL,
|
||||
},
|
||||
DOMAIN, context={CONF_SOURCE: SOURCE_SSDP}, data=discovery_info
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
|
@ -241,14 +233,17 @@ async def test_ssdp_discovery(hass: HomeAssistantType) -> None:
|
|||
) as mock_setup, patch(
|
||||
"homeassistant.components.roku.async_setup_entry", return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result = await async_configure_flow(hass, result["flow_id"], {})
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
flow_id=result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == UPNP_FRIENDLY_NAME
|
||||
assert result["data"] == {
|
||||
CONF_HOST: HOST,
|
||||
CONF_NAME: UPNP_FRIENDLY_NAME,
|
||||
}
|
||||
|
||||
assert result["data"]
|
||||
assert result["data"][CONF_HOST] == HOST
|
||||
assert result["data"][CONF_NAME] == UPNP_FRIENDLY_NAME
|
||||
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
|
|
@ -3,6 +3,7 @@ from socket import gaierror as SocketGIAError
|
|||
|
||||
from asynctest import patch
|
||||
from requests.exceptions import RequestException
|
||||
from requests_mock import Mocker
|
||||
from roku import RokuException
|
||||
|
||||
from homeassistant.components.roku.const import DOMAIN
|
||||
|
@ -13,50 +14,56 @@ from homeassistant.config_entries import (
|
|||
)
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from tests.components.roku import MockDeviceInfo, setup_integration
|
||||
from tests.components.roku import setup_integration
|
||||
|
||||
|
||||
async def test_config_entry_not_ready(hass: HomeAssistantType) -> None:
|
||||
async def test_config_entry_not_ready(
|
||||
hass: HomeAssistantType, requests_mock: Mocker
|
||||
) -> None:
|
||||
"""Test the Roku configuration entry not ready."""
|
||||
with patch(
|
||||
"homeassistant.components.roku.Roku._call", side_effect=RokuException,
|
||||
):
|
||||
entry = await setup_integration(hass)
|
||||
entry = await setup_integration(hass, requests_mock)
|
||||
|
||||
assert entry.state == ENTRY_STATE_SETUP_RETRY
|
||||
|
||||
|
||||
async def test_config_entry_not_ready_request(hass: HomeAssistantType) -> None:
|
||||
async def test_config_entry_not_ready_request(
|
||||
hass: HomeAssistantType, requests_mock: Mocker
|
||||
) -> None:
|
||||
"""Test the Roku configuration entry not ready."""
|
||||
with patch(
|
||||
"homeassistant.components.roku.Roku._call", side_effect=RequestException,
|
||||
):
|
||||
entry = await setup_integration(hass)
|
||||
entry = await setup_integration(hass, requests_mock)
|
||||
|
||||
assert entry.state == ENTRY_STATE_SETUP_RETRY
|
||||
|
||||
|
||||
async def test_config_entry_not_ready_socket(hass: HomeAssistantType) -> None:
|
||||
async def test_config_entry_not_ready_socket(
|
||||
hass: HomeAssistantType, requests_mock: Mocker
|
||||
) -> None:
|
||||
"""Test the Roku configuration entry not ready."""
|
||||
with patch(
|
||||
"homeassistant.components.roku.Roku._call", side_effect=SocketGIAError,
|
||||
):
|
||||
entry = await setup_integration(hass)
|
||||
entry = await setup_integration(hass, requests_mock)
|
||||
|
||||
assert entry.state == ENTRY_STATE_SETUP_RETRY
|
||||
|
||||
|
||||
async def test_unload_config_entry(hass: HomeAssistantType) -> None:
|
||||
async def test_unload_config_entry(
|
||||
hass: HomeAssistantType, requests_mock: Mocker
|
||||
) -> None:
|
||||
"""Test the Roku configuration entry unloading."""
|
||||
with patch(
|
||||
"homeassistant.components.roku.Roku.device_info", return_value=MockDeviceInfo,
|
||||
), patch(
|
||||
"homeassistant.components.roku.media_player.async_setup_entry",
|
||||
return_value=True,
|
||||
), patch(
|
||||
"homeassistant.components.roku.remote.async_setup_entry", return_value=True,
|
||||
):
|
||||
entry = await setup_integration(hass)
|
||||
entry = await setup_integration(hass, requests_mock)
|
||||
|
||||
assert hass.data[DOMAIN][entry.entry_id]
|
||||
assert entry.state == ENTRY_STATE_LOADED
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
"""Tests for the Roku Media Player platform."""
|
||||
from asynctest import patch
|
||||
from requests_mock import Mocker
|
||||
|
||||
from homeassistant.components.media_player.const import (
|
||||
ATTR_INPUT_SOURCE,
|
||||
ATTR_MEDIA_CONTENT_ID,
|
||||
ATTR_MEDIA_CONTENT_TYPE,
|
||||
ATTR_MEDIA_VOLUME_MUTED,
|
||||
DOMAIN as MP_DOMAIN,
|
||||
MEDIA_TYPE_CHANNEL,
|
||||
MEDIA_TYPE_MOVIE,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
SERVICE_SELECT_SOURCE,
|
||||
SUPPORT_NEXT_TRACK,
|
||||
SUPPORT_PLAY,
|
||||
SUPPORT_PLAY_MEDIA,
|
||||
SUPPORT_PREVIOUS_TRACK,
|
||||
SUPPORT_SELECT_SOURCE,
|
||||
SUPPORT_TURN_OFF,
|
||||
SUPPORT_TURN_ON,
|
||||
SUPPORT_VOLUME_MUTE,
|
||||
SUPPORT_VOLUME_SET,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_MEDIA_NEXT_TRACK,
|
||||
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
SERVICE_VOLUME_DOWN,
|
||||
SERVICE_VOLUME_MUTE,
|
||||
SERVICE_VOLUME_UP,
|
||||
STATE_PLAYING,
|
||||
)
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from tests.components.roku import UPNP_SERIAL, setup_integration
|
||||
|
||||
MAIN_ENTITY_ID = f"{MP_DOMAIN}.my_roku_3"
|
||||
TV_ENTITY_ID = f"{MP_DOMAIN}.58_onn_roku_tv"
|
||||
|
||||
TV_HOST = "192.168.1.161"
|
||||
TV_SERIAL = "YN00H5555555"
|
||||
|
||||
|
||||
async def test_setup(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test setup with basic config."""
|
||||
await setup_integration(hass, requests_mock)
|
||||
await setup_integration(
|
||||
hass,
|
||||
requests_mock,
|
||||
device="rokutv",
|
||||
app="tvinput-dtv",
|
||||
host=TV_HOST,
|
||||
unique_id=TV_SERIAL,
|
||||
)
|
||||
|
||||
entity_registry = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
main = entity_registry.async_get(MAIN_ENTITY_ID)
|
||||
assert hass.states.get(MAIN_ENTITY_ID)
|
||||
assert main.unique_id == UPNP_SERIAL
|
||||
|
||||
tv = entity_registry.async_get(TV_ENTITY_ID)
|
||||
assert hass.states.get(TV_ENTITY_ID)
|
||||
assert tv.unique_id == TV_SERIAL
|
||||
|
||||
|
||||
async def test_supported_features(
|
||||
hass: HomeAssistantType, requests_mock: Mocker
|
||||
) -> None:
|
||||
"""Test supported features."""
|
||||
await setup_integration(hass, requests_mock)
|
||||
|
||||
# Features supported for Rokus
|
||||
state = hass.states.get(MAIN_ENTITY_ID)
|
||||
assert (
|
||||
SUPPORT_PREVIOUS_TRACK
|
||||
| SUPPORT_NEXT_TRACK
|
||||
| SUPPORT_VOLUME_SET
|
||||
| SUPPORT_VOLUME_MUTE
|
||||
| SUPPORT_SELECT_SOURCE
|
||||
| SUPPORT_PLAY
|
||||
| SUPPORT_PLAY_MEDIA
|
||||
| SUPPORT_TURN_ON
|
||||
| SUPPORT_TURN_OFF
|
||||
== state.attributes.get("supported_features")
|
||||
)
|
||||
|
||||
|
||||
async def test_tv_supported_features(
|
||||
hass: HomeAssistantType, requests_mock: Mocker
|
||||
) -> None:
|
||||
"""Test supported features for Roku TV."""
|
||||
await setup_integration(
|
||||
hass,
|
||||
requests_mock,
|
||||
device="rokutv",
|
||||
app="tvinput-dtv",
|
||||
host=TV_HOST,
|
||||
unique_id=TV_SERIAL,
|
||||
)
|
||||
|
||||
state = hass.states.get(TV_ENTITY_ID)
|
||||
assert (
|
||||
SUPPORT_PREVIOUS_TRACK
|
||||
| SUPPORT_NEXT_TRACK
|
||||
| SUPPORT_VOLUME_SET
|
||||
| SUPPORT_VOLUME_MUTE
|
||||
| SUPPORT_SELECT_SOURCE
|
||||
| SUPPORT_PLAY
|
||||
| SUPPORT_PLAY_MEDIA
|
||||
| SUPPORT_TURN_ON
|
||||
| SUPPORT_TURN_OFF
|
||||
== state.attributes.get("supported_features")
|
||||
)
|
||||
|
||||
|
||||
async def test_attributes(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test attributes."""
|
||||
await setup_integration(hass, requests_mock)
|
||||
|
||||
state = hass.states.get(MAIN_ENTITY_ID)
|
||||
assert state.state == "home"
|
||||
|
||||
assert state.attributes.get(ATTR_MEDIA_CONTENT_TYPE) is None
|
||||
assert state.attributes.get(ATTR_INPUT_SOURCE) == "Roku"
|
||||
|
||||
|
||||
async def test_tv_attributes(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test attributes for Roku TV."""
|
||||
await setup_integration(
|
||||
hass,
|
||||
requests_mock,
|
||||
device="rokutv",
|
||||
app="tvinput-dtv",
|
||||
host=TV_HOST,
|
||||
unique_id=TV_SERIAL,
|
||||
)
|
||||
|
||||
state = hass.states.get(TV_ENTITY_ID)
|
||||
assert state.state == STATE_PLAYING
|
||||
|
||||
assert state.attributes.get(ATTR_MEDIA_CONTENT_TYPE) == MEDIA_TYPE_MOVIE
|
||||
assert state.attributes.get(ATTR_INPUT_SOURCE) == "Antenna TV"
|
||||
|
||||
|
||||
async def test_services(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test the different media player services."""
|
||||
await setup_integration(hass, requests_mock)
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: MAIN_ENTITY_ID}, blocking=True
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/keypress/PowerOff")
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: MAIN_ENTITY_ID}, blocking=True
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/keypress/PowerOn")
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_MEDIA_NEXT_TRACK,
|
||||
{ATTR_ENTITY_ID: MAIN_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/keypress/Fwd")
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||
{ATTR_ENTITY_ID: MAIN_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/keypress/Rev")
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_SELECT_SOURCE,
|
||||
{ATTR_ENTITY_ID: MAIN_ENTITY_ID, ATTR_INPUT_SOURCE: "Home"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/keypress/Home")
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_SELECT_SOURCE,
|
||||
{ATTR_ENTITY_ID: MAIN_ENTITY_ID, ATTR_INPUT_SOURCE: "Netflix"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/launch/12", params={"contentID": "12"})
|
||||
|
||||
|
||||
async def test_tv_services(hass: HomeAssistantType, requests_mock: Mocker) -> None:
|
||||
"""Test the media player services related to Roku TV."""
|
||||
await setup_integration(
|
||||
hass,
|
||||
requests_mock,
|
||||
device="rokutv",
|
||||
app="tvinput-dtv",
|
||||
host=TV_HOST,
|
||||
unique_id=TV_SERIAL,
|
||||
)
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN, SERVICE_VOLUME_UP, {ATTR_ENTITY_ID: TV_ENTITY_ID}, blocking=True
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/keypress/VolumeUp")
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_VOLUME_DOWN,
|
||||
{ATTR_ENTITY_ID: TV_ENTITY_ID},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/keypress/VolumeDown")
|
||||
|
||||
with patch("roku.Roku._post") as remote_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_VOLUME_MUTE,
|
||||
{ATTR_ENTITY_ID: TV_ENTITY_ID, ATTR_MEDIA_VOLUME_MUTED: True},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
remote_mock.assert_called_once_with("/keypress/VolumeMute")
|
||||
|
||||
with patch("roku.Roku.launch") as tune_mock:
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
{
|
||||
ATTR_ENTITY_ID: TV_ENTITY_ID,
|
||||
ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_CHANNEL,
|
||||
ATTR_MEDIA_CONTENT_ID: "55",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
tune_mock.assert_called_once()
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<active-app>
|
||||
<app id="12" type="appl" version="4.1.218">Netflix</app>
|
||||
</active-app>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<active-app>
|
||||
<app>Roku</app>
|
||||
</active-app>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<active-app>
|
||||
<app>Roku</app>
|
||||
<screensaver id="55545" type="ssvr" version="2.0.1">Default screensaver</screensaver>
|
||||
</active-app>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<active-app>
|
||||
<app id="tvinput.dtv" type="tvin" version="1.0.0">Antenna TV</app>
|
||||
</active-app>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<apps>
|
||||
<app id="tvinput.hdmi2" type="tvin" version="1.0.0">Satellite TV</app>
|
||||
<app id="tvinput.hdmi1" type="tvin" version="1.0.0">Blu-ray player</app>
|
||||
<app id="tvinput.dtv" type="tvin" version="1.0.0">Antenna TV</app>
|
||||
<app id="11">Roku Channel Store</app>
|
||||
<app id="12">Netflix</app>
|
||||
<app id="13">Amazon Video on Demand</app>
|
||||
<app id="14">MLB.TV®</app>
|
||||
<app id="26">Free FrameChannel Service</app>
|
||||
<app id="27">Mediafly</app>
|
||||
<app id="28">Pandora</app>
|
||||
</apps>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<apps>
|
||||
<app id="11">Roku Channel Store</app>
|
||||
<app id="12">Netflix</app>
|
||||
<app id="13">Amazon Video on Demand</app>
|
||||
<app id="14">MLB.TV®</app>
|
||||
<app id="26">Free FrameChannel Service</app>
|
||||
<app id="27">Mediafly</app>
|
||||
<app id="28">Pandora</app>
|
||||
</apps>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<device-info>
|
||||
<udn>015e5108-9000-1046-8035-b0a737964dfb</udn>
|
||||
<serial-number>1GU48T017973</serial-number>
|
||||
<device-id>1GU48T017973</device-id>
|
||||
<vendor-name>Roku</vendor-name>
|
||||
<model-number>4200X</model-number>
|
||||
<model-name>Roku 3</model-name>
|
||||
<model-region>US</model-region>
|
||||
<supports-ethernet>true</supports-ethernet>
|
||||
<wifi-mac>b0:a7:37:96:4d:fb</wifi-mac>
|
||||
<ethernet-mac>b0:a7:37:96:4d:fa</ethernet-mac>
|
||||
<network-type>ethernet</network-type>
|
||||
<user-device-name>My Roku 3</user-device-name>
|
||||
<software-version>7.5.0</software-version>
|
||||
<software-build>09021</software-build>
|
||||
<secure-device>true</secure-device>
|
||||
<language>en</language>
|
||||
<country>US</country>
|
||||
<locale>en_US</locale>
|
||||
<time-zone>US/Pacific</time-zone>
|
||||
<time-zone-offset>-480</time-zone-offset>
|
||||
<power-mode>PowerOn</power-mode>
|
||||
<supports-suspend>false</supports-suspend>
|
||||
<supports-find-remote>false</supports-find-remote>
|
||||
<supports-audio-guide>false</supports-audio-guide>
|
||||
<developer-enabled>true</developer-enabled>
|
||||
<keyed-developer-id>70f6ed9c90cf60718a26f3a7c3e5af1c3ec29558</keyed-developer-id>
|
||||
<search-enabled>true</search-enabled>
|
||||
<voice-search-enabled>true</voice-search-enabled>
|
||||
<notifications-enabled>true</notifications-enabled>
|
||||
<notifications-first-use>false</notifications-first-use>
|
||||
<supports-private-listening>false</supports-private-listening>
|
||||
<headphones-connected>false</headphones-connected>
|
||||
</device-info>
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<device-info>
|
||||
<udn>015e5555-9000-5555-5555-b0a555555dfb</udn>
|
||||
<serial-number>YN00H5555555</serial-number>
|
||||
<device-id>0S596H055555</device-id>
|
||||
<advertising-id>055555a9-d82b-5c75-b8fe-5555550cb7ee</advertising-id>
|
||||
<vendor-name>Onn</vendor-name>
|
||||
<model-name>100005844</model-name>
|
||||
<model-number>7820X</model-number>
|
||||
<model-region>US</model-region>
|
||||
<is-tv>true</is-tv>
|
||||
<is-stick>false</is-stick>
|
||||
<screen-size>58</screen-size>
|
||||
<panel-id>2</panel-id>
|
||||
<tuner-type>ATSC</tuner-type>
|
||||
<supports-ethernet>true</supports-ethernet>
|
||||
<wifi-mac>d8:13:99:f8:b0:c6</wifi-mac>
|
||||
<wifi-driver>realtek</wifi-driver>
|
||||
<ethernet-mac>d4:3a:2e:07:fd:cb</ethernet-mac>
|
||||
<network-type>wifi</network-type>
|
||||
<network-name>NetworkSSID</network-name>
|
||||
<friendly-device-name>58" Onn Roku TV</friendly-device-name>
|
||||
<friendly-model-name>Onn Roku TV</friendly-model-name>
|
||||
<default-device-name>Onn Roku TV - YN00H5555555</default-device-name>
|
||||
<user-device-name>58" Onn Roku TV</user-device-name>
|
||||
<user-device-location>Living room</user-device-location>
|
||||
<build-number>AT9.20E04502A</build-number>
|
||||
<software-version>9.2.0</software-version>
|
||||
<software-build>4502</software-build>
|
||||
<secure-device>true</secure-device>
|
||||
<language>en</language>
|
||||
<country>US</country>
|
||||
<locale>en_US</locale>
|
||||
<time-zone-auto>true</time-zone-auto>
|
||||
<time-zone>US/Central</time-zone>
|
||||
<time-zone-name>United States/Central</time-zone-name>
|
||||
<time-zone-tz>America/Chicago</time-zone-tz>
|
||||
<time-zone-offset>-300</time-zone-offset>
|
||||
<clock-format>12-hour</clock-format>
|
||||
<uptime>264789</uptime>
|
||||
<power-mode>PowerOn</power-mode>
|
||||
<supports-suspend>true</supports-suspend>
|
||||
<supports-find-remote>true</supports-find-remote>
|
||||
<find-remote-is-possible>false</find-remote-is-possible>
|
||||
<supports-audio-guide>true</supports-audio-guide>
|
||||
<supports-rva>true</supports-rva>
|
||||
<developer-enabled>false</developer-enabled>
|
||||
<keyed-developer-id/>
|
||||
<search-enabled>true</search-enabled>
|
||||
<search-channels-enabled>true</search-channels-enabled>
|
||||
<voice-search-enabled>true</voice-search-enabled>
|
||||
<notifications-enabled>true</notifications-enabled>
|
||||
<notifications-first-use>false</notifications-first-use>
|
||||
<supports-private-listening>true</supports-private-listening>
|
||||
<supports-private-listening-dtv>true</supports-private-listening-dtv>
|
||||
<supports-warm-standby>true</supports-warm-standby>
|
||||
<headphones-connected>false</headphones-connected>
|
||||
<expert-pq-enabled>0.9</expert-pq-enabled>
|
||||
<supports-ecs-textedit>true</supports-ecs-textedit>
|
||||
<supports-ecs-microphone>true</supports-ecs-microphone>
|
||||
<supports-wake-on-wlan>true</supports-wake-on-wlan>
|
||||
<has-play-on-roku>true</has-play-on-roku>
|
||||
<has-mobile-screensaver>true</has-mobile-screensaver>
|
||||
<support-url>https://www.onntvsupport.com/</support-url>
|
||||
<grandcentral-version>2.9.57</grandcentral-version>
|
||||
<trc-version>3.0</trc-version>
|
||||
<trc-channel-version>2.9.42</trc-channel-version>
|
||||
<davinci-version>2.8.20</davinci-version>
|
||||
<has-wifi-extender>false</has-wifi-extender>
|
||||
<has-wifi-5G-support>true</has-wifi-5G-support>
|
||||
<can-use-wifi-extender>true</can-use-wifi-extender>
|
||||
</device-info>
|
Loading…
Reference in New Issue