diff --git a/homeassistant/components/bring/config_flow.py b/homeassistant/components/bring/config_flow.py index b8ee9d1e6ae..bfb5a2cd50f 100644 --- a/homeassistant/components/bring/config_flow.py +++ b/homeassistant/components/bring/config_flow.py @@ -63,7 +63,8 @@ class BringConfigFlow(ConfigFlow, domain=DOMAIN): ): self._abort_if_unique_id_configured() return self.async_create_entry( - title=self.info.get("name") or user_input[CONF_EMAIL], data=user_input + title=self.info.name or user_input[CONF_EMAIL], + data=user_input, ) return self.async_show_form( diff --git a/homeassistant/components/bring/coordinator.py b/homeassistant/components/bring/coordinator.py index d02237e84eb..0511d285afc 100644 --- a/homeassistant/components/bring/coordinator.py +++ b/homeassistant/components/bring/coordinator.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import dataclass from datetime import timedelta import logging @@ -12,6 +13,7 @@ from bring_api import ( BringRequestException, ) from bring_api.types import BringItemsResponse, BringList, BringUserSettingsResponse +from mashumaro.mixins.orjson import DataClassORJSONMixin from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_EMAIL @@ -24,9 +26,13 @@ from .const import DOMAIN _LOGGER = logging.getLogger(__name__) -class BringData(BringList, BringItemsResponse): +@dataclass(frozen=True) +class BringData(DataClassORJSONMixin): """Coordinator data class.""" + lst: BringList + content: BringItemsResponse + class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]): """A Bring Data Update Coordinator.""" @@ -67,11 +73,11 @@ class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]): return self.data list_dict: dict[str, BringData] = {} - for lst in lists_response["lists"]: - if (ctx := set(self.async_contexts())) and lst["listUuid"] not in ctx: + for lst in lists_response.lists: + if (ctx := set(self.async_contexts())) and lst.listUuid not in ctx: continue try: - items = await self.bring.get_list(lst["listUuid"]) + items = await self.bring.get_list(lst.listUuid) except BringRequestException as e: raise UpdateFailed( "Unable to connect and retrieve data from bring" @@ -79,7 +85,7 @@ class BringDataUpdateCoordinator(DataUpdateCoordinator[dict[str, BringData]]): except BringParseException as e: raise UpdateFailed("Unable to parse response from bring") from e else: - list_dict[lst["listUuid"]] = BringData(**lst, **items) + list_dict[lst.listUuid] = BringData(lst, items) return list_dict diff --git a/homeassistant/components/bring/diagnostics.py b/homeassistant/components/bring/diagnostics.py index f4193a9993c..1dec8f3a5ed 100644 --- a/homeassistant/components/bring/diagnostics.py +++ b/homeassistant/components/bring/diagnostics.py @@ -2,15 +2,16 @@ from __future__ import annotations +from typing import Any + from homeassistant.core import HomeAssistant from . import BringConfigEntry -from .coordinator import BringData async def async_get_config_entry_diagnostics( hass: HomeAssistant, config_entry: BringConfigEntry -) -> dict[str, BringData]: +) -> dict[str, Any]: """Return diagnostics for a config entry.""" - return config_entry.runtime_data.data + return {k: v.to_dict() for k, v in config_entry.runtime_data.data.items()} diff --git a/homeassistant/components/bring/entity.py b/homeassistant/components/bring/entity.py index a1e0cb2edc0..74076d66df9 100644 --- a/homeassistant/components/bring/entity.py +++ b/homeassistant/components/bring/entity.py @@ -20,13 +20,13 @@ class BringBaseEntity(CoordinatorEntity[BringDataUpdateCoordinator]): bring_list: BringData, ) -> None: """Initialize the entity.""" - super().__init__(coordinator, bring_list["listUuid"]) + super().__init__(coordinator, bring_list.lst.listUuid) - self._list_uuid = bring_list["listUuid"] + self._list_uuid = bring_list.lst.listUuid self.device_info = DeviceInfo( entry_type=DeviceEntryType.SERVICE, - name=bring_list["name"], + name=bring_list.lst.name, identifiers={ (DOMAIN, f"{coordinator.config_entry.unique_id}_{self._list_uuid}") }, diff --git a/homeassistant/components/bring/manifest.json b/homeassistant/components/bring/manifest.json index 71fe733ccf5..ecd3e911078 100644 --- a/homeassistant/components/bring/manifest.json +++ b/homeassistant/components/bring/manifest.json @@ -7,5 +7,5 @@ "integration_type": "service", "iot_class": "cloud_polling", "loggers": ["bring_api"], - "requirements": ["bring-api==0.9.1"] + "requirements": ["bring-api==1.0.0"] } diff --git a/homeassistant/components/bring/sensor.py b/homeassistant/components/bring/sensor.py index bd33ce9bf88..02bd0e50788 100644 --- a/homeassistant/components/bring/sensor.py +++ b/homeassistant/components/bring/sensor.py @@ -65,7 +65,7 @@ SENSOR_DESCRIPTIONS: tuple[BringSensorEntityDescription, ...] = ( translation_key=BringSensor.LIST_LANGUAGE, value_fn=( lambda lst, settings: x.lower() - if (x := list_language(lst["listUuid"], settings)) + if (x := list_language(lst.lst.listUuid, settings)) else None ), entity_category=EntityCategory.DIAGNOSTIC, @@ -75,7 +75,7 @@ SENSOR_DESCRIPTIONS: tuple[BringSensorEntityDescription, ...] = ( BringSensorEntityDescription( key=BringSensor.LIST_ACCESS, translation_key=BringSensor.LIST_ACCESS, - value_fn=lambda lst, _: lst["status"].lower(), + value_fn=lambda lst, _: lst.content.status.value.lower(), entity_category=EntityCategory.DIAGNOSTIC, options=["registered", "shared", "invitation"], device_class=SensorDeviceClass.ENUM, diff --git a/homeassistant/components/bring/todo.py b/homeassistant/components/bring/todo.py index 75657e2fd64..7ab60084314 100644 --- a/homeassistant/components/bring/todo.py +++ b/homeassistant/components/bring/todo.py @@ -2,6 +2,7 @@ from __future__ import annotations +from itertools import chain from typing import TYPE_CHECKING import uuid @@ -59,7 +60,7 @@ async def async_setup_entry( SERVICE_PUSH_NOTIFICATION, { vol.Required(ATTR_NOTIFICATION_TYPE): vol.All( - vol.Upper, cv.enum(BringNotificationType) + vol.Upper, vol.Coerce(BringNotificationType) ), vol.Optional(ATTR_ITEM_NAME): cv.string, }, @@ -92,21 +93,21 @@ class BringTodoListEntity(BringBaseEntity, TodoListEntity): return [ *( TodoItem( - uid=item["uuid"], - summary=item["itemId"], - description=item["specification"] or "", + uid=item.uuid, + summary=item.itemId, + description=item.specification, status=TodoItemStatus.NEEDS_ACTION, ) - for item in self.bring_list["purchase"] + for item in self.bring_list.content.items.purchase ), *( TodoItem( - uid=item["uuid"], - summary=item["itemId"], - description=item["specification"] or "", + uid=item.uuid, + summary=item.itemId, + description=item.specification, status=TodoItemStatus.COMPLETED, ) - for item in self.bring_list["recently"] + for item in self.bring_list.content.items.recently ), ] @@ -119,7 +120,7 @@ class BringTodoListEntity(BringBaseEntity, TodoListEntity): """Add an item to the To-do list.""" try: await self.coordinator.bring.save_item( - self.bring_list["listUuid"], + self._list_uuid, item.summary or "", item.description or "", str(uuid.uuid4()), @@ -154,26 +155,25 @@ class BringTodoListEntity(BringBaseEntity, TodoListEntity): bring_list = self.bring_list - bring_purchase_item = next( - (i for i in bring_list["purchase"] if i["uuid"] == item.uid), + current_item = next( + ( + i + for i in chain( + bring_list.content.items.purchase, bring_list.content.items.recently + ) + if i.uuid == item.uid + ), None, ) - bring_recently_item = next( - (i for i in bring_list["recently"] if i["uuid"] == item.uid), - None, - ) - - current_item = bring_purchase_item or bring_recently_item - if TYPE_CHECKING: assert item.uid assert current_item - if item.summary == current_item["itemId"]: + if item.summary == current_item.itemId: try: await self.coordinator.bring.batch_update_list( - bring_list["listUuid"], + self._list_uuid, BringItem( itemId=item.summary or "", spec=item.description or "", @@ -192,10 +192,10 @@ class BringTodoListEntity(BringBaseEntity, TodoListEntity): else: try: await self.coordinator.bring.batch_update_list( - bring_list["listUuid"], + self._list_uuid, [ BringItem( - itemId=current_item["itemId"], + itemId=current_item.itemId, spec=item.description or "", uuid=item.uid, operation=BringItemOperation.REMOVE, @@ -225,7 +225,7 @@ class BringTodoListEntity(BringBaseEntity, TodoListEntity): try: await self.coordinator.bring.batch_update_list( - self.bring_list["listUuid"], + self._list_uuid, [ BringItem( itemId=uid, diff --git a/homeassistant/components/bring/util.py b/homeassistant/components/bring/util.py index b706156a3d3..9a075f7bb89 100644 --- a/homeassistant/components/bring/util.py +++ b/homeassistant/components/bring/util.py @@ -14,27 +14,25 @@ def list_language( """Get the lists language setting.""" try: list_settings = next( - filter( - lambda x: x["listUuid"] == list_uuid, - user_settings["userlistsettings"], - ) + filter(lambda x: x.listUuid == list_uuid, user_settings.userlistsettings) ) - return next( - filter( - lambda x: x["key"] == "listArticleLanguage", - list_settings["usersettings"], + return ( + next( + filter( + lambda x: x.key == "listArticleLanguage", list_settings.usersettings + ) ) - )["value"] + ).value - except (StopIteration, KeyError): + except StopIteration: return None def sum_attributes(bring_list: BringData, attribute: str) -> int: """Count items with given attribute set.""" return sum( - item["attributes"][0]["content"][attribute] - for item in bring_list["purchase"] - if len(item.get("attributes", [])) + getattr(item.attributes[0].content, attribute) + for item in bring_list.content.items.purchase + if item.attributes ) diff --git a/requirements_all.txt b/requirements_all.txt index 8e5081db52d..f154531e83b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -644,7 +644,7 @@ boto3==1.34.131 botocore==1.34.131 # homeassistant.components.bring -bring-api==0.9.1 +bring-api==1.0.0 # homeassistant.components.broadlink broadlink==0.19.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 4a28323c95e..9be1cd9dab5 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -564,7 +564,7 @@ boschshcpy==0.2.91 botocore==1.34.131 # homeassistant.components.bring -bring-api==0.9.1 +bring-api==1.0.0 # homeassistant.components.broadlink broadlink==0.19.0 diff --git a/tests/components/bring/conftest.py b/tests/components/bring/conftest.py index 7d1b787ff0b..2b2e9257097 100644 --- a/tests/components/bring/conftest.py +++ b/tests/components/bring/conftest.py @@ -1,17 +1,21 @@ """Common fixtures for the Bring! tests.""" from collections.abc import Generator -from typing import cast from unittest.mock import AsyncMock, patch import uuid -from bring_api.types import BringAuthResponse +from bring_api.types import ( + BringAuthResponse, + BringItemsResponse, + BringListResponse, + BringUserSettingsResponse, +) import pytest from homeassistant.components.bring.const import DOMAIN from homeassistant.const import CONF_EMAIL, CONF_PASSWORD -from tests.common import MockConfigEntry, load_json_object_fixture +from tests.common import MockConfigEntry, load_fixture EMAIL = "test-email" PASSWORD = "test-password" @@ -44,11 +48,17 @@ def mock_bring_client() -> Generator[AsyncMock]: client = mock_client.return_value client.uuid = UUID client.mail = EMAIL - client.login.return_value = cast(BringAuthResponse, {"name": "Bring"}) - client.load_lists.return_value = load_json_object_fixture("lists.json", DOMAIN) - client.get_list.return_value = load_json_object_fixture("items.json", DOMAIN) - client.get_all_user_settings.return_value = load_json_object_fixture( - "usersettings.json", DOMAIN + client.login.return_value = BringAuthResponse.from_json( + load_fixture("login.json", DOMAIN) + ) + client.load_lists.return_value = BringListResponse.from_json( + load_fixture("lists.json", DOMAIN) + ) + client.get_list.return_value = BringItemsResponse.from_json( + load_fixture("items.json", DOMAIN) + ) + client.get_all_user_settings.return_value = BringUserSettingsResponse.from_json( + load_fixture("usersettings.json", DOMAIN) ) yield client diff --git a/tests/components/bring/fixtures/items.json b/tests/components/bring/fixtures/items.json index e0b9006167b..eecdbaac8c7 100644 --- a/tests/components/bring/fixtures/items.json +++ b/tests/components/bring/fixtures/items.json @@ -1,44 +1,46 @@ { "uuid": "77a151f8-77c4-47a3-8295-c750a0e69d4f", "status": "REGISTERED", - "purchase": [ - { - "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", - "itemId": "Paprika", - "specification": "Rot", - "attributes": [ - { - "type": "PURCHASE_CONDITIONS", - "content": { - "urgent": true, - "convenient": true, - "discounted": true + "items": { + "purchase": [ + { + "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", + "itemId": "Paprika", + "specification": "Rot", + "attributes": [ + { + "type": "PURCHASE_CONDITIONS", + "content": { + "urgent": true, + "convenient": true, + "discounted": true + } } - } - ] - }, - { - "uuid": "72d370ab-d8ca-4e41-b956-91df94795b4e", - "itemId": "Pouletbrüstli", - "specification": "Bio", - "attributes": [ - { - "type": "PURCHASE_CONDITIONS", - "content": { - "urgent": true, - "convenient": true, - "discounted": true + ] + }, + { + "uuid": "72d370ab-d8ca-4e41-b956-91df94795b4e", + "itemId": "Pouletbrüstli", + "specification": "Bio", + "attributes": [ + { + "type": "PURCHASE_CONDITIONS", + "content": { + "urgent": true, + "convenient": true, + "discounted": true + } } - } - ] - } - ], - "recently": [ - { - "uuid": "fc8db30a-647e-4e6c-9d71-3b85d6a2d954", - "itemId": "Ananas", - "specification": "", - "attributes": [] - } - ] + ] + } + ], + "recently": [ + { + "uuid": "fc8db30a-647e-4e6c-9d71-3b85d6a2d954", + "itemId": "Ananas", + "specification": "", + "attributes": [] + } + ] + } } diff --git a/tests/components/bring/fixtures/items_invitation.json b/tests/components/bring/fixtures/items_invitation.json index 82ef623e439..be3671c359a 100644 --- a/tests/components/bring/fixtures/items_invitation.json +++ b/tests/components/bring/fixtures/items_invitation.json @@ -1,44 +1,46 @@ { "uuid": "77a151f8-77c4-47a3-8295-c750a0e69d4f", "status": "INVITATION", - "purchase": [ - { - "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", - "itemId": "Paprika", - "specification": "Rot", - "attributes": [ - { - "type": "PURCHASE_CONDITIONS", - "content": { - "urgent": true, - "convenient": true, - "discounted": true + "items": { + "purchase": [ + { + "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", + "itemId": "Paprika", + "specification": "Rot", + "attributes": [ + { + "type": "PURCHASE_CONDITIONS", + "content": { + "urgent": true, + "convenient": true, + "discounted": true + } } - } - ] - }, - { - "uuid": "72d370ab-d8ca-4e41-b956-91df94795b4e", - "itemId": "Pouletbrüstli", - "specification": "Bio", - "attributes": [ - { - "type": "PURCHASE_CONDITIONS", - "content": { - "urgent": true, - "convenient": true, - "discounted": true + ] + }, + { + "uuid": "72d370ab-d8ca-4e41-b956-91df94795b4e", + "itemId": "Pouletbrüstli", + "specification": "Bio", + "attributes": [ + { + "type": "PURCHASE_CONDITIONS", + "content": { + "urgent": true, + "convenient": true, + "discounted": true + } } - } - ] - } - ], - "recently": [ - { - "uuid": "fc8db30a-647e-4e6c-9d71-3b85d6a2d954", - "itemId": "Ananas", - "specification": "", - "attributes": [] - } - ] + ] + } + ], + "recently": [ + { + "uuid": "fc8db30a-647e-4e6c-9d71-3b85d6a2d954", + "itemId": "Ananas", + "specification": "", + "attributes": [] + } + ] + } } diff --git a/tests/components/bring/fixtures/items_shared.json b/tests/components/bring/fixtures/items_shared.json index 9ac999729d3..5e381d27ca8 100644 --- a/tests/components/bring/fixtures/items_shared.json +++ b/tests/components/bring/fixtures/items_shared.json @@ -1,44 +1,46 @@ { "uuid": "77a151f8-77c4-47a3-8295-c750a0e69d4f", "status": "SHARED", - "purchase": [ - { - "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", - "itemId": "Paprika", - "specification": "Rot", - "attributes": [ - { - "type": "PURCHASE_CONDITIONS", - "content": { - "urgent": true, - "convenient": true, - "discounted": true + "items": { + "purchase": [ + { + "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", + "itemId": "Paprika", + "specification": "Rot", + "attributes": [ + { + "type": "PURCHASE_CONDITIONS", + "content": { + "urgent": true, + "convenient": true, + "discounted": true + } } - } - ] - }, - { - "uuid": "72d370ab-d8ca-4e41-b956-91df94795b4e", - "itemId": "Pouletbrüstli", - "specification": "Bio", - "attributes": [ - { - "type": "PURCHASE_CONDITIONS", - "content": { - "urgent": true, - "convenient": true, - "discounted": true + ] + }, + { + "uuid": "72d370ab-d8ca-4e41-b956-91df94795b4e", + "itemId": "Pouletbrüstli", + "specification": "Bio", + "attributes": [ + { + "type": "PURCHASE_CONDITIONS", + "content": { + "urgent": true, + "convenient": true, + "discounted": true + } } - } - ] - } - ], - "recently": [ - { - "uuid": "fc8db30a-647e-4e6c-9d71-3b85d6a2d954", - "itemId": "Ananas", - "specification": "", - "attributes": [] - } - ] + ] + } + ], + "recently": [ + { + "uuid": "fc8db30a-647e-4e6c-9d71-3b85d6a2d954", + "itemId": "Ananas", + "specification": "", + "attributes": [] + } + ] + } } diff --git a/tests/components/bring/fixtures/login.json b/tests/components/bring/fixtures/login.json new file mode 100644 index 00000000000..62616471734 --- /dev/null +++ b/tests/components/bring/fixtures/login.json @@ -0,0 +1,12 @@ +{ + "uuid": "4d717571-174a-4bc1-ab24-929c7227ca43", + "publicUuid": "9a21fdfc-63a4-441a-afc1-ef3030605a9d", + "email": "test-email", + "name": "Bring", + "photoPath": "", + "bringListUUID": "e542eef6-dba7-4c31-a52c-29e6ab9d83a5", + "access_token": "ACCESS_TOKEN", + "refresh_token": "REFRESH_TOKEN", + "token_type": "Bearer", + "expires_in": 604799 +} diff --git a/tests/components/bring/snapshots/test_diagnostics.ambr b/tests/components/bring/snapshots/test_diagnostics.ambr index 6d830a12133..5955ded832a 100644 --- a/tests/components/bring/snapshots/test_diagnostics.ambr +++ b/tests/components/bring/snapshots/test_diagnostics.ambr @@ -2,100 +2,112 @@ # name: test_diagnostics dict({ 'b4776778-7f6c-496e-951b-92a35d3db0dd': dict({ - 'listUuid': 'b4776778-7f6c-496e-951b-92a35d3db0dd', - 'name': 'Baumarkt', - 'purchase': list([ - dict({ - 'attributes': list([ + 'content': dict({ + 'items': dict({ + 'purchase': list([ dict({ - 'content': dict({ - 'convenient': True, - 'discounted': True, - 'urgent': True, - }), - 'type': 'PURCHASE_CONDITIONS', + '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', }), ]), - 'itemId': 'Paprika', - 'specification': 'Rot', - 'uuid': 'b5d0790b-5f32-4d5c-91da-e29066f167de', - }), - dict({ - 'attributes': list([ + 'recently': list([ dict({ - 'content': dict({ - 'convenient': True, - 'discounted': True, - 'urgent': True, - }), - 'type': 'PURCHASE_CONDITIONS', + 'attributes': list([ + ]), + 'itemId': 'Ananas', + 'specification': '', + 'uuid': 'fc8db30a-647e-4e6c-9d71-3b85d6a2d954', }), ]), - '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', - 'theme': 'ch.publisheria.bring.theme.home', - 'uuid': '77a151f8-77c4-47a3-8295-c750a0e69d4f', + 'status': 'REGISTERED', + 'uuid': '77a151f8-77c4-47a3-8295-c750a0e69d4f', + }), + 'lst': dict({ + 'listUuid': 'b4776778-7f6c-496e-951b-92a35d3db0dd', + 'name': 'Baumarkt', + 'theme': 'ch.publisheria.bring.theme.home', + }), }), 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5': dict({ - 'listUuid': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5', - 'name': 'Einkauf', - 'purchase': list([ - dict({ - 'attributes': list([ + 'content': dict({ + 'items': dict({ + 'purchase': list([ dict({ - 'content': dict({ - 'convenient': True, - 'discounted': True, - 'urgent': True, - }), - 'type': 'PURCHASE_CONDITIONS', + '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', }), ]), - 'itemId': 'Paprika', - 'specification': 'Rot', - 'uuid': 'b5d0790b-5f32-4d5c-91da-e29066f167de', - }), - dict({ - 'attributes': list([ + 'recently': list([ dict({ - 'content': dict({ - 'convenient': True, - 'discounted': True, - 'urgent': True, - }), - 'type': 'PURCHASE_CONDITIONS', + 'attributes': list([ + ]), + 'itemId': 'Ananas', + 'specification': '', + 'uuid': 'fc8db30a-647e-4e6c-9d71-3b85d6a2d954', }), ]), - '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', - 'theme': 'ch.publisheria.bring.theme.home', - 'uuid': '77a151f8-77c4-47a3-8295-c750a0e69d4f', + 'status': 'REGISTERED', + 'uuid': '77a151f8-77c4-47a3-8295-c750a0e69d4f', + }), + 'lst': dict({ + 'listUuid': 'e542eef6-dba7-4c31-a52c-29e6ab9d83a5', + 'name': 'Einkauf', + 'theme': 'ch.publisheria.bring.theme.home', + }), }), }) # --- diff --git a/tests/components/bring/test_sensor.py b/tests/components/bring/test_sensor.py index 974818ccedf..442fea5a247 100644 --- a/tests/components/bring/test_sensor.py +++ b/tests/components/bring/test_sensor.py @@ -3,6 +3,7 @@ from collections.abc import Generator from unittest.mock import AsyncMock, patch +from bring_api import BringItemsResponse import pytest from syrupy.assertion import SnapshotAssertion @@ -12,7 +13,7 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er -from tests.common import MockConfigEntry, load_json_object_fixture, snapshot_platform +from tests.common import MockConfigEntry, load_fixture, snapshot_platform @pytest.fixture(autouse=True) @@ -62,10 +63,9 @@ async def test_list_access_states( ) -> None: """Snapshot test states of list access sensor.""" - mock_bring_client.get_list.return_value = load_json_object_fixture( - f"{fixture}.json", DOMAIN + mock_bring_client.get_list.return_value = BringItemsResponse.from_json( + load_fixture(f"{fixture}.json", DOMAIN) ) - bring_config_entry.add_to_hass(hass) await hass.config_entries.async_setup(bring_config_entry.entry_id) await hass.async_block_till_done() diff --git a/tests/components/bring/test_util.py b/tests/components/bring/test_util.py index 88379530362..3060f31c134 100644 --- a/tests/components/bring/test_util.py +++ b/tests/components/bring/test_util.py @@ -1,15 +1,13 @@ """Test for utility functions of the Bring! integration.""" -from typing import cast - -from bring_api import BringUserSettingsResponse +from bring_api import BringItemsResponse, BringListResponse, BringUserSettingsResponse import pytest from homeassistant.components.bring.const import DOMAIN from homeassistant.components.bring.coordinator import BringData from homeassistant.components.bring.util import list_language, sum_attributes -from tests.common import load_json_object_fixture +from tests.common import load_fixture @pytest.mark.parametrize( @@ -17,7 +15,7 @@ from tests.common import load_json_object_fixture [ ("e542eef6-dba7-4c31-a52c-29e6ab9d83a5", "de-DE"), ("b4776778-7f6c-496e-951b-92a35d3db0dd", "en-US"), - ("00000000-0000-0000-0000-00000000", None), + ("00000000-0000-0000-0000-000000000000", None), ], ) def test_list_language(list_uuid: str, expected: str | None) -> None: @@ -25,10 +23,7 @@ def test_list_language(list_uuid: str, expected: str | None) -> None: result = list_language( list_uuid, - cast( - BringUserSettingsResponse, - load_json_object_fixture("usersettings.json", DOMAIN), - ), + BringUserSettingsResponse.from_json(load_fixture("usersettings.json", DOMAIN)), ) assert result == expected @@ -44,12 +39,11 @@ def test_list_language(list_uuid: str, expected: str | None) -> None: ) def test_sum_attributes(attribute: str, expected: int) -> None: """Test function sum_attributes.""" + items = BringItemsResponse.from_json(load_fixture("items.json", DOMAIN)) + lst = BringListResponse.from_json(load_fixture("lists.json", DOMAIN)) result = sum_attributes( - cast( - BringData, - load_json_object_fixture("items.json", DOMAIN), - ), + BringData(lst.lists[0], items), attribute, )