mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Add support for login credentials to homeworks (#122877)
* Add support for login credentials to homeworks * Store credentials in config entry data
This commit is contained in:
parent
718bc61c88
commit
f6f7459c36
@ -9,7 +9,12 @@ import logging
|
||||
from typing import Any
|
||||
|
||||
from pyhomeworks import exceptions as hw_exceptions
|
||||
from pyhomeworks.pyhomeworks import HW_BUTTON_PRESSED, HW_BUTTON_RELEASED, Homeworks
|
||||
from pyhomeworks.pyhomeworks import (
|
||||
HW_BUTTON_PRESSED,
|
||||
HW_BUTTON_RELEASED,
|
||||
HW_LOGIN_INCORRECT,
|
||||
Homeworks,
|
||||
)
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -17,7 +22,9 @@ from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_ID,
|
||||
CONF_NAME,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_USERNAME,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
Platform,
|
||||
)
|
||||
@ -137,12 +144,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
def hw_callback(msg_type: Any, values: Any) -> None:
|
||||
"""Dispatch state changes."""
|
||||
_LOGGER.debug("callback: %s, %s", msg_type, values)
|
||||
if msg_type == HW_LOGIN_INCORRECT:
|
||||
_LOGGER.debug("login incorrect")
|
||||
return
|
||||
addr = values[0]
|
||||
signal = f"homeworks_entity_{controller_id}_{addr}"
|
||||
dispatcher_send(hass, signal, msg_type, values)
|
||||
|
||||
config = entry.options
|
||||
controller = Homeworks(config[CONF_HOST], config[CONF_PORT], hw_callback)
|
||||
controller = Homeworks(
|
||||
config[CONF_HOST],
|
||||
config[CONF_PORT],
|
||||
hw_callback,
|
||||
entry.data.get(CONF_USERNAME),
|
||||
entry.data.get(CONF_PASSWORD),
|
||||
)
|
||||
try:
|
||||
await hass.async_add_executor_job(controller.connect)
|
||||
except hw_exceptions.HomeworksException as err:
|
||||
|
@ -14,7 +14,13 @@ from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAI
|
||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN
|
||||
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_USERNAME,
|
||||
)
|
||||
from homeassistant.core import async_get_hass, callback
|
||||
from homeassistant.data_entry_flow import AbortFlow
|
||||
from homeassistant.helpers import (
|
||||
@ -62,6 +68,10 @@ CONTROLLER_EDIT = {
|
||||
mode=selector.NumberSelectorMode.BOX,
|
||||
)
|
||||
),
|
||||
vol.Optional(CONF_USERNAME): selector.TextSelector(),
|
||||
vol.Optional(CONF_PASSWORD): selector.TextSelector(
|
||||
selector.TextSelectorConfig(type=selector.TextSelectorType.PASSWORD)
|
||||
),
|
||||
}
|
||||
|
||||
LIGHT_EDIT: VolDictType = {
|
||||
@ -92,10 +102,17 @@ BUTTON_EDIT: VolDictType = {
|
||||
validate_addr = cv.matches_regex(r"\[(?:\d\d:){2,4}\d\d\]")
|
||||
|
||||
|
||||
def _validate_credentials(user_input: dict[str, Any]) -> None:
|
||||
"""Validate credentials."""
|
||||
if CONF_PASSWORD in user_input and CONF_USERNAME not in user_input:
|
||||
raise SchemaFlowError("need_username_with_password")
|
||||
|
||||
|
||||
async def validate_add_controller(
|
||||
handler: ConfigFlow | SchemaOptionsFlowHandler, user_input: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Validate controller setup."""
|
||||
_validate_credentials(user_input)
|
||||
user_input[CONF_CONTROLLER_ID] = slugify(user_input[CONF_NAME])
|
||||
user_input[CONF_PORT] = int(user_input[CONF_PORT])
|
||||
try:
|
||||
@ -128,7 +145,13 @@ async def _try_connection(user_input: dict[str, Any]) -> None:
|
||||
_LOGGER.debug(
|
||||
"Trying to connect to %s:%s", user_input[CONF_HOST], user_input[CONF_PORT]
|
||||
)
|
||||
controller = Homeworks(host, port, lambda msg_types, values: None)
|
||||
controller = Homeworks(
|
||||
host,
|
||||
port,
|
||||
lambda msg_types, values: None,
|
||||
user_input.get(CONF_USERNAME),
|
||||
user_input.get(CONF_PASSWORD),
|
||||
)
|
||||
controller.connect()
|
||||
controller.close()
|
||||
|
||||
@ -138,7 +161,14 @@ async def _try_connection(user_input: dict[str, Any]) -> None:
|
||||
_try_connect, user_input[CONF_HOST], user_input[CONF_PORT]
|
||||
)
|
||||
except hw_exceptions.HomeworksConnectionFailed as err:
|
||||
_LOGGER.debug("Caught HomeworksConnectionFailed")
|
||||
raise SchemaFlowError("connection_error") from err
|
||||
except hw_exceptions.HomeworksInvalidCredentialsProvided as err:
|
||||
_LOGGER.debug("Caught HomeworksInvalidCredentialsProvided")
|
||||
raise SchemaFlowError("invalid_credentials") from err
|
||||
except hw_exceptions.HomeworksNoCredentialsProvided as err:
|
||||
_LOGGER.debug("Caught HomeworksNoCredentialsProvided")
|
||||
raise SchemaFlowError("credentials_needed") from err
|
||||
except Exception as err:
|
||||
_LOGGER.exception("Caught unexpected exception %s")
|
||||
raise SchemaFlowError("unknown_error") from err
|
||||
@ -529,6 +559,7 @@ class HomeworksConfigFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
self, user_input: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Validate controller setup."""
|
||||
_validate_credentials(user_input)
|
||||
user_input[CONF_PORT] = int(user_input[CONF_PORT])
|
||||
|
||||
our_entry = self.hass.config_entries.async_get_entry(self.context["entry_id"])
|
||||
@ -569,12 +600,19 @@ class HomeworksConfigFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
except SchemaFlowError as err:
|
||||
errors["base"] = str(err)
|
||||
else:
|
||||
password = user_input.pop(CONF_PASSWORD, None)
|
||||
username = user_input.pop(CONF_USERNAME, None)
|
||||
new_data = entry.data | {
|
||||
CONF_PASSWORD: password,
|
||||
CONF_USERNAME: username,
|
||||
}
|
||||
new_options = entry.options | {
|
||||
CONF_HOST: user_input[CONF_HOST],
|
||||
CONF_PORT: user_input[CONF_PORT],
|
||||
}
|
||||
return self.async_update_reload_and_abort(
|
||||
entry,
|
||||
data=new_data,
|
||||
options=new_options,
|
||||
reason="reconfigure_successful",
|
||||
reload_even_if_entry_is_unchanged=False,
|
||||
@ -603,8 +641,14 @@ class HomeworksConfigFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
{CONF_HOST: user_input[CONF_HOST], CONF_PORT: user_input[CONF_PORT]}
|
||||
)
|
||||
name = user_input.pop(CONF_NAME)
|
||||
password = user_input.pop(CONF_PASSWORD, None)
|
||||
username = user_input.pop(CONF_USERNAME, None)
|
||||
user_input |= {CONF_DIMMERS: [], CONF_KEYPADS: []}
|
||||
return self.async_create_entry(title=name, data={}, options=user_input)
|
||||
return self.async_create_entry(
|
||||
title=name,
|
||||
data={CONF_PASSWORD: password, CONF_USERNAME: username},
|
||||
options=user_input,
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
|
@ -2,8 +2,11 @@
|
||||
"config": {
|
||||
"error": {
|
||||
"connection_error": "Could not connect to the controller.",
|
||||
"credentials_needed": "The controller needs credentials.",
|
||||
"duplicated_controller_id": "The controller name is already in use.",
|
||||
"duplicated_host_port": "The specified host and port is already configured.",
|
||||
"invalid_credentials": "The provided credentials are not valid.",
|
||||
"need_username_with_password": "Credentials must be either a username and a password or only a username.",
|
||||
"unknown_error": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"step": {
|
||||
@ -22,7 +25,13 @@
|
||||
"reconfigure": {
|
||||
"data": {
|
||||
"host": "[%key:common::config_flow::data::host%]",
|
||||
"port": "[%key:common::config_flow::data::port%]"
|
||||
"port": "[%key:common::config_flow::data::port%]",
|
||||
"username": "[%key:common::config_flow::data::username%]",
|
||||
"password": "[%key:common::config_flow::data::password%]"
|
||||
},
|
||||
"data_description": {
|
||||
"password": "Optional password, leave blank if your system does not need credentials or only needs a single credential",
|
||||
"username": "Optional username, leave blank if your system does not need login credentials"
|
||||
},
|
||||
"description": "Modify a Lutron Homeworks controller connection settings"
|
||||
},
|
||||
@ -30,10 +39,14 @@
|
||||
"data": {
|
||||
"host": "[%key:common::config_flow::data::host%]",
|
||||
"name": "Controller name",
|
||||
"port": "[%key:common::config_flow::data::port%]"
|
||||
"port": "[%key:common::config_flow::data::port%]",
|
||||
"username": "[%key:common::config_flow::data::username%]",
|
||||
"password": "[%key:common::config_flow::data::password%]"
|
||||
},
|
||||
"data_description": {
|
||||
"name": "A unique name identifying the Lutron Homeworks controller"
|
||||
"name": "A unique name identifying the Lutron Homeworks controller",
|
||||
"password": "[%key:component::homeworks::config::step::reconfigure::data_description::password%]",
|
||||
"username": "[%key:component::homeworks::config::step::reconfigure::data_description::username%]"
|
||||
},
|
||||
"description": "Add a Lutron Homeworks controller"
|
||||
}
|
||||
|
@ -17,10 +17,55 @@ from homeassistant.components.homeworks.const import (
|
||||
CONF_RELEASE_DELAY,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_USERNAME,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
CONFIG_ENTRY_OPTIONS = {
|
||||
CONF_CONTROLLER_ID: "main_controller",
|
||||
CONF_HOST: "192.168.0.1",
|
||||
CONF_PORT: 1234,
|
||||
CONF_DIMMERS: [
|
||||
{
|
||||
CONF_ADDR: "[02:08:01:01]",
|
||||
CONF_NAME: "Foyer Sconces",
|
||||
CONF_RATE: 1.0,
|
||||
}
|
||||
],
|
||||
CONF_KEYPADS: [
|
||||
{
|
||||
CONF_ADDR: "[02:08:02:01]",
|
||||
CONF_NAME: "Foyer Keypad",
|
||||
CONF_BUTTONS: [
|
||||
{
|
||||
CONF_NAME: "Morning",
|
||||
CONF_NUMBER: 1,
|
||||
CONF_LED: True,
|
||||
CONF_RELEASE_DELAY: None,
|
||||
},
|
||||
{
|
||||
CONF_NAME: "Relax",
|
||||
CONF_NUMBER: 2,
|
||||
CONF_LED: True,
|
||||
CONF_RELEASE_DELAY: None,
|
||||
},
|
||||
{
|
||||
CONF_NAME: "Dim up",
|
||||
CONF_NUMBER: 3,
|
||||
CONF_LED: False,
|
||||
CONF_RELEASE_DELAY: 0.2,
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
@ -28,45 +73,19 @@ def mock_config_entry() -> MockConfigEntry:
|
||||
return MockConfigEntry(
|
||||
title="Lutron Homeworks",
|
||||
domain=DOMAIN,
|
||||
data={},
|
||||
options={
|
||||
CONF_CONTROLLER_ID: "main_controller",
|
||||
CONF_HOST: "192.168.0.1",
|
||||
CONF_PORT: 1234,
|
||||
CONF_DIMMERS: [
|
||||
{
|
||||
CONF_ADDR: "[02:08:01:01]",
|
||||
CONF_NAME: "Foyer Sconces",
|
||||
CONF_RATE: 1.0,
|
||||
}
|
||||
],
|
||||
CONF_KEYPADS: [
|
||||
{
|
||||
CONF_ADDR: "[02:08:02:01]",
|
||||
CONF_NAME: "Foyer Keypad",
|
||||
CONF_BUTTONS: [
|
||||
{
|
||||
CONF_NAME: "Morning",
|
||||
CONF_NUMBER: 1,
|
||||
CONF_LED: True,
|
||||
CONF_RELEASE_DELAY: None,
|
||||
},
|
||||
{
|
||||
CONF_NAME: "Relax",
|
||||
CONF_NUMBER: 2,
|
||||
CONF_LED: True,
|
||||
CONF_RELEASE_DELAY: None,
|
||||
},
|
||||
{
|
||||
CONF_NAME: "Dim up",
|
||||
CONF_NUMBER: 3,
|
||||
CONF_LED: False,
|
||||
CONF_RELEASE_DELAY: 0.2,
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
data={CONF_PASSWORD: None, CONF_USERNAME: None},
|
||||
options=CONFIG_ENTRY_OPTIONS,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry_username_password() -> MockConfigEntry:
|
||||
"""Return the default mocked config entry with credentials."""
|
||||
return MockConfigEntry(
|
||||
title="Lutron Homeworks",
|
||||
domain=DOMAIN,
|
||||
data={CONF_PASSWORD: "hunter2", CONF_USERNAME: "username"},
|
||||
options=CONFIG_ENTRY_OPTIONS,
|
||||
)
|
||||
|
||||
|
||||
|
@ -30,7 +30,7 @@ async def test_binary_sensor_attributes_state_update(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY)
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY, None, None)
|
||||
hw_callback = mock_homeworks.mock_calls[0][1][2]
|
||||
|
||||
assert entity_id in hass.states.async_entity_ids(BINARY_SENSOR_DOMAIN)
|
||||
|
@ -18,7 +18,13 @@ from homeassistant.components.homeworks.const import (
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.config_entries import SOURCE_RECONFIGURE, SOURCE_USER
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_USERNAME,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
@ -46,7 +52,7 @@ async def test_user_flow(
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Main controller"
|
||||
assert result["data"] == {}
|
||||
assert result["data"] == {"password": None, "username": None}
|
||||
assert result["options"] == {
|
||||
"controller_id": "main_controller",
|
||||
"dimmers": [],
|
||||
@ -54,11 +60,109 @@ async def test_user_flow(
|
||||
"keypads": [],
|
||||
"port": 1234,
|
||||
}
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY)
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY, None, None)
|
||||
mock_controller.close.assert_called_once_with()
|
||||
mock_controller.join.assert_not_called()
|
||||
|
||||
|
||||
async def test_user_flow_credentials(
|
||||
hass: HomeAssistant, mock_homeworks: MagicMock, mock_setup_entry
|
||||
) -> None:
|
||||
"""Test the user configuration flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
)
|
||||
|
||||
mock_controller = MagicMock()
|
||||
mock_homeworks.return_value = mock_controller
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_HOST: "192.168.0.1",
|
||||
CONF_NAME: "Main controller",
|
||||
CONF_PASSWORD: "hunter2",
|
||||
CONF_PORT: 1234,
|
||||
CONF_USERNAME: "username",
|
||||
},
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Main controller"
|
||||
assert result["data"] == {"password": "hunter2", "username": "username"}
|
||||
assert result["options"] == {
|
||||
"controller_id": "main_controller",
|
||||
"dimmers": [],
|
||||
"host": "192.168.0.1",
|
||||
"keypads": [],
|
||||
"port": 1234,
|
||||
}
|
||||
mock_homeworks.assert_called_once_with(
|
||||
"192.168.0.1", 1234, ANY, "username", "hunter2"
|
||||
)
|
||||
mock_controller.close.assert_called_once_with()
|
||||
mock_controller.join.assert_not_called()
|
||||
|
||||
|
||||
async def test_user_flow_credentials_user_only(
|
||||
hass: HomeAssistant, mock_homeworks: MagicMock, mock_setup_entry
|
||||
) -> None:
|
||||
"""Test the user configuration flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
)
|
||||
|
||||
mock_controller = MagicMock()
|
||||
mock_homeworks.return_value = mock_controller
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_HOST: "192.168.0.1",
|
||||
CONF_NAME: "Main controller",
|
||||
CONF_PORT: 1234,
|
||||
CONF_USERNAME: "username",
|
||||
},
|
||||
)
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Main controller"
|
||||
assert result["data"] == {"password": None, "username": "username"}
|
||||
assert result["options"] == {
|
||||
"controller_id": "main_controller",
|
||||
"dimmers": [],
|
||||
"host": "192.168.0.1",
|
||||
"keypads": [],
|
||||
"port": 1234,
|
||||
}
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY, "username", None)
|
||||
mock_controller.close.assert_called_once_with()
|
||||
mock_controller.join.assert_not_called()
|
||||
|
||||
|
||||
async def test_user_flow_credentials_password_only(
|
||||
hass: HomeAssistant, mock_homeworks: MagicMock, mock_setup_entry
|
||||
) -> None:
|
||||
"""Test the user configuration flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
)
|
||||
|
||||
mock_controller = MagicMock()
|
||||
mock_homeworks.return_value = mock_controller
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_HOST: "192.168.0.1",
|
||||
CONF_NAME: "Main controller",
|
||||
CONF_PASSWORD: "hunter2",
|
||||
CONF_PORT: 1234,
|
||||
},
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": "need_username_with_password"}
|
||||
|
||||
|
||||
async def test_user_flow_already_exists(
|
||||
hass: HomeAssistant, mock_empty_config_entry: MockConfigEntry, mock_setup_entry
|
||||
) -> None:
|
||||
@ -99,6 +203,8 @@ async def test_user_flow_already_exists(
|
||||
("side_effect", "error"),
|
||||
[
|
||||
(hw_exceptions.HomeworksConnectionFailed, "connection_error"),
|
||||
(hw_exceptions.HomeworksInvalidCredentialsProvided, "invalid_credentials"),
|
||||
(hw_exceptions.HomeworksNoCredentialsProvided, "credentials_needed"),
|
||||
(Exception, "unknown_error"),
|
||||
],
|
||||
)
|
||||
@ -270,6 +376,32 @@ async def test_reconfigure_flow_flow_no_change(
|
||||
}
|
||||
|
||||
|
||||
async def test_reconfigure_flow_credentials_password_only(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_homeworks: MagicMock
|
||||
) -> None:
|
||||
"""Test reconfigure flow."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_RECONFIGURE, "entry_id": mock_config_entry.entry_id},
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "reconfigure"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
CONF_HOST: "192.168.0.2",
|
||||
CONF_PASSWORD: "hunter2",
|
||||
CONF_PORT: 1234,
|
||||
},
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "reconfigure"
|
||||
assert result["errors"] == {"base": "need_username_with_password"}
|
||||
|
||||
|
||||
async def test_options_add_light_flow(
|
||||
hass: HomeAssistant,
|
||||
mock_empty_config_entry: MockConfigEntry,
|
||||
|
@ -3,7 +3,11 @@
|
||||
from unittest.mock import ANY, MagicMock
|
||||
|
||||
from pyhomeworks import exceptions as hw_exceptions
|
||||
from pyhomeworks.pyhomeworks import HW_BUTTON_PRESSED, HW_BUTTON_RELEASED
|
||||
from pyhomeworks.pyhomeworks import (
|
||||
HW_BUTTON_PRESSED,
|
||||
HW_BUTTON_RELEASED,
|
||||
HW_LOGIN_INCORRECT,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.homeworks import EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE
|
||||
@ -27,7 +31,7 @@ async def test_load_unload_config_entry(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY)
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY, None, None)
|
||||
|
||||
await hass.config_entries.async_unload(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -36,6 +40,51 @@ async def test_load_unload_config_entry(
|
||||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
|
||||
|
||||
async def test_load_config_entry_with_credentials(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry_username_password: MockConfigEntry,
|
||||
mock_homeworks: MagicMock,
|
||||
) -> None:
|
||||
"""Test the Homeworks configuration entry loading/unloading."""
|
||||
mock_config_entry_username_password.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry_username_password.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry_username_password.state is ConfigEntryState.LOADED
|
||||
mock_homeworks.assert_called_once_with(
|
||||
"192.168.0.1", 1234, ANY, "username", "hunter2"
|
||||
)
|
||||
|
||||
await hass.config_entries.async_unload(mock_config_entry_username_password.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert not hass.data.get(DOMAIN)
|
||||
assert mock_config_entry_username_password.state is ConfigEntryState.NOT_LOADED
|
||||
|
||||
|
||||
async def test_controller_credentials_changed(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry_username_password: MockConfigEntry,
|
||||
mock_homeworks: MagicMock,
|
||||
) -> None:
|
||||
"""Test controller credentials changed.
|
||||
|
||||
Note: This just ensures we don't blow up when credentials changed, in the future a
|
||||
reauth flow should be added.
|
||||
"""
|
||||
mock_config_entry_username_password.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry_username_password.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry_username_password.state is ConfigEntryState.LOADED
|
||||
mock_homeworks.assert_called_once_with(
|
||||
"192.168.0.1", 1234, ANY, "username", "hunter2"
|
||||
)
|
||||
hw_callback = mock_homeworks.mock_calls[0][1][2]
|
||||
|
||||
hw_callback(HW_LOGIN_INCORRECT, [])
|
||||
|
||||
|
||||
async def test_config_entry_not_ready(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
@ -66,7 +115,7 @@ async def test_keypad_events(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY)
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY, None, None)
|
||||
hw_callback = mock_homeworks.mock_calls[0][1][2]
|
||||
|
||||
hw_callback(HW_BUTTON_PRESSED, ["[02:08:02:01]", 1])
|
||||
@ -184,7 +233,7 @@ async def test_cleanup_on_ha_shutdown(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY)
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY, None, None)
|
||||
mock_controller.stop.assert_not_called()
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
|
@ -35,7 +35,7 @@ async def test_light_attributes_state_update(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY)
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY, None, None)
|
||||
hw_callback = mock_homeworks.mock_calls[0][1][2]
|
||||
|
||||
assert len(mock_controller.request_dimmer_level.mock_calls) == 1
|
||||
@ -106,7 +106,7 @@ async def test_light_restore_brightness(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY)
|
||||
mock_homeworks.assert_called_once_with("192.168.0.1", 1234, ANY, None, None)
|
||||
hw_callback = mock_homeworks.mock_calls[0][1][2]
|
||||
|
||||
assert hass.states.async_entity_ids("light") == unordered([entity_id])
|
||||
|
Loading…
x
Reference in New Issue
Block a user