diff --git a/homeassistant/components/heos/services.py b/homeassistant/components/heos/services.py index f4d5961cc47..4dc3b247707 100644 --- a/homeassistant/components/heos/services.py +++ b/homeassistant/components/heos/services.py @@ -7,7 +7,7 @@ import voluptuous as vol from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant, ServiceCall -from homeassistant.exceptions import HomeAssistantError +from homeassistant.exceptions import HomeAssistantError, ServiceValidationError from homeassistant.helpers import config_validation as cv, issue_registry as ir from .const import ( @@ -46,7 +46,6 @@ def register(hass: HomeAssistant): def _get_controller(hass: HomeAssistant) -> Heos: """Get the HEOS controller instance.""" - _LOGGER.warning( "Actions 'heos.sign_in' and 'heos.sign_out' are deprecated and will be removed in the 2025.8.0 release" ) @@ -79,16 +78,25 @@ async def _sign_in_handler(service: ServiceCall) -> None: try: await controller.sign_in(username, password) except CommandAuthenticationError as err: - _LOGGER.error("Sign in failed: %s", err) + raise ServiceValidationError( + translation_domain=DOMAIN, translation_key="sign_in_auth_error" + ) from err except HeosError as err: - _LOGGER.error("Unable to sign in: %s", err) + raise HomeAssistantError( + translation_domain=DOMAIN, + translation_key="sign_in_error", + translation_placeholders={"error": str(err)}, + ) from err async def _sign_out_handler(service: ServiceCall) -> None: """Sign out of the HEOS account.""" - controller = _get_controller(service.hass) try: await controller.sign_out() except HeosError as err: - _LOGGER.error("Unable to sign out: %s", err) + raise HomeAssistantError( + translation_domain=DOMAIN, + translation_key="sign_out_error", + translation_placeholders={"error": str(err)}, + ) from err diff --git a/homeassistant/components/heos/strings.json b/homeassistant/components/heos/strings.json index 907804d10e1..4092d4360db 100644 --- a/homeassistant/components/heos/strings.json +++ b/homeassistant/components/heos/strings.json @@ -100,6 +100,15 @@ "integration_not_loaded": { "message": "The HEOS integration is not loaded" }, + "sign_in_auth_error": { + "message": "Failed to sign in: Invalid username and/or password" + }, + "sign_in_error": { + "message": "Unable to sign in: {error}" + }, + "sign_out_error": { + "message": "Unable to sign out: {error}" + }, "not_heos_media_player": { "message": "Entity {entity_id} is not a HEOS media player entity" }, diff --git a/tests/components/heos/test_services.py b/tests/components/heos/test_services.py index 8ca365497c6..8eda26d2b3d 100644 --- a/tests/components/heos/test_services.py +++ b/tests/components/heos/test_services.py @@ -11,7 +11,7 @@ from homeassistant.components.heos.const import ( SERVICE_SIGN_OUT, ) from homeassistant.core import HomeAssistant -from homeassistant.exceptions import HomeAssistantError +from homeassistant.exceptions import HomeAssistantError, ServiceValidationError from tests.common import MockConfigEntry @@ -34,10 +34,7 @@ async def test_sign_in( async def test_sign_in_failed( - hass: HomeAssistant, - config_entry: MockConfigEntry, - controller: Heos, - caplog: pytest.LogCaptureFixture, + hass: HomeAssistant, config_entry: MockConfigEntry, controller: Heos ) -> None: """Test sign-in service logs error when not connected.""" config_entry.add_to_hass(hass) @@ -47,22 +44,19 @@ async def test_sign_in_failed( "", "Invalid credentials", 6 ) - await hass.services.async_call( - DOMAIN, - SERVICE_SIGN_IN, - {ATTR_USERNAME: "test@test.com", ATTR_PASSWORD: "password"}, - blocking=True, - ) + with pytest.raises(ServiceValidationError): + await hass.services.async_call( + DOMAIN, + SERVICE_SIGN_IN, + {ATTR_USERNAME: "test@test.com", ATTR_PASSWORD: "password"}, + blocking=True, + ) controller.sign_in.assert_called_once_with("test@test.com", "password") - assert "Sign in failed: Invalid credentials (6)" in caplog.text async def test_sign_in_unknown_error( - hass: HomeAssistant, - config_entry: MockConfigEntry, - controller: Heos, - caplog: pytest.LogCaptureFixture, + hass: HomeAssistant, config_entry: MockConfigEntry, controller: Heos ) -> None: """Test sign-in service logs error for failure.""" config_entry.add_to_hass(hass) @@ -70,15 +64,15 @@ async def test_sign_in_unknown_error( controller.sign_in.side_effect = HeosError() - await hass.services.async_call( - DOMAIN, - SERVICE_SIGN_IN, - {ATTR_USERNAME: "test@test.com", ATTR_PASSWORD: "password"}, - blocking=True, - ) + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + DOMAIN, + SERVICE_SIGN_IN, + {ATTR_USERNAME: "test@test.com", ATTR_PASSWORD: "password"}, + blocking=True, + ) controller.sign_in.assert_called_once_with("test@test.com", "password") - assert "Unable to sign in" in caplog.text async def test_sign_in_not_loaded_raises( @@ -123,17 +117,14 @@ async def test_sign_out_not_loaded_raises( async def test_sign_out_unknown_error( - hass: HomeAssistant, - config_entry: MockConfigEntry, - controller: Heos, - caplog: pytest.LogCaptureFixture, + hass: HomeAssistant, config_entry: MockConfigEntry, controller: Heos ) -> None: """Test the sign-out service.""" config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) controller.sign_out.side_effect = HeosError() - await hass.services.async_call(DOMAIN, SERVICE_SIGN_OUT, {}, blocking=True) + with pytest.raises(HomeAssistantError): + await hass.services.async_call(DOMAIN, SERVICE_SIGN_OUT, {}, blocking=True) assert controller.sign_out.call_count == 1 - assert "Unable to sign out" in caplog.text