Add change service to timer (#84775)
* Add change service * test subtract * Test no change if timer not running * Modify example * Raise * Finalize * test event * Fix tests * Fix tracking time
This commit is contained in:
parent
fc7a421a48
commit
ddb9a6e33c
3 changed files with 217 additions and 22 deletions
|
@ -17,11 +17,13 @@ from homeassistant.components.timer import (
|
|||
DEFAULT_DURATION,
|
||||
DOMAIN,
|
||||
EVENT_TIMER_CANCELLED,
|
||||
EVENT_TIMER_CHANGED,
|
||||
EVENT_TIMER_FINISHED,
|
||||
EVENT_TIMER_PAUSED,
|
||||
EVENT_TIMER_RESTARTED,
|
||||
EVENT_TIMER_STARTED,
|
||||
SERVICE_CANCEL,
|
||||
SERVICE_CHANGE,
|
||||
SERVICE_FINISH,
|
||||
SERVICE_PAUSE,
|
||||
SERVICE_START,
|
||||
|
@ -43,7 +45,7 @@ from homeassistant.const import (
|
|||
SERVICE_RELOAD,
|
||||
)
|
||||
from homeassistant.core import Context, CoreState, HomeAssistant, State
|
||||
from homeassistant.exceptions import Unauthorized
|
||||
from homeassistant.exceptions import HomeAssistantError, Unauthorized
|
||||
from homeassistant.helpers import config_validation as cv, entity_registry as er
|
||||
from homeassistant.helpers.restore_state import (
|
||||
DATA_RESTORE_STATE_TASK,
|
||||
|
@ -60,7 +62,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def storage_setup(hass, hass_storage):
|
||||
def storage_setup(hass: HomeAssistant, hass_storage):
|
||||
"""Storage setup."""
|
||||
|
||||
async def _storage(items=None, config=None):
|
||||
|
@ -168,26 +170,91 @@ async def test_methods_and_events(hass: HomeAssistant) -> None:
|
|||
hass.bus.async_listen(EVENT_TIMER_PAUSED, fake_event_listener)
|
||||
hass.bus.async_listen(EVENT_TIMER_FINISHED, fake_event_listener)
|
||||
hass.bus.async_listen(EVENT_TIMER_CANCELLED, fake_event_listener)
|
||||
hass.bus.async_listen(EVENT_TIMER_CHANGED, fake_event_listener)
|
||||
|
||||
steps = [
|
||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_STARTED},
|
||||
{"call": SERVICE_PAUSE, "state": STATUS_PAUSED, "event": EVENT_TIMER_PAUSED},
|
||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_RESTARTED},
|
||||
{"call": SERVICE_CANCEL, "state": STATUS_IDLE, "event": EVENT_TIMER_CANCELLED},
|
||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_STARTED},
|
||||
{"call": SERVICE_FINISH, "state": STATUS_IDLE, "event": EVENT_TIMER_FINISHED},
|
||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_STARTED},
|
||||
{"call": SERVICE_PAUSE, "state": STATUS_PAUSED, "event": EVENT_TIMER_PAUSED},
|
||||
{"call": SERVICE_CANCEL, "state": STATUS_IDLE, "event": EVENT_TIMER_CANCELLED},
|
||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_STARTED},
|
||||
{"call": SERVICE_START, "state": STATUS_ACTIVE, "event": EVENT_TIMER_RESTARTED},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_STARTED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_PAUSE,
|
||||
"state": STATUS_PAUSED,
|
||||
"event": EVENT_TIMER_PAUSED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_RESTARTED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_CANCEL,
|
||||
"state": STATUS_IDLE,
|
||||
"event": EVENT_TIMER_CANCELLED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_STARTED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_FINISH,
|
||||
"state": STATUS_IDLE,
|
||||
"event": EVENT_TIMER_FINISHED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_STARTED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_PAUSE,
|
||||
"state": STATUS_PAUSED,
|
||||
"event": EVENT_TIMER_PAUSED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_CANCEL,
|
||||
"state": STATUS_IDLE,
|
||||
"event": EVENT_TIMER_CANCELLED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_STARTED,
|
||||
"data": {},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_CHANGE,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_CHANGED,
|
||||
"data": {CONF_DURATION: 15},
|
||||
},
|
||||
{
|
||||
"call": SERVICE_START,
|
||||
"state": STATUS_ACTIVE,
|
||||
"event": EVENT_TIMER_RESTARTED,
|
||||
"data": {},
|
||||
},
|
||||
]
|
||||
|
||||
expectedEvents = 0
|
||||
expected_events = 0
|
||||
for step in steps:
|
||||
if step["call"] is not None:
|
||||
await hass.services.async_call(
|
||||
DOMAIN, step["call"], {CONF_ENTITY_ID: "timer.test1"}
|
||||
DOMAIN,
|
||||
step["call"],
|
||||
{CONF_ENTITY_ID: "timer.test1", **step["data"]},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -197,9 +264,9 @@ async def test_methods_and_events(hass: HomeAssistant) -> None:
|
|||
assert state.state == step["state"]
|
||||
|
||||
if step["event"] is not None:
|
||||
expectedEvents += 1
|
||||
expected_events += 1
|
||||
assert results[-1].event_type == step["event"]
|
||||
assert len(results) == expectedEvents
|
||||
assert len(results) == expected_events
|
||||
|
||||
|
||||
async def test_start_service(hass: HomeAssistant) -> None:
|
||||
|
@ -212,7 +279,7 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
|||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}
|
||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("timer.test1")
|
||||
|
@ -222,7 +289,7 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
|||
assert state.attributes[ATTR_REMAINING] == "0:00:10"
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_CANCEL, {CONF_ENTITY_ID: "timer.test1"}
|
||||
DOMAIN, SERVICE_CANCEL, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("timer.test1")
|
||||
|
@ -231,8 +298,20 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
|||
assert state.attributes[ATTR_DURATION] == "0:00:10"
|
||||
assert ATTR_REMAINING not in state.attributes
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_CHANGE,
|
||||
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 10},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 15}
|
||||
DOMAIN,
|
||||
SERVICE_START,
|
||||
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 15},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("timer.test1")
|
||||
|
@ -241,6 +320,57 @@ async def test_start_service(hass: HomeAssistant) -> None:
|
|||
assert state.attributes[ATTR_DURATION] == "0:00:15"
|
||||
assert state.attributes[ATTR_REMAINING] == "0:00:15"
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_CHANGE,
|
||||
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 15},
|
||||
blocking=True,
|
||||
)
|
||||
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:30"
|
||||
assert state.attributes[ATTR_REMAINING] == "0:00:30"
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_CHANGE,
|
||||
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: -10},
|
||||
blocking=True,
|
||||
)
|
||||
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"
|
||||
assert state.attributes[ATTR_REMAINING] == "0:00:20"
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_CANCEL, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||
)
|
||||
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"
|
||||
assert ATTR_REMAINING not in state.attributes
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_CHANGE,
|
||||
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 10},
|
||||
blocking=True,
|
||||
)
|
||||
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"
|
||||
assert ATTR_REMAINING not in state.attributes
|
||||
|
||||
|
||||
async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
||||
"""Test for a timer to end."""
|
||||
|
@ -262,9 +392,10 @@ async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
|||
hass.bus.async_listen(EVENT_TIMER_PAUSED, fake_event_listener)
|
||||
hass.bus.async_listen(EVENT_TIMER_FINISHED, fake_event_listener)
|
||||
hass.bus.async_listen(EVENT_TIMER_CANCELLED, fake_event_listener)
|
||||
hass.bus.async_listen(EVENT_TIMER_CHANGED, fake_event_listener)
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}
|
||||
DOMAIN, SERVICE_START, {CONF_ENTITY_ID: "timer.test1"}, blocking=True
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -275,15 +406,37 @@ async def test_wait_till_timer_expires(hass: HomeAssistant) -> None:
|
|||
assert results[-1].event_type == EVENT_TIMER_STARTED
|
||||
assert len(results) == 1
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_CHANGE,
|
||||
{CONF_ENTITY_ID: "timer.test1", CONF_DURATION: 10},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_CHANGED
|
||||
assert len(results) == 2
|
||||
|
||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=10))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_ACTIVE
|
||||
|
||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=20))
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("timer.test1")
|
||||
assert state
|
||||
assert state.state == STATUS_IDLE
|
||||
|
||||
assert results[-1].event_type == EVENT_TIMER_FINISHED
|
||||
assert len(results) == 2
|
||||
assert len(results) == 3
|
||||
|
||||
|
||||
async def test_no_initial_state_and_no_restore_state(hass: HomeAssistant) -> None:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue