Add ServiceValidationError and translation support (#102592)

* Add ServiceValidationError

* Add translation support

* Extend translation support to HomeAssistantError

* Add translation support for ServiceNotFound exc

* Frontend translation & translation_key from caller

* Improve fallback message

* Set websocket_api as default translation_domain

* Add MQTT ServiceValidationError exception

* Follow up comments

* Revert removing gueard on translation_key

* Revert test changes to fix CI test

* Follow up comments

* Fix CI test

* Follow up

* Improve language

* Follow up comment
This commit is contained in:
Jan Bouwhuis
2023-11-06 15:45:04 +01:00
committed by GitHub
parent 5cd61a0cf4
commit 54cf7010cd
12 changed files with 206 additions and 18 deletions
+3 -3
View File
@@ -205,7 +205,7 @@ async def test_get_trace(
_assert_raw_config(domain, sun_config, trace)
assert trace["blueprint_inputs"] is None
assert trace["context"]
assert trace["error"] == "Unable to find service test.automation"
assert trace["error"] == "Service test.automation not found."
assert trace["state"] == "stopped"
assert trace["script_execution"] == "error"
assert trace["item_id"] == "sun"
@@ -893,7 +893,7 @@ async def test_list_traces(
assert len(_find_traces(response["result"], domain, "sun")) == 1
trace = _find_traces(response["result"], domain, "sun")[0]
assert trace["last_step"] == last_step[0].format(prefix=prefix)
assert trace["error"] == "Unable to find service test.automation"
assert trace["error"] == "Service test.automation not found."
assert trace["state"] == "stopped"
assert trace["script_execution"] == script_execution[0]
assert trace["timestamp"]
@@ -1632,7 +1632,7 @@ async def test_trace_blueprint_automation(
assert trace["config"]["id"] == "sun"
assert trace["blueprint_inputs"] == sun_config
assert trace["context"]
assert trace["error"] == "Unable to find service test.automation"
assert trace["error"] == "Service test.automation not found."
assert trace["state"] == "stopped"
assert trace["script_execution"] == "error"
assert trace["item_id"] == "sun"
@@ -19,7 +19,7 @@ from homeassistant.components.websocket_api.auth import (
from homeassistant.components.websocket_api.const import FEATURE_COALESCE_MESSAGES, URL
from homeassistant.const import SIGNAL_BOOTSTRAP_INTEGRATIONS
from homeassistant.core import Context, HomeAssistant, State, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.loader import async_get_integration
@@ -343,6 +343,13 @@ async def test_call_service_not_found(
assert msg["type"] == const.TYPE_RESULT
assert not msg["success"]
assert msg["error"]["code"] == const.ERR_NOT_FOUND
assert msg["error"]["message"] == "Service domain_test.test_service not found."
assert msg["error"]["translation_placeholders"] == {
"domain": "domain_test",
"service": "test_service",
}
assert msg["error"]["translation_key"] == "service_not_found"
assert msg["error"]["translation_domain"] == "homeassistant"
async def test_call_service_child_not_found(
@@ -370,6 +377,18 @@ async def test_call_service_child_not_found(
assert msg["type"] == const.TYPE_RESULT
assert not msg["success"]
assert msg["error"]["code"] == const.ERR_HOME_ASSISTANT_ERROR
assert (
msg["error"]["message"] == "Service non.existing called service "
"domain_test.test_service which was not found."
)
assert msg["error"]["translation_placeholders"] == {
"domain": "non",
"service": "existing",
"child_domain": "domain_test",
"child_service": "test_service",
}
assert msg["error"]["translation_key"] == "child_service_not_found"
assert msg["error"]["translation_domain"] == "websocket_api"
async def test_call_service_schema_validation_error(
@@ -450,10 +469,26 @@ async def test_call_service_error(
@callback
def ha_error_call(_):
raise HomeAssistantError("error_message")
raise HomeAssistantError(
"error_message",
translation_domain="test",
translation_key="custom_error",
translation_placeholders={"option": "bla"},
)
hass.services.async_register("domain_test", "ha_error", ha_error_call)
@callback
def service_error_call(_):
raise ServiceValidationError(
"error_message",
translation_domain="test",
translation_key="custom_error",
translation_placeholders={"option": "bla"},
)
hass.services.async_register("domain_test", "service_error", service_error_call)
async def unknown_error_call(_):
raise ValueError("value_error")
@@ -474,18 +509,40 @@ async def test_call_service_error(
assert msg["success"] is False
assert msg["error"]["code"] == "home_assistant_error"
assert msg["error"]["message"] == "error_message"
assert msg["error"]["translation_placeholders"] == {"option": "bla"}
assert msg["error"]["translation_key"] == "custom_error"
assert msg["error"]["translation_domain"] == "test"
await websocket_client.send_json(
{
"id": 6,
"type": "call_service",
"domain": "domain_test",
"service": "service_error",
}
)
msg = await websocket_client.receive_json()
assert msg["id"] == 6
assert msg["type"] == const.TYPE_RESULT
assert msg["success"] is False
assert msg["error"]["code"] == "service_validation_error"
assert msg["error"]["message"] == "Validation error: error_message"
assert msg["error"]["translation_placeholders"] == {"option": "bla"}
assert msg["error"]["translation_key"] == "custom_error"
assert msg["error"]["translation_domain"] == "test"
await websocket_client.send_json(
{
"id": 7,
"type": "call_service",
"domain": "domain_test",
"service": "unknown_error",
}
)
msg = await websocket_client.receive_json()
assert msg["id"] == 6
assert msg["id"] == 7
assert msg["type"] == const.TYPE_RESULT
assert msg["success"] is False
assert msg["error"]["code"] == "unknown_error"