Add event platform to Bring! integration (#136935)

* Add event platform

* update
This commit is contained in:
Manu 2025-02-07 09:44:14 +01:00 committed by GitHub
parent eaf31051c5
commit b9a9da1e1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 848 additions and 95 deletions

View File

@ -12,7 +12,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .coordinator import BringConfigEntry, BringDataUpdateCoordinator from .coordinator import BringConfigEntry, BringDataUpdateCoordinator
PLATFORMS: list[Platform] = [Platform.SENSOR, Platform.TODO] PLATFORMS: list[Platform] = [Platform.EVENT, Platform.SENSOR, Platform.TODO]
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View File

@ -8,12 +8,14 @@ import logging
from bring_api import ( from bring_api import (
Bring, Bring,
BringActivityResponse,
BringAuthException, BringAuthException,
BringItemsResponse, BringItemsResponse,
BringList, BringList,
BringParseException, BringParseException,
BringRequestException, BringRequestException,
BringUserSettingsResponse, BringUserSettingsResponse,
BringUsersResponse,
) )
from mashumaro.mixins.orjson import DataClassORJSONMixin from mashumaro.mixins.orjson import DataClassORJSONMixin
@ -37,6 +39,8 @@ class BringData(DataClassORJSONMixin):
lst: BringList lst: BringList
content: BringItemsResponse content: BringItemsResponse
activity: BringActivityResponse
users: BringUsersResponse
class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]): class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]):
@ -94,6 +98,8 @@ class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]):
continue continue
try: try:
items = await self.bring.get_list(lst.listUuid) items = await self.bring.get_list(lst.listUuid)
activity = await self.bring.get_activity(lst.listUuid)
users = await self.bring.get_list_users(lst.listUuid)
except BringRequestException as e: except BringRequestException as e:
raise UpdateFailed( raise UpdateFailed(
translation_domain=DOMAIN, translation_domain=DOMAIN,
@ -105,7 +111,7 @@ class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]):
translation_key="setup_parse_exception", translation_key="setup_parse_exception",
) from e ) from e
else: else:
list_dict[lst.listUuid] = BringData(lst, items) list_dict[lst.listUuid] = BringData(lst, items, activity, users)
return list_dict return list_dict

View File

