主要变更: - 将 templates_dir 参数改为 template_file,支持单个模板库 YAML 文件 - 添加模板库 YAML 验证功能 - 为模板添加 base_dir 支持,正确解析相对路径资源 - 内联模板与外部模板同名时改为警告(内联优先) - 移除模板缓存机制,直接使用模板库字典 - 更新所有相关测试以适配新的模板加载方式 此重构简化了模板管理,使模板资源的路径解析更加清晰明确。
577 lines
22 KiB
Python
577 lines
22 KiB
Python
"""
|
|
模板系统单元测试
|
|
|
|
测试 Template 类的初始化、变量解析、条件渲染和模板渲染功能
|
|
"""
|
|
|
|
import pytest
|
|
from pathlib import Path
|
|
from loaders.yaml_loader import YAMLError
|
|
from core.template import Template
|
|
from core.presentation import Presentation
|
|
|
|
|
|
# ============= 模板初始化测试 =============
|
|
|
|
|
|
class TestTemplateFromData:
|
|
"""Template.from_data 方法测试类"""
|
|
|
|
def test_from_data_with_valid_template(self, temp_dir):
|
|
"""测试从有效数据创建模板"""
|
|
template_data = {
|
|
"vars": [
|
|
{"name": "title", "required": True},
|
|
{"name": "subtitle", "required": False, "default": ""}
|
|
],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{title}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test-template", base_dir=temp_dir)
|
|
assert template.data is not None
|
|
assert "elements" in template.data
|
|
assert "vars" in template.data
|
|
assert template.base_dir == temp_dir
|
|
|
|
def test_from_data_without_vars(self, temp_dir):
|
|
"""测试创建没有变量的模板"""
|
|
template_data = {
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "Static Text"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "static-template", base_dir=temp_dir)
|
|
assert len(template.vars_def) == 0
|
|
assert len(template.elements) == 1
|
|
|
|
def test_from_data_with_empty_vars(self, temp_dir):
|
|
"""测试创建空变量列表的模板"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": []
|
|
}
|
|
template = Template.from_data(template_data, "empty-template", base_dir=temp_dir)
|
|
assert len(template.vars_def) == 0
|
|
assert len(template.elements) == 0
|
|
|
|
def test_from_data_render_with_vars(self, temp_dir):
|
|
"""测试使用 from_data 创建的模板可以正常渲染"""
|
|
template_data = {
|
|
"vars": [{"name": "title", "required": True}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{title}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test-template", base_dir=temp_dir)
|
|
rendered = template.render({"title": "Hello"})
|
|
assert rendered[0]["content"] == "Hello"
|
|
|
|
def test_from_data_render_with_default_value(self, temp_dir):
|
|
"""测试使用默认值渲染"""
|
|
template_data = {
|
|
"vars": [
|
|
{"name": "title", "required": False, "default": "Default Title"}
|
|
],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{title}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test-template", base_dir=temp_dir)
|
|
rendered = template.render({})
|
|
assert rendered[0]["content"] == "Default Title"
|
|
|
|
def test_from_data_with_conditional_element(self, temp_dir):
|
|
"""测试条件元素"""
|
|
template_data = {
|
|
"vars": [{"name": "show", "required": False, "default": ""}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "Always", "visible": "True"},
|
|
{"type": "text", "box": [1, 3, 8, 1], "content": "Conditional", "visible": "{show != ''}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test-template", base_dir=temp_dir)
|
|
|
|
# 不提供 show 变量
|
|
rendered = template.render({})
|
|
assert len(rendered) == 1
|
|
assert rendered[0]["content"] == "Always"
|
|
|
|
# 提供 show 变量
|
|
rendered = template.render({"show": "yes"})
|
|
assert len(rendered) == 2
|
|
|
|
def test_from_data_with_nested_variable_in_default(self, temp_dir):
|
|
"""测试默认值中的嵌套变量"""
|
|
template_data = {
|
|
"vars": [
|
|
{"name": "prefix", "required": True},
|
|
{"name": "title", "required": False, "default": "{prefix} Title"}
|
|
],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{title}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test-template", base_dir=temp_dir)
|
|
rendered = template.render({"prefix": "My"})
|
|
assert rendered[0]["content"] == "My Title"
|
|
|
|
def test_from_data_rejects_template_reference_in_elements(self, temp_dir):
|
|
"""测试元素中包含 template 字段会引发错误"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": [
|
|
{"template": "nested-template"} # 内联模板不支持相互引用
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test-template", base_dir=temp_dir)
|
|
# 渲染时应该引发错误
|
|
with pytest.raises(YAMLError, match="内联模板不支持相互引用"):
|
|
template.render({})
|
|
|
|
def test_from_data_with_description(self, temp_dir):
|
|
"""测试模板描述字段"""
|
|
template_data = {
|
|
"description": "这是一个测试模板",
|
|
"vars": [],
|
|
"elements": []
|
|
}
|
|
template = Template.from_data(template_data, "test-template", base_dir=temp_dir)
|
|
assert template.description == "这是一个测试模板"
|
|
|
|
def test_from_data_without_description(self, temp_dir):
|
|
"""测试没有描述字段的模板"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": []
|
|
}
|
|
template = Template.from_data(template_data, "test-template", base_dir=temp_dir)
|
|
assert template.description is None
|
|
|
|
|
|
# ============= 变量解析测试 =============
|
|
|
|
|
|
class TestResolveValue:
|
|
"""resolve_value 方法测试类"""
|
|
|
|
def test_resolve_value_simple_variable(self, temp_dir):
|
|
"""测试解析简单变量"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
result = template.resolve_value("{title}", {"title": "My Title"})
|
|
assert result == "My Title"
|
|
|
|
def test_resolve_value_multiple_variables(self, temp_dir):
|
|
"""测试解析多个变量"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
result = template.resolve_value(
|
|
"{title} - {subtitle}", {"title": "Main", "subtitle": "Sub"}
|
|
)
|
|
assert result == "Main - Sub"
|
|
|
|
def test_resolve_value_undefined_variable_raises_error(self, temp_dir):
|
|
"""测试未定义变量会引发错误"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
with pytest.raises(YAMLError, match="未定义的变量"):
|
|
template.resolve_value("{undefined}", {"title": "Test"})
|
|
|
|
def test_resolve_value_preserves_non_string(self, temp_dir):
|
|
"""测试非字符串值保持原样"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
assert template.resolve_value(123, {}) == 123
|
|
assert template.resolve_value(None, {}) is None
|
|
assert template.resolve_value(["list"], {}) == ["list"]
|
|
|
|
def test_resolve_value_converts_to_integer(self, temp_dir):
|
|
"""测试结果转换为整数"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
result = template.resolve_value("{value}", {"value": "42"})
|
|
assert result == 42
|
|
assert isinstance(result, int)
|
|
|
|
def test_resolve_value_converts_to_float(self, temp_dir):
|
|
"""测试结果转换为浮点数"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
result = template.resolve_value("{value}", {"value": "3.14"})
|
|
assert result == 3.14
|
|
assert isinstance(result, float)
|
|
|
|
|
|
# ============= resolve_element 测试 =============
|
|
|
|
|
|
class TestResolveElement:
|
|
"""resolve_element 方法测试类"""
|
|
|
|
def test_resolve_element_dict(self, temp_dir):
|
|
"""测试解析字典元素"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
elem = {"content": "{title}", "box": [1, 2, 3, 4]}
|
|
result = template.resolve_element(elem, {"title": "Test"})
|
|
assert result["content"] == "Test"
|
|
assert result["box"] == [1, 2, 3, 4]
|
|
|
|
def test_resolve_element_list(self, temp_dir):
|
|
"""测试解析列表元素"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
elem = ["{title}", "{subtitle}"]
|
|
result = template.resolve_element(elem, {"title": "A", "subtitle": "B"})
|
|
assert result == ["A", "B"]
|
|
|
|
def test_resolve_element_nested_structure(self, temp_dir):
|
|
"""测试解析嵌套结构"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
elem = {
|
|
"content": "{title}",
|
|
"font": {"size": "{size}", "color": "#000"}
|
|
}
|
|
result = template.resolve_element(elem, {"title": "Test", "size": "24"})
|
|
assert result["content"] == "Test"
|
|
assert result["font"]["size"] == 24
|
|
assert result["font"]["color"] == "#000"
|
|
|
|
def test_resolve_element_excludes_visible(self, temp_dir):
|
|
"""测试 visible 字段在 resolve_element 中被排除"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
elem = {"content": "{title}", "visible": "{show}"}
|
|
result = template.resolve_element(elem, {"title": "Test", "show": "true"})
|
|
assert result["content"] == "Test"
|
|
# visible 字段在 resolve_element 中被排除,在 render 中单独处理
|
|
assert "visible" not in result
|
|
|
|
|
|
# ============= 条件评估测试 =============
|
|
|
|
|
|
class TestEvaluateCondition:
|
|
"""evaluate_condition 方法测试类"""
|
|
|
|
def test_evaluate_condition_with_non_empty_variable(self, temp_dir):
|
|
"""测试非空变量条件"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
result = template.evaluate_condition("{title != ''}", {"title": "Hello"})
|
|
assert result is True
|
|
|
|
def test_evaluate_condition_with_empty_variable(self, temp_dir):
|
|
"""测试空变量条件"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
result = template.evaluate_condition("{title != ''}", {"title": ""})
|
|
assert result is False
|
|
|
|
def test_evaluate_condition_with_missing_variable(self, temp_dir):
|
|
"""测试缺失变量条件会引发错误"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
# 缺失变量应该引发错误
|
|
with pytest.raises(YAMLError, match="变量未定义"):
|
|
template.evaluate_condition("{title != ''}", {})
|
|
|
|
def test_evaluate_condition_complex_logic(self, temp_dir):
|
|
"""测试复杂逻辑条件"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
result = template.evaluate_condition(
|
|
"{a == 'yes' and b != ''}",
|
|
{"a": "yes", "b": "value"}
|
|
)
|
|
assert result is True
|
|
|
|
def test_evaluate_condition_member_test(self, temp_dir):
|
|
"""测试成员测试条件"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
result = template.evaluate_condition("{type in ['A', 'B']}", {"type": "A"})
|
|
assert result is True
|
|
|
|
def test_evaluate_condition_math_operation(self, temp_dir):
|
|
"""测试数学运算条件"""
|
|
template_data = {"vars": [], "elements": []}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
# 使用整数而不是字符串进行比较
|
|
result = template.evaluate_condition("{count > 5}", {"count": 10})
|
|
assert result is True
|
|
|
|
|
|
# ============= 渲染测试 =============
|
|
|
|
|
|
class TestRender:
|
|
"""render 方法测试类"""
|
|
|
|
def test_render_with_required_variable(self, temp_dir):
|
|
"""测试使用必需变量渲染"""
|
|
template_data = {
|
|
"vars": [{"name": "title", "required": True}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{title}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({"title": "Hello"})
|
|
assert len(rendered) == 1
|
|
assert rendered[0]["content"] == "Hello"
|
|
|
|
def test_render_with_optional_variable(self, temp_dir):
|
|
"""测试使用可选变量渲染"""
|
|
template_data = {
|
|
"vars": [{"name": "subtitle", "required": False, "default": ""}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{subtitle}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({"subtitle": "Sub"})
|
|
assert rendered[0]["content"] == "Sub"
|
|
|
|
def test_render_without_optional_variable(self, temp_dir):
|
|
"""测试不提供可选变量时使用默认值"""
|
|
template_data = {
|
|
"vars": [{"name": "subtitle", "required": False, "default": "Default"}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{subtitle}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({})
|
|
assert rendered[0]["content"] == "Default"
|
|
|
|
def test_render_missing_required_variable_raises_error(self, temp_dir):
|
|
"""测试缺少必需变量会引发错误"""
|
|
template_data = {
|
|
"vars": [{"name": "title", "required": True}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{title}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
with pytest.raises(YAMLError, match="缺少必需变量"):
|
|
template.render({})
|
|
|
|
def test_render_with_default_value(self, temp_dir):
|
|
"""测试使用默认值渲染"""
|
|
template_data = {
|
|
"vars": [{"name": "title", "required": False, "default": "Default Title"}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{title}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({})
|
|
assert rendered[0]["content"] == "Default Title"
|
|
|
|
def test_render_filters_elements_by_visible_condition(self, temp_dir):
|
|
"""测试根据 visible 条件过滤元素"""
|
|
template_data = {
|
|
"vars": [{"name": "show", "required": False, "default": ""}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "Always"},
|
|
{"type": "text", "box": [1, 3, 8, 1], "content": "Conditional", "visible": "{show != ''}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
|
|
# 不显示条件元素
|
|
rendered = template.render({})
|
|
assert len(rendered) == 1
|
|
|
|
# 显示条件元素
|
|
rendered = template.render({"show": "yes"})
|
|
assert len(rendered) == 2
|
|
|
|
|
|
# ============= 边界情况测试 =============
|
|
|
|
|
|
class TestTemplateBoundaryCases:
|
|
"""模板边界情况测试"""
|
|
|
|
def test_nested_variable_resolution(self, temp_dir):
|
|
"""测试嵌套变量解析"""
|
|
template_data = {
|
|
"vars": [
|
|
{"name": "prefix", "required": True},
|
|
{"name": "title", "required": False, "default": "{prefix} Title"}
|
|
],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{title}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({"prefix": "My"})
|
|
assert rendered[0]["content"] == "My Title"
|
|
|
|
def test_variable_with_special_characters(self, temp_dir):
|
|
"""测试包含特殊字符的变量"""
|
|
template_data = {
|
|
"vars": [{"name": "text", "required": True}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "{text}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({"text": "Hello & <World>"})
|
|
assert rendered[0]["content"] == "Hello & <World>"
|
|
|
|
def test_variable_with_numeric_value(self, temp_dir):
|
|
"""测试数值变量"""
|
|
template_data = {
|
|
"vars": [{"name": "count", "required": True}],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "Count: {count}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({"count": 42})
|
|
assert rendered[0]["content"] == "Count: 42"
|
|
|
|
def test_empty_vars_list(self, temp_dir):
|
|
"""测试空变量列表"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "Static"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({})
|
|
assert len(rendered) == 1
|
|
assert rendered[0]["content"] == "Static"
|
|
|
|
def test_multiple_visible_conditions(self, temp_dir):
|
|
"""测试多个可见性条件"""
|
|
template_data = {
|
|
"vars": [
|
|
{"name": "show_a", "required": False, "default": ""},
|
|
{"name": "show_b", "required": False, "default": ""}
|
|
],
|
|
"elements": [
|
|
{"type": "text", "box": [1, 2, 8, 1], "content": "A", "visible": "{show_a != ''}"},
|
|
{"type": "text", "box": [1, 3, 8, 1], "content": "B", "visible": "{show_b != ''}"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
|
|
rendered = template.render({"show_a": "yes"})
|
|
assert len(rendered) == 1
|
|
assert rendered[0]["content"] == "A"
|
|
|
|
def test_variable_in_position(self, temp_dir):
|
|
"""测试位置中的变量"""
|
|
template_data = {
|
|
"vars": [{"name": "x", "required": True}],
|
|
"elements": [
|
|
{"type": "text", "box": ["{x}", 2, 8, 1], "content": "Text"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({"x": "5"})
|
|
assert rendered[0]["box"][0] == 5
|
|
|
|
def test_empty_template_elements(self, temp_dir):
|
|
"""测试空元素列表"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": []
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({})
|
|
assert len(rendered) == 0
|
|
|
|
def test_variable_replacement_in_font(self, temp_dir):
|
|
"""测试字体属性中的变量替换"""
|
|
template_data = {
|
|
"vars": [{"name": "size", "required": True}],
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"box": [1, 2, 8, 1],
|
|
"content": "Text",
|
|
"font": {"size": "{size}"}
|
|
}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({"size": "24"})
|
|
assert rendered[0]["font"]["size"] == 24
|
|
|
|
|
|
# ============= 图片路径解析测试 =============
|
|
|
|
|
|
class TestImagePathResolution:
|
|
"""图片路径解析测试"""
|
|
|
|
def test_render_resolves_relative_image_paths(self, temp_dir, sample_image):
|
|
"""测试渲染时解析相对图片路径"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": [
|
|
{"type": "image", "box": [1, 2, 8, 4], "src": sample_image.name}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({})
|
|
|
|
# 相对路径应该被解析为绝对路径
|
|
assert Path(rendered[0]["src"]).is_absolute()
|
|
assert rendered[0]["src"] == str(temp_dir / sample_image.name)
|
|
|
|
def test_render_preserves_absolute_image_paths(self, temp_dir, sample_image):
|
|
"""测试渲染时保留绝对图片路径"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": [
|
|
{"type": "image", "box": [1, 2, 8, 4], "src": str(sample_image)}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({})
|
|
|
|
# 绝对路径应该保持不变
|
|
assert rendered[0]["src"] == str(sample_image)
|
|
|
|
def test_render_without_base_dir(self, temp_dir):
|
|
"""测试没有 base_dir 时不解析路径"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": [
|
|
{"type": "image", "box": [1, 2, 8, 4], "src": "image.png"}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=None)
|
|
rendered = template.render({})
|
|
|
|
# 没有 base_dir 时,相对路径保持不变
|
|
assert rendered[0]["src"] == "image.png"
|
|
|
|
def test_render_resolves_nested_image_paths(self, temp_dir):
|
|
"""测试解析嵌套结构中的图片路径"""
|
|
template_data = {
|
|
"vars": [],
|
|
"elements": [
|
|
{
|
|
"type": "image",
|
|
"box": [1, 2, 8, 4],
|
|
"src": "images/logo.png"
|
|
}
|
|
]
|
|
}
|
|
template = Template.from_data(template_data, "test", base_dir=temp_dir)
|
|
rendered = template.render({})
|
|
|
|
# 相对路径应该被解析
|
|
assert Path(rendered[0]["src"]).is_absolute()
|
|
assert rendered[0]["src"] == str(temp_dir / "images" / "logo.png")
|