core/tests/components/ourgroceries/test_todo.py

244 lines
6.9 KiB
Python
Raw Normal View History

"""Unit tests for the OurGroceries todo platform."""
from asyncio import TimeoutError as AsyncIOTimeoutError
from unittest.mock import AsyncMock
from aiohttp import ClientError
from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant.components.ourgroceries.coordinator import SCAN_INTERVAL
from homeassistant.components.todo import DOMAIN as TODO_DOMAIN
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_component import async_update_entity
from . import items_to_shopping_list
from tests.common import async_fire_time_changed
@pytest.mark.parametrize(
("items", "expected_state"),
[
([], "0"),
([{"id": "12345", "name": "Soda"}], "1"),
([{"id": "12345", "name": "Soda", "crossedOffAt": 1699107501}], "0"),
(
[
{"id": "12345", "name": "Soda"},
{"id": "54321", "name": "Milk"},
],
"2",
),
],
)
async def test_todo_item_state(
hass: HomeAssistant,
setup_integration: None,
expected_state: str,
) -> None:
"""Test for a shopping list entity state."""
state = hass.states.get("todo.test_list")
assert state
assert state.state == expected_state
async def test_add_todo_list_item(
hass: HomeAssistant,
setup_integration: None,
ourgroceries: AsyncMock,
) -> None:
"""Test for adding an item."""
state = hass.states.get("todo.test_list")
assert state
assert state.state == "0"
ourgroceries.add_item_to_list = AsyncMock()
# Fake API response when state is refreshed after create
ourgroceries.get_list_items.return_value = items_to_shopping_list(
[{"id": "12345", "name": "Soda"}]
)
await hass.services.async_call(
TODO_DOMAIN,
"add_item",
{"item": "Soda"},
target={"entity_id": "todo.test_list"},
blocking=True,
)
args = ourgroceries.add_item_to_list.call_args
assert args
assert args.args == ("test_list", "Soda")
assert args.kwargs.get("auto_category") is True
# Verify state is refreshed
state = hass.states.get("todo.test_list")
assert state
assert state.state == "1"
@pytest.mark.parametrize(("items"), [[{"id": "12345", "name": "Soda"}]])
async def test_update_todo_item_status(
hass: HomeAssistant,
setup_integration: None,
ourgroceries: AsyncMock,
) -> None:
"""Test for updating the completion status of an item."""
state = hass.states.get("todo.test_list")
assert state
assert state.state == "1"
ourgroceries.toggle_item_crossed_off = AsyncMock()
# Fake API response when state is refreshed after crossing off
ourgroceries.get_list_items.return_value = items_to_shopping_list(
[{"id": "12345", "name": "Soda", "crossedOffAt": 1699107501}]
)
await hass.services.async_call(
TODO_DOMAIN,
"update_item",
{"item": "12345", "status": "completed"},
target={"entity_id": "todo.test_list"},
blocking=True,
)
assert ourgroceries.toggle_item_crossed_off.called
args = ourgroceries.toggle_item_crossed_off.call_args
assert args
assert args.args == ("test_list", "12345")
assert args.kwargs.get("cross_off") is True
# Verify state is refreshed
state = hass.states.get("todo.test_list")
assert state
assert state.state == "0"
# Fake API response when state is refreshed after reopen
ourgroceries.get_list_items.return_value = items_to_shopping_list(
[{"id": "12345", "name": "Soda"}]
)
await hass.services.async_call(
TODO_DOMAIN,
"update_item",
{"item": "12345", "status": "needs_action"},
target={"entity_id": "todo.test_list"},
blocking=True,
)
assert ourgroceries.toggle_item_crossed_off.called
args = ourgroceries.toggle_item_crossed_off.call_args
assert args
assert args.args == ("test_list", "12345")
assert args.kwargs.get("cross_off") is False
# Verify state is refreshed
state = hass.states.get("todo.test_list")
assert state
assert state.state == "1"
@pytest.mark.parametrize(
("items"), [[{"id": "12345", "name": "Soda", "categoryId": "test_category"}]]
)
async def test_update_todo_item_summary(
hass: HomeAssistant,
setup_integration: None,
ourgroceries: AsyncMock,
) -> None:
"""Test for updating an item summary."""
state = hass.states.get("todo.test_list")
assert state
assert state.state == "1"
ourgroceries.change_item_on_list = AsyncMock()
# Fake API response when state is refreshed update
ourgroceries.get_list_items.return_value = items_to_shopping_list(
[{"id": "12345", "name": "Milk"}]
)
await hass.services.async_call(
TODO_DOMAIN,
"update_item",
{"item": "12345", "rename": "Milk"},
target={"entity_id": "todo.test_list"},
blocking=True,
)
assert ourgroceries.change_item_on_list
args = ourgroceries.change_item_on_list.call_args
assert args.args == ("test_list", "12345", "test_category", "Milk")
@pytest.mark.parametrize(
("items"),
[
[
{"id": "12345", "name": "Soda"},
{"id": "54321", "name": "Milk"},
]
],
)
async def test_remove_todo_item(
hass: HomeAssistant,
setup_integration: None,
ourgroceries: AsyncMock,
) -> None:
"""Test for removing an item."""
state = hass.states.get("todo.test_list")
assert state
assert state.state == "2"
ourgroceries.remove_item_from_list = AsyncMock()
# Fake API response when state is refreshed after remove
ourgroceries.get_list_items.return_value = items_to_shopping_list([])
await hass.services.async_call(
TODO_DOMAIN,
"remove_item",
{"item": ["12345", "54321"]},
target={"entity_id": "todo.test_list"},
blocking=True,
)
assert ourgroceries.remove_item_from_list.call_count == 2
args = ourgroceries.remove_item_from_list.call_args_list
assert args[0].args == ("test_list", "12345")
assert args[1].args == ("test_list", "54321")
await async_update_entity(hass, "todo.test_list")
state = hass.states.get("todo.test_list")
assert state
assert state.state == "0"
@pytest.mark.parametrize(
("exception"),
[
(ClientError),
(AsyncIOTimeoutError),
],
)
async def test_coordinator_error(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
setup_integration: None,
ourgroceries: AsyncMock,
exception: Exception,
) -> None:
"""Test error on coordinator update."""
state = hass.states.get("todo.test_list")
assert state.state == "0"
ourgroceries.get_list_items.side_effect = exception
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("todo.test_list")
assert state.state == STATE_UNAVAILABLE