@ -14,4 +14,8 @@ async def async_get_config_entry_diagnostics(
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Return diagnostics for a config entry.""" """Return diagnostics for a config entry."""
return {k: v.to_dict() for k, v in config_entry.runtime_data.data.items()} return {
"data": {k: v.to_dict() for k, v in config_entry.runtime_data.data.items()},
"lists": [lst.to_dict() for lst in config_entry.runtime_data.lists],
"user_settings": config_entry.runtime_data.user_settings.to_dict(),
}

View File

@ -0,0 +1,108 @@
"""Event platform for Bring integration."""
from __future__ import annotations
from dataclasses import asdict
from datetime import datetime
from bring_api import ActivityType, BringList
from homeassistant.components.event import EventEntity
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import BringConfigEntry
from .coordinator import BringDataUpdateCoordinator
from .entity import BringBaseEntity
PARALLEL_UPDATES = 0
async def async_setup_entry(
hass: HomeAssistant,
config_entry: BringConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the event platform."""
coordinator = config_entry.runtime_data
lists_added: set[str] = set()
@callback
def add_entities() -> None:
"""Add event entities."""
nonlocal lists_added
if new_lists := {lst.listUuid for lst in coordinator.lists} - lists_added:
async_add_entities(
BringEventEntity(
coordinator,
bring_list,
)
for bring_list in coordinator.lists
if bring_list.listUuid in new_lists
)
lists_added |= new_lists
coordinator.async_add_listener(add_entities)
add_entities()
class BringEventEntity(BringBaseEntity, EventEntity):
"""An event entity."""
_attr_translation_key = "activities"
def __init__(
self,
coordinator: BringDataUpdateCoordinator,
bring_list: BringList,
) -> None:
"""Initialize the entity."""
super().__init__(coordinator, bring_list)
self._attr_unique_id = (
f"{coordinator.config_entry.unique_id}_{self._list_uuid}_activities"
)
self._attr_event_types = [event.name.lower() for event in ActivityType]
def _async_handle_event(self) -> None:
"""Handle the activity event."""
bring_list = self.coordinator.data[self._list_uuid]
last_event_triggered = self.state
if bring_list.activity.timeline and (
last_event_triggered is None
or datetime.fromisoformat(last_event_triggered)
< bring_list.activity.timestamp
):
activity = bring_list.activity.timeline[0]
attributes = asdict(activity.content)
attributes["last_activity_by"] = next(
x.name
for x in bring_list.users.users
if x.publicUuid == activity.content.publicUserUuid
)
self._trigger_event(
activity.type.name.lower(),
attributes,
)
self.async_write_ha_state()
@property
def entity_picture(self) -> str | None:
"""Return the entity picture to use in the frontend, if any."""
return (
f"https://api.getbring.com/rest/v2/bringusers/profilepictures/{public_uuid}"
if (public_uuid := self.state_attributes.get("publicUserUuid"))
else super().entity_picture
)
async def async_added_to_hass(self) -> None:
"""Register callbacks with your device API/library."""
await super().async_added_to_hass()
self._async_handle_event()
def _handle_coordinator_update(self):
self._async_handle_event()
return super()._handle_coordinator_update()

View File

@ -1,5 +1,10 @@
{ {
"entity": { "entity": {
"event": {
"activity": {
"default": "mdi:bell"
}
},
"sensor": { "sensor": {
"urgent": { "urgent": {
"default": "mdi:run-fast" "default": "mdi:run-fast"

View File

@ -41,6 +41,20 @@
} }
}, },
"entity": { "entity": {
"event": {
"activities": {
"name": "Activities",
"state_attributes": {
"event_type": {
"state": {
"list_items_added": "Items added",
"list_items_changed": "Items changed",
"list_items_removed": "Items removed"
}
}
}
}
},
"sensor": { "sensor": {
"urgent": { "urgent": {
"name": "Urgent", "name": "Urgent",

View File

@ -5,10 +5,12 @@ from unittest.mock import AsyncMock, patch
import uuid import uuid
from bring_api import ( from bring_api import (
BringActivityResponse,
BringAuthResponse, BringAuthResponse,
BringItemsResponse, BringItemsResponse,
BringListResponse, BringListResponse,
BringUserSettingsResponse, BringUserSettingsResponse,
BringUsersResponse,
) )
import pytest import pytest
@ -60,6 +62,13 @@ def mock_bring_client() -> Generator[AsyncMock]:
client.get_all_user_settings.return_value = BringUserSettingsResponse.from_json( client.get_all_user_settings.return_value = BringUserSettingsResponse.from_json(
load_fixture("usersettings.json", DOMAIN) load_fixture("usersettings.json", DOMAIN)
) )
client.get_activity.return_value = BringActivityResponse.from_json(
load_fixture("activity.json", DOMAIN)
)
client.get_list_users.return_value = BringUsersResponse.from_json(
load_fixture("users.json", DOMAIN)
)
yield client yield client

View File

@ -0,0 +1,62 @@
{
"timeline": [
{
"type": "LIST_ITEMS_CHANGED",
"content": {
"uuid": "673594a9-f92d-4cb6-adf1-d2f7a83207a4",
"purchase": [
{
"uuid": "658a3770-1a03-4ee0-94a6-10362a642377",
"itemId": "Gurke",
"specification": "",
"attributes": []
}
],
"recently": [
{
"uuid": "1ed22d3d-f19b-4530-a518-19872da3fd3e",
"itemId": "Milch",
"specification": "",
"attributes": []
}
],
"sessionDate": "2025-01-01T03:09:33.036Z",
"publicUserUuid": "9a21fdfc-63a4-441a-afc1-ef3030605a9d"
}
},
{
"type": "LIST_ITEMS_ADDED",
"content": {
"uuid": "9a16635c-dea2-4e00-904a-c5034f9cfecf",
"items": [
{
"uuid": "66a633a2-ae09-47bf-8845-3c0198480544",
"itemId": "Joghurt",
"specification": "",
"attributes": []
}
],
"sessionDate": "2025-01-01T02:54:57.656Z",
"publicUserUuid": "73af455f-c158-4004-a5e0-79f4f8a6d4bd"
}
},
{
"type": "LIST_ITEMS_REMOVED",
"content": {
"uuid": "303dedf6-d4b2-4d25-a8cd-1c7967b84fcb",
"items": [
{
"uuid": "2ba8ddb6-01c6-4b0b-a89d-f3da6b291528",
"itemId": "Tofu",
"specification": "",
"attributes": []
}
],
"sessionDate": "2025-01-01T03:09:12.380Z",
"publicUserUuid": "7d5e9d08-877a-4c36-8740-a9bf74ec690a"
}
}
],
"timestamp": "2025-01-01T03:09:33.036Z",
"totalEvents": 3
}

View File

@ -0,0 +1,31 @@
{
"users": [
{
"publicUuid": "9a21fdfc-63a4-441a-afc1-ef3030605a9d",
"name": "Bring",
"email": "test-email",
"photoPath": "",
"pushEnabled": true,
"plusTryOut": false,
"country": "DE",
"language": "de"
},
{
"publicUuid": "73af455f-c158-4004-a5e0-79f4f8a6d4bd",
"name": "NAME",
"email": "EMAIL",
"photoPath": "",
"pushEnabled": true,
"plusTryOut": false,
"country": "US",
"language": "en"
},
{
"publicUuid": "7d5e9d08-877a-4c36-8740-a9bf74ec690a",
"pushEnabled": true,
"plusTryOut": false,
"country": "US",
"language": "en"
}
]
}

View File

@ -1,113 +1,407 @@
# serializer version: 1 # serializer version: 1
# name: test_diagnostics # name: test_diagnostics
dict({ dict({
'b4776778-7f6c-496e-951b-92a35d3db0dd': dict({ 'data': dict({
'content': dict({ 'b4776778-7f6c-496e-951b-92a35d3db0dd': dict({
'items': dict({ 'activity': dict({
'purchase': list([ 'timeline': list([
dict({ dict({
'attributes': list([ 'content': dict({
dict({ 'items': list([
'content': dict({ ]),
'convenient': True, 'publicUserUuid': '9a21fdfc-63a4-441a-afc1-ef3030605a9d',
'discounted': True, 'purchase': list([
'urgent': True, dict({
'attributes': list([
]),
'itemId': 'Gurke',
'specification': '',
'uuid': '658a3770-1a03-4ee0-94a6-10362a642377',
}), }),
'type': 'PURCHASE_CONDITIONS', ]),
}), 'recently': list([
]), dict({
'itemId': 'Paprika', 'attributes': list([
'specification': 'Rot', ]),
'uuid': 'b5d0790b-5f32-4d5c-91da-e29066f167de', 'itemId': 'Milch',
'specification': '',
'uuid': '1ed22d3d-f19b-4530-a518-19872da3fd3e',
}),
]),
'sessionDate': '2025-01-01T03:09:33.036000+00:00',
'uuid': '673594a9-f92d-4cb6-adf1-d2f7a83207a4',
}),
'type': 'LIST_ITEMS_CHANGED',
}), }),
dict({ dict({
'attributes': list([ 'content': dict({
dict({ 'items': list([
'content': dict({ dict({
'convenient': True, 'attributes': list([
'discounted': True, ]),
'urgent': True, 'itemId': 'Joghurt',
'specification': '',
'uuid': '66a633a2-ae09-47bf-8845-3c0198480544',
}), }),
'type': 'PURCHASE_CONDITIONS', ]),
}), 'publicUserUuid': '73af455f-c158-4004-a5e0-79f4f8a6d4bd',
]), 'purchase': list([
'itemId': 'Pouletbrüstli', ]),
'specification': 'Bio', 'recently': list([
'uuid': '72d370ab-d8ca-4e41-b956-91df94795b4e', ]),
'sessionDate': '2025-01-01T02:54:57.656000+00:00',
'uuid': '9a16635c-dea2-4e00-904a-c5034f9cfecf',
}),
'type': 'LIST_ITEMS_ADDED',
}),
dict({
'content': dict({
'items': list([
dict({
'attributes': list([
]),
'itemId': 'Tofu',
'specification': '',
'uuid': '2ba8ddb6-01c6-4b0b-a89d-f3da6b291528',
}),
]),
'publicUserUuid': '7d5e9d08-877a-4c36-8740-a9bf74ec690a',
'purchase': list([
]),
'recently': list([
]),
'sessionDate': '2025-01-01T03:09:12.380000+00:00',
'uuid': '303dedf6-d4b2-4d25-a8cd-1c7967b84fcb',
}),
'type': 'LIST_ITEMS_REMOVED',
}), }),
]), ]),
'recently': list([ 'timestamp': '2025-01-01T03:09:33.036000+00:00',
'totalEvents': 3,
}),
'content': dict({
'items': dict({
'purchase': list([
dict({
'attributes': list([
dict({
'content': dict({
'convenient': True,
'discounted': True,
'urgent': True,
}),
'type': 'PURCHASE_CONDITIONS',
}),
]),
'itemId': 'Paprika',
'specification': 'Rot',
'uuid': 'b5d0790b-5f32-4d5c-91da-e29066f167de',
}),
dict({
'attributes': list([
dict({
'content': dict({
'convenient': True,
'discounted': True,
'urgent': True,
}),
'type': 'PURCHASE_CONDITIONS',
}),
]),
'itemId': 'Pouletbrüstli',
'specification': 'Bio',
'uuid': '72d370ab-d8ca-4e41-b956-91df94795b4e',
}),
]),
'recently': list([
dict({
'attributes': list([
]),
'itemId': 'Ananas',
'specification': '',
'uuid': 'fc8db30a-647e-4e6c-9d71-3b85d6a2d954',
}),
]),
}),
'status': 'REGISTERED',
'uuid': 'b4776778-7f6c-496e-951b-92a35d3db0dd',
}),
'lst': dict({
'listUuid': 'b4776778-7f6c-496e-951b-92a35d3db0dd',
'name': 'Baumarkt',
'theme': 'ch.publisheria.bring.theme.home',
}),
'users': dict({
'users': list([
dict({ dict({
'attributes': list([ 'country': 'DE',
]), 'email': 'test-email',
'itemId': 'Ananas', 'language': 'de',
'specification': '', 'name': 'Bring',
'uuid': 'fc8db30a-647e-4e6c-9d71-3b85d6a2d954', 'photoPath': '',
'plusTryOut': False,
'publicUuid': '9a21fdfc-63a4-441a-afc1-ef3030605a9d',
'pushEnabled': True,
}),
dict({
'country': 'US',
'email': 'EMAIL',
'language': 'en',
'name': 'NAME',
'photoPath': '',
'plusTryOut': False,
'publicUuid': '73af455f-c158-4004-a5e0-79f4f8a6d4bd',
'pushEnabled': True,
}),
dict({
'country': 'US',
'email': None,
'language': 'en',
'name': None,
'photoPath': None,
'plusTryOut': False,
'publicUuid': '7d5e9d08-877a-4c36-8740-a9bf74ec690a',
'pushEnabled': True,
}), }),
]), ]),
}), }),
'status': 'REGISTERED',
'uuid': 'b4776778-7f6c-496e-951b-92a35d3db0dd',
}), }),
'lst': dict({ 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5': dict({
'listUuid': 'b4776778-7f6c-496e-951b-92a35d3db0dd', 'activity': dict({
'name': 'Baumarkt', 'timeline': list([
'theme': 'ch.publisheria.bring.theme.home', dict({
'content': dict({
'items': list([
]),
'publicUserUuid': '9a21fdfc-63a4-441a-afc1-ef3030605a9d',
'purchase': list([
dict({
'attributes': list([
]),
'itemId': 'Gurke',
'specification': '',
'uuid': '658a3770-1a03-4ee0-94a6-10362a642377',
}),
]),
'recently': list([
dict({
'attributes': list([
]),
'itemId': 'Milch',
'specification': '',
'uuid': '1ed22d3d-f19b-4530-a518-19872da3fd3e',
}),
]),
'sessionDate': '2025-01-01T03:09:33.036000+00:00',
'uuid': '673594a9-f92d-4cb6-adf1-d2f7a83207a4',
}),
'type': 'LIST_ITEMS_CHANGED',
}),
dict({
'content': dict({
'items': list([
dict({
'attributes': list([
]),
'itemId': 'Joghurt',
'specification': '',
'uuid': '66a633a2-ae09-47bf-8845-3c0198480544',
}),
]),
'publicUserUuid': '73af455f-c158-4004-a5e0-79f4f8a6d4bd',
'purchase': list([
]),
'recently': list([
]),
'sessionDate': '2025-01-01T02:54:57.656000+00:00',
'uuid': '9a16635c-dea2-4e00-904a-c5034f9cfecf',
}),
'type': 'LIST_ITEMS_ADDED',
}),
dict({
'content': dict({
'items': list([
dict({
'attributes': list([
]),
'itemId': 'Tofu',
'specification': '',
'uuid': '2ba8ddb6-01c6-4b0b-a89d-f3da6b291528',
}),
]),
'publicUserUuid': '7d5e9d08-877a-4c36-8740-a9bf74ec690a',
'purchase': list([
]),
'recently': list([
]),
'sessionDate': '2025-01-01T03:09:12.380000+00:00',
'uuid': '303dedf6-d4b2-4d25-a8cd-1c7967b84fcb',
}),
'type': 'LIST_ITEMS_REMOVED',
}),
]),
'timestamp': '2025-01-01T03:09:33.036000+00:00',
'totalEvents': 3,
}),
'content': dict({
'items': dict({
'purchase': list([
dict({
'attributes': list([
dict({
'content': dict({
'convenient': True,
'discounted': True,
'urgent': True,
}),
'type': 'PURCHASE_CONDITIONS',
}),
]),
'itemId': 'Paprika',
'specification': 'Rot',
'uuid': 'b5d0790b-5f32-4d5c-91da-e29066f167de',
}),
dict({
'attributes': list([
dict({
'content': dict({
'convenient': True,
'discounted': True,
'urgent': True,
}),
'type': 'PURCHASE_CONDITIONS',
}),
]),
'itemId': 'Pouletbrüstli',
'specification': 'Bio',
'uuid': '72d370ab-d8ca-4e41-b956-91df94795b4e',
}),
]),
'recently': list([
dict({
'attributes': list([
]),
'itemId': 'Ananas',
'specification': '',
'uuid': 'fc8db30a-647e-4e6c-9d71-3b85d6a2d954',
}),
]),
}),
'status': 'REGISTERED',
'uuid': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5',
}),
'lst': dict({
'listUuid': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5',
'name': 'Einkauf',
'theme': 'ch.publisheria.bring.theme.home',
}),
'users': dict({
'users': list([
dict({
'country': 'DE',
'email': 'test-email',
'language': 'de',
'name': 'Bring',
'photoPath': '',
'plusTryOut': False,
'publicUuid': '9a21fdfc-63a4-441a-afc1-ef3030605a9d',
'pushEnabled': True,
}),
dict({
'country': 'US',
'email': 'EMAIL',
'language': 'en',
'name': 'NAME',
'photoPath': '',
'plusTryOut': False,
'publicUuid': '73af455f-c158-4004-a5e0-79f4f8a6d4bd',
'pushEnabled': True,
}),
dict({
'country': 'US',
'email': None,
'language': 'en',
'name': None,
'photoPath': None,
'plusTryOut': False,
'publicUuid': '7d5e9d08-877a-4c36-8740-a9bf74ec690a',
'pushEnabled': True,
}),
]),
}),
}), }),
}), }),
'e542eef6-dba7-4c31-a52c-29e6ab9d83a5': dict({ 'lists': list([
'content': dict({ dict({
'items': dict({
'purchase': list([
dict({
'attributes': list([
dict({
'content': dict({
'convenient': True,
'discounted': True,
'urgent': True,
}),
'type': 'PURCHASE_CONDITIONS',
}),
]),
'itemId': 'Paprika',
'specification': 'Rot',
'uuid': 'b5d0790b-5f32-4d5c-91da-e29066f167de',
}),
dict({
'attributes': list([
dict({
'content': dict({
'convenient': True,
'discounted': True,
'urgent': True,
}),
'type': 'PURCHASE_CONDITIONS',
}),
]),
'itemId': 'Pouletbrüstli',
'specification': 'Bio',
'uuid': '72d370ab-d8ca-4e41-b956-91df94795b4e',
}),
]),
'recently': list([
dict({
'attributes': list([
]),
'itemId': 'Ananas',
'specification': '',
'uuid': 'fc8db30a-647e-4e6c-9d71-3b85d6a2d954',
}),
]),
}),
'status': 'REGISTERED',
'uuid': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5',
}),
'lst': dict({
'listUuid': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5', 'listUuid': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5',
'name': 'Einkauf', 'name': 'Einkauf',
'theme': 'ch.publisheria.bring.theme.home', 'theme': 'ch.publisheria.bring.theme.home',
}), }),
dict({
'listUuid': 'b4776778-7f6c-496e-951b-92a35d3db0dd',
'name': 'Baumarkt',
'theme': 'ch.publisheria.bring.theme.home',
}),
]),
'user_settings': dict({
'userlistsettings': list([
dict({
'listUuid': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5',
'usersettings': list([
dict({
'key': 'listSectionOrder',
'value': '["Früchte & Gemüse","Brot & Gebäck","Milch & Käse","Fleisch & Fisch","Zutaten & Gewürze","Fertig- & Tiefkühlprodukte","Getreideprodukte","Snacks & Süsswaren","Getränke & Tabak","Haushalt & Gesundheit","Pflege & Gesundheit","Tierbedarf","Baumarkt & Garten","Eigene Artikel"]',
}),
dict({
'key': 'listArticleLanguage',
'value': 'de-DE',
}),
]),
}),
dict({
'listUuid': 'b4776778-7f6c-496e-951b-92a35d3db0dd',
'usersettings': list([
dict({
'key': 'listSectionOrder',
'value': '["Früchte & Gemüse","Brot & Gebäck","Milch & Käse","Fleisch & Fisch","Zutaten & Gewürze","Fertig- & Tiefkühlprodukte","Getreideprodukte","Snacks & Süsswaren","Getränke & Tabak","Haushalt & Gesundheit","Pflege & Gesundheit","Tierbedarf","Baumarkt & Garten","Eigene Artikel"]',
}),
dict({
'key': 'listArticleLanguage',
'value': 'en-US',
}),
]),
}),
]),
'usersettings': list([
dict({
'key': 'autoPush',
'value': 'ON',
}),
dict({
'key': 'premiumHideOffersBadge',
'value': 'ON',
}),
dict({
'key': 'premiumHideSponsoredCategories',
'value': 'ON',
}),
dict({
'key': 'premiumHideInspirationsBadge',
'value': 'ON',
}),
dict({
'key': 'onboardClient',
'value': 'android',
}),
dict({
'key': 'premiumHideOffersOnMain',
'value': 'ON',
}),
dict({
'key': 'defaultListUUID',
'value': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5',
}),
]),
}), }),
}) })
# --- # ---

View File

@ -0,0 +1,167 @@
# serializer version: 1
# name: test_setup[event.baumarkt_activities-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'event_types': list([
'list_items_changed',
'list_items_added',
'list_items_removed',
]),
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'event',
'entity_category': None,
'entity_id': 'event.baumarkt_activities',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Activities',
'platform': 'bring',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'activities',
'unique_id': '00000000-00000000-00000000-00000000_b4776778-7f6c-496e-951b-92a35d3db0dd_activities',
'unit_of_measurement': None,
})
# ---
# name: test_setup[event.baumarkt_activities-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'entity_picture': 'https://api.getbring.com/rest/v2/bringusers/profilepictures/9a21fdfc-63a4-441a-afc1-ef3030605a9d',
'event_type': 'list_items_changed',
'event_types': list([
'list_items_changed',
'list_items_added',
'list_items_removed',
]),
'friendly_name': 'Baumarkt Activities',
'items': list([
]),
'last_activity_by': 'Bring',
'publicUserUuid': '9a21fdfc-63a4-441a-afc1-ef3030605a9d',
'purchase': list([
dict({
'attributes': list([
]),
'itemId': 'Gurke',
'specification': '',
'uuid': '658a3770-1a03-4ee0-94a6-10362a642377',
}),
]),
'recently': list([
dict({
'attributes': list([
]),
'itemId': 'Milch',
'specification': '',
'uuid': '1ed22d3d-f19b-4530-a518-19872da3fd3e',
}),
]),
'sessionDate': HAFakeDatetime(2025, 1, 1, 3, 9, 33, 36000, tzinfo=datetime.timezone.utc),
'uuid': '673594a9-f92d-4cb6-adf1-d2f7a83207a4',
}),
'context': <ANY>,
'entity_id': 'event.baumarkt_activities',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2025-01-01T03:30:00.000+00:00',
})
# ---
# name: test_setup[event.einkauf_activities-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'event_types': list([
'list_items_changed',
'list_items_added',
'list_items_removed',
]),
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'event',
'entity_category': None,
'entity_id': 'event.einkauf_activities',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Activities',
'platform': 'bring',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'activities',
'unique_id': '00000000-00000000-00000000-00000000_e542eef6-dba7-4c31-a52c-29e6ab9d83a5_activities',
'unit_of_measurement': None,
})
# ---
# name: test_setup[event.einkauf_activities-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'entity_picture': 'https://api.getbring.com/rest/v2/bringusers/profilepictures/9a21fdfc-63a4-441a-afc1-ef3030605a9d',
'event_type': 'list_items_changed',
'event_types': list([
'list_items_changed',
'list_items_added',
'list_items_removed',
]),
'friendly_name': 'Einkauf Activities',
'items': list([
]),
'last_activity_by': 'Bring',
'publicUserUuid': '9a21fdfc-63a4-441a-afc1-ef3030605a9d',
'purchase': list([
dict({
'attributes': list([
]),
'itemId': 'Gurke',
'specification': '',
'uuid': '658a3770-1a03-4ee0-94a6-10362a642377',
}),
]),
'recently': list([
dict({
'attributes': list([
]),
'itemId': 'Milch',
'specification': '',
'uuid': '1ed22d3d-f19b-4530-a518-19872da3fd3e',
}),
]),
'sessionDate': HAFakeDatetime(2025, 1, 1, 3, 9, 33, 36000, tzinfo=datetime.timezone.utc),
'uuid': '673594a9-f92d-4cb6-adf1-d2f7a83207a4',
}),
'context': <ANY>,
'entity_id': 'event.einkauf_activities',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2025-01-01T03:30:00.000+00:00',
})
# ---

