Add remember the milk entity tests (#138991)

* Add remember the milk entity tests

* Fix docstring
pull/138999/head
Martin Hjelmare 2025-02-21 16:45:00 +01:00 committed by GitHub
parent 059a6dddbe
commit 26c60880e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 331 additions and 8 deletions

View File

@ -60,20 +60,21 @@ class RememberTheMilkEntity(Entity):
result = self._rtm_api.rtm.timelines.create()
timeline = result.timeline.value
if hass_id is None or rtm_id is None:
if rtm_id is None:
result = self._rtm_api.rtm.tasks.add(
timeline=timeline, name=task_name, parse="1"
)
_LOGGER.debug(
"Created new task '%s' in account %s", task_name, self.name
)
self._rtm_config.set_rtm_id(
self._name,
hass_id,
result.list.id,
result.list.taskseries.id,
result.list.taskseries.task.id,
)
if hass_id is not None:
self._rtm_config.set_rtm_id(
self._name,
hass_id,
result.list.id,
result.list.taskseries.id,
result.list.taskseries.task.id,
)
else:
self._rtm_api.rtm.tasks.setName(
name=task_name,

View File

@ -0,0 +1,40 @@
"""Provide common pytest fixtures."""
from collections.abc import AsyncGenerator, Generator
from unittest.mock import MagicMock, patch
import pytest
from homeassistant.core import HomeAssistant
from .const import TOKEN
@pytest.fixture(name="client")
def client_fixture() -> Generator[MagicMock]:
"""Create a mock client."""
with patch("homeassistant.components.remember_the_milk.entity.Rtm") as client_class:
client = client_class.return_value
client.token_valid.return_value = True
timelines = MagicMock()
timelines.timeline.value = "1234"
client.rtm.timelines.create.return_value = timelines
add_response = MagicMock()
add_response.list.id = "1"
add_response.list.taskseries.id = "2"
add_response.list.taskseries.task.id = "3"
client.rtm.tasks.add.return_value = add_response
yield client
@pytest.fixture
async def storage(hass: HomeAssistant, client) -> AsyncGenerator[MagicMock]:
"""Mock the config storage."""
with patch(
"homeassistant.components.remember_the_milk.RememberTheMilkConfiguration"
) as storage_class:
storage = storage_class.return_value
storage.get_token.return_value = TOKEN
storage.get_rtm_id.return_value = None
yield storage

View File

@ -0,0 +1,282 @@
"""Test the Remember The Milk entity."""
from typing import Any
from unittest.mock import MagicMock, call
import pytest
from rtmapi import RtmRequestFailedException
from homeassistant.components.remember_the_milk import DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .const import PROFILE
CONFIG = {
"name": f"{PROFILE}",
"api_key": "test-api-key",
"shared_secret": "test-shared-secret",
}
@pytest.mark.parametrize(
("valid_token", "entity_state"), [(True, "ok"), (False, "API token invalid")]
)
async def test_entity_state(
hass: HomeAssistant,
client: MagicMock,
storage: MagicMock,
valid_token: bool,
entity_state: str,
) -> None:
"""Test the entity state."""
client.token_valid.return_value = valid_token
assert await async_setup_component(hass, DOMAIN, {DOMAIN: CONFIG})
entity_id = f"{DOMAIN}.{PROFILE}"
state = hass.states.get(entity_id)
assert state
assert state.state == entity_state
@pytest.mark.parametrize(
(
"get_rtm_id_return_value",
"service",
"service_data",
"get_rtm_id_call_count",
"get_rtm_id_call_args",
"timelines_call_count",
"api_method",
"api_method_call_count",
"api_method_call_args",
"storage_method",
"storage_method_call_count",
"storage_method_call_args",
),
[
(
("1", "2", "3"),
f"{PROFILE}_create_task",
{"name": "Test 1"},
0,
None,
1,
"rtm.tasks.add",
1,
call(
timeline="1234",
name="Test 1",
parse="1",
),
"set_rtm_id",
0,
None,
),
(
None,
f"{PROFILE}_create_task",
{"name": "Test 1", "id": "test_1"},
1,
call(PROFILE, "test_1"),
1,
"rtm.tasks.add",
1,
call(
timeline="1234",
name="Test 1",
parse="1",
),
"set_rtm_id",
1,
call(PROFILE, "test_1", "1", "2", "3"),
),
(
("1", "2", "3"),
f"{PROFILE}_create_task",
{"name": "Test 1", "id": "test_1"},
1,
call(PROFILE, "test_1"),
1,
"rtm.tasks.setName",
1,
call(
name="Test 1",
list_id="1",
taskseries_id="2",
task_id="3",
timeline="1234",
),
"set_rtm_id",
0,
None,
),
(
("1", "2", "3"),
f"{PROFILE}_complete_task",
{"id": "test_1"},
1,
call(PROFILE, "test_1"),
1,
"rtm.tasks.complete",
1,
call(
list_id="1",
taskseries_id="2",
task_id="3",
timeline="1234",
),
"delete_rtm_id",
1,
call(PROFILE, "test_1"),
),
],
)
async def test_services(
hass: HomeAssistant,
client: MagicMock,
storage: MagicMock,
get_rtm_id_return_value: Any,
service: str,
service_data: dict[str, Any],
get_rtm_id_call_count: int,
get_rtm_id_call_args: tuple[tuple, dict] | None,
timelines_call_count: int,
api_method: str,
api_method_call_count: int,
api_method_call_args: tuple[tuple, dict],
storage_method: str,
storage_method_call_count: int,
storage_method_call_args: tuple[tuple, dict] | None,
) -> None:
"""Test create and complete task service."""
storage.get_rtm_id.return_value = get_rtm_id_return_value
assert await async_setup_component(hass, DOMAIN, {DOMAIN: CONFIG})
await hass.services.async_call(DOMAIN, service, service_data, blocking=True)
assert storage.get_rtm_id.call_count == get_rtm_id_call_count
assert storage.get_rtm_id.call_args == get_rtm_id_call_args
assert client.rtm.timelines.create.call_count == timelines_call_count
client_method = client
for name in api_method.split("."):
client_method = getattr(client_method, name)
assert client_method.call_count == api_method_call_count
assert client_method.call_args == api_method_call_args
storage_method_attribute = getattr(storage, storage_method)
assert storage_method_attribute.call_count == storage_method_call_count
assert storage_method_attribute.call_args == storage_method_call_args
@pytest.mark.parametrize(
(
"get_rtm_id_return_value",
"service",
"service_data",
"method",
"exception",
"error_message",
),
[
(
("1", "2", "3"),
f"{PROFILE}_create_task",
{"name": "Test 1"},
"rtm.timelines.create",
RtmRequestFailedException("rtm.timelines.create", "400", "Bad request"),
"Request rtm.timelines.create failed. Status: 400, reason: Bad request.",
),
(
("1", "2", "3"),
f"{PROFILE}_create_task",
{"name": "Test 1"},
"rtm.tasks.add",
RtmRequestFailedException("rtm.tasks.add", "400", "Bad request"),
"Request rtm.tasks.add failed. Status: 400, reason: Bad request.",
),
(
None,
f"{PROFILE}_create_task",
{"name": "Test 1", "id": "test_1"},
"rtm.timelines.create",
RtmRequestFailedException("rtm.timelines.create", "400", "Bad request"),
"Request rtm.timelines.create failed. Status: 400, reason: Bad request.",
),
(
None,
f"{PROFILE}_create_task",
{"name": "Test 1", "id": "test_1"},
"rtm.tasks.add",
RtmRequestFailedException("rtm.tasks.add", "400", "Bad request"),
"Request rtm.tasks.add failed. Status: 400, reason: Bad request.",
),
(
("1", "2", "3"),
f"{PROFILE}_create_task",
{"name": "Test 1", "id": "test_1"},
"rtm.timelines.create",
RtmRequestFailedException("rtm.timelines.create", "400", "Bad request"),
"Request rtm.timelines.create failed. Status: 400, reason: Bad request.",
),
(
("1", "2", "3"),
f"{PROFILE}_create_task",
{"name": "Test 1", "id": "test_1"},
"rtm.tasks.setName",
RtmRequestFailedException("rtm.tasks.setName", "400", "Bad request"),
"Request rtm.tasks.setName failed. Status: 400, reason: Bad request.",
),
(
None,
f"{PROFILE}_complete_task",
{"id": "test_1"},
"rtm.timelines.create",
None,
(
f"Could not find task with ID test_1 in account {PROFILE}. "
"So task could not be closed"
),
),
(
("1", "2", "3"),
f"{PROFILE}_complete_task",
{"id": "test_1"},
"rtm.timelines.create",
RtmRequestFailedException("rtm.timelines.create", "400", "Bad request"),
"Request rtm.timelines.create failed. Status: 400, reason: Bad request.",
),
(
("1", "2", "3"),
f"{PROFILE}_complete_task",
{"id": "test_1"},
"rtm.tasks.complete",
RtmRequestFailedException("rtm.tasks.complete", "400", "Bad request"),
"Request rtm.tasks.complete failed. Status: 400, reason: Bad request.",
),
],
)
async def test_services_errors(
hass: HomeAssistant,
client: MagicMock,
storage: MagicMock,
caplog: pytest.LogCaptureFixture,
get_rtm_id_return_value: Any,
service: str,
service_data: dict[str, Any],
method: str,
exception: Exception,
error_message: str,
) -> None:
"""Test create and complete task service errors."""
assert await async_setup_component(hass, DOMAIN, {DOMAIN: CONFIG})
storage.get_rtm_id.return_value = get_rtm_id_return_value
client_method = client
for name in method.split("."):
client_method = getattr(client_method, name)
client_method.side_effect = exception
await hass.services.async_call(DOMAIN, service, service_data, blocking=True)
assert error_message in caplog.text