From b1c95d5acd8109c7f9a9b212d87899241dcfb3be Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 30 Mar 2026 16:33:49 +0200 Subject: [PATCH] Set up todo frontend resources when first platform is set up --- homeassistant/components/todo/__init__.py | 31 +++++++++++++-- tests/components/todo/test_init.py | 48 ++++++++++++++++++++++- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/todo/__init__.py b/homeassistant/components/todo/__init__.py index f5110f41e59..2c5dd724d86 100644 --- a/homeassistant/components/todo/__init__.py +++ b/homeassistant/components/todo/__init__.py @@ -27,6 +27,9 @@ 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.integration_platform import ( + async_process_integration_platforms, +) from homeassistant.helpers.typing import ConfigType from homeassistant.util import dt as dt_util @@ -124,11 +127,31 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: _LOGGER, DOMAIN, hass, SCAN_INTERVAL ) - frontend.async_register_built_in_panel(hass, "todo", "todo", "mdi:clipboard-list") + frontend_loaded = False - 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) + @callback + def async_platform_loaded( + hass: HomeAssistant, integration_domain: str, platform: Any + ) -> None: + """Register frontend resources for calendar.""" + nonlocal frontend_loaded + + if frontend_loaded: + return + + frontend_loaded = True + + 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) + + await async_process_integration_platforms(hass, DOMAIN, async_platform_loaded) component.async_register_entity_service( TodoServices.ADD_ITEM, diff --git a/tests/components/todo/test_init.py b/tests/components/todo/test_init.py index e7a9fd364f9..363ffc119f7 100644 --- a/tests/components/todo/test_init.py +++ b/tests/components/todo/test_init.py @@ -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", + }