mirror of https://github.com/home-assistant/core
165 lines
5.6 KiB
Python
165 lines
5.6 KiB
Python
"""The tests for the androidtv remote platform."""
|
|
|
|
from typing import Any
|
|
from unittest.mock import call, patch
|
|
|
|
from androidtv.constants import KEYS
|
|
import pytest
|
|
|
|
from homeassistant.components.androidtv.const import (
|
|
CONF_TURN_OFF_COMMAND,
|
|
CONF_TURN_ON_COMMAND,
|
|
)
|
|
from homeassistant.components.remote import (
|
|
ATTR_NUM_REPEATS,
|
|
DOMAIN as REMOTE_DOMAIN,
|
|
SERVICE_SEND_COMMAND,
|
|
)
|
|
from homeassistant.const import (
|
|
ATTR_COMMAND,
|
|
ATTR_ENTITY_ID,
|
|
SERVICE_TURN_OFF,
|
|
SERVICE_TURN_ON,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import ServiceValidationError
|
|
|
|
from . import patchers
|
|
from .common import (
|
|
CONFIG_ANDROID_DEFAULT,
|
|
CONFIG_FIRETV_DEFAULT,
|
|
SHELL_RESPONSE_OFF,
|
|
SHELL_RESPONSE_STANDBY,
|
|
setup_mock_entry,
|
|
)
|
|
|
|
from tests.common import MockConfigEntry
|
|
|
|
|
|
def _setup(config: dict[str, Any]) -> tuple[str, str, MockConfigEntry]:
|
|
"""Prepare mock entry for the media player tests."""
|
|
return setup_mock_entry(config, REMOTE_DOMAIN)
|
|
|
|
|
|
async def _test_service(
|
|
hass: HomeAssistant,
|
|
entity_id,
|
|
ha_service_name,
|
|
androidtv_method,
|
|
additional_service_data=None,
|
|
expected_call_args=None,
|
|
) -> None:
|
|
"""Test generic Android media player entity service."""
|
|
if expected_call_args is None:
|
|
expected_call_args = [None]
|
|
|
|
service_data = {ATTR_ENTITY_ID: entity_id}
|
|
if additional_service_data:
|
|
service_data.update(additional_service_data)
|
|
|
|
androidtv_patch = (
|
|
"androidtv.androidtv_async.AndroidTVAsync"
|
|
if "android" in entity_id
|
|
else "firetv.firetv_async.FireTVAsync"
|
|
)
|
|
with patch(f"androidtv.{androidtv_patch}.{androidtv_method}") as api_call:
|
|
await hass.services.async_call(
|
|
REMOTE_DOMAIN,
|
|
ha_service_name,
|
|
service_data=service_data,
|
|
blocking=True,
|
|
)
|
|
assert api_call.called
|
|
assert api_call.call_count == len(expected_call_args)
|
|
expected_calls = [call(s) if s else call() for s in expected_call_args]
|
|
assert api_call.call_args_list == expected_calls
|
|
|
|
|
|
@pytest.mark.parametrize("config", [CONFIG_ANDROID_DEFAULT, CONFIG_FIRETV_DEFAULT])
|
|
async def test_services_remote(hass: HomeAssistant, config) -> None:
|
|
"""Test services for remote entity."""
|
|
patch_key, entity_id, config_entry = _setup(config)
|
|
config_entry.add_to_hass(hass)
|
|
|
|
with patchers.patch_connect(True)[patch_key]:
|
|
with patchers.patch_shell(SHELL_RESPONSE_OFF)[patch_key]:
|
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
with (
|
|
patchers.patch_shell(SHELL_RESPONSE_STANDBY)[patch_key],
|
|
patchers.PATCH_SCREENCAP,
|
|
):
|
|
await _test_service(hass, entity_id, SERVICE_TURN_OFF, "turn_off")
|
|
await _test_service(hass, entity_id, SERVICE_TURN_ON, "turn_on")
|
|
await _test_service(
|
|
hass,
|
|
entity_id,
|
|
SERVICE_SEND_COMMAND,
|
|
"adb_shell",
|
|
{ATTR_COMMAND: ["BACK", "test"], ATTR_NUM_REPEATS: 2},
|
|
[
|
|
f"input keyevent {KEYS["BACK"]}",
|
|
"test",
|
|
f"input keyevent {KEYS["BACK"]}",
|
|
"test",
|
|
],
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("config", [CONFIG_ANDROID_DEFAULT, CONFIG_FIRETV_DEFAULT])
|
|
async def test_services_remote_custom(hass: HomeAssistant, config) -> None:
|
|
"""Test services with custom options for remote entity."""
|
|
patch_key, entity_id, config_entry = _setup(config)
|
|
config_entry.add_to_hass(hass)
|
|
hass.config_entries.async_update_entry(
|
|
config_entry,
|
|
options={
|
|
CONF_TURN_OFF_COMMAND: "test off",
|
|
CONF_TURN_ON_COMMAND: "test on",
|
|
},
|
|
)
|
|
|
|
with patchers.patch_connect(True)[patch_key]:
|
|
with patchers.patch_shell(SHELL_RESPONSE_OFF)[patch_key]:
|
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
with (
|
|
patchers.patch_shell(SHELL_RESPONSE_STANDBY)[patch_key],
|
|
patchers.PATCH_SCREENCAP,
|
|
):
|
|
await _test_service(
|
|
hass, entity_id, SERVICE_TURN_OFF, "adb_shell", None, ["test off"]
|
|
)
|
|
await _test_service(
|
|
hass, entity_id, SERVICE_TURN_ON, "adb_shell", None, ["test on"]
|
|
)
|
|
|
|
|
|
async def test_remote_unicode_decode_error(hass: HomeAssistant) -> None:
|
|
"""Test sending a command via the send_command remote service that raises a UnicodeDecodeError exception."""
|
|
patch_key, entity_id, config_entry = _setup(CONFIG_ANDROID_DEFAULT)
|
|
config_entry.add_to_hass(hass)
|
|
response = b"test response"
|
|
|
|
with patchers.patch_connect(True)[patch_key]:
|
|
with patchers.patch_shell(SHELL_RESPONSE_OFF)[patch_key]:
|
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
|
await hass.async_block_till_done()
|
|
|
|
with patch(
|
|
"androidtv.basetv.basetv_async.BaseTVAsync.adb_shell",
|
|
side_effect=UnicodeDecodeError("utf-8", response, 0, len(response), "TEST"),
|
|
) as api_call:
|
|
try:
|
|
await hass.services.async_call(
|
|
REMOTE_DOMAIN,
|
|
SERVICE_SEND_COMMAND,
|
|
service_data={ATTR_ENTITY_ID: entity_id, ATTR_COMMAND: "BACK"},
|
|
blocking=True,
|
|
)
|
|
pytest.fail("Exception not raised")
|
|
except ServiceValidationError:
|
|
assert api_call.call_count == 1
|