Workday only update once a day (#116419)

* Workday only update once a day

* Fix tests
This commit is contained in:
G Johansson 2024-05-01 17:11:47 +02:00 committed by GitHub
parent b7a138b02a
commit 51f9e661a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 62 additions and 20 deletions

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from datetime import date, timedelta
from datetime import date, datetime, timedelta
from typing import Final
from holidays import (
@ -15,13 +15,20 @@ import voluptuous as vol
from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.config_entries import ConfigEntry
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
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import (
AddEntitiesCallback,
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.util import dt as dt_util, slugify
@ -201,6 +208,8 @@ class IsWorkdaySensor(BinarySensorEntity):
_attr_has_entity_name = True
_attr_name = None
_attr_translation_key = DOMAIN
_attr_should_poll = False
unsub: CALLBACK_TYPE | None = None
def __init__(
self,
@ -248,11 +257,34 @@ class IsWorkdaySensor(BinarySensorEntity):
return False
async def async_update(self) -> None:
"""Get date and look whether it is a holiday."""
self._attr_is_on = self.date_is_workday(dt_util.now())
def get_next_interval(self, now: datetime) -> datetime:
"""Compute next time an update should occur."""
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."""
return {"workday": self.date_is_workday(check_date)}

View file

@ -1,6 +1,6 @@
"""Tests the Home Assistant workday binary sensor."""
from datetime import date, datetime
from datetime import date, datetime, timedelta
from typing import Any
from freezegun.api import FrozenDateTimeFactory
@ -41,31 +41,34 @@ from . import (
init_integration,
)
from tests.common import async_fire_time_changed
@pytest.mark.parametrize(
("config", "expected_state"),
("config", "expected_state", "expected_state_weekend"),
[
(TEST_CONFIG_NO_COUNTRY, "on"),
(TEST_CONFIG_WITH_PROVINCE, "off"),
(TEST_CONFIG_NO_PROVINCE, "off"),
(TEST_CONFIG_WITH_STATE, "on"),
(TEST_CONFIG_NO_STATE, "on"),
(TEST_CONFIG_EXAMPLE_1, "on"),
(TEST_CONFIG_EXAMPLE_2, "off"),
(TEST_CONFIG_TOMORROW, "off"),
(TEST_CONFIG_DAY_AFTER_TOMORROW, "off"),
(TEST_CONFIG_YESTERDAY, "on"),
(TEST_CONFIG_NO_LANGUAGE_CONFIGURED, "off"),
(TEST_CONFIG_NO_COUNTRY, "on", "off"),
(TEST_CONFIG_WITH_PROVINCE, "off", "off"),
(TEST_CONFIG_NO_PROVINCE, "off", "off"),
(TEST_CONFIG_WITH_STATE, "on", "off"),
(TEST_CONFIG_NO_STATE, "on", "off"),
(TEST_CONFIG_EXAMPLE_1, "on", "off"),
(TEST_CONFIG_EXAMPLE_2, "off", "off"),
(TEST_CONFIG_TOMORROW, "off", "off"),
(TEST_CONFIG_DAY_AFTER_TOMORROW, "off", "off"),
(TEST_CONFIG_YESTERDAY, "on", "off"), # Friday was good Friday
(TEST_CONFIG_NO_LANGUAGE_CONFIGURED, "off", "off"),
],
)
async def test_setup(
hass: HomeAssistant,
config: dict[str, Any],
expected_state: str,
expected_state_weekend: str,
freezer: FrozenDateTimeFactory,
) -> None:
"""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)
state = hass.states.get("binary_sensor.workday_sensor")
@ -78,6 +81,13 @@ async def test_setup(
"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:
"""Test setup invalid province with import."""