mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Replace periodic tasks with background tasks (#112726)
* Phase out periodic tasks * false by default or some tests will block forever, will need to fix each one manually * kwarg works * kwarg works * kwarg works * fixes * fix more tests * fix more tests * fix lifx * opensky * pvpc_hourly_pricing * adjust more * adjust more * smarttub * adjust more * adjust more * adjust more * adjust more * adjust * no eager executor * zha * qnap_qsw * fix more * fix fix * docs * its a wrapper now * add more coverage * coverage * cover all combos * more fixes * more fixes * more fixes * remaining issues are legit bugs in tests * make tplink test more predictable * more fixes * feedreader * grind out some more * make test race safe * one more
This commit is contained in:
parent
08416974c9
commit
65358c129a
@ -878,7 +878,7 @@ async def _async_set_up_integrations(
|
||||
_LOGGER.debug("Waiting for startup to wrap up")
|
||||
try:
|
||||
async with hass.timeout.async_timeout(WRAP_UP_TIMEOUT, cool_down=COOLDOWN_TIME):
|
||||
await hass.async_block_till_done(wait_periodic_tasks=False)
|
||||
await hass.async_block_till_done()
|
||||
except TimeoutError:
|
||||
_LOGGER.warning(
|
||||
"Setup timed out for bootstrap waiting on %s - moving forward",
|
||||
|
@ -18,7 +18,6 @@ from contextvars import ContextVar
|
||||
from copy import deepcopy
|
||||
from enum import Enum, StrEnum
|
||||
import functools
|
||||
from itertools import chain
|
||||
import logging
|
||||
from random import randint
|
||||
from types import MappingProxyType
|
||||
@ -379,7 +378,6 @@ class ConfigEntry:
|
||||
|
||||
self._tasks: set[asyncio.Future[Any]] = set()
|
||||
self._background_tasks: set[asyncio.Future[Any]] = set()
|
||||
self._periodic_tasks: set[asyncio.Future[Any]] = set()
|
||||
|
||||
self._integration_for_domain: loader.Integration | None = None
|
||||
self._tries = 0
|
||||
@ -857,15 +855,15 @@ class ConfigEntry:
|
||||
if job := self._on_unload.pop()():
|
||||
self.async_create_task(hass, job)
|
||||
|
||||
if not self._tasks and not self._background_tasks and not self._periodic_tasks:
|
||||
if not self._tasks and not self._background_tasks:
|
||||
return
|
||||
|
||||
cancel_message = f"Config entry {self.title} with {self.domain} unloading"
|
||||
for task in chain(self._background_tasks, self._periodic_tasks):
|
||||
for task in self._background_tasks:
|
||||
task.cancel(cancel_message)
|
||||
|
||||
_, pending = await asyncio.wait(
|
||||
[*self._tasks, *self._background_tasks, *self._periodic_tasks], timeout=10
|
||||
[*self._tasks, *self._background_tasks], timeout=10
|
||||
)
|
||||
|
||||
for task in pending:
|
||||
@ -1044,35 +1042,6 @@ class ConfigEntry:
|
||||
task.add_done_callback(self._background_tasks.remove)
|
||||
return task
|
||||
|
||||
@callback
|
||||
def async_create_periodic_task(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
target: Coroutine[Any, Any, _R],
|
||||
name: str,
|
||||
eager_start: bool = False,
|
||||
) -> asyncio.Task[_R]:
|
||||
"""Create a periodic task tied to the config entry lifecycle.
|
||||
|
||||
Periodic tasks are automatically canceled when config entry is unloaded.
|
||||
|
||||
This type of task is typically used for polling.
|
||||
|
||||
A periodic task is different from a normal task:
|
||||
|
||||
- Will not block startup
|
||||
- Will be automatically cancelled on shutdown
|
||||
- Calls to async_block_till_done will wait for completion by default
|
||||
|
||||
This method must be run in the event loop.
|
||||
"""
|
||||
task = hass.async_create_periodic_task(target, name, eager_start)
|
||||
if task.done():
|
||||
return task
|
||||
self._periodic_tasks.add(task)
|
||||
task.add_done_callback(self._periodic_tasks.remove)
|
||||
return task
|
||||
|
||||
|
||||
current_entry: ContextVar[ConfigEntry | None] = ContextVar(
|
||||
"current_entry", default=None
|
||||
|
@ -375,7 +375,6 @@ class HomeAssistant:
|
||||
self.loop = asyncio.get_running_loop()
|
||||
self._tasks: set[asyncio.Future[Any]] = set()
|
||||
self._background_tasks: set[asyncio.Future[Any]] = set()
|
||||
self._periodic_tasks: set[asyncio.Future[Any]] = set()
|
||||
self.bus = EventBus(self)
|
||||
self.services = ServiceRegistry(self)
|
||||
self.states = StateMachine(self.bus, self.loop)
|
||||
@ -585,23 +584,38 @@ class HomeAssistant:
|
||||
@overload
|
||||
@callback
|
||||
def async_add_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R]], *args: Any
|
||||
self,
|
||||
hassjob: HassJob[..., Coroutine[Any, Any, _R]],
|
||||
*args: Any,
|
||||
eager_start: bool = False,
|
||||
background: bool = False,
|
||||
) -> asyncio.Future[_R] | None:
|
||||
...
|
||||
|
||||
@overload
|
||||
@callback
|
||||
def async_add_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R], *args: Any
|
||||
self,
|
||||
hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R],
|
||||
*args: Any,
|
||||
eager_start: bool = False,
|
||||
background: bool = False,
|
||||
) -> asyncio.Future[_R] | None:
|
||||
...
|
||||
|
||||
@callback
|
||||
def async_add_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R], *args: Any
|
||||
self,
|
||||
hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R],
|
||||
*args: Any,
|
||||
eager_start: bool = False,
|
||||
background: bool = False,
|
||||
) -> asyncio.Future[_R] | None:
|
||||
"""Add a HassJob from within the event loop.
|
||||
|
||||
If eager_start is True, coroutine functions will be scheduled eagerly.
|
||||
If background is True, the task will created as a background task.
|
||||
|
||||
This method must be run in the event loop.
|
||||
hassjob: HassJob to call.
|
||||
args: parameters for method to call.
|
||||
@ -618,7 +632,14 @@ class HomeAssistant:
|
||||
)
|
||||
# Use loop.create_task
|
||||
# to avoid the extra function call in asyncio.create_task.
|
||||
task = self.loop.create_task(hassjob.target(*args), name=hassjob.name)
|
||||
if eager_start:
|
||||
task = create_eager_task(
|
||||
hassjob.target(*args), name=hassjob.name, loop=self.loop
|
||||
)
|
||||
if task.done():
|
||||
return task
|
||||
else:
|
||||
task = self.loop.create_task(hassjob.target(*args), name=hassjob.name)
|
||||
elif hassjob.job_type is HassJobType.Callback:
|
||||
if TYPE_CHECKING:
|
||||
hassjob.target = cast(Callable[..., _R], hassjob.target)
|
||||
@ -629,58 +650,9 @@ class HomeAssistant:
|
||||
hassjob.target = cast(Callable[..., _R], hassjob.target)
|
||||
task = self.loop.run_in_executor(None, hassjob.target, *args)
|
||||
|
||||
self._tasks.add(task)
|
||||
task.add_done_callback(self._tasks.remove)
|
||||
|
||||
return task
|
||||
|
||||
@overload
|
||||
@callback
|
||||
def async_run_periodic_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R]], *args: Any
|
||||
) -> asyncio.Future[_R] | None:
|
||||
...
|
||||
|
||||
@overload
|
||||
@callback
|
||||
def async_run_periodic_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R], *args: Any
|
||||
) -> asyncio.Future[_R] | None:
|
||||
...
|
||||
|
||||
@callback
|
||||
def async_run_periodic_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R], *args: Any
|
||||
) -> asyncio.Future[_R] | None:
|
||||
"""Add a periodic HassJob from within the event loop.
|
||||
|
||||
This method must be run in the event loop.
|
||||
hassjob: HassJob to call.
|
||||
args: parameters for method to call.
|
||||
"""
|
||||
task: asyncio.Future[_R]
|
||||
# This code path is performance sensitive and uses
|
||||
# if TYPE_CHECKING to avoid the overhead of constructing
|
||||
# the type used for the cast. For history see:
|
||||
# https://github.com/home-assistant/core/pull/71960
|
||||
if hassjob.job_type is HassJobType.Coroutinefunction:
|
||||
if TYPE_CHECKING:
|
||||
hassjob.target = cast(
|
||||
Callable[..., Coroutine[Any, Any, _R]], hassjob.target
|
||||
)
|
||||
task = create_eager_task(hassjob.target(*args), name=hassjob.name)
|
||||
elif hassjob.job_type is HassJobType.Callback:
|
||||
if TYPE_CHECKING:
|
||||
hassjob.target = cast(Callable[..., _R], hassjob.target)
|
||||
hassjob.target(*args)
|
||||
return None
|
||||
else:
|
||||
if TYPE_CHECKING:
|
||||
hassjob.target = cast(Callable[..., _R], hassjob.target)
|
||||
task = self.loop.run_in_executor(None, hassjob.target, *args)
|
||||
|
||||
self._periodic_tasks.add(task)
|
||||
task.add_done_callback(self._periodic_tasks.remove)
|
||||
task_bucket = self._background_tasks if background else self._tasks
|
||||
task_bucket.add(task)
|
||||
task.add_done_callback(task_bucket.remove)
|
||||
|
||||
return task
|
||||
|
||||
@ -751,37 +723,6 @@ class HomeAssistant:
|
||||
task.add_done_callback(self._background_tasks.remove)
|
||||
return task
|
||||
|
||||
@callback
|
||||
def async_create_periodic_task(
|
||||
self, target: Coroutine[Any, Any, _R], name: str, eager_start: bool = False
|
||||
) -> asyncio.Task[_R]:
|
||||
"""Create a task from within the event loop.
|
||||
|
||||
This type of task is typically used for polling.
|
||||
|
||||
A periodic task is different from a normal task:
|
||||
|
||||
- Will not block startup
|
||||
- Will be automatically cancelled on shutdown
|
||||
- Calls to async_block_till_done will wait for completion by default
|
||||
|
||||
If you are using this in your integration, use the create task
|
||||
methods on the config entry instead.
|
||||
|
||||
This method must be run in the event loop.
|
||||
"""
|
||||
if eager_start:
|
||||
task = create_eager_task(target, name=name, loop=self.loop)
|
||||
if task.done():
|
||||
return task
|
||||
else:
|
||||
# Use loop.create_task
|
||||
# to avoid the extra function call in asyncio.create_task.
|
||||
task = self.loop.create_task(target, name=name)
|
||||
self._periodic_tasks.add(task)
|
||||
task.add_done_callback(self._periodic_tasks.remove)
|
||||
return task
|
||||
|
||||
@callback
|
||||
def async_add_executor_job(
|
||||
self, target: Callable[..., _T], *args: Any
|
||||
@ -806,25 +747,40 @@ class HomeAssistant:
|
||||
@overload
|
||||
@callback
|
||||
def async_run_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R]], *args: Any
|
||||
self,
|
||||
hassjob: HassJob[..., Coroutine[Any, Any, _R]],
|
||||
*args: Any,
|
||||
eager_start: bool = False,
|
||||
background: bool = False,
|
||||
) -> asyncio.Future[_R] | None:
|
||||
...
|
||||
|
||||
@overload
|
||||
@callback
|
||||
def async_run_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R], *args: Any
|
||||
self,
|
||||
hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R],
|
||||
*args: Any,
|
||||
eager_start: bool = False,
|
||||
background: bool = False,
|
||||
) -> asyncio.Future[_R] | None:
|
||||
...
|
||||
|
||||
@callback
|
||||
def async_run_hass_job(
|
||||
self, hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R], *args: Any
|
||||
self,
|
||||
hassjob: HassJob[..., Coroutine[Any, Any, _R] | _R],
|
||||
*args: Any,
|
||||
eager_start: bool = False,
|
||||
background: bool = False,
|
||||
) -> asyncio.Future[_R] | None:
|
||||
"""Run a HassJob from within the event loop.
|
||||
|
||||
This method must be run in the event loop.
|
||||
|
||||
If eager_start is True, coroutine functions will be scheduled eagerly.
|
||||
If background is True, the task will created as a background task.
|
||||
|
||||
hassjob: HassJob
|
||||
args: parameters for method to call.
|
||||
"""
|
||||
@ -838,7 +794,9 @@ class HomeAssistant:
|
||||
hassjob.target(*args)
|
||||
return None
|
||||
|
||||
return self.async_add_hass_job(hassjob, *args)
|
||||
return self.async_add_hass_job(
|
||||
hassjob, *args, eager_start=eager_start, background=background
|
||||
)
|
||||
|
||||
@overload
|
||||
@callback
|
||||
@ -891,7 +849,7 @@ class HomeAssistant:
|
||||
self.async_block_till_done(), self.loop
|
||||
).result()
|
||||
|
||||
async def async_block_till_done(self, wait_periodic_tasks: bool = True) -> None:
|
||||
async def async_block_till_done(self, wait_background_tasks: bool = False) -> None:
|
||||
"""Block until all pending work is done."""
|
||||
# To flush out any call_soon_threadsafe
|
||||
await asyncio.sleep(0)
|
||||
@ -900,8 +858,8 @@ class HomeAssistant:
|
||||
while tasks := [
|
||||
task
|
||||
for task in (
|
||||
self._tasks | self._periodic_tasks
|
||||
if wait_periodic_tasks
|
||||
self._tasks | self._background_tasks
|
||||
if wait_background_tasks
|
||||
else self._tasks
|
||||
)
|
||||
if task is not current_task and not cancelling(task)
|
||||
@ -1034,7 +992,7 @@ class HomeAssistant:
|
||||
self._tasks = set()
|
||||
|
||||
# Cancel all background tasks
|
||||
for task in self._background_tasks | self._periodic_tasks:
|
||||
for task in self._background_tasks:
|
||||
self._tasks.add(task)
|
||||
task.add_done_callback(self._tasks.remove)
|
||||
task.cancel("Home Assistant is stopping")
|
||||
@ -1046,7 +1004,7 @@ class HomeAssistant:
|
||||
self.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
try:
|
||||
async with self.timeout.async_timeout(STOP_STAGE_SHUTDOWN_TIMEOUT):
|
||||
await self.async_block_till_done(wait_periodic_tasks=False)
|
||||
await self.async_block_till_done()
|
||||
except TimeoutError:
|
||||
_LOGGER.warning(
|
||||
"Timed out waiting for integrations to stop, the shutdown will"
|
||||
@ -1059,7 +1017,7 @@ class HomeAssistant:
|
||||
self.bus.async_fire(EVENT_HOMEASSISTANT_FINAL_WRITE)
|
||||
try:
|
||||
async with self.timeout.async_timeout(FINAL_WRITE_STAGE_SHUTDOWN_TIMEOUT):
|
||||
await self.async_block_till_done(wait_periodic_tasks=False)
|
||||
await self.async_block_till_done()
|
||||
except TimeoutError:
|
||||
_LOGGER.warning(
|
||||
"Timed out waiting for final writes to complete, the shutdown will"
|
||||
@ -1111,7 +1069,7 @@ class HomeAssistant:
|
||||
|
||||
try:
|
||||
async with self.timeout.async_timeout(CLOSE_STAGE_SHUTDOWN_TIMEOUT):
|
||||
await self.async_block_till_done(wait_periodic_tasks=False)
|
||||
await self.async_block_till_done()
|
||||
except TimeoutError:
|
||||
_LOGGER.warning(
|
||||
"Timed out waiting for close event to be processed, the shutdown will"
|
||||
|
@ -643,14 +643,14 @@ class EntityPlatform:
|
||||
def _async_handle_interval_callback(self, now: datetime) -> None:
|
||||
"""Update all the entity states in a single platform."""
|
||||
if self.config_entry:
|
||||
self.config_entry.async_create_periodic_task(
|
||||
self.config_entry.async_create_background_task(
|
||||
self.hass,
|
||||
self._update_entity_states(now),
|
||||
name=f"EntityPlatform poll {self.domain}.{self.platform_name}",
|
||||
eager_start=True,
|
||||
)
|
||||
else:
|
||||
self.hass.async_create_periodic_task(
|
||||
self.hass.async_create_background_task(
|
||||
self._update_entity_states(now),
|
||||
name=f"EntityPlatform poll {self.domain}.{self.platform_name}",
|
||||
eager_start=True,
|
||||
|
@ -1599,7 +1599,7 @@ class _TrackTimeInterval:
|
||||
self._track_job,
|
||||
hass.loop.time() + self.seconds,
|
||||
)
|
||||
hass.async_run_periodic_hass_job(self._run_job, now)
|
||||
hass.async_run_hass_job(self._run_job, now, eager_start=True, background=True)
|
||||
|
||||
@callback
|
||||
def async_cancel(self) -> None:
|
||||
@ -1684,7 +1684,7 @@ class SunListener:
|
||||
"""Handle solar event."""
|
||||
self._unsub_sun = None
|
||||
self._listen_next_sun_event()
|
||||
self.hass.async_run_periodic_hass_job(self.job)
|
||||
self.hass.async_run_hass_job(self.job, eager_start=True, background=True)
|
||||
|
||||
@callback
|
||||
def _handle_config_event(self, _event: Any) -> None:
|
||||
@ -1770,7 +1770,9 @@ class _TrackUTCTimeChange:
|
||||
# time when the timer was scheduled
|
||||
utc_now = time_tracker_utcnow()
|
||||
localized_now = dt_util.as_local(utc_now) if self.local else utc_now
|
||||
hass.async_run_periodic_hass_job(self.job, localized_now)
|
||||
hass.async_run_hass_job(
|
||||
self.job, localized_now, eager_start=True, background=True
|
||||
)
|
||||
if TYPE_CHECKING:
|
||||
assert self._pattern_time_change_listener_job is not None
|
||||
self._cancel_callback = async_track_point_in_utc_time(
|
||||
|
@ -258,14 +258,14 @@ class DataUpdateCoordinator(BaseDataUpdateCoordinatorProtocol, Generic[_DataT]):
|
||||
def __wrap_handle_refresh_interval(self) -> None:
|
||||
"""Handle a refresh interval occurrence."""
|
||||
if self.config_entry:
|
||||
self.config_entry.async_create_periodic_task(
|
||||
self.config_entry.async_create_background_task(
|
||||
self.hass,
|
||||
self._handle_refresh_interval(),
|
||||
name=f"{self.name} - {self.config_entry.title} - refresh",
|
||||
eager_start=True,
|
||||
)
|
||||
else:
|
||||
self.hass.async_create_periodic_task(
|
||||
self.hass.async_create_background_task(
|
||||
self._handle_refresh_interval(),
|
||||
name=f"{self.name} - refresh",
|
||||
eager_start=True,
|
||||
|
@ -30,7 +30,7 @@ async def test_coordinator_error(
|
||||
):
|
||||
freezer.tick(WEATHER_UPDATE_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("weather.aemet")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
@ -62,7 +62,7 @@ async def test_coordinator_client_connector_error(hass: HomeAssistant) -> None:
|
||||
|
||||
mock_device_status.side_effect = AirzoneCloudError
|
||||
async_fire_time_changed(hass, utcnow() + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
mock_device_status.assert_called()
|
||||
|
||||
|
@ -51,7 +51,7 @@ async def test_heartbeat_trigger_right_time(hass: HomeAssistant) -> None:
|
||||
async_fire_time_changed(
|
||||
hass, dt_util.utcnow() + BroadlinkHeartbeat.HEARTBEAT_INTERVAL
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert mock_ping.call_count == 1
|
||||
assert mock_ping.call_args == call(device.host)
|
||||
@ -69,7 +69,7 @@ async def test_heartbeat_do_not_trigger_before_time(hass: HomeAssistant) -> None
|
||||
hass,
|
||||
dt_util.utcnow() + BroadlinkHeartbeat.HEARTBEAT_INTERVAL // 2,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert mock_ping.call_count == 0
|
||||
|
||||
@ -88,6 +88,7 @@ async def test_heartbeat_unload(hass: HomeAssistant) -> None:
|
||||
async_fire_time_changed(
|
||||
hass, dt_util.utcnow() + BroadlinkHeartbeat.HEARTBEAT_INTERVAL
|
||||
)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert mock_ping.call_count == 0
|
||||
|
||||
@ -108,7 +109,7 @@ async def test_heartbeat_do_not_unload(hass: HomeAssistant) -> None:
|
||||
async_fire_time_changed(
|
||||
hass, dt_util.utcnow() + BroadlinkHeartbeat.HEARTBEAT_INTERVAL
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert mock_ping.call_count == 1
|
||||
assert mock_ping.call_args == call(device_b.host)
|
||||
|
@ -209,7 +209,7 @@ async def test_integration_update_interval(
|
||||
async_fire_time_changed(
|
||||
hass, dt_util.utcnow() + timedelta(minutes=DEFAULT_UPDATE_INTERVAL)
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(instance.update_dns_record.mock_calls) == 2
|
||||
assert "All target records are up to date" not in caplog.text
|
||||
|
||||
@ -217,12 +217,12 @@ async def test_integration_update_interval(
|
||||
async_fire_time_changed(
|
||||
hass, dt_util.utcnow() + timedelta(minutes=DEFAULT_UPDATE_INTERVAL)
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(instance.update_dns_record.mock_calls) == 2
|
||||
|
||||
instance.list_dns_records.side_effect = pycfdns.ComunicationException()
|
||||
async_fire_time_changed(
|
||||
hass, dt_util.utcnow() + timedelta(minutes=DEFAULT_UPDATE_INTERVAL)
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(instance.update_dns_record.mock_calls) == 2
|
||||
|
@ -324,7 +324,7 @@ async def test_availability(
|
||||
hass.states.async_set("sensor.input1", "on")
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("binary_sensor.test")
|
||||
assert entity_state
|
||||
@ -335,7 +335,7 @@ async def test_availability(
|
||||
with mock_asyncio_subprocess_run(b"0"):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("binary_sensor.test")
|
||||
assert entity_state
|
||||
|
@ -265,7 +265,7 @@ async def test_updating_to_often(
|
||||
not in caplog.text
|
||||
)
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=11))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert called
|
||||
called.clear()
|
||||
|
||||
@ -282,7 +282,7 @@ async def test_updating_to_often(
|
||||
wait_till_event.set()
|
||||
|
||||
# Finish processing update
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert called
|
||||
assert (
|
||||
"Updating Command Line Cover Test took longer than the scheduled update interval"
|
||||
@ -327,7 +327,7 @@ async def test_updating_manually(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert called
|
||||
called.clear()
|
||||
|
||||
@ -367,7 +367,7 @@ async def test_availability(
|
||||
hass.states.async_set("sensor.input1", "on")
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("cover.test")
|
||||
assert entity_state
|
||||
@ -378,7 +378,7 @@ async def test_availability(
|
||||
with mock_asyncio_subprocess_run(b"50\n"):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("cover.test")
|
||||
assert entity_state
|
||||
|
@ -20,7 +20,7 @@ async def test_setup_config(hass: HomeAssistant, load_yaml_integration: None) ->
|
||||
"""Test setup from yaml."""
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=10))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state_binary_sensor = hass.states.get("binary_sensor.test")
|
||||
state_sensor = hass.states.get("sensor.test")
|
||||
|
@ -108,7 +108,7 @@ async def test_template_render(
|
||||
hass,
|
||||
dt_util.utcnow() + timedelta(minutes=1),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("sensor.test")
|
||||
assert entity_state
|
||||
@ -140,7 +140,7 @@ async def test_template_render_with_quote(hass: HomeAssistant) -> None:
|
||||
hass,
|
||||
dt_util.utcnow() + timedelta(minutes=1),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert len(mock_subprocess_run.mock_calls) == 1
|
||||
mock_subprocess_run.assert_called_with(
|
||||
@ -734,7 +734,7 @@ async def test_availability(
|
||||
hass.states.async_set("sensor.input1", "on")
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("sensor.test")
|
||||
assert entity_state
|
||||
@ -745,7 +745,7 @@ async def test_availability(
|
||||
with mock_asyncio_subprocess_run(b"January 17, 2022"):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("sensor.test")
|
||||
assert entity_state
|
||||
|
@ -350,7 +350,7 @@ async def test_switch_command_state_fail(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("switch.test")
|
||||
assert entity_state
|
||||
@ -734,7 +734,7 @@ async def test_availability(
|
||||
hass.states.async_set("sensor.input1", "on")
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("switch.test")
|
||||
assert entity_state
|
||||
@ -745,7 +745,7 @@ async def test_availability(
|
||||
with mock_asyncio_subprocess_run(b"50\n"):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
entity_state = hass.states.get("switch.test")
|
||||
assert entity_state
|
||||
|
@ -129,11 +129,11 @@ async def test_failed_update_and_reconnection(
|
||||
await mock_responses(hass, aioclient_mock, error=True)
|
||||
next_update = dt_util.utcnow() + timedelta(seconds=30)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.efergy_power_usage").state == STATE_UNAVAILABLE
|
||||
aioclient_mock.clear_requests()
|
||||
await mock_responses(hass, aioclient_mock)
|
||||
next_update = dt_util.utcnow() + timedelta(seconds=30)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.efergy_power_usage").state == "1580"
|
||||
|
@ -370,14 +370,14 @@ async def test_feed_updates(
|
||||
# Change time and fetch more entries
|
||||
future = dt_util.utcnow() + timedelta(hours=1, seconds=1)
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert len(events) == 2
|
||||
|
||||
# Change time but no new entries
|
||||
future = dt_util.utcnow() + timedelta(hours=2, seconds=2)
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert len(events) == 2
|
||||
|
||||
|
@ -79,7 +79,7 @@ async def test_binary_sensors(
|
||||
mock_fully_kiosk.getDeviceInfo.return_value = {}
|
||||
freezer.tick(UPDATE_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("binary_sensor.amazon_fire_plugged_in")
|
||||
assert state
|
||||
@ -89,7 +89,7 @@ async def test_binary_sensors(
|
||||
mock_fully_kiosk.getDeviceInfo.side_effect = FullyKioskError("error", "status")
|
||||
freezer.tick(UPDATE_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("binary_sensor.amazon_fire_plugged_in")
|
||||
assert state
|
||||
|
@ -53,7 +53,7 @@ async def test_numbers(
|
||||
# Test invalid numeric data
|
||||
mock_fully_kiosk.getSettings.return_value = {"screenBrightness": "invalid"}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + UPDATE_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("number.amazon_fire_screen_brightness")
|
||||
assert state
|
||||
@ -62,7 +62,7 @@ async def test_numbers(
|
||||
# Test unknown/missing data
|
||||
mock_fully_kiosk.getSettings.return_value = {}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + UPDATE_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("number.amazon_fire_screensaver_timer")
|
||||
assert state
|
||||
|
@ -145,7 +145,7 @@ async def test_sensors_sensors(
|
||||
mock_fully_kiosk.getDeviceInfo.return_value = {}
|
||||
freezer.tick(UPDATE_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("sensor.amazon_fire_internal_storage_free_space")
|
||||
assert state
|
||||
@ -155,7 +155,7 @@ async def test_sensors_sensors(
|
||||
mock_fully_kiosk.getDeviceInfo.side_effect = FullyKioskError("error", "status")
|
||||
freezer.tick(UPDATE_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("sensor.amazon_fire_internal_storage_free_space")
|
||||
assert state
|
||||
@ -181,7 +181,7 @@ async def test_url_sensor_truncating(
|
||||
"currentPage": long_url,
|
||||
}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + UPDATE_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("sensor.amazon_fire_current_page")
|
||||
assert state
|
||||
|
@ -831,11 +831,11 @@ async def test_device_registry_calls(hass: HomeAssistant) -> None:
|
||||
return_value=os_mock_data,
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=1))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(dev_reg.devices) == 5
|
||||
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=2))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(dev_reg.devices) == 5
|
||||
|
||||
supervisor_mock_data = {
|
||||
|
@ -298,7 +298,7 @@ async def test_stats_addon_sensor(
|
||||
|
||||
freezer.tick(HASSIO_UPDATE_INTERVAL + timedelta(seconds=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert "Could not fetch stats" not in caplog.text
|
||||
|
||||
@ -308,7 +308,7 @@ async def test_stats_addon_sensor(
|
||||
|
||||
freezer.tick(HASSIO_UPDATE_INTERVAL + timedelta(seconds=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert "Could not fetch stats" not in caplog.text
|
||||
|
||||
@ -316,7 +316,7 @@ async def test_stats_addon_sensor(
|
||||
entity_registry.async_update_entity(entity_id, disabled_by=None)
|
||||
freezer.tick(config_entries.RELOAD_AFTER_UPDATE_DELAY)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert config_entry.state is config_entries.ConfigEntryState.LOADED
|
||||
# Verify the entity is still enabled
|
||||
assert entity_registry.async_get(entity_id).disabled_by is None
|
||||
@ -324,13 +324,13 @@ async def test_stats_addon_sensor(
|
||||
# The config entry just reloaded, so we need to wait for the next update
|
||||
freezer.tick(HASSIO_UPDATE_INTERVAL + timedelta(seconds=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get(entity_id) is not None
|
||||
|
||||
freezer.tick(HASSIO_UPDATE_INTERVAL + timedelta(seconds=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
# Verify that the entity have the expected state.
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == expected
|
||||
@ -341,7 +341,7 @@ async def test_stats_addon_sensor(
|
||||
|
||||
freezer.tick(HASSIO_UPDATE_INTERVAL + timedelta(seconds=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
@ -1003,7 +1003,7 @@ async def test_does_not_work_into_the_future(
|
||||
one_hour_in = start_time + timedelta(minutes=60)
|
||||
with freeze_time(one_hour_in):
|
||||
async_fire_time_changed(hass, one_hour_in)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get("sensor.sensor1").state == STATE_UNKNOWN
|
||||
assert hass.states.get("sensor.sensor2").state == STATE_UNKNOWN
|
||||
@ -1013,7 +1013,7 @@ async def test_does_not_work_into_the_future(
|
||||
hass.states.async_set("binary_sensor.state", "off")
|
||||
await hass.async_block_till_done()
|
||||
async_fire_time_changed(hass, turn_off_time)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get("sensor.sensor1").state == STATE_UNKNOWN
|
||||
assert hass.states.get("sensor.sensor2").state == STATE_UNKNOWN
|
||||
@ -1021,7 +1021,7 @@ async def test_does_not_work_into_the_future(
|
||||
turn_back_on_time = start_time + timedelta(minutes=105)
|
||||
with freeze_time(turn_back_on_time):
|
||||
async_fire_time_changed(hass, turn_back_on_time)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get("sensor.sensor1").state == STATE_UNKNOWN
|
||||
assert hass.states.get("sensor.sensor2").state == STATE_UNKNOWN
|
||||
@ -1036,7 +1036,7 @@ async def test_does_not_work_into_the_future(
|
||||
end_time = start_time + timedelta(minutes=120)
|
||||
with freeze_time(end_time):
|
||||
async_fire_time_changed(hass, end_time)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get("sensor.sensor1").state == STATE_UNKNOWN
|
||||
assert hass.states.get("sensor.sensor2").state == STATE_UNKNOWN
|
||||
@ -1044,7 +1044,7 @@ async def test_does_not_work_into_the_future(
|
||||
in_the_window = start_time + timedelta(hours=23, minutes=5)
|
||||
with freeze_time(in_the_window):
|
||||
async_fire_time_changed(hass, in_the_window)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get("sensor.sensor1").state == "0.08"
|
||||
assert hass.states.get("sensor.sensor2").state == "0.0833333333333333"
|
||||
@ -1055,7 +1055,7 @@ async def test_does_not_work_into_the_future(
|
||||
return_value=[],
|
||||
), freeze_time(past_the_window):
|
||||
async_fire_time_changed(hass, past_the_window)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get("sensor.sensor1").state == STATE_UNKNOWN
|
||||
|
||||
@ -1077,7 +1077,7 @@ async def test_does_not_work_into_the_future(
|
||||
_fake_off_states,
|
||||
), freeze_time(past_the_window_with_data):
|
||||
async_fire_time_changed(hass, past_the_window_with_data)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get("sensor.sensor1").state == STATE_UNKNOWN
|
||||
|
||||
@ -1087,7 +1087,7 @@ async def test_does_not_work_into_the_future(
|
||||
_fake_off_states,
|
||||
), freeze_time(at_the_next_window_with_data):
|
||||
async_fire_time_changed(hass, at_the_next_window_with_data)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert hass.states.get("sensor.sensor1").state == "0.0"
|
||||
|
||||
@ -1487,7 +1487,7 @@ async def test_end_time_with_microseconds_zeroed(
|
||||
)
|
||||
|
||||
async_fire_time_changed(hass, time_200)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.heatpump_compressor_today").state == "1.83"
|
||||
assert (
|
||||
hass.states.get("sensor.heatpump_compressor_today2").state
|
||||
@ -1499,7 +1499,7 @@ async def test_end_time_with_microseconds_zeroed(
|
||||
time_400 = start_of_today + timedelta(hours=4)
|
||||
with freeze_time(time_400):
|
||||
async_fire_time_changed(hass, time_400)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.heatpump_compressor_today").state == "1.83"
|
||||
assert (
|
||||
hass.states.get("sensor.heatpump_compressor_today2").state
|
||||
@ -1510,7 +1510,7 @@ async def test_end_time_with_microseconds_zeroed(
|
||||
time_600 = start_of_today + timedelta(hours=6)
|
||||
with freeze_time(time_600):
|
||||
async_fire_time_changed(hass, time_600)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.heatpump_compressor_today").state == "3.83"
|
||||
assert (
|
||||
hass.states.get("sensor.heatpump_compressor_today2").state
|
||||
@ -1525,7 +1525,7 @@ async def test_end_time_with_microseconds_zeroed(
|
||||
|
||||
with freeze_time(rolled_to_next_day):
|
||||
async_fire_time_changed(hass, rolled_to_next_day)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.heatpump_compressor_today").state == "0.0"
|
||||
assert hass.states.get("sensor.heatpump_compressor_today2").state == "0.0"
|
||||
|
||||
@ -1534,7 +1534,7 @@ async def test_end_time_with_microseconds_zeroed(
|
||||
)
|
||||
with freeze_time(rolled_to_next_day_plus_12):
|
||||
async_fire_time_changed(hass, rolled_to_next_day_plus_12)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.heatpump_compressor_today").state == "12.0"
|
||||
assert hass.states.get("sensor.heatpump_compressor_today2").state == "12.0"
|
||||
|
||||
@ -1543,7 +1543,7 @@ async def test_end_time_with_microseconds_zeroed(
|
||||
)
|
||||
with freeze_time(rolled_to_next_day_plus_14):
|
||||
async_fire_time_changed(hass, rolled_to_next_day_plus_14)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.heatpump_compressor_today").state == "14.0"
|
||||
assert hass.states.get("sensor.heatpump_compressor_today2").state == "14.0"
|
||||
|
||||
@ -1554,12 +1554,12 @@ async def test_end_time_with_microseconds_zeroed(
|
||||
hass.states.async_set("binary_sensor.heatpump_compressor_state", "off")
|
||||
await async_wait_recording_done(hass)
|
||||
async_fire_time_changed(hass, rolled_to_next_day_plus_16_860000)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
rolled_to_next_day_plus_18 = start_of_today + timedelta(days=1, hours=18)
|
||||
with freeze_time(rolled_to_next_day_plus_18):
|
||||
async_fire_time_changed(hass, rolled_to_next_day_plus_18)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get("sensor.heatpump_compressor_today").state == "16.0"
|
||||
assert (
|
||||
hass.states.get("sensor.heatpump_compressor_today2").state
|
||||
|
@ -177,7 +177,7 @@ async def test_setup(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> Non
|
||||
[mock_entry_1, mock_entry_4, mock_entry_3],
|
||||
)
|
||||
async_fire_time_changed(hass, utcnow + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
all_states = hass.states.async_all()
|
||||
assert len(all_states) == 3
|
||||
@ -186,7 +186,7 @@ async def test_setup(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> Non
|
||||
# so no changes to entities.
|
||||
mock_feed_update.return_value = "OK_NO_DATA", None
|
||||
async_fire_time_changed(hass, utcnow + 2 * SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
all_states = hass.states.async_all()
|
||||
assert len(all_states) == 3
|
||||
@ -194,7 +194,7 @@ async def test_setup(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> Non
|
||||
# Simulate an update - empty data, removes all entities
|
||||
mock_feed_update.return_value = "ERROR", None
|
||||
async_fire_time_changed(hass, utcnow + 3 * SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
all_states = hass.states.async_all()
|
||||
assert len(all_states) == 0
|
||||
|
@ -6,9 +6,18 @@ import pytest
|
||||
|
||||
from homeassistant.components.lifx import config_flow, coordinator, util
|
||||
|
||||
from . import _patch_discovery
|
||||
|
||||
from tests.common import mock_device_registry, mock_registry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_discovery():
|
||||
"""Mock discovery."""
|
||||
with _patch_discovery():
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_effect_conductor():
|
||||
"""Mock the effect conductor."""
|
||||
|
@ -4,6 +4,8 @@ from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import lifx
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
from homeassistant.const import (
|
||||
@ -32,6 +34,7 @@ from . import (
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_hev_cycle_state(
|
||||
hass: HomeAssistant, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
@ -65,11 +68,11 @@ async def test_hev_cycle_state(
|
||||
bulb.hev_cycle = {"duration": 7200, "remaining": 0, "last_power": False}
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
bulb.hev_cycle = None
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get(entity_id).state == STATE_UNKNOWN
|
||||
|
@ -64,15 +64,15 @@ async def test_configuring_lifx_causes_discovery(hass: HomeAssistant) -> None:
|
||||
assert start_calls == 1
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=5))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert start_calls == 2
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=15))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert start_calls == 3
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert start_calls == 4
|
||||
|
||||
|
||||
|
@ -663,6 +663,7 @@ async def test_extended_multizone_messages(hass: HomeAssistant) -> None:
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_matrix_flame_morph_effects(hass: HomeAssistant) -> None:
|
||||
"""Test the firmware flame and morph effects on a matrix device."""
|
||||
config_entry = MockConfigEntry(
|
||||
@ -721,7 +722,7 @@ async def test_matrix_flame_morph_effects(hass: HomeAssistant) -> None:
|
||||
],
|
||||
}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
@ -777,7 +778,7 @@ async def test_matrix_flame_morph_effects(hass: HomeAssistant) -> None:
|
||||
],
|
||||
}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
@ -803,6 +804,7 @@ async def test_matrix_flame_morph_effects(hass: HomeAssistant) -> None:
|
||||
bulb.set_power.reset_mock()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_lightstrip_move_effect(hass: HomeAssistant) -> None:
|
||||
"""Test the firmware move effect on a light strip."""
|
||||
config_entry = MockConfigEntry(
|
||||
@ -859,7 +861,7 @@ async def test_lightstrip_move_effect(hass: HomeAssistant) -> None:
|
||||
bulb.power_level = 65535
|
||||
bulb.effect = {"name": "MOVE", "speed": 4.5, "direction": "Left"}
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_ON
|
||||
@ -1119,6 +1121,7 @@ async def test_white_bulb(hass: HomeAssistant) -> None:
|
||||
bulb.set_color.reset_mock()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_config_zoned_light_strip_fails(
|
||||
hass: HomeAssistant, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
@ -1154,7 +1157,7 @@ async def test_config_zoned_light_strip_fails(
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
|
@ -144,15 +144,15 @@ async def test_discovery_is_more_frequent_during_migration(
|
||||
assert start_calls == 1
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=5))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert start_calls == 3
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=10))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert start_calls == 4
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=15))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert start_calls == 5
|
||||
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import lifx
|
||||
from homeassistant.components.lifx.const import DOMAIN
|
||||
from homeassistant.components.select import DOMAIN as SELECT_DOMAIN
|
||||
@ -95,6 +97,7 @@ async def test_infrared_brightness(
|
||||
assert state.state == "100%"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_set_infrared_brightness_25_percent(hass: HomeAssistant) -> None:
|
||||
"""Test getting and setting infrared brightness."""
|
||||
|
||||
@ -124,7 +127,7 @@ async def test_set_infrared_brightness_25_percent(hass: HomeAssistant) -> None:
|
||||
bulb.get_infrared = MockLifxCommand(bulb, infrared_brightness=16383)
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert bulb.set_infrared.calls[0][0][0] == 16383
|
||||
|
||||
@ -134,6 +137,7 @@ async def test_set_infrared_brightness_25_percent(hass: HomeAssistant) -> None:
|
||||
bulb.set_infrared.reset_mock()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_set_infrared_brightness_50_percent(hass: HomeAssistant) -> None:
|
||||
"""Test getting and setting infrared brightness."""
|
||||
|
||||
@ -163,7 +167,7 @@ async def test_set_infrared_brightness_50_percent(hass: HomeAssistant) -> None:
|
||||
bulb.get_infrared = MockLifxCommand(bulb, infrared_brightness=32767)
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert bulb.set_infrared.calls[0][0][0] == 32767
|
||||
|
||||
@ -173,6 +177,7 @@ async def test_set_infrared_brightness_50_percent(hass: HomeAssistant) -> None:
|
||||
bulb.set_infrared.reset_mock()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_set_infrared_brightness_100_percent(hass: HomeAssistant) -> None:
|
||||
"""Test getting and setting infrared brightness."""
|
||||
|
||||
@ -202,7 +207,7 @@ async def test_set_infrared_brightness_100_percent(hass: HomeAssistant) -> None:
|
||||
bulb.get_infrared = MockLifxCommand(bulb, infrared_brightness=65535)
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert bulb.set_infrared.calls[0][0][0] == 65535
|
||||
|
||||
@ -212,6 +217,7 @@ async def test_set_infrared_brightness_100_percent(hass: HomeAssistant) -> None:
|
||||
bulb.set_infrared.reset_mock()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_disable_infrared(hass: HomeAssistant) -> None:
|
||||
"""Test getting and setting infrared brightness."""
|
||||
|
||||
@ -241,7 +247,7 @@ async def test_disable_infrared(hass: HomeAssistant) -> None:
|
||||
bulb.get_infrared = MockLifxCommand(bulb, infrared_brightness=0)
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert bulb.set_infrared.calls[0][0][0] == 0
|
||||
|
||||
@ -251,6 +257,7 @@ async def test_disable_infrared(hass: HomeAssistant) -> None:
|
||||
bulb.set_infrared.reset_mock()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_discovery")
|
||||
async def test_invalid_infrared_brightness(hass: HomeAssistant) -> None:
|
||||
"""Test getting and setting infrared brightness."""
|
||||
|
||||
@ -273,7 +280,7 @@ async def test_invalid_infrared_brightness(hass: HomeAssistant) -> None:
|
||||
bulb.get_infrared = MockLifxCommand(bulb, infrared_brightness=12345)
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
@ -73,7 +73,7 @@ async def test_sensor_updating(
|
||||
async def skip_time_and_check_events() -> None:
|
||||
freezer.tick(timedelta(minutes=15))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert events == snapshot
|
||||
|
||||
|
@ -275,7 +275,7 @@ async def test_coordinator_error(
|
||||
ourgroceries.get_list_items.side_effect = exception
|
||||
freezer.tick(SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("todo.test_list")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
@ -223,7 +223,7 @@ async def test_reauth(
|
||||
# check reauth trigger with bad-auth responses
|
||||
freezer.move_to(_MOCK_TIME_BAD_AUTH_RESPONSES)
|
||||
async_fire_time_changed(hass, _MOCK_TIME_BAD_AUTH_RESPONSES)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert pvpc_aioclient_mock.call_count == 6
|
||||
|
||||
result = hass.config_entries.flow.async_progress_by_handler(DOMAIN)[0]
|
||||
@ -252,5 +252,5 @@ async def test_reauth(
|
||||
assert result["reason"] == "reauth_successful"
|
||||
assert pvpc_aioclient_mock.call_count == 8
|
||||
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert pvpc_aioclient_mock.call_count == 10
|
||||
|
@ -178,7 +178,7 @@ async def test_setup(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> Non
|
||||
# so no changes to entities.
|
||||
mock_feed_update.return_value = "OK_NO_DATA", None
|
||||
async_fire_time_changed(hass, utcnow + 2 * SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
all_states = hass.states.async_all()
|
||||
assert len(all_states) == 3
|
||||
@ -186,7 +186,7 @@ async def test_setup(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> Non
|
||||
# Simulate an update - empty data, removes all entities
|
||||
mock_feed_update.return_value = "ERROR", None
|
||||
async_fire_time_changed(hass, utcnow + 3 * SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
all_states = hass.states.async_all()
|
||||
assert len(all_states) == 0
|
||||
|
@ -103,7 +103,7 @@ async def test_coordinator_client_connector_error(
|
||||
mock_system_sensor.side_effect = QswError
|
||||
freezer.tick(DATA_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
mock_system_sensor.assert_called_once()
|
||||
mock_users_verification.assert_called()
|
||||
@ -115,7 +115,7 @@ async def test_coordinator_client_connector_error(
|
||||
mock_firmware_update_check.side_effect = APIError
|
||||
freezer.tick(FW_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
mock_firmware_update_check.assert_called_once()
|
||||
mock_firmware_update_check.reset_mock()
|
||||
@ -123,7 +123,7 @@ async def test_coordinator_client_connector_error(
|
||||
mock_firmware_update_check.side_effect = QswError
|
||||
freezer.tick(FW_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
mock_firmware_update_check.assert_called_once()
|
||||
|
||||
|
@ -147,7 +147,7 @@ async def test_auth_failure_on_device_update(
|
||||
side_effect=AuthenticationError,
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(minutes=20))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert "Authentication failed while fetching devices data: " in [
|
||||
record.message
|
||||
@ -191,7 +191,7 @@ async def test_error_on_global_update(
|
||||
side_effect=error_type,
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(minutes=20))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert log_msg in [
|
||||
record.message for record in caplog.records if record.levelname == "ERROR"
|
||||
@ -232,7 +232,7 @@ async def test_error_on_device_update(
|
||||
side_effect=error_type,
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.now() + timedelta(minutes=20))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert log_msg in [
|
||||
record.message for record in caplog.records if record.levelname == "ERROR"
|
||||
|
@ -326,7 +326,7 @@ async def test_update_off_ws_with_power_state(
|
||||
next_update = mock_now + timedelta(minutes=1)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
remotews.start_listening.assert_called_once()
|
||||
rest_api.rest_device_info.assert_called_once()
|
||||
@ -342,7 +342,7 @@ async def test_update_off_ws_with_power_state(
|
||||
next_update = mock_now + timedelta(minutes=2)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
rest_api.rest_device_info.assert_called_once()
|
||||
|
||||
@ -355,7 +355,7 @@ async def test_update_off_ws_with_power_state(
|
||||
next_update = mock_now + timedelta(minutes=3)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
rest_api.rest_device_info.assert_called_once()
|
||||
|
||||
@ -386,7 +386,7 @@ async def test_update_off_encryptedws(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_OFF
|
||||
@ -407,12 +407,12 @@ async def test_update_access_denied(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
next_update = mock_now + timedelta(minutes=10)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert [
|
||||
flow
|
||||
@ -442,7 +442,7 @@ async def test_update_ws_connection_failure(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert (
|
||||
"Unexpected ConnectionFailure trying to get remote for fake_host, please "
|
||||
@ -470,7 +470,7 @@ async def test_update_ws_connection_closed(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_OFF
|
||||
@ -492,7 +492,7 @@ async def test_update_ws_unauthorized_error(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert [
|
||||
flow
|
||||
@ -517,7 +517,7 @@ async def test_update_unhandled_response(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_ON
|
||||
@ -537,7 +537,7 @@ async def test_connection_closed_during_update_can_recover(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
@ -545,7 +545,7 @@ async def test_connection_closed_during_update_can_recover(
|
||||
next_update = mock_now + timedelta(minutes=10)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_ON
|
||||
@ -705,7 +705,7 @@ async def test_state(hass: HomeAssistant, freezer: FrozenDateTimeFactory) -> Non
|
||||
):
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
# Should be STATE_UNAVAILABLE since there is no way to turn it back on
|
||||
@ -1444,7 +1444,7 @@ async def test_upnp_re_subscribe_events(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_OFF
|
||||
@ -1454,7 +1454,7 @@ async def test_upnp_re_subscribe_events(
|
||||
next_update = mock_now + timedelta(minutes=10)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_ON
|
||||
@ -1490,7 +1490,7 @@ async def test_upnp_failed_re_subscribe_events(
|
||||
next_update = mock_now + timedelta(minutes=5)
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_OFF
|
||||
@ -1501,7 +1501,7 @@ async def test_upnp_failed_re_subscribe_events(
|
||||
with patch.object(dmr_device, "async_subscribe_services", side_effect=error):
|
||||
freezer.move_to(next_update)
|
||||
async_fire_time_changed(hass, next_update)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == STATE_ON
|
||||
|
@ -139,15 +139,15 @@ async def _setup_seventeentrack(hass, config=None, summary_data=None):
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def _goto_future(hass, future=None):
|
||||
async def _goto_future(hass: HomeAssistant, future=None):
|
||||
"""Move to future."""
|
||||
if not future:
|
||||
future = utcnow() + datetime.timedelta(minutes=10)
|
||||
with patch("homeassistant.util.utcnow", return_value=future):
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
|
||||
async def test_full_valid_config(hass: HomeAssistant) -> None:
|
||||
|
@ -64,7 +64,7 @@ async def test_switch_get_states(hass: HomeAssistant, mock_asyncsleepiq) -> None
|
||||
mock_asyncsleepiq.beds[BED_ID].foundation.lights[0].is_on = True
|
||||
|
||||
async_fire_time_changed(hass, utcnow() + LONGER_UPDATE_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert (
|
||||
hass.states.get(f"light.sleepnumber_{BED_NAME_LOWER}_light_1").state == STATE_ON
|
||||
|
@ -59,7 +59,7 @@ async def test_switch_get_states(hass: HomeAssistant, mock_asyncsleepiq) -> None
|
||||
mock_asyncsleepiq.beds[BED_ID].paused = True
|
||||
|
||||
async_fire_time_changed(hass, utcnow() + LONGER_UPDATE_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert (
|
||||
hass.states.get(f"switch.sleepnumber_{BED_NAME_LOWER}_pause_mode").state
|
||||
|
@ -3,13 +3,14 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.components.smarttub.const import SCAN_INTERVAL
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
||||
|
||||
async def trigger_update(hass):
|
||||
async def trigger_update(hass: HomeAssistant) -> None:
|
||||
"""Trigger a polling update by moving time forward."""
|
||||
new_time = dt_util.utcnow() + timedelta(seconds=SCAN_INTERVAL + 1)
|
||||
async_fire_time_changed(hass, new_time)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
@ -248,7 +248,7 @@ async def test_invalid_url_on_update(
|
||||
hass,
|
||||
dt_util.utcnow() + timedelta(minutes=1),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert "sqlite://****:****@homeassistant.local" in caplog.text
|
||||
|
||||
@ -287,7 +287,7 @@ async def test_templates_with_yaml(
|
||||
hass,
|
||||
dt_util.utcnow() + timedelta(minutes=1),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("sensor.get_values_with_template")
|
||||
assert state.state == "5"
|
||||
@ -301,7 +301,7 @@ async def test_templates_with_yaml(
|
||||
hass,
|
||||
dt_util.utcnow() + timedelta(minutes=2),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("sensor.get_values_with_template")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
@ -314,7 +314,7 @@ async def test_templates_with_yaml(
|
||||
hass,
|
||||
dt_util.utcnow() + timedelta(minutes=3),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("sensor.get_values_with_template")
|
||||
assert state.state == "5"
|
||||
@ -488,7 +488,7 @@ async def test_no_issue_when_view_has_the_text_entity_id_in_it(
|
||||
hass,
|
||||
dt_util.utcnow() + timedelta(minutes=1),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert (
|
||||
"Query contains entity_id but does not reference states_meta" not in caplog.text
|
||||
@ -622,7 +622,7 @@ async def test_query_recover_from_rollback(
|
||||
):
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert "sqlite3.OperationalError" in caplog.text
|
||||
|
||||
state = hass.states.get("sensor.select_value_sql_query")
|
||||
@ -631,7 +631,7 @@ async def test_query_recover_from_rollback(
|
||||
|
||||
freezer.tick(timedelta(minutes=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
state = hass.states.get("sensor.select_value_sql_query")
|
||||
assert state.state == "5"
|
||||
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from discovery30303 import AIODiscovery30303
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import steamist
|
||||
@ -113,7 +114,9 @@ async def test_config_entry_fills_unique_id_with_directed_discovery(
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_single_broadcast_address")
|
||||
async def test_discovery_happens_at_interval(hass: HomeAssistant) -> None:
|
||||
async def test_discovery_happens_at_interval(
|
||||
hass: HomeAssistant, freezer: FrozenDateTimeFactory
|
||||
) -> None:
|
||||
"""Test that discovery happens at interval."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN, data=DEFAULT_ENTRY_DATA, unique_id=FORMATTED_MAC_ADDRESS
|
||||
@ -126,10 +129,11 @@ async def test_discovery_happens_at_interval(hass: HomeAssistant) -> None:
|
||||
return_value=mock_aio_discovery,
|
||||
), _patch_status(MOCK_ASYNC_GET_STATUS_ACTIVE):
|
||||
await async_setup_component(hass, steamist.DOMAIN, {steamist.DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert len(mock_aio_discovery.async_scan.mock_calls) == 2
|
||||
|
||||
async_fire_time_changed(hass, utcnow() + steamist.DISCOVERY_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
freezer.move_to(utcnow() + steamist.DISCOVERY_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(mock_aio_discovery.async_scan.mock_calls) == 3
|
||||
|
@ -6,6 +6,7 @@ import copy
|
||||
from datetime import timedelta
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from kasa.exceptions import AuthenticationException
|
||||
import pytest
|
||||
|
||||
@ -41,23 +42,28 @@ from . import (
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
|
||||
async def test_configuring_tplink_causes_discovery(hass: HomeAssistant) -> None:
|
||||
async def test_configuring_tplink_causes_discovery(
|
||||
hass: HomeAssistant, freezer: FrozenDateTimeFactory
|
||||
) -> None:
|
||||
"""Test that specifying empty config does discovery."""
|
||||
with patch("homeassistant.components.tplink.Discover.discover") as discover, patch(
|
||||
"homeassistant.components.tplink.Discover.discover_single"
|
||||
):
|
||||
discover.return_value = {MagicMock(): MagicMock()}
|
||||
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
# call_count will differ based on number of broadcast addresses
|
||||
call_count = len(discover.mock_calls)
|
||||
assert discover.mock_calls
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=15))
|
||||
await hass.async_block_till_done()
|
||||
freezer.tick(tplink.DISCOVERY_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(discover.mock_calls) == call_count * 2
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=30))
|
||||
await hass.async_block_till_done()
|
||||
freezer.tick(tplink.DISCOVERY_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
assert len(discover.mock_calls) == call_count * 3
|
||||
|
||||
|
||||
|
@ -1118,7 +1118,7 @@ async def test_elec_measurement_sensor_polling(
|
||||
# let the polling happen
|
||||
future = dt_util.utcnow() + timedelta(seconds=90)
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
# ensure the state has been updated to 6.0
|
||||
state = hass.states.get(entity_id)
|
||||
|
@ -72,7 +72,7 @@ async def test_polling_only_updates_entities_it_should_poll(
|
||||
poll_ent.async_update.reset_mock()
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=20))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert not no_poll_ent.async_update.called
|
||||
assert poll_ent.async_update.called
|
||||
@ -121,7 +121,7 @@ async def test_polling_updates_entities_with_exception(hass: HomeAssistant) -> N
|
||||
update_err.clear()
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=20))
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert len(update_ok) == 3
|
||||
assert len(update_err) == 1
|
||||
@ -140,7 +140,7 @@ async def test_update_state_adds_entities(hass: HomeAssistant) -> None:
|
||||
ent2.update = lambda *_: component.add_entities([ent1])
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + DEFAULT_SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
assert len(hass.states.async_entity_ids()) == 2
|
||||
|
||||
|
@ -4330,12 +4330,6 @@ async def test_task_tracking(hass: HomeAssistant) -> None:
|
||||
entry.async_create_background_task(
|
||||
hass, test_task(), "background-task-name", eager_start=False
|
||||
)
|
||||
entry.async_create_periodic_task(
|
||||
hass, test_task(), "periodic-task-name", eager_start=False
|
||||
)
|
||||
entry.async_create_periodic_task(
|
||||
hass, test_task(), "periodic-task-name", eager_start=True
|
||||
)
|
||||
await asyncio.sleep(0)
|
||||
hass.loop.call_soon(event.set)
|
||||
await entry._async_process_on_unload(hass)
|
||||
@ -4343,8 +4337,6 @@ async def test_task_tracking(hass: HomeAssistant) -> None:
|
||||
"on_unload",
|
||||
"background",
|
||||
"background",
|
||||
"background",
|
||||
"background",
|
||||
"normal",
|
||||
]
|
||||
|
||||
|
@ -57,6 +57,7 @@ from homeassistant.exceptions import (
|
||||
ServiceNotFound,
|
||||
)
|
||||
from homeassistant.helpers.json import json_dumps
|
||||
from homeassistant.util.async_ import create_eager_task
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.util.read_only_dict import ReadOnlyDict
|
||||
from homeassistant.util.unit_system import METRIC_SYSTEM
|
||||
@ -97,6 +98,134 @@ async def test_async_add_hass_job_schedule_callback() -> None:
|
||||
assert len(hass.add_job.mock_calls) == 0
|
||||
|
||||
|
||||
async def test_async_add_hass_job_eager_start_coro_suspends(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test scheduling a coro as a task that will suspend with eager_start."""
|
||||
|
||||
async def job_that_suspends():
|
||||
await asyncio.sleep(0)
|
||||
|
||||
task = hass.async_add_hass_job(
|
||||
ha.HassJob(ha.callback(job_that_suspends)), eager_start=True
|
||||
)
|
||||
assert not task.done()
|
||||
assert task in hass._tasks
|
||||
await task
|
||||
assert task not in hass._tasks
|
||||
|
||||
|
||||
async def test_async_run_hass_job_eager_start_coro_suspends(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test scheduling a coro as a task that will suspend with eager_start."""
|
||||
|
||||
async def job_that_suspends():
|
||||
await asyncio.sleep(0)
|
||||
|
||||
task = hass.async_run_hass_job(
|
||||
ha.HassJob(ha.callback(job_that_suspends)), eager_start=True
|
||||
)
|
||||
assert not task.done()
|
||||
assert task in hass._tasks
|
||||
await task
|
||||
assert task not in hass._tasks
|
||||
|
||||
|
||||
async def test_async_add_hass_job_background(hass: HomeAssistant) -> None:
|
||||
"""Test scheduling a coro as a background task with async_add_hass_job."""
|
||||
|
||||
async def job_that_suspends():
|
||||
await asyncio.sleep(0)
|
||||
|
||||
task = hass.async_add_hass_job(
|
||||
ha.HassJob(ha.callback(job_that_suspends)), background=True
|
||||
)
|
||||
assert not task.done()
|
||||
assert task in hass._background_tasks
|
||||
await task
|
||||
assert task not in hass._background_tasks
|
||||
|
||||
|
||||
async def test_async_run_hass_job_background(hass: HomeAssistant) -> None:
|
||||
"""Test scheduling a coro as a background task with async_run_hass_job."""
|
||||
|
||||
async def job_that_suspends():
|
||||
await asyncio.sleep(0)
|
||||
|
||||
task = hass.async_run_hass_job(
|
||||
ha.HassJob(ha.callback(job_that_suspends)), background=True
|
||||
)
|
||||
assert not task.done()
|
||||
assert task in hass._background_tasks
|
||||
await task
|
||||
assert task not in hass._background_tasks
|
||||
|
||||
|
||||
async def test_async_add_hass_job_eager_background(hass: HomeAssistant) -> None:
|
||||
"""Test scheduling a coro as an eager background task with async_add_hass_job."""
|
||||
|
||||
async def job_that_suspends():
|
||||
await asyncio.sleep(0)
|
||||
|
||||
task = hass.async_add_hass_job(
|
||||
ha.HassJob(ha.callback(job_that_suspends)), eager_start=True, background=True
|
||||
)
|
||||
assert not task.done()
|
||||
assert task in hass._background_tasks
|
||||
await task
|
||||
assert task not in hass._background_tasks
|
||||
|
||||
|
||||
async def test_async_run_hass_job_eager_background(hass: HomeAssistant) -> None:
|
||||
"""Test scheduling a coro as an eager background task with async_run_hass_job."""
|
||||
|
||||
async def job_that_suspends():
|
||||
await asyncio.sleep(0)
|
||||
|
||||
task = hass.async_run_hass_job(
|
||||
ha.HassJob(ha.callback(job_that_suspends)), eager_start=True, background=True
|
||||
)
|
||||
assert not task.done()
|
||||
assert task in hass._background_tasks
|
||||
await task
|
||||
assert task not in hass._background_tasks
|
||||
|
||||
|
||||
async def test_async_run_hass_job_background_synchronous(hass: HomeAssistant) -> None:
|
||||
"""Test scheduling a coro as an eager background task with async_run_hass_job."""
|
||||
|
||||
async def job_that_does_not_suspends():
|
||||
pass
|
||||
|
||||
task = hass.async_run_hass_job(
|
||||
ha.HassJob(ha.callback(job_that_does_not_suspends)),
|
||||
eager_start=True,
|
||||
background=True,
|
||||
)
|
||||
assert task.done()
|
||||
assert task not in hass._background_tasks
|
||||
assert task not in hass._tasks
|
||||
await task
|
||||
|
||||
|
||||
async def test_async_run_hass_job_synchronous(hass: HomeAssistant) -> None:
|
||||
"""Test scheduling a coro as an eager task with async_run_hass_job."""
|
||||
|
||||
async def job_that_does_not_suspends():
|
||||
pass
|
||||
|
||||
task = hass.async_run_hass_job(
|
||||
ha.HassJob(ha.callback(job_that_does_not_suspends)),
|
||||
eager_start=True,
|
||||
background=False,
|
||||
)
|
||||
assert task.done()
|
||||
assert task not in hass._background_tasks
|
||||
assert task not in hass._tasks
|
||||
await task
|
||||
|
||||
|
||||
async def test_async_add_hass_job_coro_named(hass: HomeAssistant) -> None:
|
||||
"""Test that we schedule coroutines and add jobs to the job pool with a name."""
|
||||
|
||||
@ -110,6 +239,19 @@ async def test_async_add_hass_job_coro_named(hass: HomeAssistant) -> None:
|
||||
assert "named coro" in str(task)
|
||||
|
||||
|
||||
async def test_async_add_hass_job_eager_start(hass: HomeAssistant) -> None:
|
||||
"""Test eager_start with async_add_hass_job."""
|
||||
|
||||
async def mycoro():
|
||||
pass
|
||||
|
||||
job = ha.HassJob(mycoro, "named coro")
|
||||
assert "named coro" in str(job)
|
||||
assert job.name == "named coro"
|
||||
task = ha.HomeAssistant.async_add_hass_job(hass, job, eager_start=True)
|
||||
assert "named coro" in str(task)
|
||||
|
||||
|
||||
async def test_async_add_hass_job_schedule_partial_callback() -> None:
|
||||
"""Test that we schedule partial coros and add jobs to the job pool."""
|
||||
hass = MagicMock()
|
||||
@ -135,6 +277,24 @@ async def test_async_add_hass_job_schedule_coroutinefunction() -> None:
|
||||
assert len(hass.add_job.mock_calls) == 0
|
||||
|
||||
|
||||
async def test_async_add_hass_job_schedule_corofunction_eager_start() -> None:
|
||||
"""Test that we schedule coroutines and add jobs to the job pool."""
|
||||
hass = MagicMock(loop=MagicMock(wraps=asyncio.get_running_loop()))
|
||||
|
||||
async def job():
|
||||
pass
|
||||
|
||||
with patch(
|
||||
"homeassistant.core.create_eager_task", wraps=create_eager_task
|
||||
) as mock_create_eager_task:
|
||||
hass_job = ha.HassJob(job)
|
||||
task = ha.HomeAssistant.async_add_hass_job(hass, hass_job, eager_start=True)
|
||||
assert len(hass.loop.call_soon.mock_calls) == 0
|
||||
assert len(hass.add_job.mock_calls) == 0
|
||||
assert mock_create_eager_task.mock_calls
|
||||
await task
|
||||
|
||||
|
||||
async def test_async_add_hass_job_schedule_partial_coroutinefunction() -> None:
|
||||
"""Test that we schedule partial coros and add jobs to the job pool."""
|
||||
hass = MagicMock(loop=MagicMock(wraps=asyncio.get_running_loop()))
|
||||
@ -224,7 +384,7 @@ async def test_async_create_task_schedule_coroutine_with_name() -> None:
|
||||
assert "named task" in str(task)
|
||||
|
||||
|
||||
async def test_async_run_periodic_hass_job_calls_callback() -> None:
|
||||
async def test_async_run_eager_hass_job_calls_callback() -> None:
|
||||
"""Test that the callback annotation is respected."""
|
||||
hass = MagicMock()
|
||||
calls = []
|
||||
@ -233,36 +393,21 @@ async def test_async_run_periodic_hass_job_calls_callback() -> None:
|
||||
asyncio.get_running_loop() # ensure we are in the event loop
|
||||
calls.append(1)
|
||||
|
||||
ha.HomeAssistant.async_run_periodic_hass_job(hass, ha.HassJob(ha.callback(job)))
|
||||
ha.HomeAssistant.async_run_hass_job(
|
||||
hass, ha.HassJob(ha.callback(job)), eager_start=True
|
||||
)
|
||||
assert len(calls) == 1
|
||||
|
||||
|
||||
async def test_async_run_periodic_hass_job_calls_coro_function() -> None:
|
||||
"""Test running coros from async_run_periodic_hass_job."""
|
||||
async def test_async_run_eager_hass_job_calls_coro_function() -> None:
|
||||
"""Test running coros from async_run_hass_job with eager_start."""
|
||||
hass = MagicMock()
|
||||
calls = []
|
||||
|
||||
async def job():
|
||||
calls.append(1)
|
||||
pass
|
||||
|
||||
await ha.HomeAssistant.async_run_periodic_hass_job(hass, ha.HassJob(job))
|
||||
assert len(calls) == 1
|
||||
|
||||
|
||||
async def test_async_run_periodic_hass_job_calls_executor_function() -> None:
|
||||
"""Test running in the executor from async_run_periodic_hass_job."""
|
||||
hass = MagicMock()
|
||||
hass.loop = asyncio.get_running_loop()
|
||||
calls = []
|
||||
|
||||
def job():
|
||||
try:
|
||||
asyncio.get_running_loop() # ensure we are not in the event loop
|
||||
except RuntimeError:
|
||||
calls.append(1)
|
||||
|
||||
await ha.HomeAssistant.async_run_periodic_hass_job(hass, ha.HassJob(job))
|
||||
assert len(calls) == 1
|
||||
ha.HomeAssistant.async_run_hass_job(hass, ha.HassJob(job), eager_start=True)
|
||||
assert len(hass.async_add_hass_job.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_async_run_hass_job_calls_callback() -> None:
|
||||
@ -556,7 +701,7 @@ async def test_shutdown_calls_block_till_done_after_shutdown_run_callback_thread
|
||||
"""Ensure shutdown_run_callback_threadsafe is called before the final async_block_till_done."""
|
||||
stop_calls = []
|
||||
|
||||
async def _record_block_till_done(wait_periodic_tasks: bool = True):
|
||||
async def _record_block_till_done(wait_background_tasks: bool = False):
|
||||
nonlocal stop_calls
|
||||
stop_calls.append("async_block_till_done")
|
||||
|
||||
@ -2142,7 +2287,7 @@ async def test_chained_logging_hits_log_timeout(
|
||||
|
||||
with patch.object(ha, "BLOCK_LOG_TIMEOUT", 0.0):
|
||||
hass.async_create_task(_task_chain_1())
|
||||
await hass.async_block_till_done(wait_periodic_tasks=False)
|
||||
await hass.async_block_till_done(wait_background_tasks=False)
|
||||
|
||||
assert "_task_chain_" in caplog.text
|
||||
|
||||
@ -2696,27 +2841,6 @@ async def test_background_task(hass: HomeAssistant, eager_start: bool) -> None:
|
||||
assert result.result() == ha.CoreState.stopping
|
||||
|
||||
|
||||
@pytest.mark.parametrize("eager_start", (True, False))
|
||||
async def test_periodic_task(hass: HomeAssistant, eager_start: bool) -> None:
|
||||
"""Test periodic tasks being quit."""
|
||||
result = asyncio.Future()
|
||||
|
||||
async def test_task():
|
||||
try:
|
||||
await asyncio.sleep(1)
|
||||
except asyncio.CancelledError:
|
||||
result.set_result(hass.state)
|
||||
raise
|
||||
|
||||
task = hass.async_create_periodic_task(
|
||||
test_task(), "happy task", eager_start=eager_start
|
||||
)
|
||||
assert "happy task" in str(task)
|
||||
await asyncio.sleep(0)
|
||||
await hass.async_stop()
|
||||
assert result.result() == ha.CoreState.stopping
|
||||
|
||||
|
||||
async def test_shutdown_does_not_block_on_normal_tasks(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
@ -2767,14 +2891,15 @@ async def test_shutdown_does_not_block_on_shielded_tasks(
|
||||
sleep_task.cancel()
|
||||
|
||||
|
||||
async def test_cancellable_hassjob(hass: HomeAssistant) -> None:
|
||||
@pytest.mark.parametrize("eager_start", (True, False))
|
||||
async def test_cancellable_hassjob(hass: HomeAssistant, eager_start: bool) -> None:
|
||||
"""Simulate a shutdown, ensure cancellable jobs are cancelled."""
|
||||
job = MagicMock()
|
||||
|
||||
@ha.callback
|
||||
def run_job(job: HassJob) -> None:
|
||||
"""Call the action."""
|
||||
hass.async_run_hass_job(job)
|
||||
hass.async_run_hass_job(job, eager_start=True)
|
||||
|
||||
timer1 = hass.loop.call_later(
|
||||
60, run_job, HassJob(ha.callback(job), cancel_on_shutdown=True)
|
||||
|
Loading…
x
Reference in New Issue
Block a user