mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Add a Google Calendar birthdays calendar (#141300)
This commit is contained in:
parent
b2377d6da3
commit
204b1e1f24
@ -89,6 +89,7 @@ OPAQUE = "opaque"
|
|||||||
RRULE_PREFIX = "RRULE:"
|
RRULE_PREFIX = "RRULE:"
|
||||||
|
|
||||||
SERVICE_CREATE_EVENT = "create_event"
|
SERVICE_CREATE_EVENT = "create_event"
|
||||||
|
FILTERED_EVENT_TYPES = [EventTypeEnum.BIRTHDAY, EventTypeEnum.WORKING_LOCATION]
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True, kw_only=True)
|
@dataclasses.dataclass(frozen=True, kw_only=True)
|
||||||
@ -103,7 +104,7 @@ class GoogleCalendarEntityDescription(CalendarEntityDescription):
|
|||||||
search: str | None
|
search: str | None
|
||||||
local_sync: bool
|
local_sync: bool
|
||||||
device_id: str
|
device_id: str
|
||||||
working_location: bool = False
|
event_type: EventTypeEnum | None = None
|
||||||
|
|
||||||
|
|
||||||
def _get_entity_descriptions(
|
def _get_entity_descriptions(
|
||||||
@ -173,14 +174,24 @@ def _get_entity_descriptions(
|
|||||||
local_sync,
|
local_sync,
|
||||||
)
|
)
|
||||||
if calendar_item.primary and local_sync:
|
if calendar_item.primary and local_sync:
|
||||||
_LOGGER.debug("work location entity")
|
# Create a separate calendar for birthdays
|
||||||
|
entity_descriptions.append(
|
||||||
|
dataclasses.replace(
|
||||||
|
entity_description,
|
||||||
|
key=f"{key}-birthdays",
|
||||||
|
translation_key="birthdays",
|
||||||
|
event_type=EventTypeEnum.BIRTHDAY,
|
||||||
|
name=None,
|
||||||
|
entity_id=None,
|
||||||
|
)
|
||||||
|
)
|
||||||
# Create an optional disabled by default entity for Work Location
|
# Create an optional disabled by default entity for Work Location
|
||||||
entity_descriptions.append(
|
entity_descriptions.append(
|
||||||
dataclasses.replace(
|
dataclasses.replace(
|
||||||
entity_description,
|
entity_description,
|
||||||
key=f"{key}-work-location",
|
key=f"{key}-work-location",
|
||||||
translation_key="working_location",
|
translation_key="working_location",
|
||||||
working_location=True,
|
event_type=EventTypeEnum.WORKING_LOCATION,
|
||||||
name=None,
|
name=None,
|
||||||
entity_id=None,
|
entity_id=None,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
@ -383,8 +394,17 @@ class GoogleCalendarEntity(
|
|||||||
for attendee in event.attendees
|
for attendee in event.attendees
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
is_working_location_event = event.event_type == EventTypeEnum.WORKING_LOCATION
|
# Calendar enttiy may be limited to a specific event type
|
||||||
if self.entity_description.working_location != is_working_location_event:
|
if (
|
||||||
|
self.entity_description.event_type is not None
|
||||||
|
and self.entity_description.event_type != event.event_type
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
# Default calendar entity omits the special types but includes all the others
|
||||||
|
if (
|
||||||
|
self.entity_description.event_type is None
|
||||||
|
and event.event_type in FILTERED_EVENT_TYPES
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if self._ignore_availability:
|
if self._ignore_availability:
|
||||||
return True
|
return True
|
||||||
|
@ -131,6 +131,9 @@
|
|||||||
"calendar": {
|
"calendar": {
|
||||||
"working_location": {
|
"working_location": {
|
||||||
"name": "Working location"
|
"name": "Working location"
|
||||||
|
},
|
||||||
|
"birthdays": {
|
||||||
|
"name": "Birthdays"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1455,6 +1455,7 @@ async def test_working_location_ignored(
|
|||||||
("event_type", "expected_event_message"),
|
("event_type", "expected_event_message"),
|
||||||
[
|
[
|
||||||
("workingLocation", "Test All Day Event"),
|
("workingLocation", "Test All Day Event"),
|
||||||
|
("birthday", None),
|
||||||
("default", None),
|
("default", None),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -1515,3 +1516,49 @@ async def test_no_working_location_entity(
|
|||||||
|
|
||||||
entity_entry = entity_registry.async_get("calendar.working_location")
|
entity_entry = entity_registry.async_get("calendar.working_location")
|
||||||
assert not entity_entry
|
assert not entity_entry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("event_type", "expected_event_message"),
|
||||||
|
[
|
||||||
|
("workingLocation", None),
|
||||||
|
("birthday", "Test All Day Event"),
|
||||||
|
("default", None),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize("calendar_is_primary", [True])
|
||||||
|
async def test_birthday_entity(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_client: ClientSessionGenerator,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_events_list_items: Callable[[list[dict[str, Any]]], None],
|
||||||
|
component_setup: ComponentSetup,
|
||||||
|
event_type: str,
|
||||||
|
expected_event_message: str | None,
|
||||||
|
) -> None:
|
||||||
|
"""Test that birthday events appear only on the birthdays calendar."""
|
||||||
|
event = {
|
||||||
|
**TEST_EVENT,
|
||||||
|
**upcoming(),
|
||||||
|
"eventType": event_type,
|
||||||
|
}
|
||||||
|
mock_events_list_items([event])
|
||||||
|
assert await component_setup()
|
||||||
|
|
||||||
|
entity_entry = entity_registry.async_get("calendar.birthdays")
|
||||||
|
assert entity_entry
|
||||||
|
assert entity_entry.disabled_by is None # Enabled by default
|
||||||
|
|
||||||
|
entity_registry.async_update_entity(
|
||||||
|
entity_id="calendar.birthdays", disabled_by=None
|
||||||
|
)
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass,
|
||||||
|
dt_util.utcnow() + datetime.timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1),
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("calendar.birthdays")
|
||||||
|
assert state
|
||||||
|
assert state.name == "Birthdays"
|
||||||
|
assert state.attributes.get("message") == expected_event_message
|
||||||
|
Loading…
x
Reference in New Issue
Block a user