core/tests/components/calendar/conftest.py

200 lines
5.8 KiB
Python

"""Test fixtures for calendar sensor platforms."""
import datetime
import secrets
from typing import Any
from unittest.mock import AsyncMock
import pytest
from typing_extensions import Generator
from homeassistant.components.calendar import DOMAIN, CalendarEntity, CalendarEvent
from homeassistant.config_entries import ConfigEntry, ConfigFlow
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import dt as dt_util
from tests.common import (
MockConfigEntry,
MockModule,
MockPlatform,
mock_config_flow,
mock_integration,
mock_platform,
)
TEST_DOMAIN = "test"
@pytest.fixture
async def set_time_zone(hass: HomeAssistant) -> None:
"""Set the time zone for the tests."""
# Set our timezone to CST/Regina so we can check calculations
# This keeps UTC-6 all year round
await hass.config.async_set_time_zone("America/Regina")
class MockFlow(ConfigFlow):
"""Test flow."""
class MockCalendarEntity(CalendarEntity):
"""Test Calendar entity."""
_attr_has_entity_name = True
def __init__(self, name: str, events: list[CalendarEvent] | None = None) -> None:
"""Initialize entity."""
self._attr_name = name.capitalize()
self._events = events or []
@property
def event(self) -> CalendarEvent | None:
"""Return the next upcoming event."""
return self._events[0] if self._events else None
def create_event(
self,
start: datetime.datetime,
end: datetime.datetime,
summary: str | None = None,
description: str | None = None,
location: str | None = None,
) -> dict[str, Any]:
"""Create a new fake event, used by tests."""
event = CalendarEvent(
start=start,
end=end,
summary=summary if summary else f"Event {secrets.token_hex(16)}",
description=description,
location=location,
)
self._events.append(event)
return event.as_dict()
async def async_get_events(
self,
hass: HomeAssistant,
start_date: datetime.datetime,
end_date: datetime.datetime,
) -> list[CalendarEvent]:
"""Return calendar events within a datetime range."""
assert start_date < end_date
events = []
for event in self._events:
if event.start_datetime_local >= end_date:
continue
if event.end_datetime_local < start_date:
continue
events.append(event)
return events
@pytest.fixture
def config_flow_fixture(hass: HomeAssistant) -> Generator[None]:
"""Mock config flow."""
mock_platform(hass, f"{TEST_DOMAIN}.config_flow")
with mock_config_flow(TEST_DOMAIN, MockFlow):
yield
@pytest.fixture(name="config_entry")
async def mock_config_entry(hass: HomeAssistant) -> MockConfigEntry:
"""Create a mock config entry."""
config_entry = MockConfigEntry(domain=TEST_DOMAIN)
config_entry.add_to_hass(hass)
return config_entry
@pytest.fixture
def mock_setup_integration(
hass: HomeAssistant,
config_flow_fixture: None,
test_entities: list[CalendarEntity],
) -> None:
"""Fixture to set up a mock integration."""
async def async_setup_entry_init(
hass: HomeAssistant, config_entry: ConfigEntry
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(config_entry, [DOMAIN])
return True
async def async_unload_entry_init(
hass: HomeAssistant,
config_entry: ConfigEntry,
) -> bool:
await hass.config_entries.async_unload_platforms(
config_entry, [Platform.CALENDAR]
)
return True
mock_platform(hass, f"{TEST_DOMAIN}.config_flow")
mock_integration(
hass,
MockModule(
TEST_DOMAIN,
async_setup_entry=async_setup_entry_init,
async_unload_entry=async_unload_entry_init,
),
)
async def async_setup_entry_platform(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up test event platform via config entry."""
new_entities = create_test_entities()
test_entities.clear()
test_entities.extend(new_entities)
async_add_entities(test_entities)
mock_platform(
hass,
f"{TEST_DOMAIN}.{DOMAIN}",
MockPlatform(async_setup_entry=async_setup_entry_platform),
)
@pytest.fixture(name="test_entities")
def mock_test_entities() -> list[MockCalendarEntity]:
"""Fixture that holdes the fake entities created during the test."""
return []
def create_test_entities() -> list[MockCalendarEntity]:
"""Create test entities used during the test."""
half_hour_from_now = dt_util.now() + datetime.timedelta(minutes=30)
entity1 = MockCalendarEntity(
"Calendar 1",
[
CalendarEvent(
start=half_hour_from_now,
end=half_hour_from_now + datetime.timedelta(minutes=60),
summary="Future Event",
description="Future Description",
location="Future Location",
)
],
)
entity1.async_get_events = AsyncMock(wraps=entity1.async_get_events)
middle_of_event = dt_util.now() - datetime.timedelta(minutes=30)
entity2 = MockCalendarEntity(
"Calendar 2",
[
CalendarEvent(
start=middle_of_event,
end=middle_of_event + datetime.timedelta(minutes=60),
summary="Current Event",
)
],
)
entity2.async_get_events = AsyncMock(wraps=entity2.async_get_events)
return [entity1, entity2]