mirror of
https://github.com/home-assistant/core.git
synced 2026-04-17 07:06:24 +02:00
Compare commits
12 Commits
event_rang
...
gj-2026040
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f1846b34a | ||
|
|
44b071762d | ||
|
|
f006283ee8 | ||
|
|
d25f3c6d2e | ||
|
|
f821952918 | ||
|
|
49ce8ed944 | ||
|
|
d4fca3737d | ||
|
|
26d8dfb695 | ||
|
|
6e92ba2fc0 | ||
|
|
7288d19abf | ||
|
|
5bbfe69bbb | ||
|
|
564280cc65 |
@@ -47,7 +47,9 @@ from .const import ( # noqa: F401
|
||||
ATTR_OBJECT_ID,
|
||||
ATTR_ORDER,
|
||||
ATTR_REMOVE_ENTITIES,
|
||||
CONF_GROUP_TYPE,
|
||||
CONF_HIDE_MEMBERS,
|
||||
CONF_IGNORE_NON_NUMERIC,
|
||||
DATA_COMPONENT,
|
||||
DOMAIN,
|
||||
GROUP_ORDER,
|
||||
|
||||
@@ -24,7 +24,7 @@ from homeassistant.helpers.schema_config_entry_flow import (
|
||||
|
||||
from .binary_sensor import CONF_ALL, async_create_preview_binary_sensor
|
||||
from .button import async_create_preview_button
|
||||
from .const import CONF_HIDE_MEMBERS, CONF_IGNORE_NON_NUMERIC, DOMAIN
|
||||
from .const import CONF_GROUP_TYPE, CONF_HIDE_MEMBERS, CONF_IGNORE_NON_NUMERIC, DOMAIN
|
||||
from .cover import async_create_preview_cover
|
||||
from .entity import GroupEntity
|
||||
from .event import async_create_preview_event
|
||||
@@ -180,7 +180,7 @@ GROUP_TYPES = [
|
||||
|
||||
async def choose_options_step(options: dict[str, Any]) -> str:
|
||||
"""Return next step_id for options flow according to group_type."""
|
||||
return cast(str, options["group_type"])
|
||||
return cast(str, options[CONF_GROUP_TYPE])
|
||||
|
||||
|
||||
def set_group_type(
|
||||
@@ -194,7 +194,7 @@ def set_group_type(
|
||||
handler: SchemaCommonFlowHandler, user_input: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Add group type to user input."""
|
||||
return {"group_type": group_type, **user_input}
|
||||
return {CONF_GROUP_TYPE: group_type, **user_input}
|
||||
|
||||
return _set_group_type
|
||||
|
||||
@@ -430,7 +430,7 @@ def ws_start_preview(
|
||||
config_entry = hass.config_entries.async_get_entry(config_entry_id)
|
||||
if not config_entry:
|
||||
raise HomeAssistantError
|
||||
group_type = config_entry.options["group_type"]
|
||||
group_type = config_entry.options[CONF_GROUP_TYPE]
|
||||
name = config_entry.options["name"]
|
||||
validated = PREVIEW_OPTIONS_SCHEMA[group_type](msg["user_input"])
|
||||
entity_registry = er.async_get(hass)
|
||||
|
||||
@@ -14,6 +14,7 @@ if TYPE_CHECKING:
|
||||
|
||||
CONF_HIDE_MEMBERS = "hide_members"
|
||||
CONF_IGNORE_NON_NUMERIC = "ignore_non_numeric"
|
||||
CONF_GROUP_TYPE = "group_type"
|
||||
|
||||
DOMAIN = "group"
|
||||
DATA_COMPONENT: HassKey[EntityComponent[Group]] = HassKey(DOMAIN)
|
||||
|
||||
@@ -1,19 +1,79 @@
|
||||
"""The min_max component."""
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from datetime import datetime
|
||||
import logging
|
||||
from types import MappingProxyType
|
||||
|
||||
from homeassistant.components.group import (
|
||||
CONF_ENTITIES,
|
||||
CONF_GROUP_TYPE,
|
||||
CONF_HIDE_MEMBERS,
|
||||
CONF_IGNORE_NON_NUMERIC,
|
||||
DOMAIN as GROUP_DOMAIN,
|
||||
)
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_USER, ConfigEntry, ConfigEntryState
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.event import async_call_later
|
||||
|
||||
from .const import CONF_ENTITY_IDS, CONF_ROUND_DIGITS, DOMAIN
|
||||
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Min/Max from a config entry."""
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
# Create group config from entry options
|
||||
config = dict(entry.options)
|
||||
config[CONF_ENTITIES] = config.pop(CONF_ENTITY_IDS)
|
||||
config.pop(CONF_ROUND_DIGITS)
|
||||
# Set group sensor defaults
|
||||
config[CONF_HIDE_MEMBERS] = False
|
||||
config[CONF_IGNORE_NON_NUMERIC] = False
|
||||
config[CONF_GROUP_TYPE] = SENSOR_DOMAIN
|
||||
|
||||
new_config_entry = ConfigEntry(
|
||||
data={},
|
||||
discovery_keys=MappingProxyType({}),
|
||||
domain=GROUP_DOMAIN,
|
||||
minor_version=1,
|
||||
options=config,
|
||||
source=SOURCE_USER,
|
||||
subentries_data=[],
|
||||
title=entry.title,
|
||||
unique_id=None,
|
||||
version=1,
|
||||
)
|
||||
|
||||
entity_reg = er.async_get(hass)
|
||||
if old_entity := entity_reg.async_get_entity_id(
|
||||
SENSOR_DOMAIN, DOMAIN, entry.entry_id
|
||||
):
|
||||
entity_reg.async_update_entity_platform(
|
||||
old_entity, GROUP_DOMAIN, new_config_entry_id=new_config_entry.entry_id
|
||||
)
|
||||
# If entity is not existing, it has already been migrated
|
||||
# and we should not create it again
|
||||
await hass.config_entries.async_add(new_config_entry)
|
||||
|
||||
# Wait for config entry setup to finish before removing the old config entry
|
||||
async def remove_old_entry(now: datetime) -> None:
|
||||
"""Remove the old config entry after migration."""
|
||||
if entry.state == ConfigEntryState.LOADED:
|
||||
await hass.config_entries.async_remove(entry.entry_id)
|
||||
else:
|
||||
async_call_later(hass, 5, remove_old_entry)
|
||||
|
||||
async_call_later(hass, 5, remove_old_entry)
|
||||
|
||||
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)
|
||||
|
||||
return True
|
||||
|
||||
@@ -2,77 +2,20 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, cast
|
||||
from typing import Any
|
||||
|
||||
import voluptuous as vol
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
|
||||
from homeassistant.components.input_number import DOMAIN as INPUT_NUMBER_DOMAIN
|
||||
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.const import CONF_TYPE
|
||||
from homeassistant.helpers import selector
|
||||
from homeassistant.helpers.schema_config_entry_flow import (
|
||||
SchemaConfigFlowHandler,
|
||||
SchemaFlowFormStep,
|
||||
)
|
||||
|
||||
from .const import CONF_ENTITY_IDS, CONF_ROUND_DIGITS, DOMAIN
|
||||
|
||||
_STATISTIC_MEASURES = [
|
||||
"min",
|
||||
"max",
|
||||
"mean",
|
||||
"median",
|
||||
"last",
|
||||
"range",
|
||||
"sum",
|
||||
]
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
OPTIONS_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_ENTITY_IDS): selector.EntitySelector(
|
||||
selector.EntitySelectorConfig(
|
||||
domain=[SENSOR_DOMAIN, NUMBER_DOMAIN, INPUT_NUMBER_DOMAIN],
|
||||
multiple=True,
|
||||
),
|
||||
),
|
||||
vol.Required(CONF_TYPE): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=_STATISTIC_MEASURES, translation_key=CONF_TYPE
|
||||
),
|
||||
),
|
||||
vol.Required(CONF_ROUND_DIGITS, default=2): selector.NumberSelector(
|
||||
selector.NumberSelectorConfig(
|
||||
min=0, max=6, mode=selector.NumberSelectorMode.BOX
|
||||
),
|
||||
),
|
||||
}
|
||||
)
|
||||
class MinMaxConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for min_max integration."""
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("name"): selector.TextSelector(),
|
||||
}
|
||||
).extend(OPTIONS_SCHEMA.schema)
|
||||
VERSION = 1
|
||||
|
||||
CONFIG_FLOW = {
|
||||
"user": SchemaFlowFormStep(CONFIG_SCHEMA),
|
||||
}
|
||||
|
||||
OPTIONS_FLOW = {
|
||||
"init": SchemaFlowFormStep(OPTIONS_SCHEMA),
|
||||
}
|
||||
|
||||
|
||||
class ConfigFlowHandler(SchemaConfigFlowHandler, domain=DOMAIN):
|
||||
"""Handle a config or options flow for Min/Max."""
|
||||
|
||||
config_flow = CONFIG_FLOW
|
||||
options_flow = OPTIONS_FLOW
|
||||
options_flow_reloads = True
|
||||
|
||||
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 ""
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle the user step."""
|
||||
return self.async_abort(reason="migrated_to_groups")
|
||||
|
||||
@@ -9,17 +9,18 @@ from typing import Any
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.group import CONF_ENTITIES
|
||||
from homeassistant.components.sensor import (
|
||||
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_NAME,
|
||||
CONF_PLATFORM,
|
||||
CONF_TYPE,
|
||||
CONF_UNIQUE_ID,
|
||||
STATE_UNAVAILABLE,
|
||||
@@ -27,15 +28,14 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import Event, EventStateChangedData, HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_validation as cv, entity_registry as er
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.entity import get_device_class
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
)
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.event import async_track_state_change_event
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
from homeassistant.helpers.reload import async_setup_reload_service
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType
|
||||
from homeassistant.util import ulid as ulid_util, yaml as yaml_util
|
||||
|
||||
from . import PLATFORMS
|
||||
from .const import CONF_ENTITY_IDS, CONF_ROUND_DIGITS, DOMAIN
|
||||
@@ -53,6 +53,7 @@ ATTR_LAST_ENTITY_ID = "last_entity_id"
|
||||
ATTR_RANGE = "range"
|
||||
ATTR_SUM = "sum"
|
||||
|
||||
|
||||
ICON = "mdi:calculator"
|
||||
|
||||
SENSOR_TYPES = {
|
||||
@@ -79,29 +80,27 @@ PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> 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 yaml_deprecation_notice(hass: HomeAssistant, config: ConfigType) -> None:
|
||||
"""Raise repair issue for YAML configuration deprecation."""
|
||||
platform_config = config.copy()
|
||||
platform_config[CONF_ENTITIES] = platform_config.pop(CONF_ENTITY_IDS)
|
||||
platform_config.pop(CONF_ROUND_DIGITS)
|
||||
platform_config.pop(CONF_PLATFORM)
|
||||
if CONF_NAME not in platform_config:
|
||||
platform_config[CONF_NAME] = f"{platform_config[CONF_TYPE]} sensor".capitalize()
|
||||
yaml_config = yaml_util.dump(platform_config)
|
||||
yaml_config = yaml_config.replace("\n", "\n ")
|
||||
yaml_config = "```yaml\nsensor:\n - platform: group\n " + yaml_config + "\n```"
|
||||
async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
ulid_util.ulid(),
|
||||
breaks_in_ha_version="2026.12.0",
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
learn_more_url="https://www.home-assistant.io/integrations/group/",
|
||||
translation_key="yaml_deprecated",
|
||||
translation_placeholders={"yaml_config": yaml_config},
|
||||
)
|
||||
|
||||
|
||||
@@ -119,6 +118,7 @@ async def async_setup_platform(
|
||||
unique_id = config.get(CONF_UNIQUE_ID)
|
||||
|
||||
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
|
||||
await yaml_deprecation_notice(hass, config)
|
||||
|
||||
async_add_entities(
|
||||
[MinMaxSensor(entity_ids, name, sensor_type, round_digits, unique_id)]
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"migrated_to_groups": "The min/max integration has been migrated to use group sensors. Please use the group integration instead."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
@@ -16,6 +19,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"yaml_deprecated": {
|
||||
"description": "The min/max integration has been migrated to use group sensor.\n\nReplace your Min/MaxYAML configuration with this converted configuration:\n{yaml_config}\n\nTo use the new configuration and replace your sensor with a group sensor, restart your Home Assistant.\n\nGroup sensors have more configuration possibilities, refer to the documentation by clicking on learn more.",
|
||||
"title": "Min/Max YAML configuration is deprecated"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
|
||||
31
tests/components/min_max/snapshots/test_init.ambr
Normal file
31
tests/components/min_max/snapshots/test_init.ambr
Normal file
@@ -0,0 +1,31 @@
|
||||
# serializer version: 1
|
||||
# name: test_setup_migrates_to_groups
|
||||
dict({
|
||||
'data': dict({
|
||||
}),
|
||||
'disabled_by': None,
|
||||
'discovery_keys': dict({
|
||||
}),
|
||||
'domain': 'group',
|
||||
'minor_version': 1,
|
||||
'options': dict({
|
||||
'entities': list([
|
||||
'sensor.input_one',
|
||||
'sensor.input_two',
|
||||
]),
|
||||
'group_type': 'sensor',
|
||||
'hide_members': False,
|
||||
'ignore_non_numeric': False,
|
||||
'name': 'My min_max',
|
||||
'type': 'max',
|
||||
}),
|
||||
'pref_disable_new_entities': False,
|
||||
'pref_disable_polling': False,
|
||||
'source': 'user',
|
||||
'subentries': list([
|
||||
]),
|
||||
'title': 'My min_max',
|
||||
'unique_id': None,
|
||||
'version': 1,
|
||||
})
|
||||
# ---
|
||||
@@ -1,124 +1,16 @@
|
||||
"""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 FlowResultType
|
||||
|
||||
from tests.common import MockConfigEntry, get_schema_suggested_value
|
||||
|
||||
|
||||
@pytest.mark.parametrize("platform", ["sensor"])
|
||||
async def test_config_flow(hass: HomeAssistant, platform: str) -> None:
|
||||
"""Test the config flow."""
|
||||
input_sensors = ["sensor.input_one", "sensor.input_two"]
|
||||
async def test_config_flow_aborts(hass: HomeAssistant) -> None:
|
||||
"""Test the config flow aborts."""
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] is FlowResultType.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"] is FlowResultType.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"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("platform", ["sensor"])
|
||||
async def test_options(hass: HomeAssistant, platform: str) -> 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"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "init"
|
||||
schema = result["data_schema"].schema
|
||||
assert get_schema_suggested_value(schema, "entity_ids") == input_sensors1
|
||||
assert get_schema_suggested_value(schema, "round_digits") == 0
|
||||
assert get_schema_suggested_value(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"] is FlowResultType.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 result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "migrated_to_groups"
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
"""Test the Min/Max integration."""
|
||||
|
||||
import pytest
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from syrupy.filters import props
|
||||
|
||||
from homeassistant.components.group import DOMAIN as GROUP_DOMAIN
|
||||
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
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
|
||||
@pytest.mark.parametrize("platform", ["sensor"])
|
||||
async def test_setup_and_remove_config_entry(
|
||||
async def test_setup_migrates_to_groups(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
platform: str,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test setting up and removing a config entry."""
|
||||
hass.states.async_set("sensor.input_one", "10")
|
||||
@@ -21,7 +24,7 @@ async def test_setup_and_remove_config_entry(
|
||||
|
||||
input_sensors = ["sensor.input_one", "sensor.input_two"]
|
||||
|
||||
min_max_entity_id = f"{platform}.my_min_max"
|
||||
min_max_entity_id = "sensor.my_min_max"
|
||||
|
||||
# Setup the config entry
|
||||
config_entry = MockConfigEntry(
|
||||
@@ -37,19 +40,29 @@ async def test_setup_and_remove_config_entry(
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
# Check the entity is registered in the entity registry
|
||||
assert entity_registry.async_get(min_max_entity_id) is not None
|
||||
entity = entity_registry.async_get(min_max_entity_id)
|
||||
assert entity is not None
|
||||
assert entity.config_entry_id is not None
|
||||
assert entity.config_entry_id != config_entry.entry_id
|
||||
assert entity.platform == GROUP_DOMAIN
|
||||
|
||||
# Check the platform is setup correctly
|
||||
assert len(hass.states.async_all()) == 3
|
||||
state = hass.states.get(min_max_entity_id)
|
||||
assert state.state == "20.0"
|
||||
|
||||
# Remove the config entry
|
||||
assert await hass.config_entries.async_remove(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
config_entry = hass.config_entries.async_entries("group")[0]
|
||||
assert config_entry.as_dict() == snapshot(
|
||||
exclude=props("created_at", "entry_id", "modified_at")
|
||||
)
|
||||
config_entry_min_max = hass.config_entries.async_entries(DOMAIN)[0]
|
||||
assert config_entry_min_max
|
||||
|
||||
# Check the state and entity registry entry are removed
|
||||
assert hass.states.get(min_max_entity_id) is None
|
||||
assert entity_registry.async_get(min_max_entity_id) is None
|
||||
freezer.tick(60 * 5)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
config_entry_min_max = hass.config_entries.async_entries(DOMAIN)
|
||||
assert not config_entry_min_max
|
||||
|
||||
@@ -23,7 +23,7 @@ from homeassistant.const import (
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import get_fixture_path
|
||||
@@ -42,6 +42,28 @@ RANGE_4_DIGITS = round(max(VALUES) - min(VALUES), 4)
|
||||
SUM_VALUE = sum(VALUES)
|
||||
|
||||
|
||||
async def test_deprecation_warning(
|
||||
hass: HomeAssistant, issue_registry: ir.IssueRegistry
|
||||
) -> None:
|
||||
"""Test the min sensor with a default name."""
|
||||
config = {
|
||||
"sensor": {
|
||||
"platform": "min_max",
|
||||
"type": "min",
|
||||
"entity_ids": ["sensor.test_1", "sensor.test_2", "sensor.test_3"],
|
||||
}
|
||||
}
|
||||
|
||||
with patch("homeassistant.util.ulid.ulid", return_value="1234"):
|
||||
assert await async_setup_component(hass, "sensor", config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue = issue_registry.async_get_issue(DOMAIN, "1234")
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_key == "yaml_deprecated"
|
||||
|
||||
|
||||
async def test_default_name_sensor(hass: HomeAssistant) -> None:
|
||||
"""Test the min sensor with a default name."""
|
||||
config = {
|
||||
|
||||
Reference in New Issue
Block a user