Files
wehub-resource-sync 6ede33ccdb
Build and Push Docker Images / create_manifest (web, surfsense-web, , cpu) (push) Has been cancelled
Build and Push Docker Images / finalize_release (push) Has been cancelled
Obsidian Plugin Lint / lint (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / compute_version (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / verify_digests (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, , cpu) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda, cuda) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda126, cuda126) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:33:44 +08:00

54 lines
2.0 KiB
Python

"""Lock the sandbox boundary: disallowed filters/tests reject, finalize coerces non-strings.
These behaviors live in ``environment.py`` but are observed through the
public ``render_template`` surface — the same surface every step uses.
"""
from __future__ import annotations
from datetime import UTC, datetime
import pytest
from jinja2.exceptions import TemplateError
from app.automations.templating.render import render_template
pytestmark = pytest.mark.unit
def test_environment_rejects_filters_not_in_the_allowlist() -> None:
"""A template that pipes through a Jinja built-in **not** in the
allowlist (e.g. ``pprint``) must fail rather than rendering. Locks
the sandbox surface against accidental re-introduction of removed
filters."""
with pytest.raises(TemplateError):
render_template("{{ value | pprint }}", {"value": {"k": 1}})
def test_environment_finalizes_datetime_output_to_iso_string() -> None:
"""A datetime that lands directly at an output site is stringified
via ``isoformat()`` rather than producing ``str(datetime)`` (which
has a space separator). Locks the wire shape templates produce
when emitting ``inputs.fired_at`` and other datetime values."""
dt = datetime(2026, 5, 28, 14, 30, tzinfo=UTC)
assert (
render_template("{{ moment }}", {"moment": dt}) == "2026-05-28T14:30:00+00:00"
)
def test_environment_finalizes_none_output_to_empty_string() -> None:
"""A ``None`` at an output site becomes the empty string. Lets
templates write ``{{ inputs.last_fired_at }}`` unconditionally on
the first run without exploding on the null."""
assert render_template("{{ missing }}", {"missing": None}) == ""
def test_environment_finalizes_dict_output_to_json() -> None:
"""A dict at an output site is JSON-serialized. Same for lists.
Locks the wire shape so users embedding structured values into
prompts get deterministic, parseable output."""
rendered = render_template("{{ payload }}", {"payload": {"a": 1, "b": [2, 3]}})
assert rendered == '{"a": 1, "b": [2, 3]}'