mirror of
https://github.com/home-assistant/core.git
synced 2026-06-06 23:46:56 +01:00
Add derivative tests exhibiting unit issues (#153051)
This commit is contained in:
@@ -1,14 +1,18 @@
|
||||
"""Test the Derivative config flow."""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun import freeze_time
|
||||
import pytest
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.derivative.const import DOMAIN
|
||||
from homeassistant.const import STATE_UNAVAILABLE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
from homeassistant.helpers import selector
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from tests.common import MockConfigEntry, get_schema_suggested_value
|
||||
|
||||
@@ -154,3 +158,86 @@ async def test_options(
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(f"{platform}.my_derivative")
|
||||
assert state.attributes["unit_of_measurement"] == "cat/h"
|
||||
|
||||
|
||||
async def test_update_unit(hass: HomeAssistant) -> None:
|
||||
"""Test behavior of changing the unit_time option."""
|
||||
# Setup the config entry
|
||||
source_id = "sensor.source"
|
||||
config_entry = MockConfigEntry(
|
||||
data={},
|
||||
domain=DOMAIN,
|
||||
options={
|
||||
"name": "My derivative",
|
||||
"round": 1.0,
|
||||
"source": source_id,
|
||||
"unit_time": "min",
|
||||
"time_window": {"seconds": 0.0},
|
||||
},
|
||||
title="My derivative",
|
||||
)
|
||||
derivative_id = "sensor.my_derivative"
|
||||
config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(derivative_id)
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
assert state.attributes.get("unit_of_measurement") is None
|
||||
|
||||
time = dt_util.utcnow()
|
||||
with freeze_time(time) as freezer:
|
||||
# First state update of the source.
|
||||
# Derivative does not learn the unit yet.
|
||||
hass.states.async_set(source_id, 5, {"unit_of_measurement": "dogs"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(derivative_id)
|
||||
assert state.state == "0.0"
|
||||
assert state.attributes.get("unit_of_measurement") is None
|
||||
|
||||
# Second state update of the source.
|
||||
time += timedelta(minutes=1)
|
||||
freezer.move_to(time)
|
||||
hass.states.async_set(source_id, "7", {"unit_of_measurement": "dogs"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(derivative_id)
|
||||
assert state.state == "2.0"
|
||||
assert state.attributes.get("unit_of_measurement") == "dogs/min"
|
||||
|
||||
# Update the unit_time from minutes to seconds.
|
||||
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={
|
||||
"source": source_id,
|
||||
"round": 1.0,
|
||||
"unit_time": "s",
|
||||
"time_window": {"seconds": 0.0},
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check the state after reconfigure. Neither unit or state has changed.
|
||||
state = hass.states.get(derivative_id)
|
||||
assert state.state == "2.0"
|
||||
assert state.attributes.get("unit_of_measurement") == "dogs/min"
|
||||
|
||||
# Third state update of the source.
|
||||
time += timedelta(seconds=1)
|
||||
freezer.move_to(time)
|
||||
hass.states.async_set(source_id, "10", {"unit_of_measurement": "dogs"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(derivative_id)
|
||||
assert state.state == "3.0"
|
||||
# While the state is correctly reporting a state of 3 dogs per second, it incorrectly keeps
|
||||
# the unit as dogs/min
|
||||
assert state.attributes.get("unit_of_measurement") == "dogs/min"
|
||||
|
||||
# Fourth state update of the source.
|
||||
time += timedelta(seconds=1)
|
||||
freezer.move_to(time)
|
||||
hass.states.async_set(source_id, "20", {"unit_of_measurement": "dogs"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(derivative_id)
|
||||
assert state.state == "10.0"
|
||||
assert state.attributes.get("unit_of_measurement") == "dogs/min"
|
||||
|
||||
@@ -934,3 +934,65 @@ async def test_unavailable_boot(
|
||||
assert state is not None
|
||||
# Now that the source sensor has two valid datapoints, we can calculate derivative
|
||||
assert state.state == "5.00"
|
||||
|
||||
|
||||
async def test_source_unit_change(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test how derivative responds when the source sensor changes unit."""
|
||||
source_id = "sensor.source"
|
||||
config = {
|
||||
"sensor": {
|
||||
"platform": "derivative",
|
||||
"name": "derivative",
|
||||
"source": source_id,
|
||||
"unit_time": "s",
|
||||
}
|
||||
}
|
||||
|
||||
assert await async_setup_component(hass, "sensor", config)
|
||||
await hass.async_block_till_done()
|
||||
entity_id = "sensor.derivative"
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
assert state.attributes.get("unit_of_measurement") is None
|
||||
|
||||
time = dt_util.utcnow()
|
||||
with freeze_time(time) as freezer:
|
||||
# First state update of the source.
|
||||
# Derivative does not learn the UoM yet.
|
||||
hass.states.async_set(source_id, "5", {"unit_of_measurement": "cats"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "0.000"
|
||||
assert state.attributes.get("unit_of_measurement") is None
|
||||
|
||||
# Second state update of the source.
|
||||
time += timedelta(seconds=1)
|
||||
freezer.move_to(time)
|
||||
hass.states.async_set(source_id, "7", {"unit_of_measurement": "cats"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "2.000"
|
||||
assert state.attributes.get("unit_of_measurement") == "cats/s"
|
||||
|
||||
# Third state update of the source, source unit changes to dogs.
|
||||
# Ignored by derivative which continues reporting cats.
|
||||
time += timedelta(seconds=1)
|
||||
freezer.move_to(time)
|
||||
hass.states.async_set(source_id, "12", {"unit_of_measurement": "dogs"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "5.000"
|
||||
assert state.attributes.get("unit_of_measurement") == "cats/s"
|
||||
|
||||
# Fourth state update of the source, still dogs.
|
||||
# Ignored by derivative which continues reporting cats.
|
||||
time += timedelta(seconds=1)
|
||||
freezer.move_to(time)
|
||||
hass.states.async_set(source_id, "20", {"unit_of_measurement": "dogs"})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "8.000"
|
||||
assert state.attributes.get("unit_of_measurement") == "cats/s"
|
||||
|
||||
Reference in New Issue
Block a user