Fix missing validation and service definition in Mealie (#121578)

This commit is contained in:
Joost Lekkerkerker 2024-07-09 11:55:12 +02:00 committed by GitHub
parent cfabb778dd
commit a1fae0e0ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 65 additions and 9 deletions

View file

@ -1,5 +1,6 @@
{
"services": {
"get_mealplan": "mdi:food"
"get_mealplan": "mdi:food",
"get_recipe": "mdi:map"
}
}

View file

@ -4,7 +4,7 @@ from dataclasses import asdict
from datetime import date
from typing import cast
from aiomealie.exceptions import MealieNotFoundError
from aiomealie.exceptions import MealieConnectionError, MealieNotFoundError
import voluptuous as vol
from homeassistant.config_entries import ConfigEntryState
@ -14,7 +14,7 @@ from homeassistant.core import (
ServiceResponse,
SupportsResponse,
)
from homeassistant.exceptions import ServiceValidationError
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from .const import (
ATTR_CONFIG_ENTRY_ID,
@ -74,7 +74,13 @@ def setup_services(hass: HomeAssistant) -> None:
translation_key="end_date_before_start_date",
)
client = cast(MealieConfigEntry, entry).runtime_data.client
mealplans = await client.get_mealplans(start_date, end_date)
try:
mealplans = await client.get_mealplans(start_date, end_date)
except MealieConnectionError as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="connection_error",
) from err
return {"mealplan": [asdict(x) for x in mealplans.items]}
async def async_get_recipe(call: ServiceCall) -> ServiceResponse:
@ -84,6 +90,11 @@ def setup_services(hass: HomeAssistant) -> None:
client = entry.runtime_data.client
try:
recipe = await client.get_recipe(recipe_id)
except MealieConnectionError as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="connection_error",
) from err
except MealieNotFoundError as err:
raise ServiceValidationError(
translation_domain=DOMAIN,

View file

@ -11,3 +11,14 @@ get_mealplan:
end_date:
selector:
date:
get_recipe:
fields:
config_entry_id:
required: true
selector:
config_entry:
integration: mealie
recipe_id:
required: true
selector:
text:

View file

@ -46,6 +46,9 @@
"end_date_before_start_date": {
"message": "End date must be after start date."
},
"connection_error": {
"message": "Error connecting to Mealie instance."
},
"recipe_not_found": {
"message": "Recipe with ID or slug `{recipe_id}` not found."
}

View file

@ -3,7 +3,7 @@
from datetime import date
from unittest.mock import AsyncMock
from aiomealie.exceptions import MealieNotFoundError
from aiomealie.exceptions import MealieConnectionError, MealieNotFoundError
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy import SnapshotAssertion
@ -20,7 +20,7 @@ from homeassistant.components.mealie.services import (
SERVICE_GET_RECIPE,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from . import setup_integration
@ -136,18 +136,27 @@ async def test_service_recipe(
assert response == snapshot
async def test_service_recipe_not_found(
@pytest.mark.parametrize(
("exception", "raised_exception"),
[
(MealieNotFoundError, ServiceValidationError),
(MealieConnectionError, HomeAssistantError),
],
)
async def test_service_recipe_exceptions(
hass: HomeAssistant,
mock_mealie_client: AsyncMock,
mock_config_entry: MockConfigEntry,
exception: Exception,
raised_exception: type[Exception],
) -> None:
"""Test the get_recipe service."""
await setup_integration(hass, mock_config_entry)
mock_mealie_client.get_recipe.side_effect = MealieNotFoundError
mock_mealie_client.get_recipe.side_effect = exception
with pytest.raises(ServiceValidationError):
with pytest.raises(raised_exception):
await hass.services.async_call(
DOMAIN,
SERVICE_GET_RECIPE,
@ -160,6 +169,27 @@ async def test_service_recipe_not_found(
)
async def test_service_mealplan_connection_error(
hass: HomeAssistant,
mock_mealie_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test a connection error in the get_mealplans service."""
await setup_integration(hass, mock_config_entry)
mock_mealie_client.get_mealplans.side_effect = MealieConnectionError
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
DOMAIN,
SERVICE_GET_MEALPLAN,
{ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id},
blocking=True,
return_response=True,
)
async def test_service_mealplan_without_entry(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,