Add Sky remote integration (#124507)
Co-authored-by: Kyle Cooke <saty9@users.noreply.github.com> Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
f6bc5f050e
commit
72b976f832
17 changed files with 530 additions and 5 deletions
|
@ -1344,6 +1344,8 @@ build.json @home-assistant/supervisor
|
|||
/tests/components/siren/ @home-assistant/core @raman325
|
||||
/homeassistant/components/sisyphus/ @jkeljo
|
||||
/homeassistant/components/sky_hub/ @rogerselwyn
|
||||
/homeassistant/components/sky_remote/ @dunnmj @saty9
|
||||
/tests/components/sky_remote/ @dunnmj @saty9
|
||||
/homeassistant/components/skybell/ @tkdrob
|
||||
/tests/components/skybell/ @tkdrob
|
||||
/homeassistant/components/slack/ @tkdrob @fletcherau
|
||||
|
|
5
homeassistant/brands/sky.json
Normal file
5
homeassistant/brands/sky.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"domain": "sky",
|
||||
"name": "Sky",
|
||||
"integrations": ["sky_hub", "sky_remote"]
|
||||
}
|
39
homeassistant/components/sky_remote/__init__.py
Normal file
39
homeassistant/components/sky_remote/__init__.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
"""The Sky Remote Control integration."""
|
||||
|
||||
import logging
|
||||
|
||||
from skyboxremote import RemoteControl, SkyBoxConnectionError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
|
||||
PLATFORMS = [Platform.REMOTE]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
type SkyRemoteConfigEntry = ConfigEntry[RemoteControl]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: SkyRemoteConfigEntry) -> bool:
|
||||
"""Set up Sky remote."""
|
||||
host = entry.data[CONF_HOST]
|
||||
port = entry.data[CONF_PORT]
|
||||
|
||||
_LOGGER.debug("Setting up Host: %s, Port: %s", host, port)
|
||||
remote = RemoteControl(host, port)
|
||||
try:
|
||||
await remote.check_connectable()
|
||||
except SkyBoxConnectionError as e:
|
||||
raise ConfigEntryNotReady from e
|
||||
|
||||
entry.runtime_data = remote
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
64
homeassistant/components/sky_remote/config_flow.py
Normal file
64
homeassistant/components/sky_remote/config_flow.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
"""Config flow for sky_remote."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from skyboxremote import RemoteControl, SkyBoxConnectionError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from .const import DEFAULT_PORT, DOMAIN, LEGACY_PORT
|
||||
|
||||
DATA_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def async_find_box_port(host: str) -> int:
|
||||
"""Find port box uses for communication."""
|
||||
logging.debug("Attempting to find port to connect to %s on", host)
|
||||
remote = RemoteControl(host, DEFAULT_PORT)
|
||||
try:
|
||||
await remote.check_connectable()
|
||||
except SkyBoxConnectionError:
|
||||
# Try legacy port if the default one failed
|
||||
remote = RemoteControl(host, LEGACY_PORT)
|
||||
await remote.check_connectable()
|
||||
return LEGACY_PORT
|
||||
return DEFAULT_PORT
|
||||
|
||||
|
||||
class SkyRemoteConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for Sky Remote."""
|
||||
|
||||
VERSION = 1
|
||||
MINOR_VERSION = 1
|
||||
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle the user step."""
|
||||
|
||||
errors: dict[str, str] = {}
|
||||
if user_input is not None:
|
||||
logging.debug("user_input: %s", user_input)
|
||||
self._async_abort_entries_match(user_input)
|
||||
try:
|
||||
port = await async_find_box_port(user_input[CONF_HOST])
|
||||
except SkyBoxConnectionError:
|
||||
logging.exception("while finding port of skybox")
|
||||
errors["base"] = "cannot_connect"
|
||||
else:
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_HOST],
|
||||
data={**user_input, CONF_PORT: port},
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user", data_schema=DATA_SCHEMA, errors=errors
|
||||
)
|
6
homeassistant/components/sky_remote/const.py
Normal file
6
homeassistant/components/sky_remote/const.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
"""Constants."""
|
||||
|
||||
DOMAIN = "sky_remote"
|
||||
|
||||
DEFAULT_PORT = 49160
|
||||
LEGACY_PORT = 5900
|
10
homeassistant/components/sky_remote/manifest.json
Normal file
10
homeassistant/components/sky_remote/manifest.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"domain": "sky_remote",
|
||||
"name": "Sky Remote Control",
|
||||
"codeowners": ["@dunnmj", "@saty9"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/sky_remote",
|
||||
"integration_type": "device",
|
||||
"iot_class": "assumed_state",
|
||||
"requirements": ["skyboxremote==0.0.6"]
|
||||
}
|
70
homeassistant/components/sky_remote/remote.py
Normal file
70
homeassistant/components/sky_remote/remote.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
"""Home Assistant integration to control a sky box using the remote platform."""
|
||||
|
||||
from collections.abc import Iterable
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from skyboxremote import VALID_KEYS, RemoteControl
|
||||
|
||||
from homeassistant.components.remote import RemoteEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import SkyRemoteConfigEntry
|
||||
from .const import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config: SkyRemoteConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the Sky remote platform."""
|
||||
async_add_entities(
|
||||
[SkyRemote(config.runtime_data, config.entry_id)],
|
||||
True,
|
||||
)
|
||||
|
||||
|
||||
class SkyRemote(RemoteEntity):
|
||||
"""Representation of a Sky Remote."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
_attr_name = None
|
||||
|
||||
def __init__(self, remote: RemoteControl, unique_id: str) -> None:
|
||||
"""Initialize the Sky Remote."""
|
||||
self._remote = remote
|
||||
self._attr_unique_id = unique_id
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, unique_id)},
|
||||
manufacturer="SKY",
|
||||
model="Sky Box",
|
||||
name=remote.host,
|
||||
)
|
||||
|
||||
def turn_on(self, activity: str | None = None, **kwargs: Any) -> None:
|
||||
"""Send the power on command."""
|
||||
self.send_command(["sky"])
|
||||
|
||||
def turn_off(self, activity: str | None = None, **kwargs: Any) -> None:
|
||||
"""Send the power command."""
|
||||
self.send_command(["power"])
|
||||
|
||||
def send_command(self, command: Iterable[str], **kwargs: Any) -> None:
|
||||
"""Send a list of commands to the device."""
|
||||
for cmd in command:
|
||||
if cmd not in VALID_KEYS:
|
||||
raise ServiceValidationError(
|
||||
f"{cmd} is not in Valid Keys: {VALID_KEYS}"
|
||||
)
|
||||
try:
|
||||
self._remote.send_keys(command)
|
||||
except ValueError as err:
|
||||
_LOGGER.error("Invalid command: %s. Error: %s", command, err)
|
||||
return
|
||||
_LOGGER.debug("Successfully sent command %s", command)
|
21
homeassistant/components/sky_remote/strings.json
Normal file
21
homeassistant/components/sky_remote/strings.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Add Sky Remote",
|
||||
"data": {
|
||||
"host": "[%key:common::config_flow::data::host%]"
|
||||
},
|
||||
"data_description": {
|
||||
"host": "Hostname or IP address of your Sky device"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -537,6 +537,7 @@ FLOWS = {
|
|||
"simplefin",
|
||||
"simplepush",
|
||||
"simplisafe",
|
||||
"sky_remote",
|
||||
"skybell",
|
||||
"slack",
|
||||
"sleepiq",
|
||||
|
|
|
@ -5608,11 +5608,22 @@
|
|||
"config_flow": false,
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
"sky_hub": {
|
||||
"name": "Sky Hub",
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling"
|
||||
"sky": {
|
||||
"name": "Sky",
|
||||
"integrations": {
|
||||
"sky_hub": {
|
||||
"integration_type": "hub",
|
||||
"config_flow": false,
|
||||
"iot_class": "local_polling",
|
||||
"name": "Sky Hub"
|
||||
},
|
||||
"sky_remote": {
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "assumed_state",
|
||||
"name": "Sky Remote Control"
|
||||
}
|
||||
}
|
||||
},
|
||||
"skybeacon": {
|
||||
"name": "Skybeacon",
|
||||
|
|
|
@ -2673,6 +2673,9 @@ simplisafe-python==2024.01.0
|
|||
# homeassistant.components.sisyphus
|
||||
sisyphus-control==3.1.4
|
||||
|
||||
# homeassistant.components.sky_remote
|
||||
skyboxremote==0.0.6
|
||||
|
||||
# homeassistant.components.slack
|
||||
slackclient==2.5.0
|
||||
|
||||
|
|
|
@ -2131,6 +2131,9 @@ simplepush==2.2.3
|
|||
# homeassistant.components.simplisafe
|
||||
simplisafe-python==2024.01.0
|
||||
|
||||
# homeassistant.components.sky_remote
|
||||
skyboxremote==0.0.6
|
||||
|
||||
# homeassistant.components.slack
|
||||
slackclient==2.5.0
|
||||
|
||||
|
|
13
tests/components/sky_remote/__init__.py
Normal file
13
tests/components/sky_remote/__init__.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
"""Tests for the Sky Remote component."""
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def setup_mock_entry(hass: HomeAssistant, entry: MockConfigEntry):
|
||||
"""Initialize a mock config entry."""
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
await hass.async_block_till_done()
|
47
tests/components/sky_remote/conftest.py
Normal file
47
tests/components/sky_remote/conftest.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
"""Test mocks and fixtures."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.sky_remote.const import DEFAULT_PORT, DOMAIN
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
SAMPLE_CONFIG = {CONF_HOST: "example.com", CONF_PORT: DEFAULT_PORT}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
"""Mock a config entry."""
|
||||
return MockConfigEntry(domain=DOMAIN, data=SAMPLE_CONFIG)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
"""Stub out setup function."""
|
||||
with patch(
|
||||
"homeassistant.components.sky_remote.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
yield mock_setup_entry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_remote_control(request: pytest.FixtureRequest) -> Generator[MagicMock]:
|
||||
"""Mock skyboxremote library."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.sky_remote.RemoteControl"
|
||||
) as mock_remote_control,
|
||||
patch(
|
||||
"homeassistant.components.sky_remote.config_flow.RemoteControl",
|
||||
mock_remote_control,
|
||||
),
|
||||
):
|
||||
mock_remote_control._instance_mock = MagicMock(host="example.com")
|
||||
mock_remote_control._instance_mock.check_connectable = AsyncMock(True)
|
||||
mock_remote_control.return_value = mock_remote_control._instance_mock
|
||||
yield mock_remote_control
|
125
tests/components/sky_remote/test_config_flow.py
Normal file
125
tests/components/sky_remote/test_config_flow.py
Normal file
|
@ -0,0 +1,125 @@
|
|||
"""Test the Sky Remote config flow."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
from skyboxremote import LEGACY_PORT, SkyBoxConnectionError
|
||||
|
||||
from homeassistant.components.sky_remote.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_USER
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
from .conftest import SAMPLE_CONFIG
|
||||
|
||||
|
||||
async def test_user_flow(
|
||||
hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_remote_control
|
||||
) -> None:
|
||||
"""Test we can setup an entry."""
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["step_id"] == "user"
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_HOST: SAMPLE_CONFIG[CONF_HOST]},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["data"] == SAMPLE_CONFIG
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_device_exists_abort(
|
||||
hass: HomeAssistant, mock_config_entry, mock_remote_control
|
||||
) -> None:
|
||||
"""Test we abort flow if device already configured."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
data={CONF_HOST: mock_config_entry.data[CONF_HOST]},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_remote_control", [LEGACY_PORT], indirect=True)
|
||||
async def test_user_flow_legacy_device(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_remote_control,
|
||||
) -> None:
|
||||
"""Test we can setup an entry with a legacy port."""
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["step_id"] == "user"
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
|
||||
async def mock_check_connectable():
|
||||
if mock_remote_control.call_args[0][1] == LEGACY_PORT:
|
||||
return True
|
||||
raise SkyBoxConnectionError("Wrong port")
|
||||
|
||||
mock_remote_control._instance_mock.check_connectable = mock_check_connectable
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_HOST: SAMPLE_CONFIG[CONF_HOST]},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["data"] == {**SAMPLE_CONFIG, CONF_PORT: LEGACY_PORT}
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mock_remote_control", [6], indirect=True)
|
||||
async def test_user_flow_unconnectable(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_remote_control,
|
||||
) -> None:
|
||||
"""Test we can setup an entry."""
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["step_id"] == "user"
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
|
||||
mock_remote_control._instance_mock.check_connectable = AsyncMock(
|
||||
side_effect=SkyBoxConnectionError("Example")
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_HOST: SAMPLE_CONFIG[CONF_HOST]},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {"base": "cannot_connect"}
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 0
|
||||
|
||||
mock_remote_control._instance_mock.check_connectable = AsyncMock(True)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_HOST: SAMPLE_CONFIG[CONF_HOST]},
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["data"] == SAMPLE_CONFIG
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
59
tests/components/sky_remote/test_init.py
Normal file
59
tests/components/sky_remote/test_init.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
"""Tests for the Sky Remote component."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from skyboxremote import SkyBoxConnectionError
|
||||
|
||||
from homeassistant.components.sky_remote.const import DEFAULT_PORT, DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
|
||||
from . import setup_mock_entry
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_remote_control,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
"""Test successful setup of entry."""
|
||||
await setup_mock_entry(hass, mock_config_entry)
|
||||
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
mock_remote_control.assert_called_once_with("example.com", DEFAULT_PORT)
|
||||
device_entry = device_registry.async_get_device(
|
||||
identifiers={(DOMAIN, mock_config_entry.entry_id)}
|
||||
)
|
||||
assert device_entry is not None
|
||||
assert device_entry.name == "example.com"
|
||||
|
||||
|
||||
async def test_setup_unconnectable_entry(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_remote_control,
|
||||
) -> None:
|
||||
"""Test unsuccessful setup of entry."""
|
||||
mock_remote_control._instance_mock.check_connectable = AsyncMock(
|
||||
side_effect=SkyBoxConnectionError()
|
||||
)
|
||||
|
||||
await setup_mock_entry(hass, mock_config_entry)
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_unload_entry(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_remote_control
|
||||
) -> None:
|
||||
"""Test unload an entry."""
|
||||
await setup_mock_entry(hass, mock_config_entry)
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
46
tests/components/sky_remote/test_remote.py
Normal file
46
tests/components/sky_remote/test_remote.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
"""Test sky_remote remote."""
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.remote import (
|
||||
ATTR_COMMAND,
|
||||
DOMAIN as REMOTE_DOMAIN,
|
||||
SERVICE_SEND_COMMAND,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ServiceValidationError
|
||||
|
||||
from . import setup_mock_entry
|
||||
|
||||
ENTITY_ID = "remote.example_com"
|
||||
|
||||
|
||||
async def test_send_command(
|
||||
hass: HomeAssistant, mock_config_entry, mock_remote_control
|
||||
) -> None:
|
||||
"""Test "send_command" method."""
|
||||
await setup_mock_entry(hass, mock_config_entry)
|
||||
await hass.services.async_call(
|
||||
REMOTE_DOMAIN,
|
||||
SERVICE_SEND_COMMAND,
|
||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_COMMAND: ["sky"]},
|
||||
blocking=True,
|
||||
)
|
||||
mock_remote_control._instance_mock.send_keys.assert_called_once_with(["sky"])
|
||||
|
||||
|
||||
async def test_send_invalid_command(
|
||||
hass: HomeAssistant, mock_config_entry, mock_remote_control
|
||||
) -> None:
|
||||
"""Test "send_command" method."""
|
||||
await setup_mock_entry(hass, mock_config_entry)
|
||||
|
||||
with pytest.raises(ServiceValidationError):
|
||||
await hass.services.async_call(
|
||||
REMOTE_DOMAIN,
|
||||
SERVICE_SEND_COMMAND,
|
||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_COMMAND: ["apple"]},
|
||||
blocking=True,
|
||||
)
|
||||
mock_remote_control._instance_mock.send_keys.assert_not_called()
|
Loading…
Add table
Reference in a new issue