Public Access
162 lines
4.8 KiB
Python
162 lines
4.8 KiB
Python
"""Unit tests for devx.utils.jinja."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import jinja2
|
|
|
|
from devx.utils.jinja import (
|
|
make_env,
|
|
make_value_env,
|
|
regex_escape,
|
|
regex_replace,
|
|
regex_search,
|
|
render_manifest_values,
|
|
render_template,
|
|
render_value,
|
|
to_bool,
|
|
to_json,
|
|
)
|
|
|
|
|
|
class TestFilters:
|
|
def test_to_json(self):
|
|
assert to_json({"a": 1}) == '{"a": 1}'
|
|
|
|
def test_to_json_list(self):
|
|
assert to_json([1, 2]) == "[1, 2]"
|
|
|
|
def test_to_bool_true(self):
|
|
assert to_bool(True) is True
|
|
|
|
def test_to_bool_false(self):
|
|
assert to_bool(False) is False
|
|
|
|
def test_to_bool_string_true(self):
|
|
assert to_bool("yes") is True
|
|
|
|
def test_to_bool_string_false(self):
|
|
assert to_bool("false") is False
|
|
|
|
def test_to_bool_empty_string(self):
|
|
assert to_bool("") is False
|
|
|
|
def test_to_bool_none(self):
|
|
assert to_bool(None) is False
|
|
|
|
def test_to_bool_int(self):
|
|
assert to_bool(1) is True
|
|
assert to_bool(0) is False
|
|
|
|
def test_regex_replace(self):
|
|
assert regex_replace("hello world", "world", "there") == "hello there"
|
|
|
|
def test_regex_replace_with_pattern(self):
|
|
assert regex_replace("abc123", r"\d+", "X") == "abcX"
|
|
|
|
def test_regex_escape(self):
|
|
assert regex_escape("a.b*c") == "a\\.b\\*c"
|
|
|
|
def test_regex_search_found(self):
|
|
assert regex_search("hello world", r"world") == "world"
|
|
|
|
def test_regex_search_not_found(self):
|
|
assert regex_search("hello", r"world") is None
|
|
|
|
def test_regex_search_group(self):
|
|
assert regex_search("abc123", r"\d+") == "123"
|
|
|
|
|
|
class TestMakeEnv:
|
|
def test_returns_environment(self, tmp_path):
|
|
(tmp_path / "test.j2").write_text("hello {{ name }}")
|
|
env = make_env(str(tmp_path))
|
|
assert isinstance(env, jinja2.Environment)
|
|
|
|
def test_has_filters(self, tmp_path):
|
|
env = make_env(str(tmp_path))
|
|
assert "to_json" in env.filters
|
|
assert "bool" in env.filters
|
|
assert "regex_replace" in env.filters
|
|
assert "regex_escape" in env.filters
|
|
assert "regex_search" in env.filters
|
|
|
|
def test_cached(self, tmp_path):
|
|
env1 = make_env(str(tmp_path))
|
|
env2 = make_env(str(tmp_path))
|
|
assert env1 is env2
|
|
|
|
def test_auto_reload_disabled(self, tmp_path):
|
|
env = make_env(str(tmp_path))
|
|
assert env.auto_reload is False
|
|
|
|
def test_strict_undefined(self, tmp_path):
|
|
env = make_env(str(tmp_path))
|
|
assert env.undefined is jinja2.StrictUndefined
|
|
|
|
|
|
class TestMakeValueEnv:
|
|
def test_returns_environment(self):
|
|
env = make_value_env()
|
|
assert isinstance(env, jinja2.Environment)
|
|
|
|
def test_chainable_undefined(self):
|
|
env = make_value_env()
|
|
assert env.undefined is jinja2.ChainableUndefined
|
|
|
|
def test_cached(self):
|
|
assert make_value_env() is make_value_env()
|
|
|
|
def test_has_filters(self):
|
|
env = make_value_env()
|
|
assert "to_json" in env.filters
|
|
|
|
|
|
class TestRenderTemplate:
|
|
def test_renders_named_template(self, tmp_path):
|
|
(tmp_path / "test.j2").write_text("hello {{ name }}")
|
|
env = make_env(str(tmp_path))
|
|
assert render_template(env, "test.j2", name="world") == "hello world"
|
|
|
|
def test_renders_with_filters(self, tmp_path):
|
|
(tmp_path / "test.j2").write_text("{{ data | to_json }}")
|
|
env = make_env(str(tmp_path))
|
|
assert render_template(env, "test.j2", data={"a": 1}) == '{"a": 1}'
|
|
|
|
|
|
class TestRenderValue:
|
|
def test_renders_string_with_expressions(self):
|
|
assert render_value("hello {{ name }}", {"name": "world"}) == "hello world"
|
|
|
|
def test_passes_through_non_string(self):
|
|
assert render_value(42, {}) == 42
|
|
|
|
def test_passes_through_string_without_expressions(self):
|
|
assert render_value("plain text", {}) == "plain text"
|
|
|
|
def test_passes_through_none(self):
|
|
assert render_value(None, {}) is None
|
|
|
|
|
|
class TestRenderManifestValues:
|
|
def test_renders_dict_values(self):
|
|
result = render_manifest_values({"key": "{{ value }}"}, {"value": "rendered"})
|
|
assert result == {"key": "rendered"}
|
|
|
|
def test_renders_list_values(self):
|
|
result = render_manifest_values(["{{ a }}", "{{ b }}"], {"a": "1", "b": "2"})
|
|
assert result == ["1", "2"]
|
|
|
|
def test_renders_nested(self):
|
|
result = render_manifest_values({"outer": {"inner": "{{ x }}"}}, {"x": "yes"})
|
|
assert result == {"outer": {"inner": "yes"}}
|
|
|
|
def test_passes_through_non_string(self):
|
|
result = render_manifest_values({"n": 42, "b": True, "l": [1, 2]}, {})
|
|
assert result == {"n": 42, "b": True, "l": [1, 2]}
|
|
|
|
def test_empty_dict(self):
|
|
assert render_manifest_values({}, {}) == {}
|
|
|
|
def test_empty_list(self):
|
|
assert render_manifest_values([], {}) == []
|