mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Make WS command render_template not give up if initial render raises (#99808)
This commit is contained in:
parent
19c2bbcd93
commit
f753f5af6e
@ -542,9 +542,8 @@ async def handle_render_template(
|
|||||||
timed_out = await template_obj.async_render_will_timeout(
|
timed_out = await template_obj.async_render_will_timeout(
|
||||||
timeout, variables, strict=msg["strict"], log_fn=log_fn
|
timeout, variables, strict=msg["strict"], log_fn=log_fn
|
||||||
)
|
)
|
||||||
except TemplateError as ex:
|
except TemplateError:
|
||||||
connection.send_error(msg["id"], const.ERR_TEMPLATE_ERROR, str(ex))
|
timed_out = False
|
||||||
return
|
|
||||||
|
|
||||||
if timed_out:
|
if timed_out:
|
||||||
connection.send_error(
|
connection.send_error(
|
||||||
@ -583,7 +582,6 @@ async def handle_render_template(
|
|||||||
hass,
|
hass,
|
||||||
[TrackTemplate(template_obj, variables)],
|
[TrackTemplate(template_obj, variables)],
|
||||||
_template_listener,
|
_template_listener,
|
||||||
raise_on_template_error=True,
|
|
||||||
strict=msg["strict"],
|
strict=msg["strict"],
|
||||||
log_fn=log_fn,
|
log_fn=log_fn,
|
||||||
)
|
)
|
||||||
|
@ -917,7 +917,6 @@ class TrackTemplateResultInfo:
|
|||||||
|
|
||||||
def async_setup(
|
def async_setup(
|
||||||
self,
|
self,
|
||||||
raise_on_template_error: bool,
|
|
||||||
strict: bool = False,
|
strict: bool = False,
|
||||||
log_fn: Callable[[int, str], None] | None = None,
|
log_fn: Callable[[int, str], None] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -955,8 +954,6 @@ class TrackTemplateResultInfo:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if info.exception:
|
if info.exception:
|
||||||
if raise_on_template_error:
|
|
||||||
raise info.exception
|
|
||||||
if not log_fn:
|
if not log_fn:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Error while processing template: %s",
|
"Error while processing template: %s",
|
||||||
@ -1239,7 +1236,6 @@ def async_track_template_result(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
track_templates: Sequence[TrackTemplate],
|
track_templates: Sequence[TrackTemplate],
|
||||||
action: TrackTemplateResultListener,
|
action: TrackTemplateResultListener,
|
||||||
raise_on_template_error: bool = False,
|
|
||||||
strict: bool = False,
|
strict: bool = False,
|
||||||
log_fn: Callable[[int, str], None] | None = None,
|
log_fn: Callable[[int, str], None] | None = None,
|
||||||
has_super_template: bool = False,
|
has_super_template: bool = False,
|
||||||
@ -1266,11 +1262,6 @@ def async_track_template_result(
|
|||||||
An iterable of TrackTemplate.
|
An iterable of TrackTemplate.
|
||||||
action
|
action
|
||||||
Callable to call with results.
|
Callable to call with results.
|
||||||
raise_on_template_error
|
|
||||||
When set to True, if there is an exception
|
|
||||||
processing the template during setup, the system
|
|
||||||
will raise the exception instead of setting up
|
|
||||||
tracking.
|
|
||||||
strict
|
strict
|
||||||
When set to True, raise on undefined variables.
|
When set to True, raise on undefined variables.
|
||||||
log_fn
|
log_fn
|
||||||
@ -1286,7 +1277,7 @@ def async_track_template_result(
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
tracker = TrackTemplateResultInfo(hass, track_templates, action, has_super_template)
|
tracker = TrackTemplateResultInfo(hass, track_templates, action, has_super_template)
|
||||||
tracker.async_setup(raise_on_template_error, strict=strict, log_fn=log_fn)
|
tracker.async_setup(strict=strict, log_fn=log_fn)
|
||||||
return tracker
|
return tracker
|
||||||
|
|
||||||
|
|
||||||
|
@ -1234,27 +1234,27 @@ EMPTY_LISTENERS = {"all": False, "entities": [], "domains": [], "time": False}
|
|||||||
|
|
||||||
ERR_MSG = {"type": "result", "success": False}
|
ERR_MSG = {"type": "result", "success": False}
|
||||||
|
|
||||||
VARIABLE_ERROR_UNDEFINED_FUNC = {
|
EVENT_UNDEFINED_FUNC_1 = {
|
||||||
"error": "'my_unknown_func' is undefined",
|
"error": "'my_unknown_func' is undefined",
|
||||||
"level": "ERROR",
|
"level": "ERROR",
|
||||||
}
|
}
|
||||||
TEMPLATE_ERROR_UNDEFINED_FUNC = {
|
EVENT_UNDEFINED_FUNC_2 = {
|
||||||
"code": "template_error",
|
"error": "UndefinedError: 'my_unknown_func' is undefined",
|
||||||
"message": "UndefinedError: 'my_unknown_func' is undefined",
|
"level": "ERROR",
|
||||||
}
|
}
|
||||||
|
|
||||||
VARIABLE_WARNING_UNDEFINED_VAR = {
|
EVENT_UNDEFINED_VAR_WARN = {
|
||||||
"error": "'my_unknown_var' is undefined",
|
"error": "'my_unknown_var' is undefined",
|
||||||
"level": "WARNING",
|
"level": "WARNING",
|
||||||
}
|
}
|
||||||
TEMPLATE_ERROR_UNDEFINED_VAR = {
|
EVENT_UNDEFINED_VAR_ERR = {
|
||||||
"code": "template_error",
|
"error": "UndefinedError: 'my_unknown_var' is undefined",
|
||||||
"message": "UndefinedError: 'my_unknown_var' is undefined",
|
"level": "ERROR",
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE_ERROR_UNDEFINED_FILTER = {
|
EVENT_UNDEFINED_FILTER = {
|
||||||
"code": "template_error",
|
"error": "TemplateAssertionError: No filter named 'unknown_filter'.",
|
||||||
"message": "TemplateAssertionError: No filter named 'unknown_filter'.",
|
"level": "ERROR",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1264,16 +1264,19 @@ TEMPLATE_ERROR_UNDEFINED_FILTER = {
|
|||||||
(
|
(
|
||||||
"{{ my_unknown_func() + 1 }}",
|
"{{ my_unknown_func() + 1 }}",
|
||||||
[
|
[
|
||||||
{"type": "event", "event": VARIABLE_ERROR_UNDEFINED_FUNC},
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_1},
|
||||||
ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_FUNC},
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_2},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_1},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_2},
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ my_unknown_var }}",
|
"{{ my_unknown_var }}",
|
||||||
[
|
[
|
||||||
{"type": "event", "event": VARIABLE_WARNING_UNDEFINED_VAR},
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_WARN},
|
||||||
{"type": "result", "success": True, "result": None},
|
{"type": "result", "success": True, "result": None},
|
||||||
{"type": "event", "event": VARIABLE_WARNING_UNDEFINED_VAR},
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_WARN},
|
||||||
{
|
{
|
||||||
"type": "event",
|
"type": "event",
|
||||||
"event": {"result": "", "listeners": EMPTY_LISTENERS},
|
"event": {"result": "", "listeners": EMPTY_LISTENERS},
|
||||||
@ -1282,11 +1285,19 @@ TEMPLATE_ERROR_UNDEFINED_FILTER = {
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ my_unknown_var + 1 }}",
|
"{{ my_unknown_var + 1 }}",
|
||||||
[ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_VAR}],
|
[
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_ERR},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_ERR},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ now() | unknown_filter }}",
|
"{{ now() | unknown_filter }}",
|
||||||
[ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_FILTER}],
|
[
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FILTER},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FILTER},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -1325,16 +1336,20 @@ async def test_render_template_with_error(
|
|||||||
(
|
(
|
||||||
"{{ my_unknown_func() + 1 }}",
|
"{{ my_unknown_func() + 1 }}",
|
||||||
[
|
[
|
||||||
{"type": "event", "event": VARIABLE_ERROR_UNDEFINED_FUNC},
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_1},
|
||||||
ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_FUNC},
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_2},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_1},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_2},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_1},
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ my_unknown_var }}",
|
"{{ my_unknown_var }}",
|
||||||
[
|
[
|
||||||
{"type": "event", "event": VARIABLE_WARNING_UNDEFINED_VAR},
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_WARN},
|
||||||
{"type": "result", "success": True, "result": None},
|
{"type": "result", "success": True, "result": None},
|
||||||
{"type": "event", "event": VARIABLE_WARNING_UNDEFINED_VAR},
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_WARN},
|
||||||
{
|
{
|
||||||
"type": "event",
|
"type": "event",
|
||||||
"event": {"result": "", "listeners": EMPTY_LISTENERS},
|
"event": {"result": "", "listeners": EMPTY_LISTENERS},
|
||||||
@ -1343,11 +1358,19 @@ async def test_render_template_with_error(
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ my_unknown_var + 1 }}",
|
"{{ my_unknown_var + 1 }}",
|
||||||
[ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_VAR}],
|
[
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_ERR},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_ERR},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ now() | unknown_filter }}",
|
"{{ now() | unknown_filter }}",
|
||||||
[ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_FILTER}],
|
[
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FILTER},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FILTER},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -1386,19 +1409,35 @@ async def test_render_template_with_timeout_and_error(
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
"{{ my_unknown_func() + 1 }}",
|
"{{ my_unknown_func() + 1 }}",
|
||||||
[ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_FUNC}],
|
[
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_2},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FUNC_2},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ my_unknown_var }}",
|
"{{ my_unknown_var }}",
|
||||||
[ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_VAR}],
|
[
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_ERR},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_ERR},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ my_unknown_var + 1 }}",
|
"{{ my_unknown_var + 1 }}",
|
||||||
[ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_VAR}],
|
[
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_ERR},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_VAR_ERR},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"{{ now() | unknown_filter }}",
|
"{{ now() | unknown_filter }}",
|
||||||
[ERR_MSG | {"error": TEMPLATE_ERROR_UNDEFINED_FILTER}],
|
[
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FILTER},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{"type": "event", "event": EVENT_UNDEFINED_FILTER},
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -1409,7 +1448,73 @@ async def test_render_template_strict_with_timeout_and_error(
|
|||||||
template: str,
|
template: str,
|
||||||
expected_events: list[dict[str, str]],
|
expected_events: list[dict[str, str]],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test a template with an error with a timeout."""
|
"""Test a template with an error with a timeout.
|
||||||
|
|
||||||
|
In this test report_errors is enabled.
|
||||||
|
"""
|
||||||
|
caplog.set_level(logging.INFO)
|
||||||
|
await websocket_client.send_json(
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"type": "render_template",
|
||||||
|
"template": template,
|
||||||
|
"timeout": 5,
|
||||||
|
"strict": True,
|
||||||
|
"report_errors": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
for expected_event in expected_events:
|
||||||
|
msg = await websocket_client.receive_json()
|
||||||
|
assert msg["id"] == 5
|
||||||
|
for key, value in expected_event.items():
|
||||||
|
assert msg[key] == value
|
||||||
|
|
||||||
|
assert "Template variable error" not in caplog.text
|
||||||
|
assert "Template variable warning" not in caplog.text
|
||||||
|
assert "TemplateError" not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("template", "expected_events"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"{{ my_unknown_func() + 1 }}",
|
||||||
|
[
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{{ my_unknown_var }}",
|
||||||
|
[
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{{ my_unknown_var + 1 }}",
|
||||||
|
[
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{{ now() | unknown_filter }}",
|
||||||
|
[
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_render_template_strict_with_timeout_and_error_2(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
websocket_client,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
template: str,
|
||||||
|
expected_events: list[dict[str, str]],
|
||||||
|
) -> None:
|
||||||
|
"""Test a template with an error with a timeout.
|
||||||
|
|
||||||
|
In this test report_errors is disabled.
|
||||||
|
"""
|
||||||
caplog.set_level(logging.INFO)
|
caplog.set_level(logging.INFO)
|
||||||
await websocket_client.send_json(
|
await websocket_client.send_json(
|
||||||
{
|
{
|
||||||
@ -1427,30 +1532,164 @@ async def test_render_template_strict_with_timeout_and_error(
|
|||||||
for key, value in expected_event.items():
|
for key, value in expected_event.items():
|
||||||
assert msg[key] == value
|
assert msg[key] == value
|
||||||
|
|
||||||
assert "Template variable error" not in caplog.text
|
assert "TemplateError" in caplog.text
|
||||||
assert "Template variable warning" not in caplog.text
|
|
||||||
assert "TemplateError" not in caplog.text
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("template", "expected_events_1", "expected_events_2"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"{{ now() | random }}",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "event",
|
||||||
|
"event": {
|
||||||
|
"error": "TypeError: object of type 'datetime.datetime' has no len()",
|
||||||
|
"level": "ERROR",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{
|
||||||
|
"type": "event",
|
||||||
|
"event": {
|
||||||
|
"error": "TypeError: object of type 'datetime.datetime' has no len()",
|
||||||
|
"level": "ERROR",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{{ float(states.sensor.foo.state) + 1 }}",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "event",
|
||||||
|
"event": {
|
||||||
|
"error": "UndefinedError: 'None' has no attribute 'state'",
|
||||||
|
"level": "ERROR",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
{
|
||||||
|
"type": "event",
|
||||||
|
"event": {
|
||||||
|
"error": "UndefinedError: 'None' has no attribute 'state'",
|
||||||
|
"level": "ERROR",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "event",
|
||||||
|
"event": {
|
||||||
|
"result": 3.0,
|
||||||
|
"listeners": EMPTY_LISTENERS | {"entities": ["sensor.foo"]},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
async def test_render_template_error_in_template_code(
|
async def test_render_template_error_in_template_code(
|
||||||
hass: HomeAssistant, websocket_client, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant,
|
||||||
|
websocket_client,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
template: str,
|
||||||
|
expected_events_1: list[dict[str, str]],
|
||||||
|
expected_events_2: list[dict[str, str]],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test a template that will throw in template.py."""
|
"""Test a template that will throw in template.py.
|
||||||
|
|
||||||
|
In this test report_errors is enabled.
|
||||||
|
"""
|
||||||
await websocket_client.send_json(
|
await websocket_client.send_json(
|
||||||
{"id": 5, "type": "render_template", "template": "{{ now() | random }}"}
|
{
|
||||||
|
"id": 5,
|
||||||
|
"type": "render_template",
|
||||||
|
"template": template,
|
||||||
|
"report_errors": True,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
msg = await websocket_client.receive_json()
|
for expected_event in expected_events_1:
|
||||||
assert msg["id"] == 5
|
msg = await websocket_client.receive_json()
|
||||||
assert msg["type"] == const.TYPE_RESULT
|
assert msg["id"] == 5
|
||||||
assert not msg["success"]
|
for key, value in expected_event.items():
|
||||||
assert msg["error"]["code"] == const.ERR_TEMPLATE_ERROR
|
assert msg[key] == value
|
||||||
|
|
||||||
|
hass.states.async_set("sensor.foo", "2")
|
||||||
|
|
||||||
|
for expected_event in expected_events_2:
|
||||||
|
msg = await websocket_client.receive_json()
|
||||||
|
assert msg["id"] == 5
|
||||||
|
for key, value in expected_event.items():
|
||||||
|
assert msg[key] == value
|
||||||
|
|
||||||
assert "Template variable error" not in caplog.text
|
assert "Template variable error" not in caplog.text
|
||||||
assert "Template variable warning" not in caplog.text
|
assert "Template variable warning" not in caplog.text
|
||||||
assert "TemplateError" not in caplog.text
|
assert "TemplateError" not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("template", "expected_events_1", "expected_events_2"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"{{ now() | random }}",
|
||||||
|
[
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"{{ float(states.sensor.foo.state) + 1 }}",
|
||||||
|
[
|
||||||
|
{"type": "result", "success": True, "result": None},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "event",
|
||||||
|
"event": {
|
||||||
|
"result": 3.0,
|
||||||
|
"listeners": EMPTY_LISTENERS | {"entities": ["sensor.foo"]},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_render_template_error_in_template_code_2(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
websocket_client,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
template: str,
|
||||||
|
expected_events_1: list[dict[str, str]],
|
||||||
|
expected_events_2: list[dict[str, str]],
|
||||||
|
) -> None:
|
||||||
|
"""Test a template that will throw in template.py.
|
||||||
|
|
||||||
|
In this test report_errors is disabled.
|
||||||
|
"""
|
||||||
|
await websocket_client.send_json(
|
||||||
|
{"id": 5, "type": "render_template", "template": template}
|
||||||
|
)
|
||||||
|
|
||||||
|
for expected_event in expected_events_1:
|
||||||
|
msg = await websocket_client.receive_json()
|
||||||
|
assert msg["id"] == 5
|
||||||
|
for key, value in expected_event.items():
|
||||||
|
assert msg[key] == value
|
||||||
|
|
||||||
|
hass.states.async_set("sensor.foo", "2")
|
||||||
|
|
||||||
|
for expected_event in expected_events_2:
|
||||||
|
msg = await websocket_client.receive_json()
|
||||||
|
assert msg["id"] == 5
|
||||||
|
for key, value in expected_event.items():
|
||||||
|
assert msg[key] == value
|
||||||
|
|
||||||
|
assert "TemplateError" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
async def test_render_template_with_delayed_error(
|
async def test_render_template_with_delayed_error(
|
||||||
hass: HomeAssistant, websocket_client, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, websocket_client, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -3239,27 +3239,6 @@ async def test_async_track_template_result_multiple_templates_mixing_domain(
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
async def test_async_track_template_result_raise_on_template_error(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
) -> None:
|
|
||||||
"""Test that we raise as soon as we encounter a failed template."""
|
|
||||||
|
|
||||||
with pytest.raises(TemplateError):
|
|
||||||
async_track_template_result(
|
|
||||||
hass,
|
|
||||||
[
|
|
||||||
TrackTemplate(
|
|
||||||
Template(
|
|
||||||
"{{ states.switch | function_that_does_not_exist | list }}"
|
|
||||||
),
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
ha.callback(lambda event, updates: None),
|
|
||||||
raise_on_template_error=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_track_template_with_time(hass: HomeAssistant) -> None:
|
async def test_track_template_with_time(hass: HomeAssistant) -> None:
|
||||||
"""Test tracking template with time."""
|
"""Test tracking template with time."""
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user