"""Test for todo platform of the Bring! integration.""" from collections.abc import Generator import re from unittest.mock import AsyncMock, patch from bring_api import BringItemOperation, BringRequestException import pytest from syrupy.assertion import SnapshotAssertion from homeassistant.components.todo import ( ATTR_DESCRIPTION, ATTR_ITEM, ATTR_RENAME, DOMAIN as TODO_DOMAIN, TodoServices, ) from homeassistant.config_entries import ConfigEntryState from homeassistant.const import ATTR_ENTITY_ID, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import entity_registry as er from tests.common import MockConfigEntry, snapshot_platform @pytest.fixture(autouse=True) def todo_only() -> Generator[None]: """Enable only the todo platform.""" with patch( "homeassistant.components.bring.PLATFORMS", [Platform.TODO], ): yield @pytest.mark.usefixtures("mock_bring_client") async def test_todo( hass: HomeAssistant, bring_config_entry: MockConfigEntry, snapshot: SnapshotAssertion, entity_registry: er.EntityRegistry, ) -> None: """Snapshot test states of todo 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 ) @pytest.mark.usefixtures("mock_uuid") async def test_add_item( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, ) -> None: """Test add item to list.""" 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 hass.services.async_call( TODO_DOMAIN, TodoServices.ADD_ITEM, service_data={ATTR_ITEM: "Äpfel", ATTR_DESCRIPTION: "rot"}, target={ATTR_ENTITY_ID: "todo.einkauf"}, blocking=True, ) mock_bring_client.save_item.assert_called_once_with( "e542eef6-dba7-4c31-a52c-29e6ab9d83a5", "Äpfel", "rot", "b669ad23-606a-4652-b302-995d34b1cb1c", ) async def test_add_item_exception( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, ) -> None: """Test add item to list with exception.""" 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 mock_bring_client.save_item.side_effect = BringRequestException with pytest.raises( HomeAssistantError, match="Failed to save item Äpfel to Bring! list" ): await hass.services.async_call( TODO_DOMAIN, TodoServices.ADD_ITEM, service_data={ATTR_ITEM: "Äpfel", ATTR_DESCRIPTION: "rot"}, target={ATTR_ENTITY_ID: "todo.einkauf"}, blocking=True, ) @pytest.mark.usefixtures("mock_uuid") async def test_update_item( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, ) -> None: """Test update item.""" 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 hass.services.async_call( TODO_DOMAIN, TodoServices.UPDATE_ITEM, service_data={ ATTR_ITEM: "b5d0790b-5f32-4d5c-91da-e29066f167de", ATTR_RENAME: "Paprika", ATTR_DESCRIPTION: "Rot", }, target={ATTR_ENTITY_ID: "todo.einkauf"}, blocking=True, ) mock_bring_client.batch_update_list.assert_called_once_with( "e542eef6-dba7-4c31-a52c-29e6ab9d83a5", { "itemId": "Paprika", "spec": "Rot", "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", }, BringItemOperation.ADD, ) async def test_update_item_exception( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, ) -> None: """Test update item with exception.""" 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 mock_bring_client.batch_update_list.side_effect = BringRequestException with pytest.raises( HomeAssistantError, match="Failed to update item Paprika to Bring! list" ): await hass.services.async_call( TODO_DOMAIN, TodoServices.UPDATE_ITEM, service_data={ ATTR_ITEM: "b5d0790b-5f32-4d5c-91da-e29066f167de", ATTR_RENAME: "Paprika", ATTR_DESCRIPTION: "Rot", }, target={ATTR_ENTITY_ID: "todo.einkauf"}, blocking=True, ) @pytest.mark.usefixtures("mock_uuid") async def test_rename_item( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, ) -> None: """Test rename item.""" 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 hass.services.async_call( TODO_DOMAIN, TodoServices.UPDATE_ITEM, service_data={ ATTR_ITEM: "b5d0790b-5f32-4d5c-91da-e29066f167de", ATTR_RENAME: "Gurke", ATTR_DESCRIPTION: "", }, target={ATTR_ENTITY_ID: "todo.einkauf"}, blocking=True, ) mock_bring_client.batch_update_list.assert_called_once_with( "e542eef6-dba7-4c31-a52c-29e6ab9d83a5", [ { "itemId": "Paprika", "spec": "", "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", "operation": BringItemOperation.REMOVE, }, { "itemId": "Gurke", "spec": "", "uuid": "b669ad23-606a-4652-b302-995d34b1cb1c", "operation": BringItemOperation.ADD, }, ], ) async def test_rename_item_exception( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, ) -> None: """Test rename item with exception.""" 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 mock_bring_client.batch_update_list.side_effect = BringRequestException with pytest.raises( HomeAssistantError, match="Failed to rename item Gurke to Bring! list" ): await hass.services.async_call( TODO_DOMAIN, TodoServices.UPDATE_ITEM, service_data={ ATTR_ITEM: "b5d0790b-5f32-4d5c-91da-e29066f167de", ATTR_RENAME: "Gurke", ATTR_DESCRIPTION: "", }, target={ATTR_ENTITY_ID: "todo.einkauf"}, blocking=True, ) @pytest.mark.usefixtures("mock_uuid") async def test_delete_items( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, ) -> None: """Test delete item.""" 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 hass.services.async_call( TODO_DOMAIN, TodoServices.REMOVE_ITEM, service_data={ATTR_ITEM: "b5d0790b-5f32-4d5c-91da-e29066f167de"}, target={ATTR_ENTITY_ID: "todo.einkauf"}, blocking=True, ) mock_bring_client.batch_update_list.assert_called_once_with( "e542eef6-dba7-4c31-a52c-29e6ab9d83a5", [ { "itemId": "b5d0790b-5f32-4d5c-91da-e29066f167de", "spec": "", "uuid": "b5d0790b-5f32-4d5c-91da-e29066f167de", }, ], BringItemOperation.REMOVE, ) async def test_delete_items_exception( hass: HomeAssistant, bring_config_entry: MockConfigEntry, mock_bring_client: AsyncMock, ) -> None: """Test delete item.""" 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 mock_bring_client.batch_update_list.side_effect = BringRequestException with pytest.raises( HomeAssistantError, match=re.escape("Failed to delete 1 item(s) from Bring! list"), ): await hass.services.async_call( TODO_DOMAIN, TodoServices.REMOVE_ITEM, service_data={ATTR_ITEM: "b5d0790b-5f32-4d5c-91da-e29066f167de"}, target={ATTR_ENTITY_ID: "todo.einkauf"}, blocking=True, )