1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-08 17:49:37 +01:00

Add initial_color property to CalendarEntity (#145606)

Co-authored-by: Allen Porter <allen.porter@gmail.com>
This commit is contained in:
Tomasz
2026-01-27 09:52:07 +01:00
committed by GitHub
parent 27b8274d3e
commit b13c2e3018
4 changed files with 85 additions and 5 deletions
+23 -3
View File
@@ -32,7 +32,7 @@ from homeassistant.core import (
callback,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import config_validation as cv, entity_registry as er
from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.event import async_track_point_in_time
@@ -516,6 +516,26 @@ class CalendarEntity(Entity):
_alarm_unsubs: list[CALLBACK_TYPE] | None = None
_attr_initial_color: str | None = None
@property
def initial_color(self) -> str | None:
"""Return the initial color for the calendar entity."""
return self._attr_initial_color
def get_initial_entity_options(self) -> er.EntityOptionsType | None:
"""Return initial entity options."""
if self.initial_color is None:
return None
# Validate that it's a valid hex color string with # prefix
try:
validated_color = cv.color_hex(self.initial_color)
except vol.Invalid:
return None
return {DOMAIN: {"color": validated_color}}
@property
def event(self) -> CalendarEvent | None:
"""Return the next upcoming event."""
@@ -533,8 +553,8 @@ class CalendarEntity(Entity):
"all_day": event.all_day,
"start_time": event.start_datetime_local.strftime(DATE_STR_FORMAT),
"end_time": event.end_datetime_local.strftime(DATE_STR_FORMAT),
"location": event.location if event.location else "",
"description": event.description if event.description else "",
"location": event.location or "",
"description": event.description or "",
}
@final
+8 -1
View File
@@ -48,11 +48,13 @@ class MockCalendarEntity(CalendarEntity):
self,
name: str,
events: list[CalendarEvent] | None = None,
initial_color: str | None = None,
unique_id: str | None = None,
) -> None:
"""Initialize entity."""
self._attr_name = name.capitalize()
self._events = events or []
self._attr_initial_color = initial_color
self._attr_unique_id = unique_id
@property
@@ -206,4 +208,9 @@ def create_test_entities() -> list[MockCalendarEntity]:
)
entity2.async_get_events = AsyncMock(wraps=entity2.async_get_events)
return [entity1, entity2]
entity3 = MockCalendarEntity(
"Calendar 3", [], initial_color="#FF0000", unique_id="calendar_3"
)
entity3.async_get_events = AsyncMock(wraps=entity3.async_get_events)
return [entity1, entity2, entity3]
+53
View File
@@ -16,6 +16,7 @@ import voluptuous as vol
from homeassistant.components.calendar import DOMAIN, SERVICE_GET_EVENTS
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError, ServiceNotSupported
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
@@ -123,6 +124,7 @@ async def test_calendars_http_api(
assert data == [
{"entity_id": "calendar.calendar_1", "name": "Calendar 1"},
{"entity_id": "calendar.calendar_2", "name": "Calendar 2"},
{"entity_id": "calendar.calendar_3", "name": "Calendar 3"},
]
@@ -604,3 +606,54 @@ async def test_list_events_service_same_dates(
blocking=True,
return_response=True,
)
async def test_calendar_initial_color_valid(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
test_entities: list[MockCalendarEntity],
) -> None:
"""Test that initial_color creates initial entity options."""
# Entity 3 was created with an initial_color
entity = test_entities[2]
# Check that entity registry was populated with the initial_color
entry = entity_registry.async_get(entity.entity_id)
assert entry is not None
assert entry.options.get(DOMAIN, {}).get("color") == "#FF0000"
@pytest.mark.parametrize(
"invalid_initial_color",
[
"FF0000", # Missing #
"#FF00", # Too short
"#FF00000", # Too long
"#GGGGGG", # Invalid hex
"red", # Not hex
"", # Empty
],
)
async def test_calendar_initial_color_invalid(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
invalid_initial_color: str,
) -> None:
"""Test that invalid initial_color is ignored."""
entity = MockCalendarEntity(
"Invalid Color Test",
[],
initial_color=invalid_initial_color,
unique_id=f"test_{invalid_initial_color}",
)
assert entity.get_initial_entity_options() is None
async def test_calendar_initial_color_none(
hass: HomeAssistant,
test_entities: list[MockCalendarEntity],
) -> None:
"""Test that entities without initial_color return None."""
# Entities 1 and 2 were created without an initial_color
entity = test_entities[0]
assert entity.get_initial_entity_options() is None
+1 -1
View File
@@ -705,7 +705,7 @@ async def test_legacy_entity_type(
"action": TEST_AUTOMATION_ACTION,
"trigger": {
"platform": calendar.DOMAIN,
"entity_id": "calendar.calendar_3",
"entity_id": "calendar.calendar_4",
},
}
},