mirror of
https://github.com/home-assistant/core.git
synced 2026-04-17 15:44:52 +01:00
Make TODO subscriptions use TodoItem instead of JSON (#165802)
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Iterable
|
||||
import copy
|
||||
import dataclasses
|
||||
import datetime
|
||||
import logging
|
||||
@@ -28,7 +29,6 @@ from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.util import dt as dt_util
|
||||
from homeassistant.util.json import JsonValueType
|
||||
|
||||
from .const import (
|
||||
ATTR_DESCRIPTION,
|
||||
@@ -240,7 +240,7 @@ class TodoListEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
||||
"""An entity that represents a To-do list."""
|
||||
|
||||
_attr_todo_items: list[TodoItem] | None = None
|
||||
_update_listeners: list[Callable[[list[JsonValueType] | None], None]] | None = None
|
||||
_update_listeners: list[Callable[[list[TodoItem]], None]] | None = None
|
||||
|
||||
@property
|
||||
def state(self) -> int | None:
|
||||
@@ -281,13 +281,9 @@ class TodoListEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
||||
@final
|
||||
@callback
|
||||
def async_subscribe_updates(
|
||||
self,
|
||||
listener: Callable[[list[JsonValueType] | None], None],
|
||||
self, listener: Callable[[list[TodoItem]], None]
|
||||
) -> CALLBACK_TYPE:
|
||||
"""Subscribe to To-do list item updates.
|
||||
|
||||
Called by websocket API.
|
||||
"""
|
||||
"""Subscribe to To-do list item updates."""
|
||||
if self._update_listeners is None:
|
||||
self._update_listeners = []
|
||||
self._update_listeners.append(listener)
|
||||
@@ -306,9 +302,7 @@ class TodoListEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
||||
if not self._update_listeners:
|
||||
return
|
||||
|
||||
todo_items: list[JsonValueType] = [
|
||||
dataclasses.asdict(item) for item in self.todo_items or ()
|
||||
]
|
||||
todo_items = [copy.copy(item) for item in self.todo_items or []]
|
||||
for listener in self._update_listeners:
|
||||
listener(todo_items)
|
||||
|
||||
@@ -341,13 +335,13 @@ async def websocket_handle_subscribe_todo_items(
|
||||
return
|
||||
|
||||
@callback
|
||||
def todo_item_listener(todo_items: list[JsonValueType] | None) -> None:
|
||||
def todo_item_listener(todo_items: list[TodoItem]) -> None:
|
||||
"""Push updated To-do list items to websocket."""
|
||||
connection.send_message(
|
||||
websocket_api.event_message(
|
||||
msg["id"],
|
||||
{
|
||||
"items": todo_items,
|
||||
"items": [dataclasses.asdict(item) for item in todo_items],
|
||||
},
|
||||
)
|
||||
)
|
||||
@@ -357,7 +351,7 @@ async def websocket_handle_subscribe_todo_items(
|
||||
)
|
||||
connection.send_result(msg["id"])
|
||||
|
||||
# Push an initial forecast update
|
||||
# Push an initial list update
|
||||
entity.async_update_listeners()
|
||||
|
||||
|
||||
|
||||
@@ -1231,3 +1231,53 @@ async def test_list_todo_items_extended_fields(
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async def test_async_subscribe_updates(
|
||||
hass: HomeAssistant, test_entity: TodoListEntity
|
||||
) -> None:
|
||||
"""Test async_subscribe_updates delivers list updates to listeners."""
|
||||
await create_mock_platform(hass, [test_entity])
|
||||
|
||||
received_updates: list[list[TodoItem]] = []
|
||||
|
||||
def listener(items: list[TodoItem]) -> None:
|
||||
received_updates.append(items)
|
||||
|
||||
unsub = test_entity.async_subscribe_updates(listener)
|
||||
|
||||
# Trigger an update
|
||||
test_entity.async_write_ha_state()
|
||||
|
||||
assert len(received_updates) == 1
|
||||
items = received_updates[0]
|
||||
assert len(items) == 2
|
||||
assert isinstance(items[0], TodoItem)
|
||||
assert items[0].summary == "Item #1"
|
||||
assert items[0].uid == "1"
|
||||
assert items[0].status == TodoItemStatus.NEEDS_ACTION
|
||||
assert isinstance(items[1], TodoItem)
|
||||
assert items[1].summary == "Item #2"
|
||||
assert items[1].uid == "2"
|
||||
assert items[1].status == TodoItemStatus.COMPLETED
|
||||
|
||||
# Verify items are copies (not the same objects)
|
||||
assert items[0] is not test_entity.todo_items[0]
|
||||
assert items[1] is not test_entity.todo_items[1]
|
||||
|
||||
# Add a new item and trigger update
|
||||
test_entity._attr_todo_items = [
|
||||
*test_entity._attr_todo_items,
|
||||
TodoItem(summary="Item #3", uid="3", status=TodoItemStatus.NEEDS_ACTION),
|
||||
]
|
||||
test_entity.async_write_ha_state()
|
||||
|
||||
assert len(received_updates) == 2
|
||||
items = received_updates[1]
|
||||
assert len(items) == 3
|
||||
assert items[2].summary == "Item #3"
|
||||
|
||||
# Unsubscribe and verify no more updates
|
||||
unsub()
|
||||
test_entity.async_write_ha_state()
|
||||
assert len(received_updates) == 2
|
||||
|
||||
Reference in New Issue
Block a user