mirror of
https://github.com/home-assistant/core.git
synced 2026-04-20 08:29:39 +02:00
Improve timer tests (#168277)
This commit is contained in:
@@ -5,6 +5,7 @@ import logging
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.timer import (
|
||||
@@ -33,7 +34,6 @@ from homeassistant.components.timer import (
|
||||
STATUS_IDLE,
|
||||
STATUS_PAUSED,
|
||||
Timer,
|
||||
_format_timedelta,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_EDITABLE,
|
||||
@@ -132,20 +132,27 @@ async def test_config_options(hass: HomeAssistant) -> None:
|
||||
assert state_3 is not None
|
||||
|
||||
assert state_1.state == STATUS_IDLE
|
||||
assert ATTR_ICON not in state_1.attributes
|
||||
assert ATTR_FRIENDLY_NAME not in state_1.attributes
|
||||
assert state_1.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:00",
|
||||
}
|
||||
|
||||
assert state_2.state == STATUS_IDLE
|
||||
assert state_2.attributes.get(ATTR_FRIENDLY_NAME) == "Hello World"
|
||||
assert state_2.attributes.get(ATTR_ICON) == "mdi:work"
|
||||
assert state_2.attributes.get(ATTR_DURATION) == "0:00:10"
|
||||
assert state_2.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FRIENDLY_NAME: "Hello World",
|
||||
ATTR_ICON: "mdi:work",
|
||||
}
|
||||
|
||||
assert state_3.state == STATUS_IDLE
|
||||
assert str(cv.time_period(DEFAULT_DURATION)) == state_3.attributes.get(
|
||||
CONF_DURATION
|
||||
)
|
||||
assert state_3.attributes == {
|
||||
ATTR_DURATION: str(cv.time_period(DEFAULT_DURATION)),
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2023-06-05 17:47:50")
|
||||
async def test_methods_and_events(hass: HomeAssistant) -> None:
|
||||
"""Test methods and events."""
|
||||
hass.set_state(CoreState.starting)
|
||||
@@ -155,13 +162,17 @@ async def test_methods_and_events(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
results: list[tuple[Event, str]] = []
|
||||
results: list[tuple[Event, State | None]] = []
|
||||
|
||||
@callback
|
||||
def fake_event_listener(event: Event):
|
||||
"""Fake event listener for trigger."""
|
||||
results.append((event, hass.states.get("timer.test1").state))
|
||||
results.append((event, hass.states.get("timer.test1")))
|
||||
|
||||
hass.bus.async_listen(EVENT_TIMER_STARTED, fake_event_listener)
|
||||
hass.bus.async_listen(EVENT_TIMER_RESTARTED, fake_event_listener)
|
||||
@@ -170,102 +181,142 @@ async def test_methods_and_events(hass: HomeAssistant) -> None:
|
||||
hass.bus.async_listen(EVENT_TIMER_CANCELLED, fake_event_listener)
|
||||
hass.bus.async_listen(EVENT_TIMER_CHANGED, fake_event_listener)
|
||||
|
||||
finish_10 = (utcnow() + timedelta(seconds=10)).isoformat()
|
||||
finish_5 = (utcnow() + timedelta(seconds=5)).isoformat()
|
||||
|
||||
steps = [
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_STARTED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_ACTIVE,
|
||||
"expected_extra_attributes": {
|
||||
ATTR_FINISHES_AT: finish_10,
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
},
|
||||
"expected_event": EVENT_TIMER_STARTED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_PAUSE,
|
||||
"state": STATUS_PAUSED,
|
||||
"event": EVENT_TIMER_PAUSED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_PAUSED,
|
||||
"expected_extra_attributes": {ATTR_REMAINING: "0:00:10"},
|
||||
"expected_event": EVENT_TIMER_PAUSED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_RESTARTED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_ACTIVE,
|
||||
"expected_extra_attributes": {
|
||||
ATTR_FINISHES_AT: finish_10,
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
},
|
||||
"expected_event": EVENT_TIMER_RESTARTED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_CANCEL,
|
||||
"state": STATUS_IDLE,
|
||||
"event": EVENT_TIMER_CANCELLED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_IDLE,
|
||||
"expected_extra_attributes": {},
|
||||
"expected_event": EVENT_TIMER_CANCELLED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_CANCEL,
|
||||
"state": STATUS_IDLE,
|
||||
"event": None,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_IDLE,
|
||||
"expected_extra_attributes": {},
|
||||
"expected_event": None,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_STARTED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_ACTIVE,
|
||||
"expected_extra_attributes": {
|
||||
ATTR_FINISHES_AT: finish_10,
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
},
|
||||
"expected_event": EVENT_TIMER_STARTED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_FINISH,
|
||||
"state": STATUS_IDLE,
|
||||
"event": EVENT_TIMER_FINISHED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_IDLE,
|
||||
"expected_extra_attributes": {},
|
||||
"expected_event": EVENT_TIMER_FINISHED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_FINISH,
|
||||
"state": STATUS_IDLE,
|
||||
"event": None,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_IDLE,
|
||||
"expected_extra_attributes": {},
|
||||
"expected_event": None,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_STARTED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_ACTIVE,
|
||||
"expected_extra_attributes": {
|
||||
ATTR_FINISHES_AT: finish_10,
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
},
|
||||
"expected_event": EVENT_TIMER_STARTED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_PAUSE,
|
||||
"state": STATUS_PAUSED,
|
||||
"event": EVENT_TIMER_PAUSED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_PAUSED,
|
||||
"expected_extra_attributes": {ATTR_REMAINING: "0:00:10"},
|
||||
"expected_event": EVENT_TIMER_PAUSED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_CANCEL,
|
||||
"state": STATUS_IDLE,
|
||||
"event": EVENT_TIMER_CANCELLED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_IDLE,
|
||||
"expected_extra_attributes": {},
|
||||
"expected_event": EVENT_TIMER_CANCELLED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_STARTED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_ACTIVE,
|
||||
"expected_extra_attributes": {
|
||||
ATTR_FINISHES_AT: finish_10,
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
},
|
||||
"expected_event": EVENT_TIMER_STARTED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_CHANGE,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_CHANGED,
|
||||
"data": {CONF_DURATION: -5},
|
||||
"call_data": {CONF_DURATION: -5},
|
||||
"expected_state": STATUS_ACTIVE,
|
||||
"expected_extra_attributes": {
|
||||
ATTR_FINISHES_AT: finish_5,
|
||||
ATTR_REMAINING: "0:00:05",
|
||||
},
|
||||
"expected_event": EVENT_TIMER_CHANGED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_RESTARTED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_ACTIVE,
|
||||
"expected_extra_attributes": {
|
||||
ATTR_FINISHES_AT: finish_5,
|
||||
ATTR_REMAINING: "0:00:05",
|
||||
},
|
||||
"expected_event": EVENT_TIMER_RESTARTED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_PAUSE,
|
||||
"state": STATUS_PAUSED,
|
||||
"event": EVENT_TIMER_PAUSED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_PAUSED,
|
||||
"expected_extra_attributes": {ATTR_REMAINING: "0:00:05"},
|
||||
"expected_event": EVENT_TIMER_PAUSED,
|
||||
},
|
||||
{
|
||||
"call": SERVICE_FINISH,
|
||||
"state": STATUS_IDLE,
|
||||
"event": EVENT_TIMER_FINISHED,
|
||||
"data": {},
|
||||
"call_data": {},
|
||||
"expected_state": STATUS_IDLE,
|
||||
"expected_extra_attributes": {},
|
||||
"expected_event": EVENT_TIMER_FINISHED,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -275,22 +326,38 @@ async def test_methods_and_events(hass: HomeAssistant) -> None:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
step["call"],
|
||||
{CONF_ENTITY_ID: "timer.test1", **step["data"]},
|
||||
{CONF_ENTITY_ID: "timer.test1", **step["call_data"]},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
if step["state"] is not None:
|
||||
assert state.state == step["state"]
|
||||
if step["expected_state"] is not None:
|
||||
assert state.state == step["expected_state"]
|
||||
assert (
|
||||
state.attributes
|
||||
== {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
| step["expected_extra_attributes"]
|
||||
)
|
||||
|
||||
if step["event"] is not None:
|
||||
if step["expected_event"] is not None:
|
||||
expected_events += 1
|
||||
last_result = results[-1]
|
||||
event, state = last_result
|
||||
assert event.event_type == step["event"]
|
||||
assert state == step["state"]
|
||||
assert event.event_type == step["expected_event"]
|
||||
assert state.state == step["expected_state"]
|
||||
assert (
|
||||
state.attributes
|
||||
== {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
| step["expected_extra_attributes"]
|
||||
)
|
||||
assert len(results) == expected_events
|
||||
|
||||
|
||||
@@ -302,7 +369,10 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||
assert state.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:10",
|
||||
}
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||
@@ -311,8 +381,12 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||
assert state.attributes[ATTR_REMAINING] == "0:00:10"
|
||||
assert state.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=10)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
}
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_CANCEL, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||
@@ -321,8 +395,10 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||
assert ATTR_REMAINING not in state.attributes
|
||||
assert state.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:10",
|
||||
}
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
@@ -342,8 +418,12 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes[ATTR_DURATION] == "0:00:15"
|
||||
assert state.attributes[ATTR_REMAINING] == "0:00:15"
|
||||
assert state.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:15",
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=15)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:15",
|
||||
}
|
||||
|
||||
with pytest.raises(
|
||||
HomeAssistantError,
|
||||
@@ -376,8 +456,12 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes[ATTR_DURATION] == "0:00:15"
|
||||
assert state.attributes[ATTR_REMAINING] == "0:00:12"
|
||||
assert state.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:15",
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=12)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:12",
|
||||
}
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
@@ -388,8 +472,12 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes[ATTR_DURATION] == "0:00:15"
|
||||
assert state.attributes[ATTR_REMAINING] == "0:00:14"
|
||||
assert state.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:15",
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=14)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:14",
|
||||
}
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_CANCEL, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||
@@ -398,8 +486,10 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||
assert ATTR_REMAINING not in state.attributes
|
||||
assert state.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:10",
|
||||
}
|
||||
|
||||
with pytest.raises(
|
||||
HomeAssistantError,
|
||||
@@ -415,11 +505,16 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||
assert ATTR_REMAINING not in state.attributes
|
||||
assert state.attributes == {
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_DURATION: "0:00:10",
|
||||
}
|
||||
|
||||
|
||||
async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
||||
@pytest.mark.freeze_time("2023-06-05 17:47:50")
|
||||
async def test_wait_till_timer_expires(
|
||||
hass: HomeAssistant, freezer: FrozenDateTimeFactory
|
||||
) -> None:
|
||||
"""Test for a timer to end."""
|
||||
hass.set_state(CoreState.starting)
|
||||
|
||||
@@ -428,6 +523,10 @@ async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:20",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
results = []
|
||||
|
||||
@@ -450,6 +549,12 @@ async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:20",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=20)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:20",
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_STARTED
|
||||
assert len(results) == 1
|
||||
@@ -465,23 +570,41 @@ async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:20",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=15)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:15",
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_CHANGED
|
||||
assert len(results) == 2
|
||||
|
||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=10))
|
||||
freezer.tick(10)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:20",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=5)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:15",
|
||||
}
|
||||
|
||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=20))
|
||||
freezer.tick(20)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:20",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_FINISHED
|
||||
assert len(results) == 3
|
||||
@@ -496,6 +619,10 @@ async def test_no_initial_state_and_no_restore_state(hass: HomeAssistant) -> Non
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
|
||||
async def test_config_reload(
|
||||
@@ -538,13 +665,18 @@ async def test_config_reload(
|
||||
assert entity_registry.async_get_entity_id(DOMAIN, DOMAIN, "test_3") is None
|
||||
|
||||
assert state_1.state == STATUS_IDLE
|
||||
assert ATTR_ICON not in state_1.attributes
|
||||
assert ATTR_FRIENDLY_NAME not in state_1.attributes
|
||||
assert state_1.attributes == {
|
||||
ATTR_DURATION: "0:00:00",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
assert state_2.state == STATUS_IDLE
|
||||
assert state_2.attributes.get(ATTR_FRIENDLY_NAME) == "Hello World"
|
||||
assert state_2.attributes.get(ATTR_ICON) == "mdi:work"
|
||||
assert state_2.attributes.get(ATTR_DURATION) == "0:00:10"
|
||||
assert state_2.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FRIENDLY_NAME: "Hello World",
|
||||
ATTR_ICON: "mdi:work",
|
||||
}
|
||||
|
||||
with patch(
|
||||
"homeassistant.config.load_yaml_config_file",
|
||||
@@ -589,15 +721,21 @@ async def test_config_reload(
|
||||
assert entity_registry.async_get_entity_id(DOMAIN, DOMAIN, "test_3") is not None
|
||||
|
||||
assert state_2.state == STATUS_IDLE
|
||||
assert state_2.attributes.get(ATTR_FRIENDLY_NAME) == "Hello World reloaded"
|
||||
assert state_2.attributes.get(ATTR_ICON) == "mdi:work-reloaded"
|
||||
assert state_2.attributes.get(ATTR_DURATION) == "0:00:20"
|
||||
assert state_2.attributes == {
|
||||
ATTR_DURATION: "0:00:20",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FRIENDLY_NAME: "Hello World reloaded",
|
||||
ATTR_ICON: "mdi:work-reloaded",
|
||||
}
|
||||
|
||||
assert state_3.state == STATUS_IDLE
|
||||
assert ATTR_ICON not in state_3.attributes
|
||||
assert ATTR_FRIENDLY_NAME not in state_3.attributes
|
||||
assert state_3.attributes == {
|
||||
ATTR_DURATION: "0:00:00",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2023-06-05 17:47:50")
|
||||
async def test_timer_restarted_event(hass: HomeAssistant) -> None:
|
||||
"""Ensure restarted event is called after starting a paused or running timer."""
|
||||
hass.set_state(CoreState.starting)
|
||||
@@ -607,6 +745,10 @@ async def test_timer_restarted_event(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
results = []
|
||||
|
||||
@@ -628,6 +770,12 @@ async def test_timer_restarted_event(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=10)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_STARTED
|
||||
assert len(results) == 1
|
||||
@@ -639,6 +787,12 @@ async def test_timer_restarted_event(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=10)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_RESTARTED
|
||||
assert len(results) == 2
|
||||
@@ -650,6 +804,11 @@ async def test_timer_restarted_event(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_PAUSED
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_PAUSED
|
||||
assert len(results) == 3
|
||||
@@ -661,11 +820,18 @@ async def test_timer_restarted_event(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=10)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_RESTARTED
|
||||
assert len(results) == 4
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2023-06-05 17:47:50")
|
||||
async def test_state_changed_when_timer_restarted(hass: HomeAssistant) -> None:
|
||||
"""Ensure timer's state changes when it restarted."""
|
||||
hass.set_state(CoreState.starting)
|
||||
@@ -675,6 +841,10 @@ async def test_state_changed_when_timer_restarted(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
results = []
|
||||
|
||||
@@ -692,6 +862,12 @@ async def test_state_changed_when_timer_restarted(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=10)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_STATE_CHANGED
|
||||
assert len(results) == 1
|
||||
@@ -703,6 +879,12 @@ async def test_state_changed_when_timer_restarted(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:10",
|
||||
ATTR_EDITABLE: False,
|
||||
ATTR_FINISHES_AT: (utcnow() + timedelta(seconds=10)).isoformat(),
|
||||
ATTR_REMAINING: "0:00:10",
|
||||
}
|
||||
|
||||
assert results[-1].event_type == EVENT_STATE_CHANGED
|
||||
assert len(results) == 2
|
||||
@@ -713,8 +895,11 @@ async def test_load_from_storage(hass: HomeAssistant, storage_setup) -> None:
|
||||
assert await storage_setup()
|
||||
state = hass.states.get(f"{DOMAIN}.timer_from_storage")
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "timer from storage"
|
||||
assert state.attributes.get(ATTR_EDITABLE)
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:00",
|
||||
ATTR_EDITABLE: True,
|
||||
ATTR_FRIENDLY_NAME: "timer from storage",
|
||||
}
|
||||
|
||||
|
||||
async def test_editable_state_attribute(hass: HomeAssistant, storage_setup) -> None:
|
||||
@@ -723,12 +908,18 @@ async def test_editable_state_attribute(hass: HomeAssistant, storage_setup) -> N
|
||||
|
||||
state = hass.states.get(f"{DOMAIN}.{DOMAIN}_from_storage")
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "timer from storage"
|
||||
assert state.attributes.get(ATTR_EDITABLE)
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:00",
|
||||
ATTR_EDITABLE: True,
|
||||
ATTR_FRIENDLY_NAME: "timer from storage",
|
||||
}
|
||||
|
||||
state = hass.states.get(f"{DOMAIN}.from_yaml")
|
||||
assert not state.attributes.get(ATTR_EDITABLE)
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:00",
|
||||
ATTR_EDITABLE: False,
|
||||
}
|
||||
|
||||
|
||||
async def test_ws_list(
|
||||
@@ -797,7 +988,12 @@ async def test_update(
|
||||
timer_entity_id = f"{DOMAIN}.{DOMAIN}_{timer_id}"
|
||||
|
||||
state = hass.states.get(timer_entity_id)
|
||||
assert state.attributes[ATTR_FRIENDLY_NAME] == "timer from storage"
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:00",
|
||||
ATTR_EDITABLE: True,
|
||||
ATTR_FRIENDLY_NAME: "timer from storage",
|
||||
}
|
||||
assert (
|
||||
entity_registry.async_get_entity_id(DOMAIN, DOMAIN, timer_id) == timer_entity_id
|
||||
)
|
||||
@@ -827,8 +1023,13 @@ async def test_update(
|
||||
}
|
||||
|
||||
state = hass.states.get(timer_entity_id)
|
||||
assert state.attributes[ATTR_DURATION] == _format_timedelta(cv.time_period(33))
|
||||
assert state.attributes[ATTR_RESTORE]
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:33",
|
||||
ATTR_EDITABLE: True,
|
||||
ATTR_FRIENDLY_NAME: "timer from storage",
|
||||
ATTR_RESTORE: True,
|
||||
}
|
||||
|
||||
|
||||
async def test_ws_create(
|
||||
@@ -862,7 +1063,11 @@ async def test_ws_create(
|
||||
|
||||
state = hass.states.get(timer_entity_id)
|
||||
assert state.state == STATUS_IDLE
|
||||
assert state.attributes[ATTR_DURATION] == _format_timedelta(cv.time_period(42))
|
||||
assert state.attributes == {
|
||||
ATTR_DURATION: "0:00:42",
|
||||
ATTR_EDITABLE: True,
|
||||
ATTR_FRIENDLY_NAME: "New Timer",
|
||||
}
|
||||
assert (
|
||||
entity_registry.async_get_entity_id(DOMAIN, DOMAIN, timer_id) == timer_entity_id
|
||||
)
|
||||
@@ -919,10 +1124,12 @@ async def test_restore_paused(hass: HomeAssistant) -> None:
|
||||
await entity.async_added_to_hass()
|
||||
await hass.async_block_till_done()
|
||||
assert entity.state == STATUS_PAUSED
|
||||
assert entity.extra_state_attributes[ATTR_DURATION] == "0:00:30"
|
||||
assert entity.extra_state_attributes[ATTR_REMAINING] == "0:00:15"
|
||||
assert ATTR_FINISHES_AT not in entity.extra_state_attributes
|
||||
assert entity.extra_state_attributes[ATTR_RESTORE]
|
||||
assert entity.extra_state_attributes == {
|
||||
ATTR_DURATION: "0:00:30",
|
||||
ATTR_EDITABLE: True,
|
||||
ATTR_REMAINING: "0:00:15",
|
||||
ATTR_RESTORE: True,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2023-06-05 17:47:50")
|
||||
@@ -967,10 +1174,13 @@ async def test_restore_active_resume(hass: HomeAssistant) -> None:
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entity.state == STATUS_ACTIVE
|
||||
assert entity.extra_state_attributes[ATTR_DURATION] == "0:00:30"
|
||||
assert entity.extra_state_attributes[ATTR_REMAINING] == "0:00:15"
|
||||
assert entity.extra_state_attributes[ATTR_FINISHES_AT] == finish.isoformat()
|
||||
assert entity.extra_state_attributes[ATTR_RESTORE]
|
||||
assert entity.extra_state_attributes == {
|
||||
ATTR_DURATION: "0:00:30",
|
||||
ATTR_EDITABLE: True,
|
||||
ATTR_FINISHES_AT: finish.isoformat(),
|
||||
ATTR_REMAINING: "0:00:15",
|
||||
ATTR_RESTORE: True,
|
||||
}
|
||||
assert len(events) == 1
|
||||
|
||||
|
||||
@@ -1013,8 +1223,9 @@ async def test_restore_active_finished_outside_grace(hass: HomeAssistant) -> Non
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entity.state == STATUS_IDLE
|
||||
assert entity.extra_state_attributes[ATTR_DURATION] == "0:01:00"
|
||||
assert ATTR_REMAINING not in entity.extra_state_attributes
|
||||
assert ATTR_FINISHES_AT not in entity.extra_state_attributes
|
||||
assert entity.extra_state_attributes[ATTR_RESTORE]
|
||||
assert entity.extra_state_attributes == {
|
||||
ATTR_DURATION: "0:01:00",
|
||||
ATTR_EDITABLE: True,
|
||||
ATTR_RESTORE: True,
|
||||
}
|
||||
assert len(events) == 1
|
||||
|
||||
Reference in New Issue
Block a user