mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Add TRIGGERcmd integration (#121268)
* Initial commit with errors * Commitable * Use triggercmd user id as hub name * Validate the token * Use switch type, no trigger yet * Working integration * Use triggercmd module instead of httpx * Add tests for triggercmd integration * Add triggercmd to requirements_test_all.txt * Add untested triggercmd files to .coveragerc * Implement cgarwood's PR suggestions * Address PR feedback * Update homeassistant/components/triggercmd/config_flow.py Co-authored-by: Robert Resch <robert@resch.dev> * Update homeassistant/components/triggercmd/hub.py Co-authored-by: Robert Resch <robert@resch.dev> * Update homeassistant/components/triggercmd/strings.json Co-authored-by: Robert Resch <robert@resch.dev> * Update homeassistant/components/triggercmd/hub.py Co-authored-by: Robert Resch <robert@resch.dev> * Get user id via triggercmd module, and better check for status 200 code * PR feedback fixes * Update homeassistant/components/triggercmd/switch.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/triggercmd/switch.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * More PR feedback fixes * Update homeassistant/components/triggercmd/config_flow.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/triggercmd/strings.json Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/triggercmd/switch.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * More PR feedback fixes * Update tests/components/triggercmd/test_config_flow.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Changes for PR feedback * Changes to address PR comments * Fix connection error when no internet * Update homeassistant/components/triggercmd/__init__.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/triggercmd/config_flow.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/triggercmd/config_flow.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/triggercmd/config_flow.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update tests/components/triggercmd/test_config_flow.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Updates for PR feedback * Update tests/components/triggercmd/test_config_flow.py --------- Co-authored-by: Robert Resch <robert@resch.dev> Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
f42bc3aaae
commit
79f3e30fb6
@ -1540,6 +1540,8 @@ build.json @home-assistant/supervisor
|
|||||||
/tests/components/transmission/ @engrbm87 @JPHutchins
|
/tests/components/transmission/ @engrbm87 @JPHutchins
|
||||||
/homeassistant/components/trend/ @jpbede
|
/homeassistant/components/trend/ @jpbede
|
||||||
/tests/components/trend/ @jpbede
|
/tests/components/trend/ @jpbede
|
||||||
|
/homeassistant/components/triggercmd/ @rvmey
|
||||||
|
/tests/components/triggercmd/ @rvmey
|
||||||
/homeassistant/components/tts/ @home-assistant/core
|
/homeassistant/components/tts/ @home-assistant/core
|
||||||
/tests/components/tts/ @home-assistant/core
|
/tests/components/tts/ @home-assistant/core
|
||||||
/homeassistant/components/tuya/ @Tuya @zlinoliver @frenck
|
/homeassistant/components/tuya/ @Tuya @zlinoliver @frenck
|
||||||
|
36
homeassistant/components/triggercmd/__init__.py
Normal file
36
homeassistant/components/triggercmd/__init__.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"""The TRIGGERcmd component."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from triggercmd import client, ha
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import Platform
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
|
|
||||||
|
from .const import CONF_TOKEN
|
||||||
|
|
||||||
|
PLATFORMS = [
|
||||||
|
Platform.SWITCH,
|
||||||
|
]
|
||||||
|
|
||||||
|
type TriggercmdConfigEntry = ConfigEntry[ha.Hub]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, entry: TriggercmdConfigEntry) -> bool:
|
||||||
|
"""Set up TRIGGERcmd from a config entry."""
|
||||||
|
hub = ha.Hub(entry.data[CONF_TOKEN])
|
||||||
|
|
||||||
|
status_code = await client.async_connection_test(entry.data[CONF_TOKEN])
|
||||||
|
if status_code != 200:
|
||||||
|
raise ConfigEntryNotReady
|
||||||
|
|
||||||
|
entry.runtime_data = hub
|
||||||
|
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_unload_entry(hass: HomeAssistant, entry: TriggercmdConfigEntry) -> bool:
|
||||||
|
"""Unload a config entry."""
|
||||||
|
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
75
homeassistant/components/triggercmd/config_flow.py
Normal file
75
homeassistant/components/triggercmd/config_flow.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
"""Config flow for TRIGGERcmd integration."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import jwt
|
||||||
|
from triggercmd import TRIGGERcmdConnectionError, client
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
|
from .const import CONF_TOKEN, DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DATA_SCHEMA = vol.Schema({(CONF_TOKEN): str})
|
||||||
|
|
||||||
|
|
||||||
|
async def validate_input(hass: HomeAssistant, data: dict) -> str:
|
||||||
|
"""Validate the user input allows us to connect.
|
||||||
|
|
||||||
|
Data has the keys from DATA_SCHEMA with values provided by the user.
|
||||||
|
"""
|
||||||
|
if len(data[CONF_TOKEN]) < 100:
|
||||||
|
raise InvalidToken
|
||||||
|
|
||||||
|
token_data = jwt.decode(data[CONF_TOKEN], options={"verify_signature": False})
|
||||||
|
if not token_data["id"]:
|
||||||
|
raise InvalidToken
|
||||||
|
|
||||||
|
try:
|
||||||
|
await client.async_connection_test(data[CONF_TOKEN])
|
||||||
|
except Exception as e:
|
||||||
|
raise TRIGGERcmdConnectionError from e
|
||||||
|
else:
|
||||||
|
return token_data["id"]
|
||||||
|
|
||||||
|
|
||||||
|
class TriggerCMDConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||||
|
"""Handle a config flow."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
|
||||||
|
async def async_step_user(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> ConfigFlowResult:
|
||||||
|
"""Handle the initial step."""
|
||||||
|
errors = {}
|
||||||
|
if user_input is not None:
|
||||||
|
try:
|
||||||
|
identifier = await validate_input(self.hass, user_input)
|
||||||
|
except InvalidToken:
|
||||||
|
errors[CONF_TOKEN] = "invalid_token"
|
||||||
|
except TRIGGERcmdConnectionError:
|
||||||
|
errors["base"] = "connection_error"
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception("Unexpected exception")
|
||||||
|
errors["base"] = "unknown"
|
||||||
|
else:
|
||||||
|
await self.async_set_unique_id(identifier)
|
||||||
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
|
return self.async_create_entry(title="TRIGGERcmd Hub", data=user_input)
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="user", data_schema=DATA_SCHEMA, errors=errors
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidToken(HomeAssistantError):
|
||||||
|
"""Invalid token."""
|
4
homeassistant/components/triggercmd/const.py
Normal file
4
homeassistant/components/triggercmd/const.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
"""Constants for the TRIGGERcmd integration."""
|
||||||
|
|
||||||
|
DOMAIN = "triggercmd"
|
||||||
|
CONF_TOKEN = "token"
|
10
homeassistant/components/triggercmd/manifest.json
Normal file
10
homeassistant/components/triggercmd/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "triggercmd",
|
||||||
|
"name": "TRIGGERcmd",
|
||||||
|
"codeowners": ["@rvmey"],
|
||||||
|
"config_flow": true,
|
||||||
|
"documentation": "https://docs.triggercmd.com",
|
||||||
|
"integration_type": "hub",
|
||||||
|
"iot_class": "cloud_polling",
|
||||||
|
"requirements": ["triggercmd==0.0.27"]
|
||||||
|
}
|
22
homeassistant/components/triggercmd/strings.json
Normal file
22
homeassistant/components/triggercmd/strings.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"token": "[%key:common::config_flow::data::access_token%]"
|
||||||
|
},
|
||||||
|
"data_description": {
|
||||||
|
"token": "The token from the TRIGGERcmd instructions page"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
|
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||||
|
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||||
|
},
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
homeassistant/components/triggercmd/switch.py
Normal file
85
homeassistant/components/triggercmd/switch.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
"""Platform for switch integration."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from triggercmd import client, ha
|
||||||
|
|
||||||
|
from homeassistant.components.switch import SwitchEntity
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from . import TriggercmdConfigEntry
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: TriggercmdConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Add switch for passed config_entry in HA."""
|
||||||
|
hub = config_entry.runtime_data
|
||||||
|
async_add_entities(TRIGGERcmdSwitch(trigger) for trigger in hub.triggers)
|
||||||
|
|
||||||
|
|
||||||
|
class TRIGGERcmdSwitch(SwitchEntity):
|
||||||
|
"""Representation of a Switch."""
|
||||||
|
|
||||||
|
_attr_has_entity_name = True
|
||||||
|
_attr_assumed_state = True
|
||||||
|
_attr_should_poll = False
|
||||||
|
|
||||||
|
computer_id: str
|
||||||
|
trigger_id: str
|
||||||
|
firmware_version: str
|
||||||
|
model: str
|
||||||
|
hub: ha.Hub
|
||||||
|
|
||||||
|
def __init__(self, trigger: TRIGGERcmdSwitch) -> None:
|
||||||
|
"""Initialize the switch."""
|
||||||
|
self._switch = trigger
|
||||||
|
self._attr_is_on = False
|
||||||
|
self._attr_unique_id = f"{trigger.computer_id}.{trigger.trigger_id}"
|
||||||
|
self._attr_name = trigger.trigger_id
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, trigger.computer_id)},
|
||||||
|
name=trigger.computer_id.capitalize(),
|
||||||
|
sw_version=trigger.firmware_version,
|
||||||
|
model=trigger.model,
|
||||||
|
manufacturer=trigger.hub.manufacturer,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Return True if hub is available."""
|
||||||
|
return self._switch.hub.online
|
||||||
|
|
||||||
|
async def async_turn_on(self, **kwargs):
|
||||||
|
"""Turn the switch on."""
|
||||||
|
await self.trigger("on")
|
||||||
|
self._attr_is_on = True
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_turn_off(self, **kwargs):
|
||||||
|
"""Turn the switch off."""
|
||||||
|
await self.trigger("off")
|
||||||
|
self._attr_is_on = False
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def trigger(self, params: str):
|
||||||
|
"""Trigger the command."""
|
||||||
|
r = await client.async_trigger(
|
||||||
|
self._switch.hub.token,
|
||||||
|
{
|
||||||
|
"computer": self._switch.computer_id,
|
||||||
|
"trigger": self._switch.trigger_id,
|
||||||
|
"params": params,
|
||||||
|
"sender": "Home Assistant",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
_LOGGER.debug("TRIGGERcmd trigger response: %s", r.json())
|
@ -618,6 +618,7 @@ FLOWS = {
|
|||||||
"trafikverket_train",
|
"trafikverket_train",
|
||||||
"trafikverket_weatherstation",
|
"trafikverket_weatherstation",
|
||||||
"transmission",
|
"transmission",
|
||||||
|
"triggercmd",
|
||||||
"tuya",
|
"tuya",
|
||||||
"twentemilieu",
|
"twentemilieu",
|
||||||
"twilio",
|
"twilio",
|
||||||
|
@ -6460,6 +6460,12 @@
|
|||||||
"config_flow": false,
|
"config_flow": false,
|
||||||
"iot_class": "cloud_polling"
|
"iot_class": "cloud_polling"
|
||||||
},
|
},
|
||||||
|
"triggercmd": {
|
||||||
|
"name": "TRIGGERcmd",
|
||||||
|
"integration_type": "hub",
|
||||||
|
"config_flow": true,
|
||||||
|
"iot_class": "cloud_polling"
|
||||||
|
},
|
||||||
"tuya": {
|
"tuya": {
|
||||||
"name": "Tuya",
|
"name": "Tuya",
|
||||||
"integration_type": "hub",
|
"integration_type": "hub",
|
||||||
|
@ -2835,6 +2835,9 @@ tplink-omada-client==1.4.2
|
|||||||
# homeassistant.components.transmission
|
# homeassistant.components.transmission
|
||||||
transmission-rpc==7.0.3
|
transmission-rpc==7.0.3
|
||||||
|
|
||||||
|
# homeassistant.components.triggercmd
|
||||||
|
triggercmd==0.0.27
|
||||||
|
|
||||||
# homeassistant.components.twinkly
|
# homeassistant.components.twinkly
|
||||||
ttls==1.8.3
|
ttls==1.8.3
|
||||||
|
|
||||||
|
@ -2242,6 +2242,9 @@ tplink-omada-client==1.4.2
|
|||||||
# homeassistant.components.transmission
|
# homeassistant.components.transmission
|
||||||
transmission-rpc==7.0.3
|
transmission-rpc==7.0.3
|
||||||
|
|
||||||
|
# homeassistant.components.triggercmd
|
||||||
|
triggercmd==0.0.27
|
||||||
|
|
||||||
# homeassistant.components.twinkly
|
# homeassistant.components.twinkly
|
||||||
ttls==1.8.3
|
ttls==1.8.3
|
||||||
|
|
||||||
|
1
tests/components/triggercmd/__init__.py
Normal file
1
tests/components/triggercmd/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Tests for the triggercmd integration."""
|
15
tests/components/triggercmd/conftest.py
Normal file
15
tests/components/triggercmd/conftest.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
"""triggercmd conftest."""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_async_setup_entry():
|
||||||
|
"""Mock async_setup_entry."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.triggercmd.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_async_setup_entry:
|
||||||
|
yield mock_async_setup_entry
|
161
tests/components/triggercmd/test_config_flow.py
Normal file
161
tests/components/triggercmd/test_config_flow.py
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
"""Define tests for the triggercmd config flow."""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from triggercmd import TRIGGERcmdConnectionError
|
||||||
|
|
||||||
|
from homeassistant.components.triggercmd.const import CONF_TOKEN, DOMAIN
|
||||||
|
from homeassistant.config_entries import SOURCE_USER
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
invalid_token_with_length_100_or_more = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEyMzQ1Njc4OTBxd2VydHl1aW9wYXNkZiIsImlhdCI6MTcxOTg4MTU4M30.E4T2S4RQfuI2ww74sUkkT-wyTGrV5_VDkgUdae5yo4E"
|
||||||
|
invalid_token_id = "1234567890qwertyuiopasdf"
|
||||||
|
invalid_token_with_length_100_or_more_and_no_id = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub2lkIjoiMTIzNDU2Nzg5MHF3ZXJ0eXVpb3Bhc2RmIiwiaWF0IjoxNzE5ODgxNTgzfQ.MaJLNWPGCE51Zibhbq-Yz7h3GkUxLurR2eoM2frnO6Y"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_full_flow(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
) -> None:
|
||||||
|
"""Test config flow happy path."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_USER},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["errors"] == {}
|
||||||
|
assert result["step_id"] == "user"
|
||||||
|
assert result["type"] is FlowResultType.FORM
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.triggercmd.client.async_connection_test",
|
||||||
|
return_value=200,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.triggercmd.ha.Hub",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_TOKEN: invalid_token_with_length_100_or_more},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["data"] == {CONF_TOKEN: invalid_token_with_length_100_or_more}
|
||||||
|
assert result["result"].unique_id == invalid_token_id
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("test_input", "expected"),
|
||||||
|
[
|
||||||
|
(invalid_token_with_length_100_or_more_and_no_id, {"base": "unknown"}),
|
||||||
|
("not-a-token", {CONF_TOKEN: "invalid_token"}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_config_flow_user_invalid_token(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
test_input: str,
|
||||||
|
expected: dict,
|
||||||
|
) -> None:
|
||||||
|
"""Test the initial step of the config flow."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_USER},
|
||||||
|
)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.triggercmd.client.async_connection_test",
|
||||||
|
return_value=200,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.triggercmd.ha.Hub",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_TOKEN: test_input},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["errors"] == expected
|
||||||
|
assert result["step_id"] == "user"
|
||||||
|
assert result["type"] is FlowResultType.FORM
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_TOKEN: invalid_token_with_length_100_or_more},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
|
|
||||||
|
async def test_config_flow_entry_already_configured(hass: HomeAssistant) -> None:
|
||||||
|
"""Test user input for config_entry that already exists."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_USER},
|
||||||
|
)
|
||||||
|
|
||||||
|
MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={CONF_TOKEN: invalid_token_with_length_100_or_more},
|
||||||
|
unique_id=invalid_token_id,
|
||||||
|
).add_to_hass(hass)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.triggercmd.client.async_connection_test",
|
||||||
|
return_value=200,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_TOKEN: invalid_token_with_length_100_or_more},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["reason"] == "already_configured"
|
||||||
|
assert result["type"] is FlowResultType.ABORT
|
||||||
|
|
||||||
|
|
||||||
|
async def test_config_flow_connection_error(hass: HomeAssistant) -> None:
|
||||||
|
"""Test a connection error."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_USER},
|
||||||
|
)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.triggercmd.client.async_connection_test",
|
||||||
|
side_effect=TRIGGERcmdConnectionError,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_TOKEN: invalid_token_with_length_100_or_more},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["errors"] == {
|
||||||
|
"base": "connection_error",
|
||||||
|
}
|
||||||
|
assert result["type"] is FlowResultType.FORM
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.triggercmd.client.async_connection_test",
|
||||||
|
return_value=200,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.triggercmd.ha.Hub",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{CONF_TOKEN: invalid_token_with_length_100_or_more},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
Loading…
x
Reference in New Issue
Block a user