Use DataUpdateCoordinator for islamic_prayer_times (#73893)

* use DataUpdateCoordinator for islamic_prayer_times

Add suggested type hints

remove uneccassry options setup

* Use entity_description for sensors

* move coordinator into separate file, sensor_descptions to sensor.py

* add strict typing

* revert strict typing

* fix test coverage

* revert unrelated file changes

* fix sorting

* Update code based on review

* add missing type hint

* more missing type hints

* Update homeassistant/components/islamic_prayer_times/coordinator.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* remove config_entry parameter

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Rami Mosleh 2023-02-25 11:05:51 +02:00 committed by GitHub
parent 3499d60401
commit 091305fc57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 272 additions and 263 deletions

View File

@ -1,22 +1,13 @@
"""The islamic_prayer_times component."""
from datetime import timedelta
import logging
from prayer_times_calculator import PrayerTimesCalculator, exceptions
from requests.exceptions import ConnectionError as ConnError
from __future__ import annotations
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_call_later, async_track_point_in_time
import homeassistant.util.dt as dt_util
from .const import CONF_CALC_METHOD, DATA_UPDATED, DEFAULT_CALC_METHOD, DOMAIN
_LOGGER = logging.getLogger(__name__)
from .const import DOMAIN
from .coordinator import IslamicPrayerDataUpdateCoordinator
PLATFORMS = [Platform.SENSOR]
@ -25,154 +16,32 @@ CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Set up the Islamic Prayer Component."""
client = IslamicPrayerClient(hass, config_entry)
hass.data[DOMAIN] = client
await client.async_setup()
coordinator = IslamicPrayerDataUpdateCoordinator(hass)
await coordinator.async_config_entry_first_refresh()
hass.data.setdefault(DOMAIN, coordinator)
config_entry.async_on_unload(
config_entry.add_update_listener(async_options_updated)
)
hass.config_entries.async_setup_platforms(config_entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload Islamic Prayer entry from config_entry."""
if hass.data[DOMAIN].event_unsub:
hass.data[DOMAIN].event_unsub()
hass.data.pop(DOMAIN)
return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS)
if unload_ok := await hass.config_entries.async_unload_platforms(
config_entry, PLATFORMS
):
coordinator: IslamicPrayerDataUpdateCoordinator = hass.data.pop(DOMAIN)
if coordinator.event_unsub:
coordinator.event_unsub()
return unload_ok
class IslamicPrayerClient:
"""Islamic Prayer Client Object."""
def __init__(self, hass, config_entry):
"""Initialize the Islamic Prayer client."""
self.hass = hass
self.config_entry = config_entry
self.prayer_times_info = {}
self.available = True
self.event_unsub = None
@property
def calc_method(self):
"""Return the calculation method."""
return self.config_entry.options[CONF_CALC_METHOD]
def get_new_prayer_times(self):
"""Fetch prayer times for today."""
calc = PrayerTimesCalculator(
latitude=self.hass.config.latitude,
longitude=self.hass.config.longitude,
calculation_method=self.calc_method,
date=str(dt_util.now().date()),
)
return calc.fetch_prayer_times()
async def async_schedule_future_update(self):
"""Schedule future update for sensors.
Midnight is a calculated time. The specifics of the calculation
depends on the method of the prayer time calculation. This calculated
midnight is the time at which the time to pray the Isha prayers have
expired.
Calculated Midnight: The Islamic midnight.
Traditional Midnight: 12:00AM
Update logic for prayer times:
If the Calculated Midnight is before the traditional midnight then wait
until the traditional midnight to run the update. This way the day
will have changed over and we don't need to do any fancy calculations.
If the Calculated Midnight is after the traditional midnight, then wait
until after the calculated Midnight. We don't want to update the prayer
times too early or else the timings might be incorrect.
Example:
calculated midnight = 11:23PM (before traditional midnight)
Update time: 12:00AM
calculated midnight = 1:35AM (after traditional midnight)
update time: 1:36AM.
"""
_LOGGER.debug("Scheduling next update for Islamic prayer times")
now = dt_util.utcnow()
midnight_dt = self.prayer_times_info["Midnight"]
if now > dt_util.as_utc(midnight_dt):
next_update_at = midnight_dt + timedelta(days=1, minutes=1)
_LOGGER.debug(
"Midnight is after day the changes so schedule update for after"
" Midnight the next day"
)
else:
_LOGGER.debug(
"Midnight is before the day changes so schedule update for the next"
" start of day"
)
next_update_at = dt_util.start_of_local_day(now + timedelta(days=1))
_LOGGER.info("Next update scheduled for: %s", next_update_at)
self.event_unsub = async_track_point_in_time(
self.hass, self.async_update, next_update_at
)
async def async_update(self, *_):
"""Update sensors with new prayer times."""
try:
prayer_times = await self.hass.async_add_executor_job(
self.get_new_prayer_times
)
self.available = True
except (exceptions.InvalidResponseError, ConnError):
self.available = False
_LOGGER.debug("Error retrieving prayer times")
async_call_later(self.hass, 60, self.async_update)
return
for prayer, time in prayer_times.items():
self.prayer_times_info[prayer] = dt_util.parse_datetime(
f"{dt_util.now().date()} {time}"
)
await self.async_schedule_future_update()
_LOGGER.debug("New prayer times retrieved. Updating sensors")
async_dispatcher_send(self.hass, DATA_UPDATED)
async def async_setup(self):
"""Set up the Islamic prayer client."""
await self.async_add_options()
try:
await self.hass.async_add_executor_job(self.get_new_prayer_times)
except (exceptions.InvalidResponseError, ConnError) as err:
raise ConfigEntryNotReady from err
await self.async_update()
self.config_entry.add_update_listener(self.async_options_updated)
await self.hass.config_entries.async_forward_entry_setups(
self.config_entry, PLATFORMS
)
return True
async def async_add_options(self):
"""Add options for entry."""
if not self.config_entry.options:
data = dict(self.config_entry.data)
calc_method = data.pop(CONF_CALC_METHOD, DEFAULT_CALC_METHOD)
self.hass.config_entries.async_update_entry(
self.config_entry, data=data, options={CONF_CALC_METHOD: calc_method}
)
@staticmethod
async def async_options_updated(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Triggered by config entry options updates."""
if hass.data[DOMAIN].event_unsub:
hass.data[DOMAIN].event_unsub()
await hass.data[DOMAIN].async_update()
coordinator: IslamicPrayerDataUpdateCoordinator = hass.data[DOMAIN]
if coordinator.event_unsub:
coordinator.event_unsub()
await coordinator.async_request_refresh()

View File

@ -1,10 +1,13 @@
"""Config flow for Islamic Prayer Times integration."""
from __future__ import annotations
from typing import Any
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from .const import CALC_METHODS, CONF_CALC_METHOD, DEFAULT_CALC_METHOD, DOMAIN, NAME
@ -22,7 +25,9 @@ class IslamicPrayerFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Get the options flow for this handler."""
return IslamicPrayerOptionsFlowHandler(config_entry)
async def async_step_user(self, user_input=None):
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle a flow initialized by the user."""
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")
@ -40,7 +45,9 @@ class IslamicPrayerOptionsFlowHandler(config_entries.OptionsFlow):
"""Initialize options flow."""
self.config_entry = config_entry
async def async_step_init(self, user_input=None):
async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Manage options."""
if user_input is not None:
return self.async_create_entry(title="", data=user_input)

View File

@ -1,23 +1,12 @@
"""Constants for the Islamic Prayer component."""
from typing import Final
from prayer_times_calculator import PrayerTimesCalculator
DOMAIN = "islamic_prayer_times"
NAME = "Islamic Prayer Times"
PRAYER_TIMES_ICON = "mdi:calendar-clock"
DOMAIN: Final = "islamic_prayer_times"
NAME: Final = "Islamic Prayer Times"
SENSOR_TYPES = {
"Fajr": "prayer",
"Sunrise": "time",
"Dhuhr": "prayer",
"Asr": "prayer",
"Maghrib": "prayer",
"Isha": "prayer",
"Midnight": "time",
}
CONF_CALC_METHOD = "calculation_method"
CONF_CALC_METHOD: Final = "calculation_method"
CALC_METHODS: list[str] = list(PrayerTimesCalculator.CALCULATION_METHODS)
DEFAULT_CALC_METHOD = "isna"
DATA_UPDATED = "Islamic_prayer_data_updated"
DEFAULT_CALC_METHOD: Final = "isna"

View File

@ -0,0 +1,121 @@
"""Coordinator for the Islamic prayer times integration."""
from __future__ import annotations
from datetime import datetime, timedelta
import logging
from prayer_times_calculator import PrayerTimesCalculator, exceptions
from requests.exceptions import ConnectionError as ConnError
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers.event import async_call_later, async_track_point_in_time
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
import homeassistant.util.dt as dt_util
from .const import CONF_CALC_METHOD, DEFAULT_CALC_METHOD, DOMAIN
_LOGGER = logging.getLogger(__name__)
class IslamicPrayerDataUpdateCoordinator(DataUpdateCoordinator[dict[str, datetime]]):
"""Islamic Prayer Client Object."""
config_entry: ConfigEntry
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize the Islamic Prayer client."""
self.event_unsub: CALLBACK_TYPE | None = None
super().__init__(
hass,
_LOGGER,
name=DOMAIN,
)
@property
def calc_method(self) -> str:
"""Return the calculation method."""
return self.config_entry.options.get(CONF_CALC_METHOD, DEFAULT_CALC_METHOD)
def get_new_prayer_times(self) -> dict[str, str]:
"""Fetch prayer times for today."""
calc = PrayerTimesCalculator(
latitude=self.hass.config.latitude,
longitude=self.hass.config.longitude,
calculation_method=self.calc_method,
date=str(dt_util.now().date()),
)
return calc.fetch_prayer_times()
@callback
def async_schedule_future_update(self, midnight_dt: datetime) -> None:
"""Schedule future update for sensors.
Midnight is a calculated time. The specifics of the calculation
depends on the method of the prayer time calculation. This calculated
midnight is the time at which the time to pray the Isha prayers have
expired.
Calculated Midnight: The Islamic midnight.
Traditional Midnight: 12:00AM
Update logic for prayer times:
If the Calculated Midnight is before the traditional midnight then wait
until the traditional midnight to run the update. This way the day
will have changed over and we don't need to do any fancy calculations.
If the Calculated Midnight is after the traditional midnight, then wait
until after the calculated Midnight. We don't want to update the prayer
times too early or else the timings might be incorrect.
Example:
calculated midnight = 11:23PM (before traditional midnight)
Update time: 12:00AM
calculated midnight = 1:35AM (after traditional midnight)
update time: 1:36AM.
"""
_LOGGER.debug("Scheduling next update for Islamic prayer times")
now = dt_util.utcnow()
if now > midnight_dt:
next_update_at = midnight_dt + timedelta(days=1, minutes=1)
_LOGGER.debug(
"Midnight is after the day changes so schedule update for after Midnight the next day"
)
else:
_LOGGER.debug(
"Midnight is before the day changes so schedule update for the next start of day"
)
next_update_at = dt_util.start_of_local_day(now + timedelta(days=1))
_LOGGER.debug("Next update scheduled for: %s", next_update_at)
self.event_unsub = async_track_point_in_time(
self.hass, self.async_request_update, next_update_at
)
async def async_request_update(self, *_) -> None:
"""Request update from coordinator."""
await self.async_request_refresh()
async def _async_update_data(self) -> dict[str, datetime]:
"""Update sensors with new prayer times."""
try:
prayer_times = await self.hass.async_add_executor_job(
self.get_new_prayer_times
)
except (exceptions.InvalidResponseError, ConnError) as err:
async_call_later(self.hass, 60, self.async_request_update)
raise UpdateFailed from err
prayer_times_info: dict[str, datetime] = {}
for prayer, time in prayer_times.items():
if prayer_time := dt_util.parse_datetime(f"{dt_util.now().date()} {time}"):
prayer_times_info[prayer] = dt_util.as_utc(prayer_time)
self.async_schedule_future_update(prayer_times_info["Midnight"])
return prayer_times_info

View File

@ -1,12 +1,51 @@
"""Platform to retrieve Islamic prayer times information for Home Assistant."""
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
from datetime import datetime
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.dt as dt_util
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DATA_UPDATED, DOMAIN, PRAYER_TIMES_ICON, SENSOR_TYPES
from . import IslamicPrayerDataUpdateCoordinator
from .const import DOMAIN, NAME
SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="Fajr",
name="Fajr prayer",
),
SensorEntityDescription(
key="Sunrise",
name="Sunrise time",
),
SensorEntityDescription(
key="Dhuhr",
name="Dhuhr prayer",
),
SensorEntityDescription(
key="Asr",
name="Asr prayer",
),
SensorEntityDescription(
key="Maghrib",
name="Maghrib prayer",
),
SensorEntityDescription(
key="Isha",
name="Isha prayer",
),
SensorEntityDescription(
key="Midnight",
name="Midnight time",
),
)
async def async_setup_entry(
@ -16,46 +55,38 @@ async def async_setup_entry(
) -> None:
"""Set up the Islamic prayer times sensor platform."""
client = hass.data[DOMAIN]
coordinator: IslamicPrayerDataUpdateCoordinator = hass.data[DOMAIN]
entities = []
for sensor_type in SENSOR_TYPES:
entities.append(IslamicPrayerTimeSensor(sensor_type, client))
async_add_entities(entities, True)
async_add_entities(
IslamicPrayerTimeSensor(coordinator, description)
for description in SENSOR_TYPES
)
class IslamicPrayerTimeSensor(SensorEntity):
class IslamicPrayerTimeSensor(
CoordinatorEntity[IslamicPrayerDataUpdateCoordinator], SensorEntity
):
"""Representation of an Islamic prayer time sensor."""
_attr_device_class = SensorDeviceClass.TIMESTAMP
_attr_icon = PRAYER_TIMES_ICON
_attr_should_poll = False
_attr_has_entity_name = True
def __init__(self, sensor_type, client):
def __init__(
self,
coordinator: IslamicPrayerDataUpdateCoordinator,
description: SensorEntityDescription,
) -> None:
"""Initialize the Islamic prayer time sensor."""
self.sensor_type = sensor_type
self.client = client
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = description.key
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, coordinator.config_entry.entry_id)},
name=NAME,
entry_type=DeviceEntryType.SERVICE,
)
@property
def name(self):
"""Return the name of the sensor."""
return f"{self.sensor_type} {SENSOR_TYPES[self.sensor_type]}"
@property
def unique_id(self):
"""Return the unique id of the entity."""
return self.sensor_type
@property
def native_value(self):
def native_value(self) -> datetime:
"""Return the state of the sensor."""
return self.client.prayer_times_info.get(self.sensor_type).astimezone(
dt_util.UTC
)
async def async_added_to_hass(self) -> None:
"""Handle entity which will be added."""
self.async_on_remove(
async_dispatcher_connect(self.hass, DATA_UPDATED, self.async_write_ha_state)
)
return self.coordinator.data[self.entity_description.key]

View File

@ -15,13 +15,13 @@ PRAYER_TIMES = {
}
PRAYER_TIMES_TIMESTAMPS = {
"Fajr": datetime(2020, 1, 1, 6, 10, 0),
"Sunrise": datetime(2020, 1, 1, 7, 25, 0),
"Dhuhr": datetime(2020, 1, 1, 12, 30, 0),
"Asr": datetime(2020, 1, 1, 15, 32, 0),
"Maghrib": datetime(2020, 1, 1, 17, 35, 0),
"Isha": datetime(2020, 1, 1, 18, 53, 0),
"Midnight": datetime(2020, 1, 1, 00, 45, 0),
"Fajr": datetime(2020, 1, 1, 6, 10, 0, tzinfo=dt_util.UTC),
"Sunrise": datetime(2020, 1, 1, 7, 25, 0, tzinfo=dt_util.UTC),
"Dhuhr": datetime(2020, 1, 1, 12, 30, 0, tzinfo=dt_util.UTC),
"Asr": datetime(2020, 1, 1, 15, 32, 0, tzinfo=dt_util.UTC),
"Maghrib": datetime(2020, 1, 1, 17, 35, 0, tzinfo=dt_util.UTC),
"Isha": datetime(2020, 1, 1, 18, 53, 0, tzinfo=dt_util.UTC),
"Midnight": datetime(2020, 1, 1, 00, 45, 0, tzinfo=dt_util.UTC),
}
NEW_PRAYER_TIMES = {
@ -35,13 +35,13 @@ NEW_PRAYER_TIMES = {
}
NEW_PRAYER_TIMES_TIMESTAMPS = {
"Fajr": datetime(2020, 1, 1, 6, 00, 0),
"Sunrise": datetime(2020, 1, 1, 7, 25, 0),
"Dhuhr": datetime(2020, 1, 1, 12, 30, 0),
"Asr": datetime(2020, 1, 1, 15, 32, 0),
"Maghrib": datetime(2020, 1, 1, 17, 45, 0),
"Isha": datetime(2020, 1, 1, 18, 53, 0),
"Midnight": datetime(2020, 1, 1, 00, 43, 0),
"Fajr": datetime(2020, 1, 1, 6, 00, 0, tzinfo=dt_util.UTC),
"Sunrise": datetime(2020, 1, 1, 7, 25, 0, tzinfo=dt_util.UTC),
"Dhuhr": datetime(2020, 1, 1, 12, 30, 0, tzinfo=dt_util.UTC),
"Asr": datetime(2020, 1, 1, 15, 32, 0, tzinfo=dt_util.UTC),
"Maghrib": datetime(2020, 1, 1, 17, 45, 0, tzinfo=dt_util.UTC),
"Isha": datetime(2020, 1, 1, 18, 53, 0, tzinfo=dt_util.UTC),
"Midnight": datetime(2020, 1, 1, 00, 43, 0, tzinfo=dt_util.UTC),
}
NOW = datetime(2020, 1, 1, 00, 00, 0, tzinfo=dt_util.UTC)

View File

@ -1,27 +1,16 @@
"""Tests for Islamic Prayer Times config flow."""
from unittest.mock import patch
import pytest
from homeassistant import config_entries, data_entry_flow
from homeassistant.components import islamic_prayer_times
from homeassistant.components.islamic_prayer_times import config_flow # noqa: F401
from homeassistant.components.islamic_prayer_times.const import CONF_CALC_METHOD, DOMAIN
from homeassistant.core import HomeAssistant
from . import PRAYER_TIMES
from tests.common import MockConfigEntry
@pytest.fixture(name="mock_setup", autouse=True)
def mock_setup():
"""Mock entry setup."""
with patch(
"homeassistant.components.islamic_prayer_times.async_setup_entry",
return_value=True,
):
yield
async def test_flow_works(hass: HomeAssistant) -> None:
"""Test user config."""
result = await hass.config_entries.flow.async_init(
@ -30,6 +19,10 @@ async def test_flow_works(hass: HomeAssistant) -> None:
assert result["type"] == data_entry_flow.FlowResultType.FORM
assert result["step_id"] == "user"
with patch(
"homeassistant.components.islamic_prayer_times.async_setup_entry",
return_value=True,
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={}
)
@ -47,6 +40,13 @@ async def test_options(hass: HomeAssistant) -> None:
)
entry.add_to_hass(hass)
with patch(
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
return_value=PRAYER_TIMES,
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
result = await hass.config_entries.options.async_init(entry.entry_id)
assert result["type"] == data_entry_flow.FlowResultType.FORM

View File

@ -22,7 +22,7 @@ from tests.common import MockConfigEntry, async_fire_time_changed
@pytest.fixture(autouse=True)
def set_utc(hass):
def set_utc(hass: HomeAssistant) -> None:
"""Set timezone to UTC."""
hass.config.set_time_zone("UTC")
@ -44,9 +44,6 @@ async def test_successful_config_entry(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
assert entry.state is config_entries.ConfigEntryState.LOADED
assert entry.options == {
islamic_prayer_times.CONF_CALC_METHOD: islamic_prayer_times.DEFAULT_CALC_METHOD
}
async def test_setup_failed(hass: HomeAssistant) -> None:
@ -100,10 +97,7 @@ async def test_islamic_prayer_times_timestamp_format(hass: HomeAssistant) -> Non
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert (
hass.data[islamic_prayer_times.DOMAIN].prayer_times_info
== PRAYER_TIMES_TIMESTAMPS
)
assert hass.data[islamic_prayer_times.DOMAIN].data == PRAYER_TIMES_TIMESTAMPS
async def test_update(hass: HomeAssistant) -> None:
@ -115,7 +109,6 @@ async def test_update(hass: HomeAssistant) -> None:
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times"
) as FetchPrayerTimes, freeze_time(NOW):
FetchPrayerTimes.side_effect = [
PRAYER_TIMES,
PRAYER_TIMES,
NEW_PRAYER_TIMES,
]
@ -124,13 +117,10 @@ async def test_update(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
pt_data = hass.data[islamic_prayer_times.DOMAIN]
assert pt_data.prayer_times_info == PRAYER_TIMES_TIMESTAMPS
assert pt_data.data == PRAYER_TIMES_TIMESTAMPS
future = pt_data.prayer_times_info["Midnight"] + timedelta(days=1, minutes=1)
future = pt_data.data["Midnight"] + timedelta(days=1, minutes=1)
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
assert (
hass.data[islamic_prayer_times.DOMAIN].prayer_times_info
== NEW_PRAYER_TIMES_TIMESTAMPS
)
assert pt_data.data == NEW_PRAYER_TIMES_TIMESTAMPS

View File

@ -4,8 +4,10 @@ from unittest.mock import patch
from freezegun import freeze_time
import pytest
from homeassistant.components import islamic_prayer_times
from homeassistant.components.islamic_prayer_times.const import DOMAIN
from homeassistant.components.islamic_prayer_times.sensor import SENSOR_TYPES
from homeassistant.core import HomeAssistant
from homeassistant.util import slugify
import homeassistant.util.dt as dt_util
from . import NOW, PRAYER_TIMES, PRAYER_TIMES_TIMESTAMPS
@ -14,14 +16,14 @@ from tests.common import MockConfigEntry
@pytest.fixture(autouse=True)
def set_utc(hass):
def set_utc(hass: HomeAssistant) -> None:
"""Set timezone to UTC."""
hass.config.set_time_zone("UTC")
async def test_islamic_prayer_times_sensors(hass: HomeAssistant) -> None:
"""Test minimum Islamic prayer times configuration."""
entry = MockConfigEntry(domain=islamic_prayer_times.DOMAIN, data={})
entry = MockConfigEntry(domain=DOMAIN, data={})
entry.add_to_hass(hass)
with patch(
@ -31,10 +33,10 @@ async def test_islamic_prayer_times_sensors(hass: HomeAssistant) -> None:
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
for prayer in PRAYER_TIMES:
for prayer in SENSOR_TYPES:
assert (
hass.states.get(
f"sensor.{prayer}_{islamic_prayer_times.const.SENSOR_TYPES[prayer]}"
).state
== PRAYER_TIMES_TIMESTAMPS[prayer].astimezone(dt_util.UTC).isoformat()
hass.states.get(f"sensor.{DOMAIN}_{slugify(prayer.name)}").state
== PRAYER_TIMES_TIMESTAMPS[prayer.key]
.astimezone(dt_util.UTC)
.isoformat()
)