From 96ff6c0165db0d65ae040d4a6ee9d0a35ecf2673 Mon Sep 17 00:00:00 2001 From: elp3dr0 <64701822+elp3dr0@users.noreply.github.com> Date: Sun, 20 Sep 2026 16:14:10 +0100 Subject: [PATCH] Fix templated Mealie mealplan ID handling (#182615) --- homeassistant/components/mealie/services.py | 14 +++--- tests/components/mealie/test_services.py | 55 ++++++++++++++++----- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/mealie/services.py b/homeassistant/components/mealie/services.py index 74f7876bd1db..d81f4ad2d712 100644 --- a/homeassistant/components/mealie/services.py +++ b/homeassistant/components/mealie/services.py @@ -116,7 +116,7 @@ SERVICE_DELETE_MEALPLAN = "delete_mealplan" SERVICE_DELETE_MEALPLAN_SCHEMA = probatio.Schema( { probatio.Required(ATTR_CONFIG_ENTRY_ID): str, - probatio.Required(ATTR_MEALPLAN_ID): str, + probatio.Required(ATTR_MEALPLAN_ID): probatio.Any(str, int), } ) SERVICE_UPDATE_MEALPLAN = "update_mealplan" @@ -124,7 +124,7 @@ SERVICE_UPDATE_MEALPLAN_SCHEMA = probatio.Any( probatio.Schema( { probatio.Required(ATTR_CONFIG_ENTRY_ID): str, - probatio.Required(ATTR_MEALPLAN_ID): str, + probatio.Required(ATTR_MEALPLAN_ID): probatio.Any(str, int), probatio.Required(ATTR_DATE): cv.date, probatio.Required(ATTR_ENTRY_TYPE): probatio.In( [x.lower() for x in MealplanEntryType] @@ -135,7 +135,7 @@ SERVICE_UPDATE_MEALPLAN_SCHEMA = probatio.Any( probatio.Schema( { probatio.Required(ATTR_CONFIG_ENTRY_ID): str, - probatio.Required(ATTR_MEALPLAN_ID): str, + probatio.Required(ATTR_MEALPLAN_ID): probatio.Any(str, int), probatio.Required(ATTR_DATE): cv.date, probatio.Required(ATTR_ENTRY_TYPE): probatio.In( [x.lower() for x in MealplanEntryType] @@ -319,7 +319,7 @@ async def _async_delete_mealplan(call: ServiceCall) -> ServiceResponse: entry: MealieConfigEntry = service.async_get_config_entry( call.hass, DOMAIN, call.data[ATTR_CONFIG_ENTRY_ID] ) - mealplan_id = call.data[ATTR_MEALPLAN_ID] + mealplan_id = int(call.data[ATTR_MEALPLAN_ID]) client = entry.runtime_data.client try: @@ -335,7 +335,7 @@ async def _async_delete_mealplan(call: ServiceCall) -> ServiceResponse: raise ServiceValidationError( translation_domain=DOMAIN, translation_key="mealplan_not_found", - translation_placeholders={"mealplan_id": mealplan_id}, + translation_placeholders={"mealplan_id": str(mealplan_id)}, ) from err return None @@ -345,7 +345,7 @@ async def _async_update_mealplan(call: ServiceCall) -> ServiceResponse: entry: MealieConfigEntry = service.async_get_config_entry( call.hass, DOMAIN, call.data[ATTR_CONFIG_ENTRY_ID] ) - mealplan_id = call.data[ATTR_MEALPLAN_ID] + mealplan_id = int(call.data[ATTR_MEALPLAN_ID]) mealplan_date = call.data[ATTR_DATE] entry_type = MealplanEntryType(call.data[ATTR_ENTRY_TYPE]) client = entry.runtime_data.client @@ -370,7 +370,7 @@ async def _async_update_mealplan(call: ServiceCall) -> ServiceResponse: raise ServiceValidationError( translation_domain=DOMAIN, translation_key="mealplan_not_found", - translation_placeholders={"mealplan_id": mealplan_id}, + translation_placeholders={"mealplan_id": str(mealplan_id)}, ) from err if call.return_response: return {"mealplan": asdict(mealplan)} diff --git a/tests/components/mealie/test_services.py b/tests/components/mealie/test_services.py index e9478905584f..aa2f4e5139c3 100644 --- a/tests/components/mealie/test_services.py +++ b/tests/components/mealie/test_services.py @@ -413,11 +413,22 @@ async def test_service_delete_mealplan( SERVICE_DELETE_MEALPLAN, { ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id, - ATTR_MEALPLAN_ID: "mealplan_id", + ATTR_MEALPLAN_ID: "16", }, blocking=True, ) - mock_mealie_client.delete_mealplan.assert_called_with("mealplan_id") + mock_mealie_client.delete_mealplan.assert_called_with(16) + + await hass.services.async_call( + DOMAIN, + SERVICE_DELETE_MEALPLAN, + { + ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id, + ATTR_MEALPLAN_ID: 16, + }, + blocking=True, + ) + mock_mealie_client.delete_mealplan.assert_called_with(16) async def test_service_delete_mealplan_not_found( @@ -436,7 +447,7 @@ async def test_service_delete_mealplan_not_found( SERVICE_DELETE_MEALPLAN, { ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id, - ATTR_MEALPLAN_ID: "invalid_mealplan_id", + ATTR_MEALPLAN_ID: "16", }, blocking=True, ) @@ -484,7 +495,7 @@ async def test_service_update_mealplan( SERVICE_UPDATE_MEALPLAN, { ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id, - ATTR_MEALPLAN_ID: "mealplan_id", + ATTR_MEALPLAN_ID: "16", ATTR_DATE: "2023-10-21", ATTR_ENTRY_TYPE: "lunch", } @@ -494,7 +505,7 @@ async def test_service_update_mealplan( ) assert response == snapshot mock_mealie_client.update_mealplan.assert_called_with( - "mealplan_id", date(2023, 10, 21), MealplanEntryType.LUNCH, **kwargs + 16, date(2023, 10, 21), MealplanEntryType.LUNCH, **kwargs ) mock_mealie_client.update_mealplan.reset_mock() @@ -503,7 +514,7 @@ async def test_service_update_mealplan( SERVICE_UPDATE_MEALPLAN, { ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id, - ATTR_MEALPLAN_ID: "mealplan_id", + ATTR_MEALPLAN_ID: "16", ATTR_DATE: "2023-10-21", ATTR_ENTRY_TYPE: "lunch", } @@ -512,7 +523,25 @@ async def test_service_update_mealplan( return_response=False, ) mock_mealie_client.update_mealplan.assert_called_with( - "mealplan_id", date(2023, 10, 21), MealplanEntryType.LUNCH, **kwargs + 16, date(2023, 10, 21), MealplanEntryType.LUNCH, **kwargs + ) + + mock_mealie_client.update_mealplan.reset_mock() + await hass.services.async_call( + DOMAIN, + SERVICE_UPDATE_MEALPLAN, + { + ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id, + ATTR_MEALPLAN_ID: 16, + ATTR_DATE: "2023-10-21", + ATTR_ENTRY_TYPE: "lunch", + } + | payload, + blocking=True, + return_response=False, + ) + mock_mealie_client.update_mealplan.assert_called_with( + 16, date(2023, 10, 21), MealplanEntryType.LUNCH, **kwargs ) @@ -532,7 +561,7 @@ async def test_service_update_mealplan_invalid_entry_type( SERVICE_UPDATE_MEALPLAN, { ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id, - ATTR_MEALPLAN_ID: "mealplan_id", + ATTR_MEALPLAN_ID: "16", ATTR_DATE: "2023-10-21", ATTR_ENTRY_TYPE: "dessert", ATTR_NOTE_TITLE: "Note Title", @@ -559,7 +588,7 @@ async def test_service_update_mealplan_not_found( SERVICE_UPDATE_MEALPLAN, { ATTR_CONFIG_ENTRY_ID: mock_config_entry.entry_id, - ATTR_MEALPLAN_ID: "invalid_mealplan_id", + ATTR_MEALPLAN_ID: "16", ATTR_DATE: "2023-10-21", ATTR_ENTRY_TYPE: "lunch", ATTR_RECIPE_ID: "recipe_id", @@ -709,7 +738,7 @@ async def test_service_get_shopping_list_items_connection_error( ), ( SERVICE_DELETE_MEALPLAN, - {ATTR_MEALPLAN_ID: "mealplan_id"}, + {ATTR_MEALPLAN_ID: "16"}, "delete_mealplan", MealieConnectionError, HomeAssistantError, @@ -719,7 +748,7 @@ async def test_service_get_shopping_list_items_connection_error( ( SERVICE_UPDATE_MEALPLAN, { - ATTR_MEALPLAN_ID: "mealplan_id", + ATTR_MEALPLAN_ID: "16", ATTR_DATE: "2023-10-21", ATTR_ENTRY_TYPE: "lunch", ATTR_RECIPE_ID: "recipe_id", @@ -786,11 +815,11 @@ async def test_services_connection_error( }, True, ), - (SERVICE_DELETE_MEALPLAN, {ATTR_MEALPLAN_ID: "mealplan_id"}, False), + (SERVICE_DELETE_MEALPLAN, {ATTR_MEALPLAN_ID: "16"}, False), ( SERVICE_UPDATE_MEALPLAN, { - ATTR_MEALPLAN_ID: "mealplan_id", + ATTR_MEALPLAN_ID: "16", ATTR_DATE: "2023-10-21", ATTR_ENTRY_TYPE: "lunch", ATTR_RECIPE_ID: "recipe_id",