mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
Improve BMW translations (#133236)
This commit is contained in:
parent
ebc8ca8419
commit
8953ac1357
@ -16,7 +16,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BMWConfigEntry
|
||||
from . import DOMAIN as BMW_DOMAIN, BMWConfigEntry
|
||||
from .entity import BMWBaseEntity
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -55,7 +55,6 @@ BUTTON_TYPES: tuple[BMWButtonEntityDescription, ...] = (
|
||||
BMWButtonEntityDescription(
|
||||
key="deactivate_air_conditioning",
|
||||
translation_key="deactivate_air_conditioning",
|
||||
name="Deactivate air conditioning",
|
||||
remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_air_conditioning_stop(),
|
||||
is_available=lambda vehicle: vehicle.is_remote_climate_stop_enabled,
|
||||
),
|
||||
@ -111,6 +110,10 @@ class BMWButton(BMWBaseEntity, ButtonEntity):
|
||||
try:
|
||||
await self.entity_description.remote_function(self.vehicle)
|
||||
except MyBMWAPIError as ex:
|
||||
raise HomeAssistantError(ex) from ex
|
||||
raise HomeAssistantError(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="remote_service_error",
|
||||
translation_placeholders={"exception": str(ex)},
|
||||
) from ex
|
||||
|
||||
self.coordinator.async_update_listeners()
|
||||
|
@ -22,7 +22,13 @@ from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
from homeassistant.util.ssl import get_default_context
|
||||
|
||||
from .const import CONF_GCID, CONF_READ_ONLY, CONF_REFRESH_TOKEN, DOMAIN, SCAN_INTERVALS
|
||||
from .const import (
|
||||
CONF_GCID,
|
||||
CONF_READ_ONLY,
|
||||
CONF_REFRESH_TOKEN,
|
||||
DOMAIN as BMW_DOMAIN,
|
||||
SCAN_INTERVALS,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -57,7 +63,7 @@ class BMWDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=f"{DOMAIN}-{config_entry.data[CONF_USERNAME]}",
|
||||
name=f"{BMW_DOMAIN}-{config_entry.data[CONF_USERNAME]}",
|
||||
update_interval=timedelta(
|
||||
seconds=SCAN_INTERVALS[config_entry.data[CONF_REGION]]
|
||||
),
|
||||
@ -75,18 +81,29 @@ class BMWDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
||||
except MyBMWCaptchaMissingError as err:
|
||||
# If a captcha is required (user/password login flow), always trigger the reauth flow
|
||||
raise ConfigEntryAuthFailed(
|
||||
translation_domain=DOMAIN,
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="missing_captcha",
|
||||
) from err
|
||||
except MyBMWAuthError as err:
|
||||
# Allow one retry interval before raising AuthFailed to avoid flaky API issues
|
||||
if self.last_update_success:
|
||||
raise UpdateFailed(err) from err
|
||||
raise UpdateFailed(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="update_failed",
|
||||
translation_placeholders={"exception": str(err)},
|
||||
) from err
|
||||
# Clear refresh token and trigger reauth if previous update failed as well
|
||||
self._update_config_entry_refresh_token(None)
|
||||
raise ConfigEntryAuthFailed(err) from err
|
||||
raise ConfigEntryAuthFailed(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="invalid_auth",
|
||||
) from err
|
||||
except (MyBMWAPIError, RequestError) as err:
|
||||
raise UpdateFailed(err) from err
|
||||
raise UpdateFailed(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="update_failed",
|
||||
translation_placeholders={"exception": str(err)},
|
||||
) from err
|
||||
|
||||
if self.account.refresh_token != old_refresh_token:
|
||||
self._update_config_entry_refresh_token(self.account.refresh_token)
|
||||
|
@ -49,7 +49,7 @@ class BMWDeviceTracker(BMWBaseEntity, TrackerEntity):
|
||||
|
||||
_attr_force_update = False
|
||||
_attr_translation_key = "car"
|
||||
_attr_icon = "mdi:car"
|
||||
_attr_name = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -58,9 +58,7 @@ class BMWDeviceTracker(BMWBaseEntity, TrackerEntity):
|
||||
) -> None:
|
||||
"""Initialize the Tracker."""
|
||||
super().__init__(coordinator, vehicle)
|
||||
|
||||
self._attr_unique_id = vehicle.vin
|
||||
self._attr_name = None
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
|
@ -14,7 +14,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BMWConfigEntry
|
||||
from . import DOMAIN as BMW_DOMAIN, BMWConfigEntry
|
||||
from .coordinator import BMWDataUpdateCoordinator
|
||||
from .entity import BMWBaseEntity
|
||||
|
||||
@ -70,7 +70,11 @@ class BMWLock(BMWBaseEntity, LockEntity):
|
||||
# Set the state to unknown if the command fails
|
||||
self._attr_is_locked = None
|
||||
self.async_write_ha_state()
|
||||
raise HomeAssistantError(ex) from ex
|
||||
raise HomeAssistantError(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="remote_service_error",
|
||||
translation_placeholders={"exception": str(ex)},
|
||||
) from ex
|
||||
finally:
|
||||
# Always update the listeners to get the latest state
|
||||
self.coordinator.async_update_listeners()
|
||||
@ -90,7 +94,11 @@ class BMWLock(BMWBaseEntity, LockEntity):
|
||||
# Set the state to unknown if the command fails
|
||||
self._attr_is_locked = None
|
||||
self.async_write_ha_state()
|
||||
raise HomeAssistantError(ex) from ex
|
||||
raise HomeAssistantError(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="remote_service_error",
|
||||
translation_placeholders={"exception": str(ex)},
|
||||
) from ex
|
||||
finally:
|
||||
# Always update the listeners to get the latest state
|
||||
self.coordinator.async_update_listeners()
|
||||
|
@ -20,7 +20,7 @@ from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from . import DOMAIN, BMWConfigEntry
|
||||
from . import DOMAIN as BMW_DOMAIN, BMWConfigEntry
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
@ -92,7 +92,7 @@ class BMWNotificationService(BaseNotificationService):
|
||||
|
||||
except (vol.Invalid, TypeError, ValueError) as ex:
|
||||
raise ServiceValidationError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="invalid_poi",
|
||||
translation_placeholders={
|
||||
"poi_exception": str(ex),
|
||||
@ -106,4 +106,8 @@ class BMWNotificationService(BaseNotificationService):
|
||||
try:
|
||||
await vehicle.remote_services.trigger_send_poi(poi)
|
||||
except MyBMWAPIError as ex:
|
||||
raise HomeAssistantError(ex) from ex
|
||||
raise HomeAssistantError(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="remote_service_error",
|
||||
translation_placeholders={"exception": str(ex)},
|
||||
) from ex
|
||||
|
@ -18,7 +18,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BMWConfigEntry
|
||||
from . import DOMAIN as BMW_DOMAIN, BMWConfigEntry
|
||||
from .coordinator import BMWDataUpdateCoordinator
|
||||
from .entity import BMWBaseEntity
|
||||
|
||||
@ -109,6 +109,10 @@ class BMWNumber(BMWBaseEntity, NumberEntity):
|
||||
try:
|
||||
await self.entity_description.remote_service(self.vehicle, value)
|
||||
except MyBMWAPIError as ex:
|
||||
raise HomeAssistantError(ex) from ex
|
||||
raise HomeAssistantError(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="remote_service_error",
|
||||
translation_placeholders={"exception": str(ex)},
|
||||
) from ex
|
||||
|
||||
self.coordinator.async_update_listeners()
|
||||
|
@ -15,7 +15,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BMWConfigEntry
|
||||
from . import DOMAIN as BMW_DOMAIN, BMWConfigEntry
|
||||
from .coordinator import BMWDataUpdateCoordinator
|
||||
from .entity import BMWBaseEntity
|
||||
|
||||
@ -123,6 +123,10 @@ class BMWSelect(BMWBaseEntity, SelectEntity):
|
||||
try:
|
||||
await self.entity_description.remote_service(self.vehicle, option)
|
||||
except MyBMWAPIError as ex:
|
||||
raise HomeAssistantError(ex) from ex
|
||||
raise HomeAssistantError(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="remote_service_error",
|
||||
translation_placeholders={"exception": str(ex)},
|
||||
) from ex
|
||||
|
||||
self.coordinator.async_update_listeners()
|
||||
|
@ -2,11 +2,16 @@
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "Enter your MyBMW/MINI Connected credentials.",
|
||||
"description": "Connect to your MyBMW/MINI Connected account to retrieve vehicle data.",
|
||||
"data": {
|
||||
"username": "[%key:common::config_flow::data::username%]",
|
||||
"password": "[%key:common::config_flow::data::password%]",
|
||||
"region": "ConnectedDrive Region"
|
||||
},
|
||||
"data_description": {
|
||||
"username": "The email address of your MyBMW/MINI Connected account.",
|
||||
"password": "The password of your MyBMW/MINI Connected account.",
|
||||
"region": "The region of your MyBMW/MINI Connected account."
|
||||
}
|
||||
},
|
||||
"captcha": {
|
||||
@ -23,6 +28,9 @@
|
||||
"description": "Update your MyBMW/MINI Connected password for account `{username}` in region `{region}`.",
|
||||
"data": {
|
||||
"password": "[%key:common::config_flow::data::password%]"
|
||||
},
|
||||
"data_description": {
|
||||
"password": "[%key:component::bmw_connected_drive::config::step::user::data_description::password%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -41,7 +49,10 @@
|
||||
"step": {
|
||||
"account_options": {
|
||||
"data": {
|
||||
"read_only": "Read-only (only sensors and notify, no execution of services, no lock)"
|
||||
"read_only": "Read-only mode"
|
||||
},
|
||||
"data_description": {
|
||||
"read_only": "Only retrieve values and send POI data, but don't offer any services that can change the vehicle state."
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,6 +94,9 @@
|
||||
"activate_air_conditioning": {
|
||||
"name": "Activate air conditioning"
|
||||
},
|
||||
"deactivate_air_conditioning": {
|
||||
"name": "Deactivate air conditioning"
|
||||
},
|
||||
"find_vehicle": {
|
||||
"name": "Find vehicle"
|
||||
}
|
||||
@ -220,6 +234,15 @@
|
||||
},
|
||||
"missing_captcha": {
|
||||
"message": "Login requires captcha validation"
|
||||
},
|
||||
"invalid_auth": {
|
||||
"message": "[%key:common::config_flow::error::invalid_auth%]"
|
||||
},
|
||||
"remote_service_error": {
|
||||
"message": "Error executing remote service on vehicle. {exception}"
|
||||
},
|
||||
"update_failed": {
|
||||
"message": "Error updating vehicle data. {exception}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BMWConfigEntry
|
||||
from . import DOMAIN as BMW_DOMAIN, BMWConfigEntry
|
||||
from .coordinator import BMWDataUpdateCoordinator
|
||||
from .entity import BMWBaseEntity
|
||||
|
||||
@ -111,8 +111,11 @@ class BMWSwitch(BMWBaseEntity, SwitchEntity):
|
||||
try:
|
||||
await self.entity_description.remote_service_on(self.vehicle)
|
||||
except MyBMWAPIError as ex:
|
||||
raise HomeAssistantError(ex) from ex
|
||||
|
||||
raise HomeAssistantError(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="remote_service_error",
|
||||
translation_placeholders={"exception": str(ex)},
|
||||
) from ex
|
||||
self.coordinator.async_update_listeners()
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
@ -120,6 +123,9 @@ class BMWSwitch(BMWBaseEntity, SwitchEntity):
|
||||
try:
|
||||
await self.entity_description.remote_service_off(self.vehicle)
|
||||
except MyBMWAPIError as ex:
|
||||
raise HomeAssistantError(ex) from ex
|
||||
|
||||
raise HomeAssistantError(
|
||||
translation_domain=BMW_DOMAIN,
|
||||
translation_key="remote_service_error",
|
||||
translation_placeholders={"exception": str(ex)},
|
||||
) from ex
|
||||
self.coordinator.async_update_listeners()
|
||||
|
@ -48,6 +48,11 @@ FIXTURE_CONFIG_ENTRY = {
|
||||
"unique_id": f"{FIXTURE_USER_INPUT[CONF_REGION]}-{FIXTURE_USER_INPUT[CONF_USERNAME]}",
|
||||
}
|
||||
|
||||
REMOTE_SERVICE_EXC_REASON = "HTTPStatusError: 502 Bad Gateway"
|
||||
REMOTE_SERVICE_EXC_TRANSLATION = (
|
||||
"Error executing remote service on vehicle. HTTPStatusError: 502 Bad Gateway"
|
||||
)
|
||||
|
||||
|
||||
async def setup_mocked_integration(hass: HomeAssistant) -> MockConfigEntry:
|
||||
"""Mock a fully setup config entry and all components based on fixtures."""
|
||||
|
@ -13,7 +13,11 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import check_remote_service_call, setup_mocked_integration
|
||||
from . import (
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
check_remote_service_call,
|
||||
setup_mocked_integration,
|
||||
)
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
@ -81,11 +85,13 @@ async def test_service_call_fail(
|
||||
monkeypatch.setattr(
|
||||
RemoteServices,
|
||||
"trigger_remote_service",
|
||||
AsyncMock(side_effect=MyBMWRemoteServiceError),
|
||||
AsyncMock(
|
||||
side_effect=MyBMWRemoteServiceError("HTTPStatusError: 502 Bad Gateway")
|
||||
),
|
||||
)
|
||||
|
||||
# Test
|
||||
with pytest.raises(HomeAssistantError):
|
||||
with pytest.raises(HomeAssistantError, match=REMOTE_SERVICE_EXC_TRANSLATION):
|
||||
await hass.services.async_call(
|
||||
"button",
|
||||
"press",
|
||||
|
@ -16,7 +16,12 @@ from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import check_remote_service_call, setup_mocked_integration
|
||||
from . import (
|
||||
REMOTE_SERVICE_EXC_REASON,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
check_remote_service_call,
|
||||
setup_mocked_integration,
|
||||
)
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
from tests.components.recorder.common import async_wait_recording_done
|
||||
@ -118,11 +123,11 @@ async def test_service_call_fail(
|
||||
monkeypatch.setattr(
|
||||
RemoteServices,
|
||||
"trigger_remote_service",
|
||||
AsyncMock(side_effect=MyBMWRemoteServiceError),
|
||||
AsyncMock(side_effect=MyBMWRemoteServiceError(REMOTE_SERVICE_EXC_REASON)),
|
||||
)
|
||||
|
||||
# Test
|
||||
with pytest.raises(HomeAssistantError):
|
||||
with pytest.raises(HomeAssistantError, match=REMOTE_SERVICE_EXC_TRANSLATION):
|
||||
await hass.services.async_call(
|
||||
"lock",
|
||||
service,
|
||||
|
@ -11,7 +11,11 @@ import respx
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
|
||||
from . import check_remote_service_call, setup_mocked_integration
|
||||
from . import (
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
check_remote_service_call,
|
||||
setup_mocked_integration,
|
||||
)
|
||||
|
||||
|
||||
async def test_legacy_notify_service_simple(
|
||||
@ -68,21 +72,21 @@ async def test_legacy_notify_service_simple(
|
||||
{
|
||||
"latitude": POI_DATA.get("lat"),
|
||||
},
|
||||
"Invalid data for point of interest: required key not provided @ data['longitude']",
|
||||
r"Invalid data for point of interest: required key not provided @ data\['longitude'\]",
|
||||
),
|
||||
(
|
||||
{
|
||||
"latitude": POI_DATA.get("lat"),
|
||||
"longitude": "text",
|
||||
},
|
||||
"Invalid data for point of interest: invalid longitude for dictionary value @ data['longitude']",
|
||||
r"Invalid data for point of interest: invalid longitude for dictionary value @ data\['longitude'\]",
|
||||
),
|
||||
(
|
||||
{
|
||||
"latitude": POI_DATA.get("lat"),
|
||||
"longitude": 9999,
|
||||
},
|
||||
"Invalid data for point of interest: invalid longitude for dictionary value @ data['longitude']",
|
||||
r"Invalid data for point of interest: invalid longitude for dictionary value @ data\['longitude'\]",
|
||||
),
|
||||
],
|
||||
)
|
||||
@ -96,7 +100,7 @@ async def test_service_call_invalid_input(
|
||||
# Setup component
|
||||
assert await setup_mocked_integration(hass)
|
||||
|
||||
with pytest.raises(ServiceValidationError) as exc:
|
||||
with pytest.raises(ServiceValidationError, match=exc_translation):
|
||||
await hass.services.async_call(
|
||||
"notify",
|
||||
"bmw_connected_drive_ix_xdrive50",
|
||||
@ -106,7 +110,6 @@ async def test_service_call_invalid_input(
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert str(exc.value) == exc_translation
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("bmw_fixture")
|
||||
@ -132,11 +135,11 @@ async def test_service_call_fail(
|
||||
monkeypatch.setattr(
|
||||
RemoteServices,
|
||||
"trigger_remote_service",
|
||||
AsyncMock(side_effect=raised),
|
||||
AsyncMock(side_effect=raised("HTTPStatusError: 502 Bad Gateway")),
|
||||
)
|
||||
|
||||
# Test
|
||||
with pytest.raises(expected):
|
||||
with pytest.raises(expected, match=REMOTE_SERVICE_EXC_TRANSLATION):
|
||||
await hass.services.async_call(
|
||||
"notify",
|
||||
"bmw_connected_drive_ix_xdrive50",
|
||||
|
@ -13,7 +13,12 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import check_remote_service_call, setup_mocked_integration
|
||||
from . import (
|
||||
REMOTE_SERVICE_EXC_REASON,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
check_remote_service_call,
|
||||
setup_mocked_integration,
|
||||
)
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
@ -89,7 +94,10 @@ async def test_service_call_invalid_input(
|
||||
old_value = hass.states.get(entity_id).state
|
||||
|
||||
# Test
|
||||
with pytest.raises(ValueError):
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match="Target SoC must be an integer between 20 and 100 that is a multiple of 5.",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
"number",
|
||||
"set_value",
|
||||
@ -102,17 +110,32 @@ async def test_service_call_invalid_input(
|
||||
|
||||
@pytest.mark.usefixtures("bmw_fixture")
|
||||
@pytest.mark.parametrize(
|
||||
("raised", "expected"),
|
||||
("raised", "expected", "exc_translation"),
|
||||
[
|
||||
(MyBMWRemoteServiceError, HomeAssistantError),
|
||||
(MyBMWAPIError, HomeAssistantError),
|
||||
(ValueError, ValueError),
|
||||
(
|
||||
MyBMWRemoteServiceError(REMOTE_SERVICE_EXC_REASON),
|
||||
HomeAssistantError,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
),
|
||||
(
|
||||
MyBMWAPIError(REMOTE_SERVICE_EXC_REASON),
|
||||
HomeAssistantError,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
),
|
||||
(
|
||||
ValueError(
|
||||
"Target SoC must be an integer between 20 and 100 that is a multiple of 5."
|
||||
),
|
||||
ValueError,
|
||||
"Target SoC must be an integer between 20 and 100 that is a multiple of 5.",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_service_call_fail(
|
||||
hass: HomeAssistant,
|
||||
raised: Exception,
|
||||
expected: Exception,
|
||||
exc_translation: str,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""Test exception handling."""
|
||||
@ -130,7 +153,7 @@ async def test_service_call_fail(
|
||||
)
|
||||
|
||||
# Test
|
||||
with pytest.raises(expected):
|
||||
with pytest.raises(expected, match=exc_translation):
|
||||
await hass.services.async_call(
|
||||
"number",
|
||||
"set_value",
|
||||
|
@ -16,7 +16,12 @@ from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.translation import async_get_translations
|
||||
|
||||
from . import check_remote_service_call, setup_mocked_integration
|
||||
from . import (
|
||||
REMOTE_SERVICE_EXC_REASON,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
check_remote_service_call,
|
||||
setup_mocked_integration,
|
||||
)
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
@ -105,7 +110,10 @@ async def test_service_call_invalid_input(
|
||||
old_value = hass.states.get(entity_id).state
|
||||
|
||||
# Test
|
||||
with pytest.raises(ServiceValidationError):
|
||||
with pytest.raises(
|
||||
ServiceValidationError,
|
||||
match=f"Option {value} is not valid for entity {entity_id}",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
"select",
|
||||
"select_option",
|
||||
@ -118,17 +126,32 @@ async def test_service_call_invalid_input(
|
||||
|
||||
@pytest.mark.usefixtures("bmw_fixture")
|
||||
@pytest.mark.parametrize(
|
||||
("raised", "expected"),
|
||||
("raised", "expected", "exc_translation"),
|
||||
[
|
||||
(MyBMWRemoteServiceError, HomeAssistantError),
|
||||
(MyBMWAPIError, HomeAssistantError),
|
||||
(ServiceValidationError, ServiceValidationError),
|
||||
(
|
||||
MyBMWRemoteServiceError(REMOTE_SERVICE_EXC_REASON),
|
||||
HomeAssistantError,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
),
|
||||
(
|
||||
MyBMWAPIError(REMOTE_SERVICE_EXC_REASON),
|
||||
HomeAssistantError,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
),
|
||||
(
|
||||
ServiceValidationError(
|
||||
"Option 17 is not valid for entity select.i4_edrive40_ac_charging_limit"
|
||||
),
|
||||
ServiceValidationError,
|
||||
"Option 17 is not valid for entity select.i4_edrive40_ac_charging_limit",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_service_call_fail(
|
||||
hass: HomeAssistant,
|
||||
raised: Exception,
|
||||
expected: Exception,
|
||||
exc_translation: str,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""Test exception handling."""
|
||||
@ -146,7 +169,7 @@ async def test_service_call_fail(
|
||||
)
|
||||
|
||||
# Test
|
||||
with pytest.raises(expected):
|
||||
with pytest.raises(expected, match=exc_translation):
|
||||
await hass.services.async_call(
|
||||
"select",
|
||||
"select_option",
|
||||
|
@ -13,7 +13,12 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import check_remote_service_call, setup_mocked_integration
|
||||
from . import (
|
||||
REMOTE_SERVICE_EXC_REASON,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
check_remote_service_call,
|
||||
setup_mocked_integration,
|
||||
)
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
@ -75,17 +80,25 @@ async def test_service_call_success(
|
||||
|
||||
@pytest.mark.usefixtures("bmw_fixture")
|
||||
@pytest.mark.parametrize(
|
||||
("raised", "expected"),
|
||||
("raised", "expected", "exc_translation"),
|
||||
[
|
||||
(MyBMWRemoteServiceError, HomeAssistantError),
|
||||
(MyBMWAPIError, HomeAssistantError),
|
||||
(ValueError, ValueError),
|
||||
(
|
||||
MyBMWRemoteServiceError(REMOTE_SERVICE_EXC_REASON),
|
||||
HomeAssistantError,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
),
|
||||
(
|
||||
MyBMWAPIError(REMOTE_SERVICE_EXC_REASON),
|
||||
HomeAssistantError,
|
||||
REMOTE_SERVICE_EXC_TRANSLATION,
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_service_call_fail(
|
||||
hass: HomeAssistant,
|
||||
raised: Exception,
|
||||
expected: Exception,
|
||||
exc_translation: str,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""Test exception handling."""
|
||||
@ -107,7 +120,7 @@ async def test_service_call_fail(
|
||||
assert hass.states.get(entity_id).state == old_value
|
||||
|
||||
# Test
|
||||
with pytest.raises(expected):
|
||||
with pytest.raises(expected, match=exc_translation):
|
||||
await hass.services.async_call(
|
||||
"switch",
|
||||
"turn_on",
|
||||
@ -122,7 +135,7 @@ async def test_service_call_fail(
|
||||
assert hass.states.get(entity_id).state == old_value
|
||||
|
||||
# Test
|
||||
with pytest.raises(expected):
|
||||
with pytest.raises(expected, match=exc_translation):
|
||||
await hass.services.async_call(
|
||||
"switch",
|
||||
"turn_off",
|
||||
|
Loading…
x
Reference in New Issue
Block a user