From 705a6dbf65da19f36f2edec653e00efea0d4e191 Mon Sep 17 00:00:00 2001 From: Jake Martin Date: Wed, 26 Aug 2026 16:50:14 +0000 Subject: [PATCH] Improve Monzo error handling and coverage --- homeassistant/components/monzo/coordinator.py | 8 +++-- homeassistant/components/monzo/icons.json | 7 ++++ homeassistant/components/monzo/strings.json | 6 ++++ tests/components/monzo/test_helpers.py | 25 ++++++++++++++ tests/components/monzo/test_sensor.py | 33 ++++++++++++++----- 5 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 tests/components/monzo/test_helpers.py diff --git a/homeassistant/components/monzo/coordinator.py b/homeassistant/components/monzo/coordinator.py index 8dd8a020533188..df633ca61bb723 100644 --- a/homeassistant/components/monzo/coordinator.py +++ b/homeassistant/components/monzo/coordinator.py @@ -62,6 +62,7 @@ async def _async_update_data(self) -> MonzoData: raise ConfigEntryAuthFailed from err except InvalidMonzoAPIResponseError as err: message = "Invalid Monzo API response." + translation_key = "invalid_api_response" if err.missing_key: _LOGGER.debug( "%s\nMissing key: %s\nResponse:\n%s", @@ -69,8 +70,11 @@ async def _async_update_data(self) -> MonzoData: err.missing_key, pformat(err.response), ) - message += " Enabling debug logging for details." - raise UpdateFailed(message) from err + translation_key = "invalid_api_response_with_details" + raise UpdateFailed( + translation_domain=DOMAIN, + translation_key=translation_key, + ) from err data = MonzoData( accounts={account["id"]: account for account in accounts}, diff --git a/homeassistant/components/monzo/icons.json b/homeassistant/components/monzo/icons.json index c0432b96dd7895..3d477b3d1cc764 100644 --- a/homeassistant/components/monzo/icons.json +++ b/homeassistant/components/monzo/icons.json @@ -1,4 +1,11 @@ { + "entity": { + "event": { + "transaction": { + "default": "mdi:bank-transfer" + } + } + }, "services": { "deposit_into_pot": { "service": "mdi:bank-transfer-in" diff --git a/homeassistant/components/monzo/strings.json b/homeassistant/components/monzo/strings.json index 41522799450894..72fc80297f9474 100644 --- a/homeassistant/components/monzo/strings.json +++ b/homeassistant/components/monzo/strings.json @@ -78,6 +78,12 @@ "invalid_account": { "message": "The selected device ({device_name}) is not an account belonging to this Monzo connection." }, + "invalid_api_response": { + "message": "The Monzo API returned an invalid response." + }, + "invalid_api_response_with_details": { + "message": "The Monzo API returned an invalid response. Enable debug logging for details." + }, "invalid_device": { "message": "The selected Monzo device could not be found." }, diff --git a/tests/components/monzo/test_helpers.py b/tests/components/monzo/test_helpers.py new file mode 100644 index 00000000000000..c5c462e04da662 --- /dev/null +++ b/tests/components/monzo/test_helpers.py @@ -0,0 +1,25 @@ +"""Tests for Monzo helpers.""" + +from homeassistant.components.monzo.helpers import ( + get_account_name, + get_authenticated_owner_name, +) + + +def test_authenticated_owner_name_without_user_id() -> None: + """Test an owner cannot be selected without an authenticated user ID.""" + assert get_authenticated_owner_name([], None) is None + + +def test_account_name_ignores_malformed_owner() -> None: + """Test malformed owner metadata does not affect a joint account name.""" + account = { + "name": "Joint Account", + "owners": [ + "invalid owner", + {"preferred_name": "Jake Martin"}, + {"preferred_name": "Jane Martin"}, + ], + } + + assert get_account_name(account) == "Joint Account — Jake Martin & Jane Martin" diff --git a/tests/components/monzo/test_sensor.py b/tests/components/monzo/test_sensor.py index 312aa6c3dd963c..baeffa8b435233 100644 --- a/tests/components/monzo/test_sensor.py +++ b/tests/components/monzo/test_sensor.py @@ -285,27 +285,44 @@ async def test_all_entities( ) +@pytest.mark.parametrize( + ("api_error", "expected_log_messages"), + [ + pytest.param( + InvalidMonzoAPIResponseError(), + ("The Monzo API returned an invalid response",), + id="invalid-response", + ), + pytest.param( + InvalidMonzoAPIResponseError({"acc_id": None}, "account_id"), + ( + "The Monzo API returned an invalid response. Enable debug logging for details", + "account_id", + "acc_id", + ), + id="missing-key", + ), + ], +) async def test_update_failed( hass: HomeAssistant, - snapshot: SnapshotAssertion, monzo: AsyncMock, polling_config_entry: MockConfigEntry, freezer: FrozenDateTimeFactory, caplog: pytest.LogCaptureFixture, + api_error: InvalidMonzoAPIResponseError, + expected_log_messages: tuple[str, ...], ) -> None: - """Test all entities.""" + """Test an invalid API response makes entities unavailable.""" await setup_integration(hass, polling_config_entry) - monzo.user_account.accounts.side_effect = InvalidMonzoAPIResponseError( - {"acc_id": None}, "account_id" - ) + monzo.user_account.accounts.side_effect = api_error freezer.tick(timedelta(minutes=10)) async_fire_time_changed(hass) await hass.async_block_till_done(wait_background_tasks=True) - assert "Invalid Monzo API response." in caplog.text - assert "account_id" in caplog.text - assert "acc_id" in caplog.text + for message in expected_log_messages: + assert message in caplog.text entity_id = await async_get_entity_id( hass, TEST_ACCOUNTS[0]["id"], ACCOUNT_SENSORS[0]