Convert recorder history tests to use async API (#116909)

This commit is contained in:
Erik Montnemery 2024-05-06 15:10:45 +02:00 committed by GitHub
parent 9517800da6
commit d01d161fe2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 352 additions and 381 deletions

View file

@ -2,7 +2,6 @@
from __future__ import annotations
from collections.abc import Callable
from copy import copy
from datetime import datetime, timedelta
import json
@ -41,12 +40,23 @@ from .common import (
assert_states_equal_without_context,
async_recorder_block_till_done,
async_wait_recording_done,
wait_recording_done,
)
from tests.typing import RecorderInstanceGenerator
@pytest.fixture
async def mock_recorder_before_hass(
async_setup_recorder_instance: RecorderInstanceGenerator,
) -> None:
"""Set up recorder."""
@pytest.fixture(autouse=True)
def setup_recorder(recorder_mock: Recorder) -> recorder.Recorder:
"""Set up recorder."""
async def _async_get_states(
hass: HomeAssistant,
utc_point_in_time: datetime,
@ -118,11 +128,10 @@ def _add_db_entries(
)
def test_get_full_significant_states_with_session_entity_no_matches(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_full_significant_states_with_session_entity_no_matches(
hass: HomeAssistant,
) -> None:
"""Test getting states at a specific point in time for entities that never have been recorded."""
hass = hass_recorder()
now = dt_util.utcnow()
time_before_recorder_ran = now - timedelta(days=1000)
with session_scope(hass=hass, read_only=True) as session:
@ -144,11 +153,10 @@ def test_get_full_significant_states_with_session_entity_no_matches(
)
def test_significant_states_with_session_entity_minimal_response_no_matches(
hass_recorder: Callable[..., HomeAssistant],
async def test_significant_states_with_session_entity_minimal_response_no_matches(
hass: HomeAssistant,
) -> None:
"""Test getting states at a specific point in time for entities that never have been recorded."""
hass = hass_recorder()
now = dt_util.utcnow()
time_before_recorder_ran = now - timedelta(days=1000)
with session_scope(hass=hass, read_only=True) as session:
@ -176,14 +184,13 @@ def test_significant_states_with_session_entity_minimal_response_no_matches(
)
def test_significant_states_with_session_single_entity(
hass_recorder: Callable[..., HomeAssistant],
async def test_significant_states_with_session_single_entity(
hass: HomeAssistant,
) -> None:
"""Test get_significant_states_with_session with a single entity."""
hass = hass_recorder()
hass.states.set("demo.id", "any", {"attr": True})
hass.states.set("demo.id", "any2", {"attr": True})
wait_recording_done(hass)
hass.states.async_set("demo.id", "any", {"attr": True})
hass.states.async_set("demo.id", "any2", {"attr": True})
await async_wait_recording_done(hass)
now = dt_util.utcnow()
with session_scope(hass=hass, read_only=True) as session:
states = history.get_significant_states_with_session(
@ -206,17 +213,15 @@ def test_significant_states_with_session_single_entity(
({}, True, 3),
],
)
def test_state_changes_during_period(
hass_recorder: Callable[..., HomeAssistant], attributes, no_attributes, limit
async def test_state_changes_during_period(
hass: HomeAssistant, attributes, no_attributes, limit
) -> None:
"""Test state change during period."""
hass = hass_recorder()
entity_id = "media_player.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state, attributes)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, attributes)
return hass.states.get(entity_id)
start = dt_util.utcnow()
@ -238,6 +243,7 @@ def test_state_changes_during_period(
freezer.move_to(end)
set_state("Netflix")
set_state("Plex")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(
hass, start, end, entity_id, no_attributes, limit=limit
@ -246,17 +252,15 @@ def test_state_changes_during_period(
assert_multiple_states_equal_without_context(states[:limit], hist[entity_id])
def test_state_changes_during_period_last_reported(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_last_reported(
hass: HomeAssistant,
) -> None:
"""Test state change during period."""
hass = hass_recorder()
entity_id = "media_player.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow()
@ -275,23 +279,22 @@ def test_state_changes_during_period_last_reported(
freezer.move_to(end)
set_state("Netflix")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(hass, start, end, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_state_changes_during_period_descending(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_descending(
hass: HomeAssistant,
) -> None:
"""Test state change during period descending."""
hass = hass_recorder()
entity_id = "media_player.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state, {"any": 1})
wait_recording_done(hass)
hass.states.async_set(entity_id, state, {"any": 1})
return hass.states.get(entity_id)
start = dt_util.utcnow().replace(microsecond=0)
@ -320,6 +323,7 @@ def test_state_changes_during_period_descending(
freezer.move_to(end)
set_state("Netflix")
set_state("Plex")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(
hass, start, end, entity_id, no_attributes=False, descending=False
@ -385,15 +389,13 @@ def test_state_changes_during_period_descending(
)
def test_get_last_state_changes(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_last_state_changes(hass: HomeAssistant) -> None:
"""Test number of state changes."""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -409,23 +411,22 @@ def test_get_last_state_changes(hass_recorder: Callable[..., HomeAssistant]) ->
freezer.move_to(point2)
states.append(set_state("3"))
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_get_last_state_changes_last_reported(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_last_state_changes_last_reported(
hass: HomeAssistant,
) -> None:
"""Test number of state changes."""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -441,21 +442,20 @@ def test_get_last_state_changes_last_reported(
freezer.move_to(point2)
states.append(set_state("2"))
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_get_last_state_change(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_last_state_change(hass: HomeAssistant) -> None:
"""Test getting the last state change for an entity."""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -471,27 +471,26 @@ def test_get_last_state_change(hass_recorder: Callable[..., HomeAssistant]) -> N
freezer.move_to(point2)
states.append(set_state("3"))
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 1, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_ensure_state_can_be_copied(
hass_recorder: Callable[..., HomeAssistant],
async def test_ensure_state_can_be_copied(
hass: HomeAssistant,
) -> None:
"""Ensure a state can pass though copy().
The filter integration uses copy() on states
from history.
"""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -502,6 +501,7 @@ def test_ensure_state_can_be_copied(
freezer.move_to(point)
set_state("2")
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
@ -509,21 +509,22 @@ def test_ensure_state_can_be_copied(
assert_states_equal_without_context(copy(hist[entity_id][1]), hist[entity_id][1])
def test_get_significant_states(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_significant_states(hass: HomeAssistant) -> None:
"""Test that only significant states are returned.
We should get back every thermostat change that
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(hass, zero, four, entity_ids=list(states))
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_minimal_response(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_minimal_response(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned.
@ -534,8 +535,9 @@ def test_get_significant_states_minimal_response(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass, zero, four, minimal_response=True, entity_ids=list(states)
)
@ -591,8 +593,8 @@ def test_get_significant_states_minimal_response(
@pytest.mark.parametrize("time_zone", ["Europe/Berlin", "US/Hawaii", "UTC"])
def test_get_significant_states_with_initial(
time_zone, hass_recorder: Callable[..., HomeAssistant]
async def test_get_significant_states_with_initial(
time_zone, hass: HomeAssistant
) -> None:
"""Test that only significant states are returned.
@ -600,9 +602,10 @@ def test_get_significant_states_with_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
hass.config.set_time_zone(time_zone)
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
one_and_half = zero + timedelta(seconds=1.5)
for entity_id in states:
if entity_id == "media_player.test":
@ -621,8 +624,8 @@ def test_get_significant_states_with_initial(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_without_initial(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_without_initial(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned.
@ -630,8 +633,9 @@ def test_get_significant_states_without_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
one = zero + timedelta(seconds=1)
one_with_microsecond = zero + timedelta(seconds=1, microseconds=1)
one_and_half = zero + timedelta(seconds=1.5)
@ -654,12 +658,13 @@ def test_get_significant_states_without_initial(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_entity_id(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_entity_id(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned for one entity."""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
del states["media_player.test2"]
del states["media_player.test3"]
del states["thermostat.test"]
@ -671,12 +676,12 @@ def test_get_significant_states_entity_id(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_multiple_entity_ids(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_multiple_entity_ids(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned for one entity."""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass,
@ -693,16 +698,17 @@ def test_get_significant_states_multiple_entity_ids(
)
def test_get_significant_states_are_ordered(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_are_ordered(
hass: HomeAssistant,
) -> None:
"""Test order of results from get_significant_states.
When entity ids are given, the results should be returned with the data
in the same order.
"""
hass = hass_recorder()
zero, four, _states = record_states(hass)
await async_wait_recording_done(hass)
entity_ids = ["media_player.test", "media_player.test2"]
hist = history.get_significant_states(hass, zero, four, entity_ids)
assert list(hist.keys()) == entity_ids
@ -711,17 +717,15 @@ def test_get_significant_states_are_ordered(
assert list(hist.keys()) == entity_ids
def test_get_significant_states_only(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_only(
hass: HomeAssistant,
) -> None:
"""Test significant states when significant_states_only is set."""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state, **kwargs):
"""Set the state."""
hass.states.set(entity_id, state, **kwargs)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, **kwargs)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=4)
@ -742,6 +746,7 @@ def test_get_significant_states_only(
freezer.move_to(points[2])
# everything is different
states.append(set_state("412", attributes={"attribute": 54.23}))
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass,
@ -775,7 +780,7 @@ def test_get_significant_states_only(
async def test_get_significant_states_only_minimal_response(
recorder_mock: Recorder, hass: HomeAssistant
hass: HomeAssistant,
) -> None:
"""Test significant states when significant_states_only is True."""
now = dt_util.utcnow()
@ -818,8 +823,7 @@ def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
def set_state(entity_id, state, **kwargs):
"""Set the state."""
hass.states.set(entity_id, state, **kwargs)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, **kwargs)
return hass.states.get(entity_id)
zero = dt_util.utcnow()
@ -886,7 +890,6 @@ def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
async def test_state_changes_during_period_query_during_migration_to_schema_25(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
recorder_db_url: str,
) -> None:
@ -895,7 +898,7 @@ async def test_state_changes_during_period_query_during_migration_to_schema_25(
# This test doesn't run on MySQL / MariaDB / Postgresql; we can't drop table state_attributes
return
instance = await async_setup_recorder_instance(hass, {})
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
start = dt_util.utcnow()
@ -953,7 +956,6 @@ async def test_state_changes_during_period_query_during_migration_to_schema_25(
async def test_get_states_query_during_migration_to_schema_25(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
recorder_db_url: str,
) -> None:
@ -962,7 +964,7 @@ async def test_get_states_query_during_migration_to_schema_25(
# This test doesn't run on MySQL / MariaDB / Postgresql; we can't drop table state_attributes
return
instance = await async_setup_recorder_instance(hass, {})
instance = recorder.get_instance(hass)
start = dt_util.utcnow()
point = start + timedelta(seconds=1)
@ -1004,7 +1006,6 @@ async def test_get_states_query_during_migration_to_schema_25(
async def test_get_states_query_during_migration_to_schema_25_multiple_entities(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
recorder_db_url: str,
) -> None:
@ -1013,7 +1014,7 @@ async def test_get_states_query_during_migration_to_schema_25_multiple_entities(
# This test doesn't run on MySQL / MariaDB / Postgresql; we can't drop table state_attributes
return
instance = await async_setup_recorder_instance(hass, {})
instance = recorder.get_instance(hass)
start = dt_util.utcnow()
point = start + timedelta(seconds=1)
@ -1058,12 +1059,9 @@ async def test_get_states_query_during_migration_to_schema_25_multiple_entities(
async def test_get_full_significant_states_handles_empty_last_changed(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
) -> None:
"""Test getting states when last_changed is null."""
await async_setup_recorder_instance(hass, {})
now = dt_util.utcnow()
hass.states.async_set("sensor.one", "on", {"attr": "original"})
state0 = hass.states.get("sensor.one")
@ -1155,21 +1153,20 @@ async def test_get_full_significant_states_handles_empty_last_changed(
)
def test_state_changes_during_period_multiple_entities_single_test(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_multiple_entities_single_test(
hass: HomeAssistant,
) -> None:
"""Test state change during period with multiple entities in the same test.
This test ensures the sqlalchemy query cache does not
generate incorrect results.
"""
hass = hass_recorder()
start = dt_util.utcnow()
test_entites = {f"sensor.{i}": str(i) for i in range(30)}
for entity_id, value in test_entites.items():
hass.states.set(entity_id, value)
hass.states.async_set(entity_id, value)
await async_wait_recording_done(hass)
wait_recording_done(hass)
end = dt_util.utcnow()
for entity_id, value in test_entites.items():
@ -1180,11 +1177,9 @@ def test_state_changes_during_period_multiple_entities_single_test(
@pytest.mark.freeze_time("2039-01-19 03:14:07.555555-00:00")
async def test_get_full_significant_states_past_year_2038(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
) -> None:
"""Test we can store times past year 2038."""
await async_setup_recorder_instance(hass, {})
past_2038_time = dt_util.parse_datetime("2039-01-19 03:14:07.555555-00:00")
hass.states.async_set("sensor.one", "on", {"attr": "original"})
state0 = hass.states.get("sensor.one")
@ -1214,31 +1209,28 @@ async def test_get_full_significant_states_past_year_2038(
assert sensor_one_states[0].last_updated == past_2038_time
def test_get_significant_states_without_entity_ids_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_without_entity_ids_raises(
hass: HomeAssistant,
) -> None:
"""Test at least one entity id is required for get_significant_states."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(ValueError, match="entity_ids must be provided"):
history.get_significant_states(hass, now, None)
def test_state_changes_during_period_without_entity_ids_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_without_entity_ids_raises(
hass: HomeAssistant,
) -> None:
"""Test at least one entity id is required for state_changes_during_period."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(ValueError, match="entity_id must be provided"):
history.state_changes_during_period(hass, now, None)
def test_get_significant_states_with_filters_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_with_filters_raises(
hass: HomeAssistant,
) -> None:
"""Test passing filters is no longer supported."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(NotImplementedError, match="Filters are no longer supported"):
history.get_significant_states(
@ -1246,29 +1238,26 @@ def test_get_significant_states_with_filters_raises(
)
def test_get_significant_states_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test get_significant_states returns an empty dict when entities not in the db."""
hass = hass_recorder()
now = dt_util.utcnow()
assert history.get_significant_states(hass, now, None, ["nonexistent.entity"]) == {}
def test_state_changes_during_period_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test state_changes_during_period returns an empty dict when entities not in the db."""
hass = hass_recorder()
now = dt_util.utcnow()
assert (
history.state_changes_during_period(hass, now, None, "nonexistent.entity") == {}
)
def test_get_last_state_changes_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_last_state_changes_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test get_last_state_changes returns an empty dict when entities not in the db."""
hass = hass_recorder()
assert history.get_last_state_changes(hass, 1, "nonexistent.entity") == {}

View file

@ -2,7 +2,6 @@
from __future__ import annotations
from collections.abc import Callable
from copy import copy
from datetime import datetime, timedelta
import json
@ -12,7 +11,7 @@ from freezegun import freeze_time
import pytest
from homeassistant.components import recorder
from homeassistant.components.recorder import history
from homeassistant.components.recorder import Recorder, history
from homeassistant.components.recorder.filters import Filters
from homeassistant.components.recorder.models import process_timestamp
from homeassistant.components.recorder.util import session_scope
@ -25,10 +24,19 @@ from .common import (
assert_multiple_states_equal_without_context,
assert_multiple_states_equal_without_context_and_last_changed,
assert_states_equal_without_context,
async_wait_recording_done,
old_db_schema,
wait_recording_done,
)
from tests.typing import RecorderInstanceGenerator
@pytest.fixture
async def mock_recorder_before_hass(
async_setup_recorder_instance: RecorderInstanceGenerator,
) -> None:
"""Set up recorder."""
@pytest.fixture(autouse=True)
def db_schema_30():
@ -37,11 +45,15 @@ def db_schema_30():
yield
def test_get_full_significant_states_with_session_entity_no_matches(
hass_recorder: Callable[..., HomeAssistant],
@pytest.fixture(autouse=True)
def setup_recorder(db_schema_30, recorder_mock: Recorder) -> recorder.Recorder:
"""Set up recorder."""
async def test_get_full_significant_states_with_session_entity_no_matches(
hass: HomeAssistant,
) -> None:
"""Test getting states at a specific point in time for entities that never have been recorded."""
hass = hass_recorder()
now = dt_util.utcnow()
time_before_recorder_ran = now - timedelta(days=1000)
instance = recorder.get_instance(hass)
@ -67,11 +79,10 @@ def test_get_full_significant_states_with_session_entity_no_matches(
)
def test_significant_states_with_session_entity_minimal_response_no_matches(
hass_recorder: Callable[..., HomeAssistant],
async def test_significant_states_with_session_entity_minimal_response_no_matches(
hass: HomeAssistant,
) -> None:
"""Test getting states at a specific point in time for entities that never have been recorded."""
hass = hass_recorder()
now = dt_util.utcnow()
time_before_recorder_ran = now - timedelta(days=1000)
instance = recorder.get_instance(hass)
@ -112,19 +123,17 @@ def test_significant_states_with_session_entity_minimal_response_no_matches(
({}, True, 3),
],
)
def test_state_changes_during_period(
hass_recorder: Callable[..., HomeAssistant], attributes, no_attributes, limit
async def test_state_changes_during_period(
hass: HomeAssistant, attributes, no_attributes, limit
) -> None:
"""Test state change during period."""
hass = hass_recorder()
entity_id = "media_player.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state, attributes)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, attributes)
return hass.states.get(entity_id)
start = dt_util.utcnow()
@ -146,6 +155,7 @@ def test_state_changes_during_period(
freezer.move_to(end)
set_state("Netflix")
set_state("Plex")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(
hass, start, end, entity_id, no_attributes, limit=limit
@ -154,19 +164,17 @@ def test_state_changes_during_period(
assert_multiple_states_equal_without_context(states[:limit], hist[entity_id])
def test_state_changes_during_period_descending(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_descending(
hass: HomeAssistant,
) -> None:
"""Test state change during period descending."""
hass = hass_recorder()
entity_id = "media_player.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state, {"any": 1})
wait_recording_done(hass)
hass.states.async_set(entity_id, state, {"any": 1})
return hass.states.get(entity_id)
start = dt_util.utcnow()
@ -196,6 +204,7 @@ def test_state_changes_during_period_descending(
freezer.move_to(end)
set_state("Netflix")
set_state("Plex")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(
hass, start, end, entity_id, no_attributes=False, descending=False
@ -210,17 +219,15 @@ def test_state_changes_during_period_descending(
)
def test_get_last_state_changes(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_last_state_changes(hass: HomeAssistant) -> None:
"""Test number of state changes."""
hass = hass_recorder()
entity_id = "sensor.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -236,29 +243,28 @@ def test_get_last_state_changes(hass_recorder: Callable[..., HomeAssistant]) ->
freezer.move_to(point2)
states.append(set_state("3"))
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_ensure_state_can_be_copied(
hass_recorder: Callable[..., HomeAssistant],
async def test_ensure_state_can_be_copied(
hass: HomeAssistant,
) -> None:
"""Ensure a state can pass though copy().
The filter integration uses copy() on states
from history.
"""
hass = hass_recorder()
entity_id = "sensor.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -269,6 +275,7 @@ def test_ensure_state_can_be_copied(
freezer.move_to(point)
set_state("2")
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
@ -280,24 +287,23 @@ def test_ensure_state_can_be_copied(
)
def test_get_significant_states(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_significant_states(hass: HomeAssistant) -> None:
"""Test that only significant states are returned.
We should get back every thermostat change that
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(hass, zero, four, entity_ids=list(states))
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_minimal_response(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
async def test_get_significant_states_minimal_response(hass: HomeAssistant) -> None:
"""Test that only significant states are returned.
When minimal responses is set only the first and
@ -306,10 +312,11 @@ def test_get_significant_states_minimal_response(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass, zero, four, minimal_response=True, entity_ids=list(states)
)
@ -364,19 +371,18 @@ def test_get_significant_states_minimal_response(
)
def test_get_significant_states_with_initial(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
async def test_get_significant_states_with_initial(hass: HomeAssistant) -> None:
"""Test that only significant states are returned.
We should get back every thermostat change that
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
one = zero + timedelta(seconds=1)
one_with_microsecond = zero + timedelta(seconds=1, microseconds=1)
one_and_half = zero + timedelta(seconds=1.5)
@ -398,19 +404,18 @@ def test_get_significant_states_with_initial(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_without_initial(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
async def test_get_significant_states_without_initial(hass: HomeAssistant) -> None:
"""Test that only significant states are returned.
We should get back every thermostat change that
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
one = zero + timedelta(seconds=1)
one_with_microsecond = zero + timedelta(seconds=1, microseconds=1)
one_and_half = zero + timedelta(seconds=1.5)
@ -432,14 +437,13 @@ def test_get_significant_states_without_initial(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_entity_id(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
async def test_get_significant_states_entity_id(hass: HomeAssistant) -> None:
"""Test that only significant states are returned for one entity."""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
del states["media_player.test2"]
del states["media_player.test3"]
del states["thermostat.test"]
@ -450,14 +454,13 @@ def test_get_significant_states_entity_id(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_multiple_entity_ids(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
async def test_get_significant_states_multiple_entity_ids(hass: HomeAssistant) -> None:
"""Test that only significant states are returned for one entity."""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
del states["media_player.test2"]
del states["media_player.test3"]
del states["thermostat.test2"]
@ -477,19 +480,18 @@ def test_get_significant_states_multiple_entity_ids(
)
def test_get_significant_states_are_ordered(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
async def test_get_significant_states_are_ordered(hass: HomeAssistant) -> None:
"""Test order of results from get_significant_states.
When entity ids are given, the results should be returned with the data
in the same order.
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, _states = record_states(hass)
await async_wait_recording_done(hass)
entity_ids = ["media_player.test", "media_player.test2"]
hist = history.get_significant_states(hass, zero, four, entity_ids)
assert list(hist.keys()) == entity_ids
@ -498,19 +500,15 @@ def test_get_significant_states_are_ordered(
assert list(hist.keys()) == entity_ids
def test_get_significant_states_only(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
async def test_get_significant_states_only(hass: HomeAssistant) -> None:
"""Test significant states when significant_states_only is set."""
hass = hass_recorder()
entity_id = "sensor.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state, **kwargs):
"""Set the state."""
hass.states.set(entity_id, state, **kwargs)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, **kwargs)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=4)
@ -531,6 +529,7 @@ def test_get_significant_states_only(
freezer.move_to(points[2])
# everything is different
states.append(set_state("412", attributes={"attribute": 54.23}))
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass,
@ -563,7 +562,9 @@ def test_get_significant_states_only(
)
def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
def record_states(
hass: HomeAssistant,
) -> tuple[datetime, datetime, dict[str, list[State]]]:
"""Record some test states.
We inject a bunch of state updates from media player, zone and
@ -579,8 +580,7 @@ def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
def set_state(entity_id, state, **kwargs):
"""Set the state."""
hass.states.set(entity_id, state, **kwargs)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, **kwargs)
return hass.states.get(entity_id)
zero = dt_util.utcnow()
@ -639,23 +639,22 @@ def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
return zero, four, states
def test_state_changes_during_period_multiple_entities_single_test(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_multiple_entities_single_test(
hass: HomeAssistant,
) -> None:
"""Test state change during period with multiple entities in the same test.
This test ensures the sqlalchemy query cache does not
generate incorrect results.
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
start = dt_util.utcnow()
test_entites = {f"sensor.{i}": str(i) for i in range(30)}
for entity_id, value in test_entites.items():
hass.states.set(entity_id, value)
hass.states.async_set(entity_id, value)
await async_wait_recording_done(hass)
wait_recording_done(hass)
end = dt_util.utcnow()
for entity_id, value in test_entites.items():
@ -664,31 +663,24 @@ def test_state_changes_during_period_multiple_entities_single_test(
assert hist[entity_id][0].state == value
def test_get_significant_states_without_entity_ids_raises(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
def test_get_significant_states_without_entity_ids_raises(hass: HomeAssistant) -> None:
"""Test at least one entity id is required for get_significant_states."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(ValueError, match="entity_ids must be provided"):
history.get_significant_states(hass, now, None)
def test_state_changes_during_period_without_entity_ids_raises(
hass_recorder: Callable[..., HomeAssistant],
hass: HomeAssistant,
) -> None:
"""Test at least one entity id is required for state_changes_during_period."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(ValueError, match="entity_id must be provided"):
history.state_changes_during_period(hass, now, None)
def test_get_significant_states_with_filters_raises(
hass_recorder: Callable[..., HomeAssistant],
) -> None:
def test_get_significant_states_with_filters_raises(hass: HomeAssistant) -> None:
"""Test passing filters is no longer supported."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(NotImplementedError, match="Filters are no longer supported"):
history.get_significant_states(
@ -697,19 +689,17 @@ def test_get_significant_states_with_filters_raises(
def test_get_significant_states_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
hass: HomeAssistant,
) -> None:
"""Test get_significant_states returns an empty dict when entities not in the db."""
hass = hass_recorder()
now = dt_util.utcnow()
assert history.get_significant_states(hass, now, None, ["nonexistent.entity"]) == {}
def test_state_changes_during_period_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
hass: HomeAssistant,
) -> None:
"""Test state_changes_during_period returns an empty dict when entities not in the db."""
hass = hass_recorder()
now = dt_util.utcnow()
assert (
history.state_changes_during_period(hass, now, None, "nonexistent.entity") == {}
@ -717,8 +707,7 @@ def test_state_changes_during_period_with_non_existent_entity_ids_returns_empty(
def test_get_last_state_changes_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
hass: HomeAssistant,
) -> None:
"""Test get_last_state_changes returns an empty dict when entities not in the db."""
hass = hass_recorder()
assert history.get_last_state_changes(hass, 1, "nonexistent.entity") == {}

View file

@ -2,7 +2,6 @@
from __future__ import annotations
from collections.abc import Callable
from copy import copy
from datetime import datetime, timedelta
import json
@ -12,7 +11,7 @@ from freezegun import freeze_time
import pytest
from homeassistant.components import recorder
from homeassistant.components.recorder import history
from homeassistant.components.recorder import Recorder, history
from homeassistant.components.recorder.filters import Filters
from homeassistant.components.recorder.models import process_timestamp
from homeassistant.components.recorder.util import session_scope
@ -25,10 +24,19 @@ from .common import (
assert_multiple_states_equal_without_context,
assert_multiple_states_equal_without_context_and_last_changed,
assert_states_equal_without_context,
async_wait_recording_done,
old_db_schema,
wait_recording_done,
)
from tests.typing import RecorderInstanceGenerator
@pytest.fixture
async def mock_recorder_before_hass(
async_setup_recorder_instance: RecorderInstanceGenerator,
) -> None:
"""Set up recorder."""
@pytest.fixture(autouse=True)
def db_schema_32():
@ -37,11 +45,15 @@ def db_schema_32():
yield
def test_get_full_significant_states_with_session_entity_no_matches(
hass_recorder: Callable[..., HomeAssistant],
@pytest.fixture(autouse=True)
def setup_recorder(db_schema_32, recorder_mock: Recorder) -> recorder.Recorder:
"""Set up recorder."""
async def test_get_full_significant_states_with_session_entity_no_matches(
hass: HomeAssistant,
) -> None:
"""Test getting states at a specific point in time for entities that never have been recorded."""
hass = hass_recorder()
now = dt_util.utcnow()
time_before_recorder_ran = now - timedelta(days=1000)
instance = recorder.get_instance(hass)
@ -67,11 +79,10 @@ def test_get_full_significant_states_with_session_entity_no_matches(
)
def test_significant_states_with_session_entity_minimal_response_no_matches(
hass_recorder: Callable[..., HomeAssistant],
async def test_significant_states_with_session_entity_minimal_response_no_matches(
hass: HomeAssistant,
) -> None:
"""Test getting states at a specific point in time for entities that never have been recorded."""
hass = hass_recorder()
now = dt_util.utcnow()
time_before_recorder_ran = now - timedelta(days=1000)
instance = recorder.get_instance(hass)
@ -112,19 +123,17 @@ def test_significant_states_with_session_entity_minimal_response_no_matches(
({}, True, 3),
],
)
def test_state_changes_during_period(
hass_recorder: Callable[..., HomeAssistant], attributes, no_attributes, limit
async def test_state_changes_during_period(
hass: HomeAssistant, attributes, no_attributes, limit
) -> None:
"""Test state change during period."""
hass = hass_recorder()
entity_id = "media_player.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state, attributes)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, attributes)
return hass.states.get(entity_id)
start = dt_util.utcnow()
@ -146,6 +155,7 @@ def test_state_changes_during_period(
freezer.move_to(end)
set_state("Netflix")
set_state("Plex")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(
hass, start, end, entity_id, no_attributes, limit=limit
@ -154,19 +164,17 @@ def test_state_changes_during_period(
assert_multiple_states_equal_without_context(states[:limit], hist[entity_id])
def test_state_changes_during_period_descending(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_descending(
hass: HomeAssistant,
) -> None:
"""Test state change during period descending."""
hass = hass_recorder()
entity_id = "media_player.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state, {"any": 1})
wait_recording_done(hass)
hass.states.async_set(entity_id, state, {"any": 1})
return hass.states.get(entity_id)
start = dt_util.utcnow()
@ -195,6 +203,7 @@ def test_state_changes_during_period_descending(
freezer.move_to(end)
set_state("Netflix")
set_state("Plex")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(
hass, start, end, entity_id, no_attributes=False, descending=False
@ -209,17 +218,15 @@ def test_state_changes_during_period_descending(
)
def test_get_last_state_changes(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_last_state_changes(hass: HomeAssistant) -> None:
"""Test number of state changes."""
hass = hass_recorder()
entity_id = "sensor.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -235,29 +242,28 @@ def test_get_last_state_changes(hass_recorder: Callable[..., HomeAssistant]) ->
freezer.move_to(point2)
states.append(set_state("3"))
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_ensure_state_can_be_copied(
hass_recorder: Callable[..., HomeAssistant],
async def test_ensure_state_can_be_copied(
hass: HomeAssistant,
) -> None:
"""Ensure a state can pass though copy().
The filter integration uses copy() on states
from history.
"""
hass = hass_recorder()
entity_id = "sensor.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -268,6 +274,7 @@ def test_ensure_state_can_be_copied(
freezer.move_to(point)
set_state("2")
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
@ -279,23 +286,24 @@ def test_ensure_state_can_be_copied(
)
def test_get_significant_states(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_significant_states(hass: HomeAssistant) -> None:
"""Test that only significant states are returned.
We should get back every thermostat change that
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(hass, zero, four, entity_ids=list(states))
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_minimal_response(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_minimal_response(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned.
@ -305,10 +313,11 @@ def test_get_significant_states_minimal_response(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass, zero, four, minimal_response=True, entity_ids=list(states)
)
@ -364,8 +373,8 @@ def test_get_significant_states_minimal_response(
@pytest.mark.parametrize("time_zone", ["Europe/Berlin", "US/Hawaii", "UTC"])
def test_get_significant_states_with_initial(
time_zone, hass_recorder: Callable[..., HomeAssistant]
async def test_get_significant_states_with_initial(
time_zone, hass: HomeAssistant
) -> None:
"""Test that only significant states are returned.
@ -373,9 +382,10 @@ def test_get_significant_states_with_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
hass.config.set_time_zone(time_zone)
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
one = zero + timedelta(seconds=1)
one_and_half = zero + timedelta(seconds=1.5)
for entity_id in states:
@ -391,8 +401,8 @@ def test_get_significant_states_with_initial(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_without_initial(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_without_initial(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned.
@ -400,10 +410,11 @@ def test_get_significant_states_without_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
one = zero + timedelta(seconds=1)
one_with_microsecond = zero + timedelta(seconds=1, microseconds=1)
one_and_half = zero + timedelta(seconds=1.5)
@ -425,14 +436,15 @@ def test_get_significant_states_without_initial(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_entity_id(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_entity_id(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned for one entity."""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
del states["media_player.test2"]
del states["media_player.test3"]
del states["thermostat.test"]
@ -443,14 +455,15 @@ def test_get_significant_states_entity_id(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_multiple_entity_ids(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_multiple_entity_ids(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned for one entity."""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
del states["media_player.test2"]
del states["media_player.test3"]
del states["thermostat.test2"]
@ -470,19 +483,19 @@ def test_get_significant_states_multiple_entity_ids(
)
def test_get_significant_states_are_ordered(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_are_ordered(
hass: HomeAssistant,
) -> None:
"""Test order of results from get_significant_states.
When entity ids are given, the results should be returned with the data
in the same order.
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
zero, four, _states = record_states(hass)
await async_wait_recording_done(hass)
entity_ids = ["media_player.test", "media_player.test2"]
hist = history.get_significant_states(hass, zero, four, entity_ids)
assert list(hist.keys()) == entity_ids
@ -491,19 +504,17 @@ def test_get_significant_states_are_ordered(
assert list(hist.keys()) == entity_ids
def test_get_significant_states_only(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_only(
hass: HomeAssistant,
) -> None:
"""Test significant states when significant_states_only is set."""
hass = hass_recorder()
entity_id = "sensor.test"
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
def set_state(state, **kwargs):
"""Set the state."""
hass.states.set(entity_id, state, **kwargs)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, **kwargs)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=4)
@ -524,6 +535,7 @@ def test_get_significant_states_only(
freezer.move_to(points[2])
# everything is different
states.append(set_state("412", attributes={"attribute": 54.23}))
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass,
@ -572,8 +584,7 @@ def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
def set_state(entity_id, state, **kwargs):
"""Set the state."""
hass.states.set(entity_id, state, **kwargs)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, **kwargs)
return hass.states.get(entity_id)
zero = dt_util.utcnow()
@ -632,23 +643,22 @@ def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
return zero, four, states
def test_state_changes_during_period_multiple_entities_single_test(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_multiple_entities_single_test(
hass: HomeAssistant,
) -> None:
"""Test state change during period with multiple entities in the same test.
This test ensures the sqlalchemy query cache does not
generate incorrect results.
"""
hass = hass_recorder()
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
start = dt_util.utcnow()
test_entites = {f"sensor.{i}": str(i) for i in range(30)}
for entity_id, value in test_entites.items():
hass.states.set(entity_id, value)
hass.states.async_set(entity_id, value)
wait_recording_done(hass)
await async_wait_recording_done(hass)
end = dt_util.utcnow()
for entity_id, value in test_entites.items():
@ -657,31 +667,28 @@ def test_state_changes_during_period_multiple_entities_single_test(
assert hist[entity_id][0].state == value
def test_get_significant_states_without_entity_ids_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_without_entity_ids_raises(
hass: HomeAssistant,
) -> None:
"""Test at least one entity id is required for get_significant_states."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(ValueError, match="entity_ids must be provided"):
history.get_significant_states(hass, now, None)
def test_state_changes_during_period_without_entity_ids_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_without_entity_ids_raises(
hass: HomeAssistant,
) -> None:
"""Test at least one entity id is required for state_changes_during_period."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(ValueError, match="entity_id must be provided"):
history.state_changes_during_period(hass, now, None)
def test_get_significant_states_with_filters_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_with_filters_raises(
hass: HomeAssistant,
) -> None:
"""Test passing filters is no longer supported."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(NotImplementedError, match="Filters are no longer supported"):
history.get_significant_states(
@ -689,29 +696,26 @@ def test_get_significant_states_with_filters_raises(
)
def test_get_significant_states_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test get_significant_states returns an empty dict when entities not in the db."""
hass = hass_recorder()
now = dt_util.utcnow()
assert history.get_significant_states(hass, now, None, ["nonexistent.entity"]) == {}
def test_state_changes_during_period_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test state_changes_during_period returns an empty dict when entities not in the db."""
hass = hass_recorder()
now = dt_util.utcnow()
assert (
history.state_changes_during_period(hass, now, None, "nonexistent.entity") == {}
)
def test_get_last_state_changes_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_last_state_changes_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test get_last_state_changes returns an empty dict when entities not in the db."""
hass = hass_recorder()
assert history.get_last_state_changes(hass, 1, "nonexistent.entity") == {}

View file

@ -2,7 +2,6 @@
from __future__ import annotations
from collections.abc import Callable
from copy import copy
from datetime import datetime, timedelta
import json
@ -35,13 +34,19 @@ from .common import (
async_recorder_block_till_done,
async_wait_recording_done,
old_db_schema,
wait_recording_done,
)
from .db_schema_42 import Events, RecorderRuns, StateAttributes, States, StatesMeta
from tests.typing import RecorderInstanceGenerator
@pytest.fixture
async def mock_recorder_before_hass(
async_setup_recorder_instance: RecorderInstanceGenerator,
) -> None:
"""Set up recorder."""
@pytest.fixture(autouse=True)
def db_schema_42():
"""Fixture to initialize the db with the old schema 42."""
@ -49,6 +54,11 @@ def db_schema_42():
yield
@pytest.fixture(autouse=True)
def setup_recorder(db_schema_42, recorder_mock: Recorder) -> recorder.Recorder:
"""Set up recorder."""
async def _async_get_states(
hass: HomeAssistant,
utc_point_in_time: datetime,
@ -120,11 +130,10 @@ def _add_db_entries(
)
def test_get_full_significant_states_with_session_entity_no_matches(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_full_significant_states_with_session_entity_no_matches(
hass: HomeAssistant,
) -> None:
"""Test getting states at a specific point in time for entities that never have been recorded."""
hass = hass_recorder()
now = dt_util.utcnow()
time_before_recorder_ran = now - timedelta(days=1000)
with session_scope(hass=hass, read_only=True) as session:
@ -146,11 +155,10 @@ def test_get_full_significant_states_with_session_entity_no_matches(
)
def test_significant_states_with_session_entity_minimal_response_no_matches(
hass_recorder: Callable[..., HomeAssistant],
async def test_significant_states_with_session_entity_minimal_response_no_matches(
hass: HomeAssistant,
) -> None:
"""Test getting states at a specific point in time for entities that never have been recorded."""
hass = hass_recorder()
now = dt_util.utcnow()
time_before_recorder_ran = now - timedelta(days=1000)
with session_scope(hass=hass, read_only=True) as session:
@ -178,14 +186,13 @@ def test_significant_states_with_session_entity_minimal_response_no_matches(
)
def test_significant_states_with_session_single_entity(
hass_recorder: Callable[..., HomeAssistant],
async def test_significant_states_with_session_single_entity(
hass: HomeAssistant,
) -> None:
"""Test get_significant_states_with_session with a single entity."""
hass = hass_recorder()
hass.states.set("demo.id", "any", {"attr": True})
hass.states.set("demo.id", "any2", {"attr": True})
wait_recording_done(hass)
hass.states.async_set("demo.id", "any", {"attr": True})
hass.states.async_set("demo.id", "any2", {"attr": True})
await async_wait_recording_done(hass)
now = dt_util.utcnow()
with session_scope(hass=hass, read_only=True) as session:
states = history.get_significant_states_with_session(
@ -208,17 +215,15 @@ def test_significant_states_with_session_single_entity(
({}, True, 3),
],
)
def test_state_changes_during_period(
hass_recorder: Callable[..., HomeAssistant], attributes, no_attributes, limit
async def test_state_changes_during_period(
hass: HomeAssistant, attributes, no_attributes, limit
) -> None:
"""Test state change during period."""
hass = hass_recorder()
entity_id = "media_player.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state, attributes)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, attributes)
return hass.states.get(entity_id)
start = dt_util.utcnow()
@ -240,6 +245,7 @@ def test_state_changes_during_period(
freezer.move_to(end)
set_state("Netflix")
set_state("Plex")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(
hass, start, end, entity_id, no_attributes, limit=limit
@ -248,17 +254,15 @@ def test_state_changes_during_period(
assert_multiple_states_equal_without_context(states[:limit], hist[entity_id])
def test_state_changes_during_period_last_reported(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_last_reported(
hass: HomeAssistant,
) -> None:
"""Test state change during period."""
hass = hass_recorder()
entity_id = "media_player.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return ha.State.from_dict(hass.states.get(entity_id).as_dict())
start = dt_util.utcnow()
@ -277,23 +281,22 @@ def test_state_changes_during_period_last_reported(
freezer.move_to(end)
set_state("Netflix")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(hass, start, end, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_state_changes_during_period_descending(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_descending(
hass: HomeAssistant,
) -> None:
"""Test state change during period descending."""
hass = hass_recorder()
entity_id = "media_player.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state, {"any": 1})
wait_recording_done(hass)
hass.states.async_set(entity_id, state, {"any": 1})
return hass.states.get(entity_id)
start = dt_util.utcnow().replace(microsecond=0)
@ -322,6 +325,7 @@ def test_state_changes_during_period_descending(
freezer.move_to(end)
set_state("Netflix")
set_state("Plex")
await async_wait_recording_done(hass)
hist = history.state_changes_during_period(
hass, start, end, entity_id, no_attributes=False, descending=False
@ -387,15 +391,13 @@ def test_state_changes_during_period_descending(
)
def test_get_last_state_changes(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_last_state_changes(hass: HomeAssistant) -> None:
"""Test number of state changes."""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -411,23 +413,22 @@ def test_get_last_state_changes(hass_recorder: Callable[..., HomeAssistant]) ->
freezer.move_to(point2)
states.append(set_state("3"))
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_get_last_state_changes_last_reported(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_last_state_changes_last_reported(
hass: HomeAssistant,
) -> None:
"""Test number of state changes."""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return ha.State.from_dict(hass.states.get(entity_id).as_dict())
start = dt_util.utcnow() - timedelta(minutes=2)
@ -443,21 +444,20 @@ def test_get_last_state_changes_last_reported(
freezer.move_to(point2)
states.append(set_state("2"))
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_get_last_state_change(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_last_state_change(hass: HomeAssistant) -> None:
"""Test getting the last state change for an entity."""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -473,27 +473,26 @@ def test_get_last_state_change(hass_recorder: Callable[..., HomeAssistant]) -> N
freezer.move_to(point2)
states.append(set_state("3"))
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 1, entity_id)
assert_multiple_states_equal_without_context(states, hist[entity_id])
def test_ensure_state_can_be_copied(
hass_recorder: Callable[..., HomeAssistant],
async def test_ensure_state_can_be_copied(
hass: HomeAssistant,
) -> None:
"""Ensure a state can pass though copy().
The filter integration uses copy() on states
from history.
"""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state):
"""Set the state."""
hass.states.set(entity_id, state)
wait_recording_done(hass)
hass.states.async_set(entity_id, state)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=2)
@ -504,6 +503,7 @@ def test_ensure_state_can_be_copied(
freezer.move_to(point)
set_state("2")
await async_wait_recording_done(hass)
hist = history.get_last_state_changes(hass, 2, entity_id)
@ -511,21 +511,22 @@ def test_ensure_state_can_be_copied(
assert_states_equal_without_context(copy(hist[entity_id][1]), hist[entity_id][1])
def test_get_significant_states(hass_recorder: Callable[..., HomeAssistant]) -> None:
async def test_get_significant_states(hass: HomeAssistant) -> None:
"""Test that only significant states are returned.
We should get back every thermostat change that
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(hass, zero, four, entity_ids=list(states))
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_minimal_response(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_minimal_response(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned.
@ -536,8 +537,9 @@ def test_get_significant_states_minimal_response(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass, zero, four, minimal_response=True, entity_ids=list(states)
)
@ -593,8 +595,8 @@ def test_get_significant_states_minimal_response(
@pytest.mark.parametrize("time_zone", ["Europe/Berlin", "US/Hawaii", "UTC"])
def test_get_significant_states_with_initial(
time_zone, hass_recorder: Callable[..., HomeAssistant]
async def test_get_significant_states_with_initial(
time_zone, hass: HomeAssistant
) -> None:
"""Test that only significant states are returned.
@ -602,9 +604,10 @@ def test_get_significant_states_with_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
hass.config.set_time_zone(time_zone)
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
one_and_half = zero + timedelta(seconds=1.5)
for entity_id in states:
if entity_id == "media_player.test":
@ -623,8 +626,8 @@ def test_get_significant_states_with_initial(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_without_initial(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_without_initial(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned.
@ -632,8 +635,9 @@ def test_get_significant_states_without_initial(
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
"""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
one = zero + timedelta(seconds=1)
one_with_microsecond = zero + timedelta(seconds=1, microseconds=1)
one_and_half = zero + timedelta(seconds=1.5)
@ -656,12 +660,13 @@ def test_get_significant_states_without_initial(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_entity_id(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_entity_id(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned for one entity."""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
del states["media_player.test2"]
del states["media_player.test3"]
del states["thermostat.test"]
@ -673,12 +678,12 @@ def test_get_significant_states_entity_id(
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
def test_get_significant_states_multiple_entity_ids(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_multiple_entity_ids(
hass: HomeAssistant,
) -> None:
"""Test that only significant states are returned for one entity."""
hass = hass_recorder()
zero, four, states = record_states(hass)
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass,
@ -695,16 +700,17 @@ def test_get_significant_states_multiple_entity_ids(
)
def test_get_significant_states_are_ordered(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_are_ordered(
hass: HomeAssistant,
) -> None:
"""Test order of results from get_significant_states.
When entity ids are given, the results should be returned with the data
in the same order.
"""
hass = hass_recorder()
zero, four, _states = record_states(hass)
await async_wait_recording_done(hass)
entity_ids = ["media_player.test", "media_player.test2"]
hist = history.get_significant_states(hass, zero, four, entity_ids)
assert list(hist.keys()) == entity_ids
@ -713,17 +719,15 @@ def test_get_significant_states_are_ordered(
assert list(hist.keys()) == entity_ids
def test_get_significant_states_only(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_only(
hass: HomeAssistant,
) -> None:
"""Test significant states when significant_states_only is set."""
hass = hass_recorder()
entity_id = "sensor.test"
def set_state(state, **kwargs):
"""Set the state."""
hass.states.set(entity_id, state, **kwargs)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, **kwargs)
return hass.states.get(entity_id)
start = dt_util.utcnow() - timedelta(minutes=4)
@ -744,6 +748,7 @@ def test_get_significant_states_only(
freezer.move_to(points[2])
# everything is different
states.append(set_state("412", attributes={"attribute": 54.23}))
await async_wait_recording_done(hass)
hist = history.get_significant_states(
hass,
@ -777,7 +782,7 @@ def test_get_significant_states_only(
async def test_get_significant_states_only_minimal_response(
recorder_mock: Recorder, hass: HomeAssistant
hass: HomeAssistant,
) -> None:
"""Test significant states when significant_states_only is True."""
now = dt_util.utcnow()
@ -820,8 +825,7 @@ def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
def set_state(entity_id, state, **kwargs):
"""Set the state."""
hass.states.set(entity_id, state, **kwargs)
wait_recording_done(hass)
hass.states.async_set(entity_id, state, **kwargs)
return hass.states.get(entity_id)
zero = dt_util.utcnow()
@ -888,7 +892,6 @@ def record_states(hass) -> tuple[datetime, datetime, dict[str, list[State]]]:
async def test_state_changes_during_period_query_during_migration_to_schema_25(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
recorder_db_url: str,
) -> None:
@ -897,7 +900,7 @@ async def test_state_changes_during_period_query_during_migration_to_schema_25(
# This test doesn't run on MySQL / MariaDB / Postgresql; we can't drop table state_attributes
return
instance = await async_setup_recorder_instance(hass, {})
instance = recorder.get_instance(hass)
with patch.object(instance.states_meta_manager, "active", False):
start = dt_util.utcnow()
@ -955,7 +958,6 @@ async def test_state_changes_during_period_query_during_migration_to_schema_25(
async def test_get_states_query_during_migration_to_schema_25(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
recorder_db_url: str,
) -> None:
@ -964,7 +966,7 @@ async def test_get_states_query_during_migration_to_schema_25(
# This test doesn't run on MySQL / MariaDB / Postgresql; we can't drop table state_attributes
return
instance = await async_setup_recorder_instance(hass, {})
instance = recorder.get_instance(hass)
start = dt_util.utcnow()
point = start + timedelta(seconds=1)
@ -1006,7 +1008,6 @@ async def test_get_states_query_during_migration_to_schema_25(
async def test_get_states_query_during_migration_to_schema_25_multiple_entities(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
recorder_db_url: str,
) -> None:
@ -1015,7 +1016,7 @@ async def test_get_states_query_during_migration_to_schema_25_multiple_entities(
# This test doesn't run on MySQL / MariaDB / Postgresql; we can't drop table state_attributes
return
instance = await async_setup_recorder_instance(hass, {})
instance = recorder.get_instance(hass)
start = dt_util.utcnow()
point = start + timedelta(seconds=1)
@ -1060,12 +1061,9 @@ async def test_get_states_query_during_migration_to_schema_25_multiple_entities(
async def test_get_full_significant_states_handles_empty_last_changed(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
) -> None:
"""Test getting states when last_changed is null."""
await async_setup_recorder_instance(hass, {})
now = dt_util.utcnow()
hass.states.async_set("sensor.one", "on", {"attr": "original"})
state0 = hass.states.get("sensor.one")
@ -1157,21 +1155,20 @@ async def test_get_full_significant_states_handles_empty_last_changed(
)
def test_state_changes_during_period_multiple_entities_single_test(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_multiple_entities_single_test(
hass: HomeAssistant,
) -> None:
"""Test state change during period with multiple entities in the same test.
This test ensures the sqlalchemy query cache does not
generate incorrect results.
"""
hass = hass_recorder()
start = dt_util.utcnow()
test_entites = {f"sensor.{i}": str(i) for i in range(30)}
for entity_id, value in test_entites.items():
hass.states.set(entity_id, value)
hass.states.async_set(entity_id, value)
wait_recording_done(hass)
await async_wait_recording_done(hass)
end = dt_util.utcnow()
for entity_id, value in test_entites.items():
@ -1182,11 +1179,9 @@ def test_state_changes_during_period_multiple_entities_single_test(
@pytest.mark.freeze_time("2039-01-19 03:14:07.555555-00:00")
async def test_get_full_significant_states_past_year_2038(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
) -> None:
"""Test we can store times past year 2038."""
await async_setup_recorder_instance(hass, {})
past_2038_time = dt_util.parse_datetime("2039-01-19 03:14:07.555555-00:00")
hass.states.async_set("sensor.one", "on", {"attr": "original"})
state0 = hass.states.get("sensor.one")
@ -1216,31 +1211,28 @@ async def test_get_full_significant_states_past_year_2038(
assert sensor_one_states[0].last_updated == past_2038_time
def test_get_significant_states_without_entity_ids_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_without_entity_ids_raises(
hass: HomeAssistant,
) -> None:
"""Test at least one entity id is required for get_significant_states."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(ValueError, match="entity_ids must be provided"):
history.get_significant_states(hass, now, None)
def test_state_changes_during_period_without_entity_ids_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_without_entity_ids_raises(
hass: HomeAssistant,
) -> None:
"""Test at least one entity id is required for state_changes_during_period."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(ValueError, match="entity_id must be provided"):
history.state_changes_during_period(hass, now, None)
def test_get_significant_states_with_filters_raises(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_with_filters_raises(
hass: HomeAssistant,
) -> None:
"""Test passing filters is no longer supported."""
hass = hass_recorder()
now = dt_util.utcnow()
with pytest.raises(NotImplementedError, match="Filters are no longer supported"):
history.get_significant_states(
@ -1248,29 +1240,26 @@ def test_get_significant_states_with_filters_raises(
)
def test_get_significant_states_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_significant_states_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test get_significant_states returns an empty dict when entities not in the db."""
hass = hass_recorder()
now = dt_util.utcnow()
assert history.get_significant_states(hass, now, None, ["nonexistent.entity"]) == {}
def test_state_changes_during_period_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_state_changes_during_period_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test state_changes_during_period returns an empty dict when entities not in the db."""
hass = hass_recorder()
now = dt_util.utcnow()
assert (
history.state_changes_during_period(hass, now, None, "nonexistent.entity") == {}
)
def test_get_last_state_changes_with_non_existent_entity_ids_returns_empty(
hass_recorder: Callable[..., HomeAssistant],
async def test_get_last_state_changes_with_non_existent_entity_ids_returns_empty(
hass: HomeAssistant,
) -> None:
"""Test get_last_state_changes returns an empty dict when entities not in the db."""
hass = hass_recorder()
assert history.get_last_state_changes(hass, 1, "nonexistent.entity") == {}