mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 16:57:10 +00:00
Add calendar to Husqvarna Automower (#120775)
* Add Calendar * update * change timezone for tests * fix requirements * bump aioautomower to 2024.6.3b0 * bump aioautomower to 2024.6.4b0 * fix req * align dates * adjust * nnbw * better * improvements * req * update requirements * tests * tweaks * shift functions to library * tests * bump to aioautomower==2024.9.0b1 * tests * remove ZoneInfo wrapper * use timetzone from start_date object * Update requirements_all.txt * Fix names in ProgramEvent
This commit is contained in:
parent
089c942233
commit
fccbaa0fbc
@ -19,6 +19,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
PLATFORMS: list[Platform] = [
|
PLATFORMS: list[Platform] = [
|
||||||
Platform.BINARY_SENSOR,
|
Platform.BINARY_SENSOR,
|
||||||
Platform.BUTTON,
|
Platform.BUTTON,
|
||||||
|
Platform.CALENDAR,
|
||||||
Platform.DEVICE_TRACKER,
|
Platform.DEVICE_TRACKER,
|
||||||
Platform.LAWN_MOWER,
|
Platform.LAWN_MOWER,
|
||||||
Platform.NUMBER,
|
Platform.NUMBER,
|
||||||
|
86
homeassistant/components/husqvarna_automower/calendar.py
Normal file
86
homeassistant/components/husqvarna_automower/calendar.py
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
"""Creates a calendar entity for the mower."""
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from homeassistant.components.calendar import CalendarEntity, CalendarEvent
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
|
from . import AutomowerConfigEntry
|
||||||
|
from .coordinator import AutomowerDataUpdateCoordinator
|
||||||
|
from .entity import AutomowerBaseEntity
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry: AutomowerConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up lawn mower platform."""
|
||||||
|
coordinator = entry.runtime_data
|
||||||
|
async_add_entities(
|
||||||
|
AutomowerCalendarEntity(mower_id, coordinator) for mower_id in coordinator.data
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AutomowerCalendarEntity(AutomowerBaseEntity, CalendarEntity):
|
||||||
|
"""Representation of the Automower Calendar element."""
|
||||||
|
|
||||||
|
_attr_name: str | None = None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
mower_id: str,
|
||||||
|
coordinator: AutomowerDataUpdateCoordinator,
|
||||||
|
) -> None:
|
||||||
|
"""Set up AutomowerCalendarEntity."""
|
||||||
|
super().__init__(mower_id, coordinator)
|
||||||
|
self._attr_unique_id = mower_id
|
||||||
|
self._event: CalendarEvent | None = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event(self) -> CalendarEvent | None:
|
||||||
|
"""Return the current or next upcoming event."""
|
||||||
|
schedule = self.mower_attributes.calendar
|
||||||
|
if schedule.timeline is None:
|
||||||
|
return None
|
||||||
|
cursor = schedule.timeline.active_after(dt_util.now())
|
||||||
|
program_event = next(cursor, None)
|
||||||
|
_LOGGER.debug("program_event %s", program_event)
|
||||||
|
if not program_event:
|
||||||
|
return None
|
||||||
|
return CalendarEvent(
|
||||||
|
summary=program_event.schedule_name,
|
||||||
|
start=program_event.start.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE),
|
||||||
|
end=program_event.end.replace(tzinfo=dt_util.DEFAULT_TIME_ZONE),
|
||||||
|
rrule=program_event.rrule_str,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_get_events(
|
||||||
|
self, hass: HomeAssistant, start_date: datetime, end_date: datetime
|
||||||
|
) -> list[CalendarEvent]:
|
||||||
|
"""Return calendar events within a datetime range.
|
||||||
|
|
||||||
|
This is only called when opening the calendar in the UI.
|
||||||
|
"""
|
||||||
|
schedule = self.mower_attributes.calendar
|
||||||
|
if schedule.timeline is None:
|
||||||
|
raise HomeAssistantError("Unable to get events: No schedule set")
|
||||||
|
cursor = schedule.timeline.overlapping(
|
||||||
|
start_date,
|
||||||
|
end_date,
|
||||||
|
)
|
||||||
|
return [
|
||||||
|
CalendarEvent(
|
||||||
|
summary=program_event.schedule_name,
|
||||||
|
start=program_event.start.replace(tzinfo=start_date.tzinfo),
|
||||||
|
end=program_event.end.replace(tzinfo=start_date.tzinfo),
|
||||||
|
rrule=program_event.rrule_str,
|
||||||
|
)
|
||||||
|
for program_event in cursor
|
||||||
|
]
|
@ -40,7 +40,8 @@
|
|||||||
"thursday": false,
|
"thursday": false,
|
||||||
"friday": true,
|
"friday": true,
|
||||||
"saturday": false,
|
"saturday": false,
|
||||||
"sunday": false
|
"sunday": false,
|
||||||
|
"workAreaId": 123456
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"start": 0,
|
"start": 0,
|
||||||
@ -51,6 +52,42 @@
|
|||||||
"thursday": true,
|
"thursday": true,
|
||||||
"friday": false,
|
"friday": false,
|
||||||
"saturday": true,
|
"saturday": true,
|
||||||
|
"sunday": false,
|
||||||
|
"workAreaId": 123456
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"duration": 480,
|
||||||
|
"monday": false,
|
||||||
|
"tuesday": true,
|
||||||
|
"wednesday": false,
|
||||||
|
"thursday": true,
|
||||||
|
"friday": false,
|
||||||
|
"saturday": true,
|
||||||
|
"sunday": false,
|
||||||
|
"workAreaId": 654321
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 60,
|
||||||
|
"duration": 480,
|
||||||
|
"monday": true,
|
||||||
|
"tuesday": true,
|
||||||
|
"wednesday": false,
|
||||||
|
"thursday": true,
|
||||||
|
"friday": false,
|
||||||
|
"saturday": true,
|
||||||
|
"sunday": false,
|
||||||
|
"workAreaId": 654321
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 120,
|
||||||
|
"duration": 480,
|
||||||
|
"monday": true,
|
||||||
|
"tuesday": false,
|
||||||
|
"wednesday": false,
|
||||||
|
"thursday": true,
|
||||||
|
"friday": false,
|
||||||
|
"saturday": true,
|
||||||
"sunday": false
|
"sunday": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -64,7 +101,7 @@
|
|||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"connected": true,
|
"connected": true,
|
||||||
"statusTimestamp": 1697669932683
|
"statusTimestamp": 1685923200000
|
||||||
},
|
},
|
||||||
"workAreas": [
|
"workAreas": [
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_calendar_snapshot[start_date0-end_date0]
|
||||||
|
dict({
|
||||||
|
'calendar.test_mower_1': dict({
|
||||||
|
'events': list([
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-05T09:00:00+02:00',
|
||||||
|
'start': '2023-06-05T01:00:00+02:00',
|
||||||
|
'summary': 'Back lawn schedule 2',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-05T10:00:00+02:00',
|
||||||
|
'start': '2023-06-05T02:00:00+02:00',
|
||||||
|
'summary': 'Schedule 1',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-06T00:00:00+02:00',
|
||||||
|
'start': '2023-06-05T19:00:00+02:00',
|
||||||
|
'summary': 'Front lawn schedule 1',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-06T08:00:00+02:00',
|
||||||
|
'start': '2023-06-06T00:00:00+02:00',
|
||||||
|
'summary': 'Back lawn schedule 1',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-06T08:00:00+02:00',
|
||||||
|
'start': '2023-06-06T00:00:00+02:00',
|
||||||
|
'summary': 'Front lawn schedule 2',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-06T09:00:00+02:00',
|
||||||
|
'start': '2023-06-06T01:00:00+02:00',
|
||||||
|
'summary': 'Back lawn schedule 2',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-08T00:00:00+02:00',
|
||||||
|
'start': '2023-06-07T19:00:00+02:00',
|
||||||
|
'summary': 'Front lawn schedule 1',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-08T08:00:00+02:00',
|
||||||
|
'start': '2023-06-08T00:00:00+02:00',
|
||||||
|
'summary': 'Back lawn schedule 1',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-08T08:00:00+02:00',
|
||||||
|
'start': '2023-06-08T00:00:00+02:00',
|
||||||
|
'summary': 'Front lawn schedule 2',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-08T09:00:00+02:00',
|
||||||
|
'start': '2023-06-08T01:00:00+02:00',
|
||||||
|
'summary': 'Back lawn schedule 2',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-08T10:00:00+02:00',
|
||||||
|
'start': '2023-06-08T02:00:00+02:00',
|
||||||
|
'summary': 'Schedule 1',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-10T00:00:00+02:00',
|
||||||
|
'start': '2023-06-09T19:00:00+02:00',
|
||||||
|
'summary': 'Front lawn schedule 1',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-10T08:00:00+02:00',
|
||||||
|
'start': '2023-06-10T00:00:00+02:00',
|
||||||
|
'summary': 'Front lawn schedule 2',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-10T08:00:00+02:00',
|
||||||
|
'start': '2023-06-10T00:00:00+02:00',
|
||||||
|
'summary': 'Back lawn schedule 1',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-10T09:00:00+02:00',
|
||||||
|
'start': '2023-06-10T01:00:00+02:00',
|
||||||
|
'summary': 'Back lawn schedule 2',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'end': '2023-06-10T10:00:00+02:00',
|
||||||
|
'start': '2023-06-10T02:00:00+02:00',
|
||||||
|
'summary': 'Schedule 1',
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
# ---
|
@ -16,8 +16,8 @@
|
|||||||
'thursday': False,
|
'thursday': False,
|
||||||
'tuesday': False,
|
'tuesday': False,
|
||||||
'wednesday': True,
|
'wednesday': True,
|
||||||
'work_area_id': None,
|
'work_area_id': 123456,
|
||||||
'work_area_name': None,
|
'work_area_name': 'Front lawn',
|
||||||
}),
|
}),
|
||||||
dict({
|
dict({
|
||||||
'duration': 480,
|
'duration': 480,
|
||||||
@ -29,6 +29,45 @@
|
|||||||
'thursday': True,
|
'thursday': True,
|
||||||
'tuesday': True,
|
'tuesday': True,
|
||||||
'wednesday': False,
|
'wednesday': False,
|
||||||
|
'work_area_id': 123456,
|
||||||
|
'work_area_name': 'Front lawn',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'duration': 480,
|
||||||
|
'friday': False,
|
||||||
|
'monday': False,
|
||||||
|
'saturday': True,
|
||||||
|
'start': 0,
|
||||||
|
'sunday': False,
|
||||||
|
'thursday': True,
|
||||||
|
'tuesday': True,
|
||||||
|
'wednesday': False,
|
||||||
|
'work_area_id': 654321,
|
||||||
|
'work_area_name': 'Back lawn',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'duration': 480,
|
||||||
|
'friday': False,
|
||||||
|
'monday': True,
|
||||||
|
'saturday': True,
|
||||||
|
'start': 60,
|
||||||
|
'sunday': False,
|
||||||
|
'thursday': True,
|
||||||
|
'tuesday': True,
|
||||||
|
'wednesday': False,
|
||||||
|
'work_area_id': 654321,
|
||||||
|
'work_area_name': 'Back lawn',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'duration': 480,
|
||||||
|
'friday': False,
|
||||||
|
'monday': True,
|
||||||
|
'saturday': True,
|
||||||
|
'start': 120,
|
||||||
|
'sunday': False,
|
||||||
|
'thursday': True,
|
||||||
|
'tuesday': False,
|
||||||
|
'wednesday': False,
|
||||||
'work_area_id': None,
|
'work_area_id': None,
|
||||||
'work_area_name': None,
|
'work_area_name': None,
|
||||||
}),
|
}),
|
||||||
@ -43,7 +82,7 @@
|
|||||||
}),
|
}),
|
||||||
'metadata': dict({
|
'metadata': dict({
|
||||||
'connected': True,
|
'connected': True,
|
||||||
'status_dateteime': '2023-10-18T22:58:52.683000+00:00',
|
'status_dateteime': '2023-06-05T00:00:00+00:00',
|
||||||
}),
|
}),
|
||||||
'mower': dict({
|
'mower': dict({
|
||||||
'activity': 'PARKED_IN_CS',
|
'activity': 'PARKED_IN_CS',
|
||||||
@ -143,7 +182,7 @@
|
|||||||
'auth_implementation': 'husqvarna_automower',
|
'auth_implementation': 'husqvarna_automower',
|
||||||
'token': dict({
|
'token': dict({
|
||||||
'access_token': '**REDACTED**',
|
'access_token': '**REDACTED**',
|
||||||
'expires_at': 1709208000.0,
|
'expires_at': 1685926800.0,
|
||||||
'expires_in': 86399,
|
'expires_in': 86399,
|
||||||
'provider': 'husqvarna',
|
'provider': 'husqvarna',
|
||||||
'refresh_token': '**REDACTED**',
|
'refresh_token': '**REDACTED**',
|
||||||
|
@ -33,7 +33,7 @@ from tests.common import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.freeze_time(datetime.datetime(2024, 2, 29, 11, tzinfo=datetime.UTC))
|
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC))
|
||||||
async def test_button_states_and_commands(
|
async def test_button_states_and_commands(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_automower_client: AsyncMock,
|
mock_automower_client: AsyncMock,
|
||||||
@ -76,7 +76,7 @@ async def test_button_states_and_commands(
|
|||||||
mocked_method.assert_called_once_with(TEST_MOWER_ID)
|
mocked_method.assert_called_once_with(TEST_MOWER_ID)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state.state == "2024-02-29T11:16:00+00:00"
|
assert state.state == "2023-06-05T00:16:00+00:00"
|
||||||
getattr(mock_automower_client.commands, "error_confirm").side_effect = ApiException(
|
getattr(mock_automower_client.commands, "error_confirm").side_effect = ApiException(
|
||||||
"Test error"
|
"Test error"
|
||||||
)
|
)
|
||||||
|
149
tests/components/husqvarna_automower/test_calendar.py
Normal file
149
tests/components/husqvarna_automower/test_calendar.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
"""Tests for calendar platform."""
|
||||||
|
|
||||||
|
from collections.abc import Awaitable, Callable
|
||||||
|
import datetime
|
||||||
|
from http import HTTPStatus
|
||||||
|
from typing import Any
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
from aioautomower.utils import mower_list_to_dictionary_dataclass
|
||||||
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
|
import pytest
|
||||||
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.calendar import (
|
||||||
|
DOMAIN as CALENDAR_DOMAIN,
|
||||||
|
EVENT_END_DATETIME,
|
||||||
|
EVENT_START_DATETIME,
|
||||||
|
SERVICE_GET_EVENTS,
|
||||||
|
)
|
||||||
|
from homeassistant.components.husqvarna_automower.const import DOMAIN
|
||||||
|
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from . import setup_integration
|
||||||
|
|
||||||
|
from tests.common import (
|
||||||
|
MockConfigEntry,
|
||||||
|
async_fire_time_changed,
|
||||||
|
load_json_value_fixture,
|
||||||
|
)
|
||||||
|
from tests.typing import ClientSessionGenerator
|
||||||
|
|
||||||
|
TEST_ENTITY = "calendar.test_mower_1"
|
||||||
|
type GetEventsFn = Callable[[str, str], Awaitable[dict[str, Any]]]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="get_events")
|
||||||
|
def get_events_fixture(
|
||||||
|
hass_client: ClientSessionGenerator,
|
||||||
|
) -> GetEventsFn:
|
||||||
|
"""Fetch calendar events from the HTTP API."""
|
||||||
|
|
||||||
|
async def _fetch(start: str, end: str) -> list[dict[str, Any]]:
|
||||||
|
client = await hass_client()
|
||||||
|
response = await client.get(
|
||||||
|
f"/api/calendars/{TEST_ENTITY}?start={urllib.parse.quote(start)}&end={urllib.parse.quote(end)}"
|
||||||
|
)
|
||||||
|
assert response.status == HTTPStatus.OK
|
||||||
|
results = await response.json()
|
||||||
|
return [{k: event[k] for k in ("summary", "start", "end")} for event in results]
|
||||||
|
|
||||||
|
return _fetch
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, 12))
|
||||||
|
async def test_calendar_state_off(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_automower_client: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
|
"""State test of the calendar."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
state = hass.states.get("calendar.test_mower_1")
|
||||||
|
assert state is not None
|
||||||
|
assert state.state == "off"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, 19))
|
||||||
|
async def test_calendar_state_on(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_automower_client: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
) -> None:
|
||||||
|
"""State test of the calendar."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
state = hass.states.get("calendar.test_mower_1")
|
||||||
|
assert state is not None
|
||||||
|
assert state.state == "on"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5))
|
||||||
|
async def test_empty_calendar(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_automower_client: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
freezer: FrozenDateTimeFactory,
|
||||||
|
get_events: GetEventsFn,
|
||||||
|
) -> None:
|
||||||
|
"""State if there is no schedule set."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
json_values = load_json_value_fixture("mower.json", DOMAIN)
|
||||||
|
json_values["data"][0]["attributes"]["calendar"]["tasks"] = []
|
||||||
|
values = mower_list_to_dictionary_dataclass(json_values)
|
||||||
|
mock_automower_client.get_status.return_value = values
|
||||||
|
freezer.tick(SCAN_INTERVAL)
|
||||||
|
async_fire_time_changed(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("calendar.test_mower_1")
|
||||||
|
assert state is not None
|
||||||
|
assert state.state == "off"
|
||||||
|
events = await get_events("2023-06-05T00:00:00", "2023-06-12T00:00:00")
|
||||||
|
assert events == []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5))
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
(
|
||||||
|
"start_date",
|
||||||
|
"end_date",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC),
|
||||||
|
datetime.datetime(2023, 6, 12, tzinfo=datetime.UTC),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_calendar_snapshot(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_automower_client: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
start_date: datetime,
|
||||||
|
end_date: datetime,
|
||||||
|
) -> None:
|
||||||
|
"""Snapshot test of the calendar entity."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
events = await hass.services.async_call(
|
||||||
|
CALENDAR_DOMAIN,
|
||||||
|
SERVICE_GET_EVENTS,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: "calendar.test_mower_1",
|
||||||
|
EVENT_START_DATETIME: start_date,
|
||||||
|
EVENT_END_DATETIME: end_date,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
return_response=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert events == snapshot
|
@ -21,7 +21,7 @@ from tests.components.diagnostics import (
|
|||||||
from tests.typing import ClientSessionGenerator
|
from tests.typing import ClientSessionGenerator
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.freeze_time(datetime.datetime(2024, 2, 29, 11, tzinfo=datetime.UTC))
|
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC))
|
||||||
async def test_entry_diagnostics(
|
async def test_entry_diagnostics(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_client: ClientSessionGenerator,
|
hass_client: ClientSessionGenerator,
|
||||||
@ -40,7 +40,7 @@ async def test_entry_diagnostics(
|
|||||||
assert result == snapshot(exclude=props("created_at", "modified_at"))
|
assert result == snapshot(exclude=props("created_at", "modified_at"))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.freeze_time(datetime.datetime(2024, 2, 29, 11, tzinfo=datetime.UTC))
|
@pytest.mark.freeze_time(datetime.datetime(2023, 6, 5, tzinfo=datetime.UTC))
|
||||||
async def test_device_diagnostics(
|
async def test_device_diagnostics(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_client: ClientSessionGenerator,
|
hass_client: ClientSessionGenerator,
|
||||||
@ -49,7 +49,7 @@ async def test_device_diagnostics(
|
|||||||
mock_config_entry: MockConfigEntry,
|
mock_config_entry: MockConfigEntry,
|
||||||
device_registry: dr.DeviceRegistry,
|
device_registry: dr.DeviceRegistry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test select platform."""
|
"""Test device diagnostics platform."""
|
||||||
|
|
||||||
mock_config_entry.add_to_hass(hass)
|
mock_config_entry.add_to_hass(hass)
|
||||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user