mirror of
https://github.com/home-assistant/core.git
synced 2025-04-26 18:27:51 +00:00
Add Komfovent (#95722)
* komfovent integration V1 * add dependency * integrate komfovent api * fix errors found in testing * tests for form handling * update deps * update coverage rc * add correct naming * minor feedback * pre-commit fixes * feedback fixes part 1 of 2 * feedback fixes part 2 of 2 * add hvac mode support * fix tests * address feedback * fix code coverage + PR feedback * PR feedback * use device name --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
787fb3b954
commit
f3cccf0a2b
@ -639,6 +639,8 @@ omit =
|
|||||||
homeassistant/components/kodi/browse_media.py
|
homeassistant/components/kodi/browse_media.py
|
||||||
homeassistant/components/kodi/media_player.py
|
homeassistant/components/kodi/media_player.py
|
||||||
homeassistant/components/kodi/notify.py
|
homeassistant/components/kodi/notify.py
|
||||||
|
homeassistant/components/komfovent/__init__.py
|
||||||
|
homeassistant/components/komfovent/climate.py
|
||||||
homeassistant/components/konnected/__init__.py
|
homeassistant/components/konnected/__init__.py
|
||||||
homeassistant/components/konnected/panel.py
|
homeassistant/components/konnected/panel.py
|
||||||
homeassistant/components/konnected/switch.py
|
homeassistant/components/konnected/switch.py
|
||||||
|
@ -664,6 +664,8 @@ build.json @home-assistant/supervisor
|
|||||||
/tests/components/knx/ @Julius2342 @farmio @marvin-w
|
/tests/components/knx/ @Julius2342 @farmio @marvin-w
|
||||||
/homeassistant/components/kodi/ @OnFreund
|
/homeassistant/components/kodi/ @OnFreund
|
||||||
/tests/components/kodi/ @OnFreund
|
/tests/components/kodi/ @OnFreund
|
||||||
|
/homeassistant/components/komfovent/ @ProstoSanja
|
||||||
|
/tests/components/komfovent/ @ProstoSanja
|
||||||
/homeassistant/components/konnected/ @heythisisnate
|
/homeassistant/components/konnected/ @heythisisnate
|
||||||
/tests/components/konnected/ @heythisisnate
|
/tests/components/konnected/ @heythisisnate
|
||||||
/homeassistant/components/kostal_plenticore/ @stegm
|
/homeassistant/components/kostal_plenticore/ @stegm
|
||||||
|
34
homeassistant/components/komfovent/__init__.py
Normal file
34
homeassistant/components/komfovent/__init__.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
"""The Komfovent integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import komfovent_api
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, Platform
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
PLATFORMS: list[Platform] = [Platform.CLIMATE]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
"""Set up Komfovent from a config entry."""
|
||||||
|
host = entry.data[CONF_HOST]
|
||||||
|
username = entry.data[CONF_USERNAME]
|
||||||
|
password = entry.data[CONF_PASSWORD]
|
||||||
|
_, credentials = komfovent_api.get_credentials(host, username, password)
|
||||||
|
result, settings = await komfovent_api.get_settings(credentials)
|
||||||
|
if result != komfovent_api.KomfoventConnectionResult.SUCCESS:
|
||||||
|
raise ConfigEntryNotReady(f"Unable to connect to {host}: {result}")
|
||||||
|
|
||||||
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = (credentials, settings)
|
||||||
|
|
||||||
|
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)
|
91
homeassistant/components/komfovent/climate.py
Normal file
91
homeassistant/components/komfovent/climate.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
"""Ventilation Units from Komfovent integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import komfovent_api
|
||||||
|
|
||||||
|
from homeassistant.components.climate import (
|
||||||
|
ClimateEntity,
|
||||||
|
ClimateEntityFeature,
|
||||||
|
HVACMode,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import UnitOfTemperature
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
HASS_TO_KOMFOVENT_MODES = {
|
||||||
|
HVACMode.COOL: komfovent_api.KomfoventModes.COOL,
|
||||||
|
HVACMode.HEAT_COOL: komfovent_api.KomfoventModes.HEAT_COOL,
|
||||||
|
HVACMode.OFF: komfovent_api.KomfoventModes.OFF,
|
||||||
|
HVACMode.AUTO: komfovent_api.KomfoventModes.AUTO,
|
||||||
|
}
|
||||||
|
KOMFOVENT_TO_HASS_MODES = {v: k for k, v in HASS_TO_KOMFOVENT_MODES.items()}
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up the Komfovent unit control."""
|
||||||
|
credentials, settings = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
async_add_entities([KomfoventDevice(credentials, settings)], True)
|
||||||
|
|
||||||
|
|
||||||
|
class KomfoventDevice(ClimateEntity):
|
||||||
|
"""Representation of a ventilation unit."""
|
||||||
|
|
||||||
|
_attr_hvac_modes = list(HASS_TO_KOMFOVENT_MODES.keys())
|
||||||
|
_attr_preset_modes = [mode.name for mode in komfovent_api.KomfoventPresets]
|
||||||
|
_attr_supported_features = ClimateEntityFeature.PRESET_MODE
|
||||||
|
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||||
|
_attr_has_entity_name = True
|
||||||
|
_attr_name = None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
credentials: komfovent_api.KomfoventCredentials,
|
||||||
|
settings: komfovent_api.KomfoventSettings,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the ventilation unit."""
|
||||||
|
self._komfovent_credentials = credentials
|
||||||
|
self._komfovent_settings = settings
|
||||||
|
|
||||||
|
self._attr_unique_id = settings.serial_number
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, settings.serial_number)},
|
||||||
|
model=settings.model,
|
||||||
|
name=settings.name,
|
||||||
|
serial_number=settings.serial_number,
|
||||||
|
sw_version=settings.version,
|
||||||
|
manufacturer="Komfovent",
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||||
|
"""Set new target preset mode."""
|
||||||
|
await komfovent_api.set_preset(
|
||||||
|
self._komfovent_credentials,
|
||||||
|
komfovent_api.KomfoventPresets[preset_mode],
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||||
|
"""Set new target hvac mode."""
|
||||||
|
await komfovent_api.set_mode(
|
||||||
|
self._komfovent_credentials, HASS_TO_KOMFOVENT_MODES[hvac_mode]
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_update(self) -> None:
|
||||||
|
"""Get the latest data."""
|
||||||
|
result, status = await komfovent_api.get_unit_status(
|
||||||
|
self._komfovent_credentials
|
||||||
|
)
|
||||||
|
if result != komfovent_api.KomfoventConnectionResult.SUCCESS or not status:
|
||||||
|
self._attr_available = False
|
||||||
|
return
|
||||||
|
self._attr_available = True
|
||||||
|
self._attr_preset_mode = status.preset
|
||||||
|
self._attr_current_temperature = status.temp_extract
|
||||||
|
self._attr_hvac_mode = KOMFOVENT_TO_HASS_MODES[status.mode]
|
74
homeassistant/components/komfovent/config_flow.py
Normal file
74
homeassistant/components/komfovent/config_flow.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
"""Config flow for Komfovent integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import komfovent_api
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
||||||
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
STEP_USER = "user"
|
||||||
|
STEP_USER_DATA_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_HOST): str,
|
||||||
|
vol.Optional(CONF_USERNAME, default="user"): str,
|
||||||
|
vol.Required(CONF_PASSWORD): str,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ERRORS_MAP = {
|
||||||
|
komfovent_api.KomfoventConnectionResult.NOT_FOUND: "cannot_connect",
|
||||||
|
komfovent_api.KomfoventConnectionResult.UNAUTHORISED: "invalid_auth",
|
||||||
|
komfovent_api.KomfoventConnectionResult.INVALID_INPUT: "invalid_input",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
"""Handle a config flow for Komfovent."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
|
||||||
|
def __return_error(
|
||||||
|
self, result: komfovent_api.KomfoventConnectionResult
|
||||||
|
) -> FlowResult:
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id=STEP_USER,
|
||||||
|
data_schema=STEP_USER_DATA_SCHEMA,
|
||||||
|
errors={"base": ERRORS_MAP.get(result, "unknown")},
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_step_user(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> FlowResult:
|
||||||
|
"""Handle the initial step."""
|
||||||
|
if user_input is None:
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id=STEP_USER, data_schema=STEP_USER_DATA_SCHEMA
|
||||||
|
)
|
||||||
|
|
||||||
|
conf_host = user_input[CONF_HOST]
|
||||||
|
conf_username = user_input[CONF_USERNAME]
|
||||||
|
conf_password = user_input[CONF_PASSWORD]
|
||||||
|
|
||||||
|
result, credentials = komfovent_api.get_credentials(
|
||||||
|
conf_host, conf_username, conf_password
|
||||||
|
)
|
||||||
|
if result != komfovent_api.KomfoventConnectionResult.SUCCESS:
|
||||||
|
return self.__return_error(result)
|
||||||
|
|
||||||
|
result, settings = await komfovent_api.get_settings(credentials)
|
||||||
|
if result != komfovent_api.KomfoventConnectionResult.SUCCESS:
|
||||||
|
return self.__return_error(result)
|
||||||
|
|
||||||
|
await self.async_set_unique_id(settings.serial_number)
|
||||||
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
|
return self.async_create_entry(title=settings.name, data=user_input)
|
3
homeassistant/components/komfovent/const.py
Normal file
3
homeassistant/components/komfovent/const.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"""Constants for the Komfovent integration."""
|
||||||
|
|
||||||
|
DOMAIN = "komfovent"
|
9
homeassistant/components/komfovent/manifest.json
Normal file
9
homeassistant/components/komfovent/manifest.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"domain": "komfovent",
|
||||||
|
"name": "Komfovent",
|
||||||
|
"codeowners": ["@ProstoSanja"],
|
||||||
|
"config_flow": true,
|
||||||
|
"documentation": "https://www.home-assistant.io/integrations/komfovent",
|
||||||
|
"iot_class": "local_polling",
|
||||||
|
"requirements": ["komfovent-api==0.0.3"]
|
||||||
|
}
|
22
homeassistant/components/komfovent/strings.json
Normal file
22
homeassistant/components/komfovent/strings.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"host": "[%key:common::config_flow::data::host%]",
|
||||||
|
"username": "[%key:common::config_flow::data::username%]",
|
||||||
|
"password": "[%key:common::config_flow::data::password%]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
|
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||||
|
"invalid_input": "Failed to parse provided hostname",
|
||||||
|
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||||
|
},
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -244,6 +244,7 @@ FLOWS = {
|
|||||||
"kmtronic",
|
"kmtronic",
|
||||||
"knx",
|
"knx",
|
||||||
"kodi",
|
"kodi",
|
||||||
|
"komfovent",
|
||||||
"konnected",
|
"konnected",
|
||||||
"kostal_plenticore",
|
"kostal_plenticore",
|
||||||
"kraken",
|
"kraken",
|
||||||
|
@ -2881,6 +2881,12 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"iot_class": "local_push"
|
"iot_class": "local_push"
|
||||||
},
|
},
|
||||||
|
"komfovent": {
|
||||||
|
"name": "Komfovent",
|
||||||
|
"integration_type": "hub",
|
||||||
|
"config_flow": true,
|
||||||
|
"iot_class": "local_polling"
|
||||||
|
},
|
||||||
"konnected": {
|
"konnected": {
|
||||||
"name": "Konnected.io",
|
"name": "Konnected.io",
|
||||||
"integration_type": "hub",
|
"integration_type": "hub",
|
||||||
|
@ -1127,6 +1127,9 @@ kiwiki-client==0.1.1
|
|||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
knx-frontend==2023.6.23.191712
|
knx-frontend==2023.6.23.191712
|
||||||
|
|
||||||
|
# homeassistant.components.komfovent
|
||||||
|
komfovent-api==0.0.3
|
||||||
|
|
||||||
# homeassistant.components.konnected
|
# homeassistant.components.konnected
|
||||||
konnected==1.2.0
|
konnected==1.2.0
|
||||||
|
|
||||||
|
@ -886,6 +886,9 @@ kegtron-ble==0.4.0
|
|||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
knx-frontend==2023.6.23.191712
|
knx-frontend==2023.6.23.191712
|
||||||
|
|
||||||
|
# homeassistant.components.komfovent
|
||||||
|
komfovent-api==0.0.3
|
||||||
|
|
||||||
# homeassistant.components.konnected
|
# homeassistant.components.konnected
|
||||||
konnected==1.2.0
|
konnected==1.2.0
|
||||||
|
|
||||||
|
1
tests/components/komfovent/__init__.py
Normal file
1
tests/components/komfovent/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Tests for the Komfovent integration."""
|
14
tests/components/komfovent/conftest.py
Normal file
14
tests/components/komfovent/conftest.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
"""Common fixtures for the Komfovent tests."""
|
||||||
|
from collections.abc import Generator
|
||||||
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_setup_entry() -> Generator[AsyncMock, None, None]:
|
||||||
|
"""Override async_setup_entry."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.komfovent.async_setup_entry", return_value=True
|
||||||
|
) as mock_setup_entry:
|
||||||
|
yield mock_setup_entry
|
189
tests/components/komfovent/test_config_flow.py
Normal file
189
tests/components/komfovent/test_config_flow.py
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
"""Test the Komfovent config flow."""
|
||||||
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
|
import komfovent_api
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.components.komfovent.const import DOMAIN
|
||||||
|
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.data_entry_flow import FlowResult, FlowResultType
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None:
|
||||||
|
"""Test flow completes as expected."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result["type"] == FlowResultType.FORM
|
||||||
|
assert result["errors"] is None
|
||||||
|
|
||||||
|
final_result = await __test_normal_flow(hass, result["flow_id"])
|
||||||
|
assert final_result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert final_result["title"] == "test-name"
|
||||||
|
assert final_result["data"] == {
|
||||||
|
CONF_HOST: "1.1.1.1",
|
||||||
|
CONF_USERNAME: "test-username",
|
||||||
|
CONF_PASSWORD: "test-password",
|
||||||
|
}
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("error", "expected_response"),
|
||||||
|
[
|
||||||
|
(komfovent_api.KomfoventConnectionResult.NOT_FOUND, "cannot_connect"),
|
||||||
|
(komfovent_api.KomfoventConnectionResult.UNAUTHORISED, "invalid_auth"),
|
||||||
|
(komfovent_api.KomfoventConnectionResult.INVALID_INPUT, "invalid_input"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_flow_error_authenticating(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_setup_entry: AsyncMock,
|
||||||
|
error: komfovent_api.KomfoventConnectionResult,
|
||||||
|
expected_response: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test errors during flow authentication step are handled and dont affect final result."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.komfovent.config_flow.komfovent_api.get_credentials",
|
||||||
|
return_value=(
|
||||||
|
error,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
CONF_HOST: "1.1.1.1",
|
||||||
|
CONF_USERNAME: "test-username",
|
||||||
|
CONF_PASSWORD: "test-password",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == FlowResultType.FORM
|
||||||
|
assert result2["errors"] == {"base": expected_response}
|
||||||
|
|
||||||
|
final_result = await __test_normal_flow(hass, result2["flow_id"])
|
||||||
|
assert final_result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert final_result["title"] == "test-name"
|
||||||
|
assert final_result["data"] == {
|
||||||
|
CONF_HOST: "1.1.1.1",
|
||||||
|
CONF_USERNAME: "test-username",
|
||||||
|
CONF_PASSWORD: "test-password",
|
||||||
|
}
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("error", "expected_response"),
|
||||||
|
[
|
||||||
|
(komfovent_api.KomfoventConnectionResult.NOT_FOUND, "cannot_connect"),
|
||||||
|
(komfovent_api.KomfoventConnectionResult.UNAUTHORISED, "invalid_auth"),
|
||||||
|
(komfovent_api.KomfoventConnectionResult.INVALID_INPUT, "invalid_input"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_flow_error_device_info(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_setup_entry: AsyncMock,
|
||||||
|
error: komfovent_api.KomfoventConnectionResult,
|
||||||
|
expected_response: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test errors during flow device info download step are handled and dont affect final result."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.komfovent.config_flow.komfovent_api.get_credentials",
|
||||||
|
return_value=(
|
||||||
|
komfovent_api.KomfoventConnectionResult.SUCCESS,
|
||||||
|
komfovent_api.KomfoventCredentials("1.1.1.1", "user", "pass"),
|
||||||
|
),
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.komfovent.config_flow.komfovent_api.get_settings",
|
||||||
|
return_value=(
|
||||||
|
error,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{
|
||||||
|
CONF_HOST: "1.1.1.1",
|
||||||
|
CONF_USERNAME: "test-username",
|
||||||
|
CONF_PASSWORD: "test-password",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result2["type"] == FlowResultType.FORM
|
||||||
|
assert result2["errors"] == {"base": expected_response}
|
||||||
|
|
||||||
|
final_result = await __test_normal_flow(hass, result2["flow_id"])
|
||||||
|
assert final_result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
|
assert final_result["title"] == "test-name"
|
||||||
|
assert final_result["data"] == {
|
||||||
|
CONF_HOST: "1.1.1.1",
|
||||||
|
CONF_USERNAME: "test-username",
|
||||||
|
CONF_PASSWORD: "test-password",
|
||||||
|
}
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_device_already_exists(
|
||||||
|
hass: HomeAssistant, mock_setup_entry: AsyncMock
|
||||||
|
) -> None:
|
||||||
|
"""Test device is not added when it already exists."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
CONF_HOST: "1.1.1.1",
|
||||||
|
CONF_USERNAME: "test-username",
|
||||||
|
CONF_PASSWORD: "test-password",
|
||||||
|
},
|
||||||
|
unique_id="test-uid",
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result["type"] == FlowResultType.FORM
|
||||||
|
assert result["errors"] is None
|
||||||
|
|
||||||
|
final_result = await __test_normal_flow(hass, result["flow_id"])
|
||||||
|
assert final_result["type"] == FlowResultType.ABORT
|
||||||
|
assert final_result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
|
async def __test_normal_flow(hass: HomeAssistant, flow_id: str) -> FlowResult:
|
||||||
|
"""Test flow completing as expected, no matter what happened before."""
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.komfovent.config_flow.komfovent_api.get_credentials",
|
||||||
|
return_value=(
|
||||||
|
komfovent_api.KomfoventConnectionResult.SUCCESS,
|
||||||
|
komfovent_api.KomfoventCredentials("1.1.1.1", "user", "pass"),
|
||||||
|
),
|
||||||
|
), patch(
|
||||||
|
"homeassistant.components.komfovent.config_flow.komfovent_api.get_settings",
|
||||||
|
return_value=(
|
||||||
|
komfovent_api.KomfoventConnectionResult.SUCCESS,
|
||||||
|
komfovent_api.KomfoventSettings("test-name", None, None, "test-uid"),
|
||||||
|
),
|
||||||
|
):
|
||||||
|
final_result = await hass.config_entries.flow.async_configure(
|
||||||
|
flow_id,
|
||||||
|
{
|
||||||
|
CONF_HOST: "1.1.1.1",
|
||||||
|
CONF_USERNAME: "test-username",
|
||||||
|
CONF_PASSWORD: "test-password",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
return final_result
|
Loading…
x
Reference in New Issue
Block a user