View File

@ -0,0 +1,46 @@
"""Test for event platform of the Bring! integration."""
from collections.abc import Generator
from unittest.mock import patch
from freezegun.api import freeze_time
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from tests.common import MockConfigEntry, snapshot_platform
@pytest.fixture(autouse=True)
def event_only() -> Generator[None]:
"""Enable only the event platform."""
with patch(
"homeassistant.components.bring.PLATFORMS",
[Platform.EVENT],
):
yield
@pytest.mark.usefixtures("mock_bring_client")
@freeze_time("2025-01-01T03:30:00.000Z")
async def test_setup(
hass: HomeAssistant,
bring_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
entity_registry: er.EntityRegistry,
) -> None:
"""Snapshot test states of event platform."""
bring_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(bring_config_entry.entry_id)
await hass.async_block_till_done()
assert bring_config_entry.state is ConfigEntryState.LOADED
await snapshot_platform(
hass, entity_registry, snapshot, bring_config_entry.entry_id
)

View File

@ -1,6 +1,12 @@
"""Test for utility functions of the Bring! integration.""" """Test for utility functions of the Bring! integration."""
from bring_api import BringItemsResponse, BringListResponse, BringUserSettingsResponse from bring_api import (
BringActivityResponse,
BringItemsResponse,
BringListResponse,
BringUserSettingsResponse,
)
from bring_api.types import BringUsersResponse
import pytest import pytest
from homeassistant.components.bring.const import DOMAIN from homeassistant.components.bring.const import DOMAIN
@ -41,9 +47,10 @@ def test_sum_attributes(attribute: str, expected: int) -> None:
"""Test function sum_attributes.""" """Test function sum_attributes."""
items = BringItemsResponse.from_json(load_fixture("items.json", DOMAIN)) items = BringItemsResponse.from_json(load_fixture("items.json", DOMAIN))
lst = BringListResponse.from_json(load_fixture("lists.json", DOMAIN)) lst = BringListResponse.from_json(load_fixture("lists.json", DOMAIN))
activity = BringActivityResponse.from_json(load_fixture("activity.json", DOMAIN))
users = BringUsersResponse.from_json(load_fixture("users.json", DOMAIN))
result = sum_attributes( result = sum_attributes(
BringData(lst.lists[0], items), BringData(lst.lists[0], items, activity, users),
attribute, attribute,
) )