Fix local calendar handling of empty recurrence ids (#112745)
* Fix handling of empty recurrence ids * Revert logging changespull/113250/head
parent
5a125bf379
commit
d99b9f7a70
|
@ -189,6 +189,11 @@ def _validate_rrule(value: Any) -> str:
|
|||
return str(value)
|
||||
|
||||
|
||||
def _empty_as_none(value: str | None) -> str | None:
|
||||
"""Convert any empty string values to None."""
|
||||
return value or None
|
||||
|
||||
|
||||
CREATE_EVENT_SERVICE = "create_event"
|
||||
CREATE_EVENT_SCHEMA = vol.All(
|
||||
cv.has_at_least_one_key(EVENT_START_DATE, EVENT_START_DATETIME, EVENT_IN),
|
||||
|
@ -733,7 +738,9 @@ async def handle_calendar_event_create(
|
|||
vol.Required("type"): "calendar/event/delete",
|
||||
vol.Required("entity_id"): cv.entity_id,
|
||||
vol.Required(EVENT_UID): cv.string,
|
||||
vol.Optional(EVENT_RECURRENCE_ID): cv.string,
|
||||
vol.Optional(EVENT_RECURRENCE_ID): vol.Any(
|
||||
vol.All(cv.string, _empty_as_none), None
|
||||
),
|
||||
vol.Optional(EVENT_RECURRENCE_RANGE): cv.string,
|
||||
}
|
||||
)
|
||||
|
@ -777,7 +784,9 @@ async def handle_calendar_event_delete(
|
|||
vol.Required("type"): "calendar/event/update",
|
||||
vol.Required("entity_id"): cv.entity_id,
|
||||
vol.Required(EVENT_UID): cv.string,
|
||||
vol.Optional(EVENT_RECURRENCE_ID): cv.string,
|
||||
vol.Optional(EVENT_RECURRENCE_ID): vol.Any(
|
||||
vol.All(cv.string, _empty_as_none), None
|
||||
),
|
||||
vol.Optional(EVENT_RECURRENCE_RANGE): cv.string,
|
||||
vol.Required(CONF_EVENT): WEBSOCKET_EVENT_SCHEMA,
|
||||
}
|
||||
|
|
|
@ -408,6 +408,46 @@ async def test_websocket_delete_recurring(
|
|||
]
|
||||
|
||||
|
||||
async def test_websocket_delete_empty_recurrence_id(
|
||||
ws_client: ClientFixture, setup_integration: None, get_events: GetEventsFn
|
||||
) -> None:
|
||||
"""Test websocket delete command with an empty recurrence id no-op."""
|
||||
client = await ws_client()
|
||||
await client.cmd_result(
|
||||
"create",
|
||||
{
|
||||
"entity_id": TEST_ENTITY,
|
||||
"event": {
|
||||
"summary": "Bastille Day Party",
|
||||
"dtstart": "1997-07-14T17:00:00+00:00",
|
||||
"dtend": "1997-07-15T04:00:00+00:00",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
events = await get_events("1997-07-14T00:00:00", "1997-07-16T00:00:00")
|
||||
assert list(map(event_fields, events)) == [
|
||||
{
|
||||
"summary": "Bastille Day Party",
|
||||
"start": {"dateTime": "1997-07-14T11:00:00-06:00"},
|
||||
"end": {"dateTime": "1997-07-14T22:00:00-06:00"},
|
||||
}
|
||||
]
|
||||
uid = events[0]["uid"]
|
||||
|
||||
# Delete the event with an empty recurrence id
|
||||
await client.cmd_result(
|
||||
"delete",
|
||||
{
|
||||
"entity_id": TEST_ENTITY,
|
||||
"uid": uid,
|
||||
"recurrence_id": "",
|
||||
},
|
||||
)
|
||||
events = await get_events("1997-07-14T00:00:00", "1997-07-16T00:00:00")
|
||||
assert list(map(event_fields, events)) == []
|
||||
|
||||
|
||||
async def test_websocket_update(
|
||||
ws_client: ClientFixture, setup_integration: None, get_events: GetEventsFn
|
||||
) -> None:
|
||||
|
@ -458,6 +498,58 @@ async def test_websocket_update(
|
|||
]
|
||||
|
||||
|
||||
async def test_websocket_update_empty_recurrence(
|
||||
ws_client: ClientFixture, setup_integration: None, get_events: GetEventsFn
|
||||
) -> None:
|
||||
"""Test an edit with an empty recurrence id (no-op)."""
|
||||
client = await ws_client()
|
||||
await client.cmd_result(
|
||||
"create",
|
||||
{
|
||||
"entity_id": TEST_ENTITY,
|
||||
"event": {
|
||||
"summary": "Bastille Day Party",
|
||||
"dtstart": "1997-07-14T17:00:00+00:00",
|
||||
"dtend": "1997-07-15T04:00:00+00:00",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
events = await get_events("1997-07-14T00:00:00", "1997-07-16T00:00:00")
|
||||
assert list(map(event_fields, events)) == [
|
||||
{
|
||||
"summary": "Bastille Day Party",
|
||||
"start": {"dateTime": "1997-07-14T11:00:00-06:00"},
|
||||
"end": {"dateTime": "1997-07-14T22:00:00-06:00"},
|
||||
}
|
||||
]
|
||||
uid = events[0]["uid"]
|
||||
|
||||
# Update the event with an empty string for the recurrence id which should
|
||||
# have no effect.
|
||||
await client.cmd_result(
|
||||
"update",
|
||||
{
|
||||
"entity_id": TEST_ENTITY,
|
||||
"uid": uid,
|
||||
"recurrence_id": "",
|
||||
"event": {
|
||||
"summary": "Bastille Day Party [To be rescheduled]",
|
||||
"dtstart": "1997-07-15T11:00:00-06:00",
|
||||
"dtend": "1997-07-15T22:00:00-06:00",
|
||||
},
|
||||
},
|
||||
)
|
||||
events = await get_events("1997-07-14T00:00:00", "1997-07-16T00:00:00")
|
||||
assert list(map(event_fields, events)) == [
|
||||
{
|
||||
"summary": "Bastille Day Party [To be rescheduled]",
|
||||
"start": {"dateTime": "1997-07-15T11:00:00-06:00"},
|
||||
"end": {"dateTime": "1997-07-15T22:00:00-06:00"},
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
async def test_websocket_update_recurring_this_and_future(
|
||||
ws_client: ClientFixture, setup_integration: None, get_events: GetEventsFn
|
||||
) -> None:
|
||||
|
|
Loading…
Reference in New Issue