Compare commits

...

1 Commits

Author SHA1 Message Date
Erik
bf33ab762b Set up todo frontend resources when first platform is set up 2026-03-30 15:24:19 +02:00
2 changed files with 95 additions and 9 deletions

View File

@@ -27,7 +27,7 @@ from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util
from .const import (
@@ -120,16 +120,10 @@ def _validate_supported_features(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up Todo entities."""
component = hass.data[DATA_COMPONENT] = EntityComponent[TodoListEntity](
component = hass.data[DATA_COMPONENT] = TodoEntityComponent(
_LOGGER, DOMAIN, hass, SCAN_INTERVAL
)
frontend.async_register_built_in_panel(hass, "todo", "todo", "mdi:clipboard-list")
websocket_api.async_register_command(hass, websocket_handle_subscribe_todo_items)
websocket_api.async_register_command(hass, websocket_handle_todo_item_list)
websocket_api.async_register_command(hass, websocket_handle_todo_item_move)
component.async_register_entity_service(
TodoServices.ADD_ITEM,
vol.All(
@@ -318,6 +312,52 @@ class TodoListEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
self.async_update_listeners()
class TodoEntityComponent(EntityComponent[TodoListEntity]):
"""To-do entity component.
Sets up frontend resources and websocket API when the first platform is added.
"""
_frontend_loaded: bool = False
async def async_setup_entry(self, config_entry: ConfigEntry) -> bool:
"""Set up a config entry."""
result = await super().async_setup_entry(config_entry)
if not self._frontend_loaded:
self._register_frontend_resources()
return result
async def async_setup_platform(
self,
platform_type: str,
platform_config: ConfigType,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up a platform for this component."""
await super().async_setup_platform(
platform_type, platform_config, discovery_info
)
if not self._frontend_loaded:
self._register_frontend_resources()
def _register_frontend_resources(self) -> None:
"""Register frontend resources for to-do."""
self._frontend_loaded = True
frontend.async_register_built_in_panel(
self.hass, "todo", "todo", "mdi:clipboard-list"
)
websocket_api.async_register_command(
self.hass, websocket_handle_subscribe_todo_items
)
websocket_api.async_register_command(self.hass, websocket_handle_todo_item_list)
websocket_api.async_register_command(self.hass, websocket_handle_todo_item_move)
@websocket_api.websocket_command(
{
vol.Required("type"): "todo/item/subscribe",

View File

@@ -2,6 +2,7 @@
import datetime
from typing import Any
from unittest.mock import AsyncMock
import zoneinfo
import pytest
@@ -22,7 +23,7 @@ from homeassistant.components.todo import (
TodoServices,
)
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES
from homeassistant.const import ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_PLATFORM
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import (
HomeAssistantError,
@@ -33,6 +34,7 @@ from homeassistant.setup import async_setup_component
from . import create_mock_platform
from tests.common import MockPlatform, mock_platform
from tests.typing import WebSocketGenerator
ITEM_1 = {
@@ -1299,3 +1301,47 @@ async def test_async_subscribe_updates(
unsub()
test_entity.async_write_ha_state()
assert len(received_updates) == 4
async def test_frontend_resources_registered_after_first_config_entry_setup(
hass: HomeAssistant,
) -> None:
"""Test that frontend resources are registered after the first config entry is set up."""
await async_setup_component(hass, "http", {})
assert "frontend_panels" not in hass.data
assert "websocket_api" not in hass.data
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
assert "frontend_panels" not in hass.data
assert "websocket_api" not in hass.data
await create_mock_platform(hass, [])
assert set(hass.data["frontend_panels"]) == {"todo"}
assert set(hass.data["websocket_api"]) == {
"todo/item/list",
"todo/item/move",
"todo/item/subscribe",
}
async def test_frontend_resources_registered_after_first_platform_setup(
hass: HomeAssistant,
) -> None:
"""Test that frontend resources are registered after the first platform is set up."""
mock_platform(
hass,
f"test.{DOMAIN}",
MockPlatform(async_setup_platform=AsyncMock()),
)
await async_setup_component(hass, "http", {})
assert "frontend_panels" not in hass.data
assert "websocket_api" not in hass.data
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
assert set(hass.data["frontend_panels"]) == {"todo"}
assert set(hass.data["websocket_api"]) == {
"todo/item/list",
"todo/item/move",
"todo/item/subscribe",
}