Workday only update once a day (#116419)
* Workday only update once a day * Fix tests
This commit is contained in:
parent
b7a138b02a
commit
51f9e661a4
2 changed files with 62 additions and 20 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import date, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
from holidays import (
|
from holidays import (
|
||||||
|
@ -15,13 +15,20 @@ import voluptuous as vol
|
||||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_COUNTRY, CONF_LANGUAGE, CONF_NAME
|
from homeassistant.const import CONF_COUNTRY, CONF_LANGUAGE, CONF_NAME
|
||||||
from homeassistant.core import HomeAssistant, ServiceResponse, SupportsResponse
|
from homeassistant.core import (
|
||||||
|
CALLBACK_TYPE,
|
||||||
|
HomeAssistant,
|
||||||
|
ServiceResponse,
|
||||||
|
SupportsResponse,
|
||||||
|
callback,
|
||||||
|
)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import (
|
from homeassistant.helpers.entity_platform import (
|
||||||
AddEntitiesCallback,
|
AddEntitiesCallback,
|
||||||
async_get_current_platform,
|
async_get_current_platform,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.event import async_track_point_in_utc_time
|
||||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||||
from homeassistant.util import dt as dt_util, slugify
|
from homeassistant.util import dt as dt_util, slugify
|
||||||
|
|
||||||
|
@ -201,6 +208,8 @@ class IsWorkdaySensor(BinarySensorEntity):
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
_attr_name = None
|
_attr_name = None
|
||||||
_attr_translation_key = DOMAIN
|
_attr_translation_key = DOMAIN
|
||||||
|
_attr_should_poll = False
|
||||||
|
unsub: CALLBACK_TYPE | None = None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -248,11 +257,34 @@ class IsWorkdaySensor(BinarySensorEntity):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
def get_next_interval(self, now: datetime) -> datetime:
|
||||||
"""Get date and look whether it is a holiday."""
|
"""Compute next time an update should occur."""
|
||||||
self._attr_is_on = self.date_is_workday(dt_util.now())
|
tomorrow = dt_util.as_local(now) + timedelta(days=1)
|
||||||
|
return dt_util.start_of_local_day(tomorrow)
|
||||||
|
|
||||||
async def check_date(self, check_date: date) -> ServiceResponse:
|
def _update_state_and_setup_listener(self) -> None:
|
||||||
|
"""Update state and setup listener for next interval."""
|
||||||
|
now = dt_util.utcnow()
|
||||||
|
self.update_data(now)
|
||||||
|
self.unsub = async_track_point_in_utc_time(
|
||||||
|
self.hass, self.point_in_time_listener, self.get_next_interval(now)
|
||||||
|
)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def point_in_time_listener(self, time_date: datetime) -> None:
|
||||||
|
"""Get the latest data and update state."""
|
||||||
|
self._update_state_and_setup_listener()
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Set up first update."""
|
||||||
|
self._update_state_and_setup_listener()
|
||||||
|
|
||||||
|
def update_data(self, now: datetime) -> None:
|
||||||
|
"""Get date and look whether it is a holiday."""
|
||||||
|
self._attr_is_on = self.date_is_workday(now)
|
||||||
|
|
||||||
|
def check_date(self, check_date: date) -> ServiceResponse:
|
||||||
"""Service to check if date is workday or not."""
|
"""Service to check if date is workday or not."""
|
||||||
return {"workday": self.date_is_workday(check_date)}
|
return {"workday": self.date_is_workday(check_date)}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Tests the Home Assistant workday binary sensor."""
|
"""Tests the Home Assistant workday binary sensor."""
|
||||||
|
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime, timedelta
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
|
@ -41,31 +41,34 @@ from . import (
|
||||||
init_integration,
|
init_integration,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from tests.common import async_fire_time_changed
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("config", "expected_state"),
|
("config", "expected_state", "expected_state_weekend"),
|
||||||
[
|
[
|
||||||
(TEST_CONFIG_NO_COUNTRY, "on"),
|
(TEST_CONFIG_NO_COUNTRY, "on", "off"),
|
||||||
(TEST_CONFIG_WITH_PROVINCE, "off"),
|
(TEST_CONFIG_WITH_PROVINCE, "off", "off"),
|
||||||
(TEST_CONFIG_NO_PROVINCE, "off"),
|
(TEST_CONFIG_NO_PROVINCE, "off", "off"),
|
||||||
(TEST_CONFIG_WITH_STATE, "on"),
|
(TEST_CONFIG_WITH_STATE, "on", "off"),
|
||||||
(TEST_CONFIG_NO_STATE, "on"),
|
(TEST_CONFIG_NO_STATE, "on", "off"),
|
||||||
(TEST_CONFIG_EXAMPLE_1, "on"),
|
(TEST_CONFIG_EXAMPLE_1, "on", "off"),
|
||||||
(TEST_CONFIG_EXAMPLE_2, "off"),
|
(TEST_CONFIG_EXAMPLE_2, "off", "off"),
|
||||||
(TEST_CONFIG_TOMORROW, "off"),
|
(TEST_CONFIG_TOMORROW, "off", "off"),
|
||||||
(TEST_CONFIG_DAY_AFTER_TOMORROW, "off"),
|
(TEST_CONFIG_DAY_AFTER_TOMORROW, "off", "off"),
|
||||||
(TEST_CONFIG_YESTERDAY, "on"),
|
(TEST_CONFIG_YESTERDAY, "on", "off"), # Friday was good Friday
|
||||||
(TEST_CONFIG_NO_LANGUAGE_CONFIGURED, "off"),
|
(TEST_CONFIG_NO_LANGUAGE_CONFIGURED, "off", "off"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_setup(
|
async def test_setup(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: dict[str, Any],
|
config: dict[str, Any],
|
||||||
expected_state: str,
|
expected_state: str,
|
||||||
|
expected_state_weekend: str,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test setup from various configs."""
|
"""Test setup from various configs."""
|
||||||
freezer.move_to(datetime(2022, 4, 15, 12, tzinfo=UTC)) # Monday
|
freezer.move_to(datetime(2022, 4, 15, 12, tzinfo=UTC)) # Friday
|
||||||
await init_integration(hass, config)
|
await init_integration(hass, config)
|
||||||
|
|
||||||
state = hass.states.get("binary_sensor.workday_sensor")
|
state = hass.states.get("binary_sensor.workday_sensor")
|
||||||
|
@ -78,6 +81,13 @@ async def test_setup(
|
||||||
"days_offset": config["days_offset"],
|
"days_offset": config["days_offset"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
freezer.tick(timedelta(days=1)) # Saturday
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
|
||||||
|
state = hass.states.get("binary_sensor.workday_sensor")
|
||||||
|
assert state is not None
|
||||||
|
assert state.state == expected_state_weekend
|
||||||
|
|
||||||
|
|
||||||
async def test_setup_with_invalid_province_from_yaml(hass: HomeAssistant) -> None:
|
async def test_setup_with_invalid_province_from_yaml(hass: HomeAssistant) -> None:
|
||||||
"""Test setup invalid province with import."""
|
"""Test setup invalid province with import."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue