From 3953b6abe27ecde0e40290b71d076fc805873e5e Mon Sep 17 00:00:00 2001 From: Eric Severance Date: Wed, 30 Mar 2022 04:30:08 -0700 Subject: [PATCH] Fix error handling for expired html5 registration (#67676) --- homeassistant/components/html5/notify.py | 4 ++- tests/components/html5/test_notify.py | 43 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/html5/notify.py b/homeassistant/components/html5/notify.py index 0a6cc689292..a6ca769250f 100644 --- a/homeassistant/components/html5/notify.py +++ b/homeassistant/components/html5/notify.py @@ -533,7 +533,9 @@ class HTML5NotificationService(BaseNotificationService): if response.status_code == 410: _LOGGER.info("Notification channel has expired") reg = self.registrations.pop(target) - if not save_json(self.registrations_json_path, self.registrations): + try: + save_json(self.registrations_json_path, self.registrations) + except HomeAssistantError: self.registrations[target] = reg _LOGGER.error("Error saving registration") else: diff --git a/tests/components/html5/test_notify.py b/tests/components/html5/test_notify.py index 116b4437d61..1614555c493 100644 --- a/tests/components/html5/test_notify.py +++ b/tests/components/html5/test_notify.py @@ -527,3 +527,46 @@ async def test_send_fcm_without_targets(hass, hass_client): assert mock_wp.mock_calls[0][1][0] == SUBSCRIPTION_5["subscription"] # Third mock_call checks the status_code of the response. assert mock_wp.mock_calls[2][0] == "().send().status_code.__eq__" + + +async def test_send_fcm_expired(hass, hass_client): + """Test that the FCM target is removed when expired.""" + registrations = {"device": SUBSCRIPTION_5} + await mock_client(hass, hass_client, registrations) + + with ( + patch("homeassistant.components.html5.notify.WebPusher") as mock_wp, + patch("homeassistant.components.html5.notify.save_json"), + ): + mock_wp().send().status_code = 410 + await hass.services.async_call( + "notify", + "notify", + {"message": "Hello", "target": ["device"], "data": {"icon": "beer.png"}}, + blocking=True, + ) + # "device" should be removed when expired. + assert "device" not in registrations + + +async def test_send_fcm_expired_save_fails(hass, hass_client): + """Test that the FCM target remains after expiry if save_json fails.""" + registrations = {"device": SUBSCRIPTION_5} + await mock_client(hass, hass_client, registrations) + + with ( + patch("homeassistant.components.html5.notify.WebPusher") as mock_wp, + patch( + "homeassistant.components.html5.notify.save_json", + side_effect=HomeAssistantError(), + ), + ): + mock_wp().send().status_code = 410 + await hass.services.async_call( + "notify", + "notify", + {"message": "Hello", "target": ["device"], "data": {"icon": "beer.png"}}, + blocking=True, + ) + # "device" should still exist if save fails. + assert "device" in registrations