mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Add config flow for min_max sensor (#67807)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com> Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
parent
1746677b61
commit
66d892237d
@ -115,7 +115,11 @@ class GroupConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
|||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
|
def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
|
||||||
"""Return config entry title."""
|
"""Return config entry title.
|
||||||
|
|
||||||
|
The options parameter contains config entry options, which is the union of user
|
||||||
|
input from the config flow steps.
|
||||||
|
"""
|
||||||
return cast(str, options["name"]) if "name" in options else ""
|
return cast(str, options["name"]) if "name" in options else ""
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -1,6 +1,26 @@
|
|||||||
"""The min_max component."""
|
"""The min_max component."""
|
||||||
|
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
DOMAIN = "min_max"
|
|
||||||
PLATFORMS = [Platform.SENSOR]
|
PLATFORMS = [Platform.SENSOR]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
"""Set up Min/Max from a config entry."""
|
||||||
|
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
|
||||||
|
|
||||||
|
entry.async_on_unload(entry.add_update_listener(config_entry_update_listener))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def config_entry_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||||
|
"""Update listener, called when the config entry options are changed."""
|
||||||
|
await hass.config_entries.async_reload(entry.entry_id)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
"""Unload a config entry."""
|
||||||
|
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
|
58
homeassistant/components/min_max/config_flow.py
Normal file
58
homeassistant/components/min_max/config_flow.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
"""Config flow for Min/Max integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Mapping
|
||||||
|
from typing import Any, cast
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.const import CONF_TYPE
|
||||||
|
from homeassistant.helpers import selector
|
||||||
|
from homeassistant.helpers.helper_config_entry_flow import (
|
||||||
|
HelperConfigFlowHandler,
|
||||||
|
HelperFlowFormStep,
|
||||||
|
HelperFlowMenuStep,
|
||||||
|
)
|
||||||
|
|
||||||
|
from .const import CONF_ENTITY_IDS, CONF_ROUND_DIGITS, DOMAIN
|
||||||
|
|
||||||
|
_STATISTIC_MEASURES = ["last", "max", "mean", "min", "median"]
|
||||||
|
|
||||||
|
OPTIONS_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_ENTITY_IDS): selector.selector(
|
||||||
|
{"entity": {"domain": "sensor", "multiple": True}}
|
||||||
|
),
|
||||||
|
vol.Required(CONF_TYPE): selector.selector(
|
||||||
|
{"select": {"options": _STATISTIC_MEASURES}}
|
||||||
|
),
|
||||||
|
vol.Required(CONF_ROUND_DIGITS, default=2): selector.selector(
|
||||||
|
{"number": {"min": 0, "max": 6, "mode": "box"}}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required("name"): selector.selector({"text": {}}),
|
||||||
|
}
|
||||||
|
).extend(OPTIONS_SCHEMA.schema)
|
||||||
|
|
||||||
|
CONFIG_FLOW: dict[str, HelperFlowFormStep | HelperFlowMenuStep] = {
|
||||||
|
"user": HelperFlowFormStep(CONFIG_SCHEMA)
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTIONS_FLOW: dict[str, HelperFlowFormStep | HelperFlowMenuStep] = {
|
||||||
|
"init": HelperFlowFormStep(OPTIONS_SCHEMA)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigFlowHandler(HelperConfigFlowHandler, domain=DOMAIN):
|
||||||
|
"""Handle a config or options flow for Min/Max."""
|
||||||
|
|
||||||
|
config_flow = CONFIG_FLOW
|
||||||
|
options_flow = OPTIONS_FLOW
|
||||||
|
|
||||||
|
def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
|
||||||
|
"""Return config entry title."""
|
||||||
|
return cast(str, options["name"]) if "name" in options else ""
|
6
homeassistant/components/min_max/const.py
Normal file
6
homeassistant/components/min_max/const.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
"""Constants for the Min/Max integration."""
|
||||||
|
|
||||||
|
DOMAIN = "min_max"
|
||||||
|
|
||||||
|
CONF_ENTITY_IDS = "entity_ids"
|
||||||
|
CONF_ROUND_DIGITS = "round_digits"
|
@ -1,8 +1,12 @@
|
|||||||
{
|
{
|
||||||
"domain": "min_max",
|
"domain": "min_max",
|
||||||
|
"integration_type": "helper",
|
||||||
"name": "Min/Max",
|
"name": "Min/Max",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/min_max",
|
"documentation": "https://www.home-assistant.io/integrations/min_max",
|
||||||
"codeowners": ["@fabaff"],
|
"codeowners": [
|
||||||
|
"@fabaff"
|
||||||
|
],
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
"iot_class": "local_push"
|
"iot_class": "local_push",
|
||||||
|
"config_flow": true
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import logging
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
@ -13,14 +14,15 @@ from homeassistant.const import (
|
|||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
STATE_UNKNOWN,
|
STATE_UNKNOWN,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import Event, HomeAssistant, callback
|
||||||
import homeassistant.helpers.config_validation as cv
|
from homeassistant.helpers import config_validation as cv, entity_registry as er
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.event import async_track_state_change_event
|
from homeassistant.helpers.event import async_track_state_change_event
|
||||||
from homeassistant.helpers.reload import async_setup_reload_service
|
from homeassistant.helpers.reload import async_setup_reload_service
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
|
||||||
from . import DOMAIN, PLATFORMS
|
from . import PLATFORMS
|
||||||
|
from .const import CONF_ENTITY_IDS, CONF_ROUND_DIGITS, DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -46,9 +48,6 @@ ATTR_TO_PROPERTY = [
|
|||||||
ATTR_LAST_ENTITY_ID,
|
ATTR_LAST_ENTITY_ID,
|
||||||
]
|
]
|
||||||
|
|
||||||
CONF_ENTITY_IDS = "entity_ids"
|
|
||||||
CONF_ROUND_DIGITS = "round_digits"
|
|
||||||
|
|
||||||
ICON = "mdi:calculator"
|
ICON = "mdi:calculator"
|
||||||
|
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
@ -71,6 +70,32 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize min/max/mean config entry."""
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
entity_ids = er.async_validate_entity_ids(
|
||||||
|
registry, config_entry.options[CONF_ENTITY_IDS]
|
||||||
|
)
|
||||||
|
sensor_type = config_entry.options[CONF_TYPE]
|
||||||
|
round_digits = int(config_entry.options[CONF_ROUND_DIGITS])
|
||||||
|
|
||||||
|
async_add_entities(
|
||||||
|
[
|
||||||
|
MinMaxSensor(
|
||||||
|
entity_ids,
|
||||||
|
config_entry.title,
|
||||||
|
sensor_type,
|
||||||
|
round_digits,
|
||||||
|
config_entry.entry_id,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: ConfigType,
|
config: ConfigType,
|
||||||
@ -85,7 +110,9 @@ async def async_setup_platform(
|
|||||||
|
|
||||||
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
|
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
|
||||||
|
|
||||||
async_add_entities([MinMaxSensor(entity_ids, name, sensor_type, round_digits)])
|
async_add_entities(
|
||||||
|
[MinMaxSensor(entity_ids, name, sensor_type, round_digits, None)]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def calc_min(sensor_values):
|
def calc_min(sensor_values):
|
||||||
@ -148,8 +175,9 @@ def calc_median(sensor_values, round_digits):
|
|||||||
class MinMaxSensor(SensorEntity):
|
class MinMaxSensor(SensorEntity):
|
||||||
"""Representation of a min/max sensor."""
|
"""Representation of a min/max sensor."""
|
||||||
|
|
||||||
def __init__(self, entity_ids, name, sensor_type, round_digits):
|
def __init__(self, entity_ids, name, sensor_type, round_digits, unique_id):
|
||||||
"""Initialize the min/max sensor."""
|
"""Initialize the min/max sensor."""
|
||||||
|
self._attr_unique_id = unique_id
|
||||||
self._entity_ids = entity_ids
|
self._entity_ids = entity_ids
|
||||||
self._sensor_type = sensor_type
|
self._sensor_type = sensor_type
|
||||||
self._round_digits = round_digits
|
self._round_digits = round_digits
|
||||||
@ -173,6 +201,12 @@ class MinMaxSensor(SensorEntity):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Replay current state of source entities
|
||||||
|
for entity_id in self._entity_ids:
|
||||||
|
state = self.hass.states.get(entity_id)
|
||||||
|
state_event = Event("", {"entity_id": entity_id, "new_state": state})
|
||||||
|
self._async_min_max_sensor_state_listener(state_event, update_state=False)
|
||||||
|
|
||||||
self._calc_values()
|
self._calc_values()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -216,16 +250,24 @@ class MinMaxSensor(SensorEntity):
|
|||||||
return ICON
|
return ICON
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_min_max_sensor_state_listener(self, event):
|
def _async_min_max_sensor_state_listener(self, event, update_state=True):
|
||||||
"""Handle the sensor state changes."""
|
"""Handle the sensor state changes."""
|
||||||
new_state = event.data.get("new_state")
|
new_state = event.data.get("new_state")
|
||||||
entity = event.data.get("entity_id")
|
entity = event.data.get("entity_id")
|
||||||
|
|
||||||
if new_state.state is None or new_state.state in [
|
if (
|
||||||
|
new_state is None
|
||||||
|
or new_state.state is None
|
||||||
|
or new_state.state
|
||||||
|
in [
|
||||||
STATE_UNKNOWN,
|
STATE_UNKNOWN,
|
||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
]:
|
]
|
||||||
|
):
|
||||||
self.states[entity] = STATE_UNKNOWN
|
self.states[entity] = STATE_UNKNOWN
|
||||||
|
if not update_state:
|
||||||
|
return
|
||||||
|
|
||||||
self._calc_values()
|
self._calc_values()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
return
|
return
|
||||||
@ -252,6 +294,9 @@ class MinMaxSensor(SensorEntity):
|
|||||||
"Unable to store state. Only numerical states are supported"
|
"Unable to store state. Only numerical states are supported"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not update_state:
|
||||||
|
return
|
||||||
|
|
||||||
self._calc_values()
|
self._calc_values()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
28
homeassistant/components/min_max/strings.json
Normal file
28
homeassistant/components/min_max/strings.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"title": "Min / max / mean / median sensor",
|
||||||
|
"config": {
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"description": "Precision controls the number of decimal digits when the statistics characteristic is mean or median.",
|
||||||
|
"data": {
|
||||||
|
"entity_ids": "Input entities",
|
||||||
|
"name": "Name",
|
||||||
|
"round_digits": "Precision",
|
||||||
|
"type": "Statistic characteristic"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"options": {
|
||||||
|
"description": "[%key:component::min_max::config::step::user::description%]",
|
||||||
|
"data": {
|
||||||
|
"entity_ids": "[%key:component::min_max::config::step::user::data::entity_ids%]",
|
||||||
|
"round_digits": "[%key:component::min_max::config::step::user::data::round_digits%]",
|
||||||
|
"type": "[%key:component::min_max::config::step::user::data::type%]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
homeassistant/components/min_max/translations/en.json
Normal file
28
homeassistant/components/min_max/translations/en.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"entity_ids": "Input entities",
|
||||||
|
"name": "Name",
|
||||||
|
"round_digits": "Precision",
|
||||||
|
"type": "Statistic characteristic"
|
||||||
|
},
|
||||||
|
"description": "Precision controls the number of decimal digits when the statistics characteristic is mean or median."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"options": {
|
||||||
|
"data": {
|
||||||
|
"entity_ids": "Input entities",
|
||||||
|
"round_digits": "Precision",
|
||||||
|
"type": "Statistic characteristic"
|
||||||
|
},
|
||||||
|
"description": "Precision controls the number of decimal digits when the statistics characteristic is mean or median."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "Min / max / mean / median sensor"
|
||||||
|
}
|
@ -403,6 +403,7 @@ FLOWS = {
|
|||||||
],
|
],
|
||||||
"helper": [
|
"helper": [
|
||||||
"derivative",
|
"derivative",
|
||||||
|
"min_max",
|
||||||
"tod"
|
"tod"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
135
tests/components/min_max/test_config_flow.py
Normal file
135
tests/components/min_max/test_config_flow.py
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
"""Test the Min/Max config flow."""
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.components.min_max.const import DOMAIN
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.data_entry_flow import RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_FORM
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("platform", ("sensor",))
|
||||||
|
async def test_config_flow(hass: HomeAssistant, platform) -> None:
|
||||||
|
"""Test the config flow."""
|
||||||
|
input_sensors = ["sensor.input_one", "sensor.input_two"]
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||||
|
)
|
||||||
|
assert result["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result["errors"] is None
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.min_max.async_setup_entry",
|
||||||
|
return_value=True,
|
||||||
|
) as mock_setup_entry:
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
{"name": "My min_max", "entity_ids": input_sensors, "type": "max"},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result["title"] == "My min_max"
|
||||||
|
assert result["data"] == {}
|
||||||
|
assert result["options"] == {
|
||||||
|
"entity_ids": input_sensors,
|
||||||
|
"name": "My min_max",
|
||||||
|
"round_digits": 2.0,
|
||||||
|
"type": "max",
|
||||||
|
}
|
||||||
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
config_entry = hass.config_entries.async_entries(DOMAIN)[0]
|
||||||
|
assert config_entry.data == {}
|
||||||
|
assert config_entry.options == {
|
||||||
|
"entity_ids": input_sensors,
|
||||||
|
"name": "My min_max",
|
||||||
|
"round_digits": 2.0,
|
||||||
|
"type": "max",
|
||||||
|
}
|
||||||
|
assert config_entry.title == "My min_max"
|
||||||
|
|
||||||
|
|
||||||
|
def get_suggested(schema, key):
|
||||||
|
"""Get suggested value for key in voluptuous schema."""
|
||||||
|
for k in schema.keys():
|
||||||
|
if k == key:
|
||||||
|
if k.description is None or "suggested_value" not in k.description:
|
||||||
|
return None
|
||||||
|
return k.description["suggested_value"]
|
||||||
|
# Wanted key absent from schema
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("platform", ("sensor",))
|
||||||
|
async def test_options(hass: HomeAssistant, platform) -> None:
|
||||||
|
"""Test reconfiguring."""
|
||||||
|
hass.states.async_set("sensor.input_one", "10")
|
||||||
|
hass.states.async_set("sensor.input_two", "20")
|
||||||
|
hass.states.async_set("sensor.input_three", "33.33")
|
||||||
|
|
||||||
|
input_sensors1 = ["sensor.input_one", "sensor.input_two"]
|
||||||
|
input_sensors2 = ["sensor.input_one", "sensor.input_two", "sensor.input_three"]
|
||||||
|
|
||||||
|
# Setup the config entry
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
data={},
|
||||||
|
domain=DOMAIN,
|
||||||
|
options={
|
||||||
|
"entity_ids": input_sensors1,
|
||||||
|
"name": "My min_max",
|
||||||
|
"round_digits": 0,
|
||||||
|
"type": "min",
|
||||||
|
},
|
||||||
|
title="My min_max",
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||||
|
assert result["type"] == RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "init"
|
||||||
|
schema = result["data_schema"].schema
|
||||||
|
assert get_suggested(schema, "entity_ids") == input_sensors1
|
||||||
|
assert get_suggested(schema, "round_digits") == 0
|
||||||
|
assert get_suggested(schema, "type") == "min"
|
||||||
|
|
||||||
|
result = await hass.config_entries.options.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={
|
||||||
|
"entity_ids": input_sensors2,
|
||||||
|
"round_digits": 1,
|
||||||
|
"type": "mean",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result["data"] == {
|
||||||
|
"entity_ids": input_sensors2,
|
||||||
|
"name": "My min_max",
|
||||||
|
"round_digits": 1,
|
||||||
|
"type": "mean",
|
||||||
|
}
|
||||||
|
assert config_entry.data == {}
|
||||||
|
assert config_entry.options == {
|
||||||
|
"entity_ids": input_sensors2,
|
||||||
|
"name": "My min_max",
|
||||||
|
"round_digits": 1,
|
||||||
|
"type": "mean",
|
||||||
|
}
|
||||||
|
assert config_entry.title == "My min_max"
|
||||||
|
|
||||||
|
# Check config entry is reloaded with new options
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Check the entity was updated, no new entity was created
|
||||||
|
assert len(hass.states.async_all()) == 4
|
||||||
|
|
||||||
|
# Check the state of the entity has changed as expected
|
||||||
|
state = hass.states.get(f"{platform}.my_min_max")
|
||||||
|
assert state.state == "21.1"
|
||||||
|
assert state.attributes["count_sensors"] == 3
|
55
tests/components/min_max/test_init.py
Normal file
55
tests/components/min_max/test_init.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
"""Test the Min/Max integration."""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.min_max.const import DOMAIN
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("platform", ("sensor",))
|
||||||
|
async def test_setup_and_remove_config_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
platform: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test setting up and removing a config entry."""
|
||||||
|
hass.states.async_set("sensor.input_one", "10")
|
||||||
|
hass.states.async_set("sensor.input_two", "20")
|
||||||
|
|
||||||
|
input_sensors = ["sensor.input_one", "sensor.input_two"]
|
||||||
|
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
min_max_entity_id = f"{platform}.my_min_max"
|
||||||
|
|
||||||
|
# Setup the config entry
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
data={},
|
||||||
|
domain=DOMAIN,
|
||||||
|
options={
|
||||||
|
"entity_ids": input_sensors,
|
||||||
|
"name": "My min_max",
|
||||||
|
"round_digits": 2.0,
|
||||||
|
"type": "max",
|
||||||
|
},
|
||||||
|
title="My min_max",
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Check the entity is registered in the entity registry
|
||||||
|
assert registry.async_get(min_max_entity_id) is not None
|
||||||
|
|
||||||
|
# Check the platform is setup correctly
|
||||||
|
state = hass.states.get(min_max_entity_id)
|
||||||
|
assert state.state == "20.0"
|
||||||
|
assert state.attributes["count_sensors"] == 2
|
||||||
|
|
||||||
|
# Remove the config entry
|
||||||
|
assert await hass.config_entries.async_remove(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Check the state and entity registry entry are removed
|
||||||
|
assert hass.states.get(min_max_entity_id) is None
|
||||||
|
assert registry.async_get(min_max_entity_id) is None
|
@ -3,7 +3,7 @@ import statistics
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from homeassistant import config as hass_config
|
from homeassistant import config as hass_config
|
||||||
from homeassistant.components.min_max import DOMAIN
|
from homeassistant.components.min_max.const import DOMAIN
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
PERCENTAGE,
|
PERCENTAGE,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user