Add calendar platform to Habitica integration (#128248)
* Add calendar platform * Add tests * add missing reminders filter by date * Add +1 day to todo end * add 1 day to dailies, remove unused line of code * Removing reminders calendar to a separate PR * fix upcoming event for dailies * util function for rrule string * Add test for get_recurrence_rule * use habitica daystart and account for isDue flag * yesterdaily is still an active event * Fix yesterdailies and add attribute * Update snapshot * Use iter, return attribute with None value * various changes * update snapshot * fix merge error * update snapshot * change date range filtering for todos * use datetimes instead of date in async_get_events * Sort events * Update snapshot * add method for todos * filter for upcoming events * dailies * refactor todos * update dailies logic * dedent loopspull/129479/head
parent
db5cb6233c
commit
6887a4419e
|
@ -29,7 +29,13 @@ from .types import HabiticaConfigEntry
|
|||
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
|
||||
|
||||
|
||||
PLATFORMS = [Platform.BUTTON, Platform.SENSOR, Platform.SWITCH, Platform.TODO]
|
||||
PLATFORMS = [
|
||||
Platform.BUTTON,
|
||||
Platform.CALENDAR,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
Platform.TODO,
|
||||
]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
"""Calendar platform for Habitica integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime, timedelta
|
||||
from enum import StrEnum
|
||||
|
||||
from dateutil.rrule import rrule
|
||||
|
||||
from homeassistant.components.calendar import (
|
||||
CalendarEntity,
|
||||
CalendarEntityDescription,
|
||||
CalendarEvent,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import HabiticaConfigEntry
|
||||
from .coordinator import HabiticaDataUpdateCoordinator
|
||||
from .entity import HabiticaBase
|
||||
from .types import HabiticaTaskType
|
||||
from .util import build_rrule, get_recurrence_rule
|
||||
|
||||
|
||||
class HabiticaCalendar(StrEnum):
|
||||
"""Habitica calendars."""
|
||||
|
||||
DAILIES = "dailys"
|
||||
TODOS = "todos"
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: HabiticaConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the calendar platform."""
|
||||
coordinator = config_entry.runtime_data
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
HabiticaTodosCalendarEntity(coordinator),
|
||||
HabiticaDailiesCalendarEntity(coordinator),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class HabiticaCalendarEntity(HabiticaBase, CalendarEntity):
|
||||
"""Base Habitica calendar entity."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: HabiticaDataUpdateCoordinator,
|
||||
) -> None:
|
||||
"""Initialize calendar entity."""
|
||||
super().__init__(coordinator, self.entity_description)
|
||||
|
||||
|
||||
class HabiticaTodosCalendarEntity(HabiticaCalendarEntity):
|
||||
"""Habitica todos calendar entity."""
|
||||
|
||||
entity_description = CalendarEntityDescription(
|
||||
key=HabiticaCalendar.TODOS,
|
||||
translation_key=HabiticaCalendar.TODOS,
|
||||
)
|
||||
|
||||
def dated_todos(
|
||||
self, start_date: datetime, end_date: datetime | None = None
|
||||
) -> list[CalendarEvent]:
|
||||
"""Get all dated todos."""
|
||||
|
||||
events = []
|
||||
for task in self.coordinator.data.tasks:
|
||||
if not (
|
||||
task["type"] == HabiticaTaskType.TODO
|
||||
and not task["completed"]
|
||||
and task.get("date") # only if has due date
|
||||
):
|
||||
continue
|
||||
|
||||
start = dt_util.start_of_local_day(datetime.fromisoformat(task["date"]))
|
||||
end = start + timedelta(days=1)
|
||||
# return current and upcoming events or events within the requested range
|
||||
|
||||
if end < start_date:
|
||||
# Event ends before date range
|
||||
continue
|
||||
|
||||
if end_date and start > end_date:
|
||||
# Event starts after date range
|
||||
continue
|
||||
|
||||
events.append(
|
||||
CalendarEvent(
|
||||
start=start.date(),
|
||||
end=end.date(),
|
||||
summary=task["text"],
|
||||
description=task["notes"],
|
||||
uid=task["id"],
|
||||
)
|
||||
)
|
||||
return sorted(
|
||||
events,
|
||||
key=lambda event: (
|
||||
event.start,
|
||||
self.coordinator.data.user["tasksOrder"]["todos"].index(event.uid),
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def event(self) -> CalendarEvent | None:
|
||||
"""Return the current or next upcoming event."""
|
||||
|
||||
return next(iter(self.dated_todos(dt_util.now())), None)
|
||||
|
||||
async def async_get_events(
|
||||
self, hass: HomeAssistant, start_date: datetime, end_date: datetime
|
||||
) -> list[CalendarEvent]:
|
||||
"""Return calendar events within a datetime range."""
|
||||
return self.dated_todos(start_date, end_date)
|
||||
|
||||
|
||||
class HabiticaDailiesCalendarEntity(HabiticaCalendarEntity):
|
||||
"""Habitica dailies calendar entity."""
|
||||
|
||||
entity_description = CalendarEntityDescription(
|
||||
key=HabiticaCalendar.DAILIES,
|
||||
translation_key=HabiticaCalendar.DAILIES,
|
||||
)
|
||||
|
||||
@property
|
||||
def today(self) -> datetime:
|
||||
"""Habitica daystart."""
|
||||
return dt_util.start_of_local_day(
|
||||
datetime.fromisoformat(self.coordinator.data.user["lastCron"])
|
||||
)
|
||||
|
||||
def end_date(self, recurrence: datetime, end: datetime | None = None) -> date:
|
||||
"""Calculate the end date for a yesterdaily.
|
||||
|
||||
The enddates of events from yesterday move forward to the end
|
||||
of the current day (until the cron resets the dailies) to show them
|
||||
as still active events on the calendar state entity (state: on).
|
||||
|
||||
Events in the calendar view will show all-day events on their due day
|
||||
"""
|
||||
if end:
|
||||
return recurrence.date() + timedelta(days=1)
|
||||
return (
|
||||
dt_util.start_of_local_day() if recurrence == self.today else recurrence
|
||||
).date() + timedelta(days=1)
|
||||
|
||||
def get_recurrence_dates(
|
||||
self, recurrences: rrule, start_date: datetime, end_date: datetime | None = None
|
||||
) -> list[datetime]:
|
||||
"""Calculate recurrence dates based on start_date and end_date."""
|
||||
if end_date:
|
||||
return recurrences.between(
|
||||
start_date, end_date - timedelta(days=1), inc=True
|
||||
)
|
||||
# if no end_date is given, return only the next recurrence
|
||||
return [recurrences.after(self.today, inc=True)]
|
||||
|
||||
def due_dailies(
|
||||
self, start_date: datetime, end_date: datetime | None = None
|
||||
) -> list[CalendarEvent]:
|
||||
"""Get dailies and recurrences for a given period or the next upcoming."""
|
||||
|
||||
# we only have dailies for today and future recurrences
|
||||
if end_date and end_date < self.today:
|
||||
return []
|
||||
start_date = max(start_date, self.today)
|
||||
|
||||
events = []
|
||||
for task in self.coordinator.data.tasks:
|
||||
# only dailies that that are not 'grey dailies'
|
||||
if not (task["type"] == HabiticaTaskType.DAILY and task["everyX"]):
|
||||
continue
|
||||
|
||||
recurrences = build_rrule(task)
|
||||
recurrence_dates = self.get_recurrence_dates(
|
||||
recurrences, start_date, end_date
|
||||
)
|
||||
for recurrence in recurrence_dates:
|
||||
is_future_event = recurrence > self.today
|
||||
is_current_event = recurrence <= self.today and not task["completed"]
|
||||
|
||||
if not (is_future_event or is_current_event):
|
||||
continue
|
||||
|
||||
events.append(
|
||||
CalendarEvent(
|
||||
start=recurrence.date(),
|
||||
end=self.end_date(recurrence, end_date),
|
||||
summary=task["text"],
|
||||
description=task["notes"],
|
||||
uid=task["id"],
|
||||
rrule=get_recurrence_rule(recurrences),
|
||||
)
|
||||
)
|
||||
return sorted(
|
||||
events,
|
||||
key=lambda event: (
|
||||
event.start,
|
||||
self.coordinator.data.user["tasksOrder"]["dailys"].index(event.uid),
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def event(self) -> CalendarEvent | None:
|
||||
"""Return the next upcoming event."""
|
||||
return next(iter(self.due_dailies(self.today)), None)
|
||||
|
||||
async def async_get_events(
|
||||
self, hass: HomeAssistant, start_date: datetime, end_date: datetime
|
||||
) -> list[CalendarEvent]:
|
||||
"""Return calendar events within a datetime range."""
|
||||
|
||||
return self.due_dailies(start_date, end_date)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, bool | None] | None:
|
||||
"""Return entity specific state attributes."""
|
||||
return {
|
||||
"yesterdaily": self.event.start < self.today.date() if self.event else None
|
||||
}
|
|
@ -58,6 +58,14 @@
|
|||
"default": "mdi:hand-heart-outline"
|
||||
}
|
||||
},
|
||||
"calendar": {
|
||||
"todos": {
|
||||
"default": "mdi:calendar-check"
|
||||
},
|
||||
"dailys": {
|
||||
"default": "mdi:calendar-multiple"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"display_name": {
|
||||
"default": "mdi:account-circle"
|
||||
|
|
|
@ -84,6 +84,23 @@
|
|||
"name": "Blessing"
|
||||
}
|
||||
},
|
||||
"calendar": {
|
||||
"todos": {
|
||||
"name": "To-Do's"
|
||||
},
|
||||
"dailys": {
|
||||
"name": "Dailies",
|
||||
"state_attributes": {
|
||||
"yesterdaily": {
|
||||
"name": "Yester-Daily",
|
||||
"state": {
|
||||
"true": "[%key:common::state::yes%]",
|
||||
"false": "[%key:common::state::no%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"display_name": {
|
||||
"name": "Display name"
|
||||
|
|
|
@ -24,7 +24,7 @@ from homeassistant.util import dt as dt_util
|
|||
from .const import ASSETS_URL, DOMAIN
|
||||
from .coordinator import HabiticaDataUpdateCoordinator
|
||||
from .entity import HabiticaBase
|
||||
from .types import HabiticaConfigEntry
|
||||
from .types import HabiticaConfigEntry, HabiticaTaskType
|
||||
from .util import next_due_date
|
||||
|
||||
|
||||
|
@ -37,15 +37,6 @@ class HabiticaTodoList(StrEnum):
|
|||
REWARDS = "rewards"
|
||||
|
||||
|
||||
class HabiticaTaskType(StrEnum):
|
||||
"""Habitica Entities."""
|
||||
|
||||
HABIT = "habit"
|
||||
DAILY = "daily"
|
||||
TODO = "todo"
|
||||
REWARD = "reward"
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: HabiticaConfigEntry,
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
"""Types for Habitica integration."""
|
||||
|
||||
from enum import StrEnum
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
|
||||
from .coordinator import HabiticaDataUpdateCoordinator
|
||||
|
||||
type HabiticaConfigEntry = ConfigEntry[HabiticaDataUpdateCoordinator]
|
||||
|
||||
|
||||
class HabiticaTaskType(StrEnum):
|
||||
"""Habitica Entities."""
|
||||
|
||||
HABIT = "habit"
|
||||
DAILY = "daily"
|
||||
TODO = "todo"
|
||||
REWARD = "reward"
|
||||
|
|
|
@ -5,6 +5,21 @@ from __future__ import annotations
|
|||
import datetime
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from dateutil.rrule import (
|
||||
DAILY,
|
||||
FR,
|
||||
MO,
|
||||
MONTHLY,
|
||||
SA,
|
||||
SU,
|
||||
TH,
|
||||
TU,
|
||||
WE,
|
||||
WEEKLY,
|
||||
YEARLY,
|
||||
rrule,
|
||||
)
|
||||
|
||||
from homeassistant.components.automation import automations_with_entity
|
||||
from homeassistant.components.script import scripts_with_entity
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -62,3 +77,65 @@ def entity_used_in(hass: HomeAssistant, entity_id: str) -> list[str]:
|
|||
used_in = automations_with_entity(hass, entity_id)
|
||||
used_in += scripts_with_entity(hass, entity_id)
|
||||
return used_in
|
||||
|
||||
|
||||
FREQUENCY_MAP = {"daily": DAILY, "weekly": WEEKLY, "monthly": MONTHLY, "yearly": YEARLY}
|
||||
WEEKDAY_MAP = {"m": MO, "t": TU, "w": WE, "th": TH, "f": FR, "s": SA, "su": SU}
|
||||
|
||||
|
||||
def build_rrule(task: dict[str, Any]) -> rrule:
|
||||
"""Build rrule string."""
|
||||
|
||||
rrule_frequency = FREQUENCY_MAP.get(task["frequency"], DAILY)
|
||||
weekdays = [
|
||||
WEEKDAY_MAP[day] for day, is_active in task["repeat"].items() if is_active
|
||||
]
|
||||
bymonthday = (
|
||||
task["daysOfMonth"]
|
||||
if rrule_frequency == MONTHLY and task["daysOfMonth"]
|
||||
else None
|
||||
)
|
||||
|
||||
bysetpos = None
|
||||
if rrule_frequency == MONTHLY and task["weeksOfMonth"]:
|
||||
bysetpos = task["weeksOfMonth"]
|
||||
weekdays = weekdays if weekdays else [MO]
|
||||
|
||||
return rrule(
|
||||
freq=rrule_frequency,
|
||||
interval=task["everyX"],
|
||||
dtstart=dt_util.start_of_local_day(
|
||||
datetime.datetime.fromisoformat(task["startDate"])
|
||||
),
|
||||
byweekday=weekdays if rrule_frequency in [WEEKLY, MONTHLY] else None,
|
||||
bymonthday=bymonthday,
|
||||
bysetpos=bysetpos,
|
||||
)
|
||||
|
||||
|
||||
def get_recurrence_rule(recurrence: rrule) -> str:
|
||||
r"""Extract and return the recurrence rule portion of an RRULE.
|
||||
|
||||
This function takes an RRULE representing a task's recurrence pattern,
|
||||
builds the RRULE string, and extracts the recurrence rule part.
|
||||
|
||||
'DTSTART:YYYYMMDDTHHMMSS\nRRULE:FREQ=YEARLY;INTERVAL=2'
|
||||
|
||||
Parameters
|
||||
----------
|
||||
recurrence : rrule
|
||||
An RRULE object.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
The recurrence rule portion of the RRULE string, starting with 'FREQ='.
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> rule = get_recurrence_rule(task)
|
||||
>>> print(rule)
|
||||
'FREQ=YEARLY;INTERVAL=2'
|
||||
|
||||
"""
|
||||
return str(recurrence).split("RRULE:")[1]
|
||||
|
|
|
@ -444,7 +444,12 @@
|
|||
"completedBy": {},
|
||||
"assignedUsers": []
|
||||
},
|
||||
"reminders": [],
|
||||
"reminders": [
|
||||
{
|
||||
"id": "91c09432-10ac-4a49-bd20-823081ec29ed",
|
||||
"time": "2024-09-22T02:00:00.0000Z"
|
||||
}
|
||||
],
|
||||
"byHabitica": false,
|
||||
"createdAt": "2024-09-21T22:17:19.513Z",
|
||||
"updatedAt": "2024-09-21T22:19:35.576Z",
|
||||
|
@ -477,7 +482,7 @@
|
|||
},
|
||||
{
|
||||
"_id": "86ea2475-d1b5-4020-bdcc-c188c7996afa",
|
||||
"date": "2024-09-26T22:15:00.000Z",
|
||||
"date": "2024-09-21T22:00:00.000Z",
|
||||
"completed": false,
|
||||
"collapseChecklist": false,
|
||||
"checklist": [],
|
||||
|
|
|
@ -34,6 +34,24 @@
|
|||
"flags": {
|
||||
"classSelected": true
|
||||
},
|
||||
"tasksOrder": {
|
||||
"rewards": ["5e2ea1df-f6e6-4ba3-bccb-97c5ec63e99b"],
|
||||
"todos": [
|
||||
"88de7cd9-af2b-49ce-9afd-bf941d87336b",
|
||||
"2f6fcabc-f670-4ec3-ba65-817e8deea490",
|
||||
"1aa3137e-ef72-4d1f-91ee-41933602f438",
|
||||
"86ea2475-d1b5-4020-bdcc-c188c7996afa"
|
||||
],
|
||||
"dailys": [
|
||||
"f21fa608-cfc6-4413-9fc7-0eb1b48ca43a",
|
||||
"bc1d1855-b2b8-4663-98ff-62e7b763dfc4",
|
||||
"e97659e0-2c42-4599-a7bb-00282adc410d",
|
||||
"564b9ac9-c53d-4638-9e7f-1cd96fe19baa",
|
||||
"f2c85972-1a19-4426-bc6d-ce3337b9d99f",
|
||||
"2c6d136c-a1c3-4bef-b7c4-fa980784b1e1"
|
||||
],
|
||||
"habits": ["1d147de6-5c02-4740-8e2f-71d3015a37f4"]
|
||||
},
|
||||
"needsCron": true,
|
||||
"lastCron": "2024-09-21T22:01:55.586Z"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,730 @@
|
|||
# serializer version: 1
|
||||
# name: test_api_events[calendar.test_user_dailies]
|
||||
list([
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-22',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-21',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Ein einstündiges Workout im Fitnessstudio absolvieren.',
|
||||
'end': dict({
|
||||
'date': '2024-09-22',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=WE,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-21',
|
||||
}),
|
||||
'summary': 'Fitnessstudio besuchen',
|
||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-23',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-22',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-23',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-22',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Ein einstündiges Workout im Fitnessstudio absolvieren.',
|
||||
'end': dict({
|
||||
'date': '2024-09-23',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=WE,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-22',
|
||||
}),
|
||||
'summary': 'Fitnessstudio besuchen',
|
||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-24',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-23',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-24',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-23',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-25',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-24',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-25',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-24',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-26',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-25',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-26',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-25',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Ein einstündiges Workout im Fitnessstudio absolvieren.',
|
||||
'end': dict({
|
||||
'date': '2024-09-26',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=WE,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-25',
|
||||
}),
|
||||
'summary': 'Fitnessstudio besuchen',
|
||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-27',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-26',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-27',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-26',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-28',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-27',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-28',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-27',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-29',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-28',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-29',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-28',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Ein einstündiges Workout im Fitnessstudio absolvieren.',
|
||||
'end': dict({
|
||||
'date': '2024-09-29',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=WE,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-28',
|
||||
}),
|
||||
'summary': 'Fitnessstudio besuchen',
|
||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-30',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-29',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-09-30',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-29',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Ein einstündiges Workout im Fitnessstudio absolvieren.',
|
||||
'end': dict({
|
||||
'date': '2024-09-30',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=WE,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-29',
|
||||
}),
|
||||
'summary': 'Fitnessstudio besuchen',
|
||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-01',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-30',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-01',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-09-30',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-02',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-01',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-02',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-01',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-03',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-02',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-03',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-02',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Ein einstündiges Workout im Fitnessstudio absolvieren.',
|
||||
'end': dict({
|
||||
'date': '2024-10-03',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=WE,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-02',
|
||||
}),
|
||||
'summary': 'Fitnessstudio besuchen',
|
||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-04',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-03',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-04',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-03',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-05',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-04',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-05',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-04',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-06',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-05',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-06',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-05',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Ein einstündiges Workout im Fitnessstudio absolvieren.',
|
||||
'end': dict({
|
||||
'date': '2024-10-06',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=WE,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-05',
|
||||
}),
|
||||
'summary': 'Fitnessstudio besuchen',
|
||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-07',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-06',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-07',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-06',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Ein einstündiges Workout im Fitnessstudio absolvieren.',
|
||||
'end': dict({
|
||||
'date': '2024-10-07',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=WE,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-06',
|
||||
}),
|
||||
'summary': 'Fitnessstudio besuchen',
|
||||
'uid': '2c6d136c-a1c3-4bef-b7c4-fa980784b1e1',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Änderungen zu machen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-08',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-07',
|
||||
}),
|
||||
'summary': 'Zahnseide benutzen',
|
||||
'uid': '564b9ac9-c53d-4638-9e7f-1cd96fe19baa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end': dict({
|
||||
'date': '2024-10-08',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU',
|
||||
'start': dict({
|
||||
'date': '2024-10-07',
|
||||
}),
|
||||
'summary': '5 Minuten ruhig durchatmen',
|
||||
'uid': 'f2c85972-1a19-4426-bc6d-ce3337b9d99f',
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
# name: test_api_events[calendar.test_user_to_do_s]
|
||||
list([
|
||||
dict({
|
||||
'description': 'Strom- und Internetrechnungen rechtzeitig überweisen.',
|
||||
'end': dict({
|
||||
'date': '2024-09-01',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': None,
|
||||
'start': dict({
|
||||
'date': '2024-08-31',
|
||||
}),
|
||||
'summary': 'Rechnungen bezahlen',
|
||||
'uid': '2f6fcabc-f670-4ec3-ba65-817e8deea490',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Den Ausflug für das kommende Wochenende organisieren.',
|
||||
'end': dict({
|
||||
'date': '2024-09-22',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': None,
|
||||
'start': dict({
|
||||
'date': '2024-09-21',
|
||||
}),
|
||||
'summary': 'Wochenendausflug planen',
|
||||
'uid': '86ea2475-d1b5-4020-bdcc-c188c7996afa',
|
||||
}),
|
||||
dict({
|
||||
'description': 'Das Buch, das du angefangen hast, bis zum Wochenende fertig lesen.',
|
||||
'end': dict({
|
||||
'date': '2024-09-28',
|
||||
}),
|
||||
'location': None,
|
||||
'recurrence_id': None,
|
||||
'rrule': None,
|
||||
'start': dict({
|
||||
'date': '2024-09-27',
|
||||
}),
|
||||
'summary': 'Buch zu Ende lesen',
|
||||
'uid': '88de7cd9-af2b-49ce-9afd-bf941d87336b',
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
# name: test_calendar_platform[calendar.test_user_dailies-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'calendar',
|
||||
'entity_category': None,
|
||||
'entity_id': 'calendar.test_user_dailies',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Dailies',
|
||||
'platform': 'habitica',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <HabiticaCalendar.DAILIES: 'dailys'>,
|
||||
'unique_id': '00000000-0000-0000-0000-000000000000_dailys',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_calendar_platform[calendar.test_user_dailies-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'all_day': True,
|
||||
'description': 'Klicke um Deinen Terminplan festzulegen!',
|
||||
'end_time': '2024-09-22 00:00:00',
|
||||
'friendly_name': 'test-user Dailies',
|
||||
'location': '',
|
||||
'message': '5 Minuten ruhig durchatmen',
|
||||
'start_time': '2024-09-21 00:00:00',
|
||||
'yesterdaily': False,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'calendar.test_user_dailies',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_calendar_platform[calendar.test_user_to_do_s-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'calendar',
|
||||
'entity_category': None,
|
||||
'entity_id': 'calendar.test_user_to_do_s',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': "To-Do's",
|
||||
'platform': 'habitica',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': <HabiticaCalendar.TODOS: 'todos'>,
|
||||
'unique_id': '00000000-0000-0000-0000-000000000000_todos',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_calendar_platform[calendar.test_user_to_do_s-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'all_day': True,
|
||||
'description': 'Den Ausflug für das kommende Wochenende organisieren.',
|
||||
'end_time': '2024-09-22 00:00:00',
|
||||
'friendly_name': "test-user To-Do's",
|
||||
'location': '',
|
||||
'message': 'Wochenendausflug planen',
|
||||
'start_time': '2024-09-21 00:00:00',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'calendar.test_user_to_do_s',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
|
@ -72,7 +72,7 @@
|
|||
}),
|
||||
dict({
|
||||
'description': 'Den Ausflug für das kommende Wochenende organisieren.',
|
||||
'due': '2024-09-26',
|
||||
'due': '2024-09-21',
|
||||
'status': 'needs_action',
|
||||
'summary': 'Wochenendausflug planen',
|
||||
'uid': '86ea2475-d1b5-4020-bdcc-c188c7996afa',
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
"""Tests for the Habitica calendar platform."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def calendar_only() -> Generator[None]:
|
||||
"""Enable only the calendar platform."""
|
||||
with patch(
|
||||
"homeassistant.components.habitica.PLATFORMS",
|
||||
[Platform.CALENDAR],
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def set_tz(hass: HomeAssistant) -> None:
|
||||
"""Fixture to set timezone."""
|
||||
await hass.config.async_set_time_zone("Europe/Berlin")
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_habitica")
|
||||
@pytest.mark.freeze_time("2024-09-20T22:00:00.000Z")
|
||||
async def test_calendar_platform(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test setup of the Habitica calendar platform."""
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("entity"),
|
||||
[
|
||||
"calendar.test_user_to_do_s",
|
||||
"calendar.test_user_dailies",
|
||||
],
|
||||
)
|
||||
@pytest.mark.freeze_time("2024-09-20T22:00:00.000Z")
|
||||
@pytest.mark.usefixtures("mock_habitica")
|
||||
async def test_api_events(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
config_entry: MockConfigEntry,
|
||||
hass_client: ClientSessionGenerator,
|
||||
entity: str,
|
||||
) -> None:
|
||||
"""Test calendar event."""
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_client()
|
||||
response = await client.get(
|
||||
f"/api/calendars/{entity}?start=2024-08-29&end=2024-10-08"
|
||||
)
|
||||
|
||||
assert await response.json() == snapshot
|
Loading…
Reference in New Issue