mirror of
https://github.com/home-assistant/core.git
synced 2026-04-02 00:20:30 +01:00
Set up todo frontend resources when first platform is set up
This commit is contained in:
@@ -27,7 +27,7 @@ from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
|||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
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 homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
@@ -120,16 +120,10 @@ def _validate_supported_features(
|
|||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Set up Todo entities."""
|
"""Set up Todo entities."""
|
||||||
component = hass.data[DATA_COMPONENT] = EntityComponent[TodoListEntity](
|
component = hass.data[DATA_COMPONENT] = TodoEntityComponent(
|
||||||
_LOGGER, DOMAIN, hass, SCAN_INTERVAL
|
_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(
|
component.async_register_entity_service(
|
||||||
TodoServices.ADD_ITEM,
|
TodoServices.ADD_ITEM,
|
||||||
vol.All(
|
vol.All(
|
||||||
@@ -318,6 +312,52 @@ class TodoListEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||||||
self.async_update_listeners()
|
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(
|
@websocket_api.websocket_command(
|
||||||
{
|
{
|
||||||
vol.Required("type"): "todo/item/subscribe",
|
vol.Required("type"): "todo/item/subscribe",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
import zoneinfo
|
import zoneinfo
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -22,7 +23,7 @@ from homeassistant.components.todo import (
|
|||||||
TodoServices,
|
TodoServices,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
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.core import HomeAssistant
|
||||||
from homeassistant.exceptions import (
|
from homeassistant.exceptions import (
|
||||||
HomeAssistantError,
|
HomeAssistantError,
|
||||||
@@ -33,6 +34,7 @@ from homeassistant.setup import async_setup_component
|
|||||||
|
|
||||||
from . import create_mock_platform
|
from . import create_mock_platform
|
||||||
|
|
||||||
|
from tests.common import MockPlatform, mock_platform
|
||||||
from tests.typing import WebSocketGenerator
|
from tests.typing import WebSocketGenerator
|
||||||
|
|
||||||
ITEM_1 = {
|
ITEM_1 = {
|
||||||
@@ -1299,3 +1301,47 @@ async def test_async_subscribe_updates(
|
|||||||
unsub()
|
unsub()
|
||||||
test_entity.async_write_ha_state()
|
test_entity.async_write_ha_state()
|
||||||
assert len(received_updates) == 4
|
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",
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user