mirror of
https://github.com/home-assistant/core.git
synced 2025-12-24 21:06:19 +00:00
Add enum device_class and state options property to sensor entities (#82489)
This commit is contained in:
@@ -6,7 +6,7 @@ import pytest
|
||||
from pytest import approx
|
||||
|
||||
from homeassistant.components.number import NumberDeviceClass
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
LENGTH_CENTIMETERS,
|
||||
@@ -32,8 +32,9 @@ from homeassistant.const import (
|
||||
VOLUME_CUBIC_METERS,
|
||||
VOLUME_FLUID_OUNCE,
|
||||
VOLUME_LITERS,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import State
|
||||
from homeassistant.core import HomeAssistant, State
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.restore_state import STORAGE_KEY as RESTORE_STATE_KEY
|
||||
from homeassistant.setup import async_setup_component
|
||||
@@ -936,3 +937,124 @@ def test_device_classes_aligned():
|
||||
for device_class in NumberDeviceClass:
|
||||
assert hasattr(SensorDeviceClass, device_class.name)
|
||||
assert getattr(SensorDeviceClass, device_class.name).value == device_class.value
|
||||
|
||||
|
||||
async def test_value_unknown_in_enumeration(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
enable_custom_integrations: None,
|
||||
):
|
||||
"""Test warning on invalid enum value."""
|
||||
platform = getattr(hass.components, "test.sensor")
|
||||
platform.init(empty=True)
|
||||
platform.ENTITIES["0"] = platform.MockSensor(
|
||||
name="Test",
|
||||
native_value="invalid_option",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=["option1", "option2"],
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
"Sensor sensor.test provides state value 'invalid_option', "
|
||||
"which is not in the list of options provided"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
async def test_invalid_enumeration_entity_with_device_class(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
enable_custom_integrations: None,
|
||||
):
|
||||
"""Test warning on entities that provide an enum with a device class."""
|
||||
platform = getattr(hass.components, "test.sensor")
|
||||
platform.init(empty=True)
|
||||
platform.ENTITIES["0"] = platform.MockSensor(
|
||||
name="Test",
|
||||
native_value=21,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
options=["option1", "option2"],
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
"Sensor sensor.test is providing enum options, but has device class 'power' "
|
||||
"instead of 'enum'"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
async def test_invalid_enumeration_entity_without_device_class(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
enable_custom_integrations: None,
|
||||
):
|
||||
"""Test warning on entities that provide an enum without a device class."""
|
||||
platform = getattr(hass.components, "test.sensor")
|
||||
platform.init(empty=True)
|
||||
platform.ENTITIES["0"] = platform.MockSensor(
|
||||
name="Test",
|
||||
native_value=21,
|
||||
options=["option1", "option2"],
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
"Sensor sensor.test is providing enum options, but is missing "
|
||||
"the enum device class"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
async def test_invalid_enumeration_with_state_class(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
enable_custom_integrations: None,
|
||||
):
|
||||
"""Test warning on numeric entities that provide an enum."""
|
||||
platform = getattr(hass.components, "test.sensor")
|
||||
platform.init(empty=True)
|
||||
platform.ENTITIES["0"] = platform.MockSensor(
|
||||
name="Test",
|
||||
native_value=42,
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
options=["option1", "option2"],
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
"Sensor sensor.test has an state_class and thus indicating "
|
||||
"it has a numeric value; however, it has the enum device class"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
async def test_invalid_enumeration_with_unit_of_measurement(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
enable_custom_integrations: None,
|
||||
):
|
||||
"""Test warning on numeric entities that provide an enum."""
|
||||
platform = getattr(hass.components, "test.sensor")
|
||||
platform.init(empty=True)
|
||||
platform.ENTITIES["0"] = platform.MockSensor(
|
||||
name="Test",
|
||||
native_value=42,
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
options=["option1", "option2"],
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
"Sensor sensor.test has an unit of measurement and thus indicating "
|
||||
"it has a numeric value; however, it has the enum device class"
|
||||
) in caplog.text
|
||||
|
||||
@@ -10,7 +10,11 @@ from pytest import approx
|
||||
|
||||
from homeassistant import loader
|
||||
from homeassistant.components.recorder import DOMAIN as RECORDER_DOMAIN, history
|
||||
from homeassistant.components.recorder.db_schema import StatisticsMeta
|
||||
from homeassistant.components.recorder.db_schema import (
|
||||
StateAttributes,
|
||||
States,
|
||||
StatisticsMeta,
|
||||
)
|
||||
from homeassistant.components.recorder.models import (
|
||||
StatisticData,
|
||||
StatisticMetaData,
|
||||
@@ -22,11 +26,14 @@ from homeassistant.components.recorder.statistics import (
|
||||
list_statistic_ids,
|
||||
)
|
||||
from homeassistant.components.recorder.util import get_instance, session_scope
|
||||
from homeassistant.const import STATE_UNAVAILABLE
|
||||
from homeassistant.components.sensor import ATTR_OPTIONS, DOMAIN
|
||||
from homeassistant.const import ATTR_FRIENDLY_NAME, STATE_UNAVAILABLE
|
||||
from homeassistant.core import HomeAssistant, State
|
||||
from homeassistant.setup import async_setup_component, setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.util.unit_system import METRIC_SYSTEM, US_CUSTOMARY_SYSTEM
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
from tests.components.recorder.common import (
|
||||
async_recorder_block_till_done,
|
||||
async_wait_recording_done,
|
||||
@@ -4320,3 +4327,27 @@ def record_states_partially_unavailable(hass, zero, entity_id, attributes):
|
||||
)
|
||||
|
||||
return four, states
|
||||
|
||||
|
||||
async def test_exclude_attributes(recorder_mock: None, hass: HomeAssistant) -> None:
|
||||
"""Test sensor attributes to be excluded."""
|
||||
await async_setup_component(hass, DOMAIN, {DOMAIN: {"platform": "demo"}})
|
||||
await hass.async_block_till_done()
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=5))
|
||||
await hass.async_block_till_done()
|
||||
await async_wait_recording_done(hass)
|
||||
|
||||
def _fetch_states() -> list[State]:
|
||||
with session_scope(hass=hass) as session:
|
||||
native_states = []
|
||||
for db_state, db_state_attributes in session.query(States, StateAttributes):
|
||||
state = db_state.to_native()
|
||||
state.attributes = db_state_attributes.to_native()
|
||||
native_states.append(state)
|
||||
return native_states
|
||||
|
||||
states: list[State] = await hass.async_add_executor_job(_fetch_states)
|
||||
assert len(states) > 1
|
||||
for state in states:
|
||||
assert ATTR_OPTIONS not in state.attributes
|
||||
assert ATTR_FRIENDLY_NAME in state.attributes
|
||||
|
||||
Reference in New Issue
Block a user