forked from cleveragents/cleveragents-core
738 lines
25 KiB
Python
738 lines
25 KiB
Python
"""
|
|
Unit tests for templates base module.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from cleveragents.templates.base import (
|
|
TemplateType,
|
|
TemplateParameter,
|
|
ComponentReference,
|
|
InstantiationContext,
|
|
BaseTemplate,
|
|
)
|
|
|
|
|
|
class TestTemplateType:
|
|
"""Test cases for TemplateType enum."""
|
|
|
|
def test_agent_type(self):
|
|
"""Test AGENT template type."""
|
|
assert TemplateType.AGENT.value == "agent"
|
|
|
|
def test_graph_type(self):
|
|
"""Test GRAPH template type."""
|
|
assert TemplateType.GRAPH.value == "graph"
|
|
|
|
def test_stream_type(self):
|
|
"""Test STREAM template type."""
|
|
assert TemplateType.STREAM.value == "stream"
|
|
|
|
|
|
class TestTemplateParameter:
|
|
"""Test cases for TemplateParameter class."""
|
|
|
|
def test_init_with_defaults(self):
|
|
"""Test TemplateParameter initialization with defaults."""
|
|
param = TemplateParameter(name="test_param")
|
|
|
|
assert param.name == "test_param"
|
|
assert param.default is None
|
|
assert param.type == "string"
|
|
assert param.values is None
|
|
assert param.description is None
|
|
assert param.required is False
|
|
|
|
def test_init_with_custom_values(self):
|
|
"""Test TemplateParameter initialization with custom values."""
|
|
param = TemplateParameter(
|
|
name="custom",
|
|
default="default_value",
|
|
type="enum",
|
|
values=["a", "b", "c"],
|
|
description="Test parameter",
|
|
required=True
|
|
)
|
|
|
|
assert param.name == "custom"
|
|
assert param.default == "default_value"
|
|
assert param.type == "enum"
|
|
assert param.values == ["a", "b", "c"]
|
|
assert param.description == "Test parameter"
|
|
assert param.required is True
|
|
|
|
def test_validate_required_missing(self):
|
|
"""Test validation fails for missing required parameter."""
|
|
param = TemplateParameter(name="required_param", required=True)
|
|
|
|
with pytest.raises(ValueError, match="Required parameter"):
|
|
param.validate(None)
|
|
|
|
def test_validate_with_default(self):
|
|
"""Test validation uses default when value is None."""
|
|
param = TemplateParameter(name="param", default="default_val")
|
|
|
|
result = param.validate(None)
|
|
assert result == "default_val"
|
|
|
|
def test_validate_string_type(self):
|
|
"""Test string type validation."""
|
|
param = TemplateParameter(name="str_param", type="string")
|
|
|
|
assert param.validate("hello") == "hello"
|
|
assert param.validate(123) == "123"
|
|
|
|
def test_validate_int_type(self):
|
|
"""Test int type validation."""
|
|
param = TemplateParameter(name="int_param", type="int")
|
|
|
|
assert param.validate(42) == 42
|
|
assert param.validate("100") == 100
|
|
|
|
def test_validate_float_type(self):
|
|
"""Test float type validation."""
|
|
param = TemplateParameter(name="float_param", type="float")
|
|
|
|
assert param.validate(3.14) == 3.14
|
|
assert param.validate("2.5") == 2.5
|
|
|
|
def test_validate_boolean_type_from_string(self):
|
|
"""Test boolean type validation from string."""
|
|
param = TemplateParameter(name="bool_param", type="boolean")
|
|
|
|
assert param.validate("true") is True
|
|
assert param.validate("yes") is True
|
|
assert param.validate("1") is True
|
|
assert param.validate("on") is True
|
|
assert param.validate("false") is False
|
|
assert param.validate("no") is False
|
|
|
|
def test_validate_boolean_type_from_bool(self):
|
|
"""Test boolean type validation from bool."""
|
|
param = TemplateParameter(name="bool_param", type="boolean")
|
|
|
|
assert param.validate(True) is True
|
|
assert param.validate(False) is False
|
|
assert param.validate(1) is True
|
|
assert param.validate(0) is False
|
|
|
|
def test_validate_enum_type_valid(self):
|
|
"""Test enum type validation with valid value."""
|
|
param = TemplateParameter(
|
|
name="enum_param",
|
|
type="enum",
|
|
values=["option1", "option2", "option3"]
|
|
)
|
|
|
|
assert param.validate("option1") == "option1"
|
|
assert param.validate("option2") == "option2"
|
|
|
|
def test_validate_enum_type_invalid(self):
|
|
"""Test enum type validation with invalid value."""
|
|
param = TemplateParameter(
|
|
name="enum_param",
|
|
type="enum",
|
|
values=["option1", "option2"]
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="must be one of"):
|
|
param.validate("invalid_option")
|
|
|
|
def test_validate_list_type_from_list(self):
|
|
"""Test list type validation from list."""
|
|
param = TemplateParameter(name="list_param", type="list")
|
|
|
|
result = param.validate([1, 2, 3])
|
|
assert result == [1, 2, 3]
|
|
|
|
def test_validate_list_type_from_single_value(self):
|
|
"""Test list type validation converts single value to list."""
|
|
param = TemplateParameter(name="list_param", type="list")
|
|
|
|
result = param.validate("single")
|
|
assert result == ["single"]
|
|
|
|
def test_validate_dict_type(self):
|
|
"""Test dict type validation."""
|
|
param = TemplateParameter(name="dict_param", type="dict")
|
|
|
|
test_dict = {"key": "value"}
|
|
assert param.validate(test_dict) == test_dict
|
|
|
|
def test_validate_agent_ref_type(self):
|
|
"""Test agent_ref type validation."""
|
|
param = TemplateParameter(name="agent_param", type="agent_ref")
|
|
|
|
ref = {"type": "agent", "name": "test"}
|
|
assert param.validate(ref) == ref
|
|
|
|
def test_validate_component_ref_type(self):
|
|
"""Test component_ref type validation."""
|
|
param = TemplateParameter(name="comp_param", type="component_ref")
|
|
|
|
ref = {"type": "component", "name": "test"}
|
|
assert param.validate(ref) == ref
|
|
|
|
def test_validate_unknown_type(self):
|
|
"""Test validation with unknown type returns value as-is."""
|
|
param = TemplateParameter(name="unknown", type="unknown_type")
|
|
|
|
assert param.validate("value") == "value"
|
|
|
|
|
|
class TestComponentReference:
|
|
"""Test cases for ComponentReference class."""
|
|
|
|
def test_init(self):
|
|
"""Test ComponentReference initialization."""
|
|
ref = ComponentReference(ref_type="agent", ref_name="test_agent")
|
|
|
|
assert ref.ref_type == "agent"
|
|
assert ref.ref_name == "test_agent"
|
|
assert ref.ref_params == {}
|
|
|
|
def test_init_with_params(self):
|
|
"""Test ComponentReference initialization with params."""
|
|
params = {"param1": "value1"}
|
|
ref = ComponentReference(
|
|
ref_type="graph",
|
|
ref_name="test_graph",
|
|
ref_params=params
|
|
)
|
|
|
|
assert ref.ref_type == "graph"
|
|
assert ref.ref_name == "test_graph"
|
|
assert ref.ref_params == params
|
|
|
|
def test_resolve(self):
|
|
"""Test ComponentReference resolve method."""
|
|
ref = ComponentReference(ref_type="agent", ref_name="test")
|
|
context = InstantiationContext()
|
|
context.add_component("agent", "test", {"config": "value"})
|
|
|
|
resolved = ref.resolve(context)
|
|
|
|
assert resolved is not None
|
|
assert resolved["config"] == "value"
|
|
|
|
|
|
class TestInstantiationContext:
|
|
"""Test cases for InstantiationContext class."""
|
|
|
|
def test_init(self):
|
|
"""Test InstantiationContext initialization."""
|
|
context = InstantiationContext()
|
|
|
|
assert context.parent is None
|
|
assert "agents" in context.components
|
|
assert "graphs" in context.components
|
|
assert "streams" in context.components
|
|
|
|
def test_init_with_parent(self):
|
|
"""Test InstantiationContext initialization with parent."""
|
|
parent = InstantiationContext()
|
|
child = InstantiationContext(parent=parent)
|
|
|
|
assert child.parent is parent
|
|
|
|
def test_add_component_agent(self):
|
|
"""Test adding an agent component."""
|
|
context = InstantiationContext()
|
|
agent_config = {"type": "llm", "model": "gpt-4"}
|
|
|
|
context.add_component("agent", "test_agent", agent_config)
|
|
|
|
assert "test_agent" in context.components["agents"]
|
|
assert context.components["agents"]["test_agent"] == agent_config
|
|
|
|
def test_add_component_graph(self):
|
|
"""Test adding a graph component."""
|
|
context = InstantiationContext()
|
|
graph_config = {"nodes": {}, "edges": []}
|
|
|
|
context.add_component("graph", "test_graph", graph_config)
|
|
|
|
assert "test_graph" in context.components["graphs"]
|
|
|
|
def test_add_component_stream(self):
|
|
"""Test adding a stream component."""
|
|
context = InstantiationContext()
|
|
stream_config = {"type": "hot"}
|
|
|
|
context.add_component("stream", "test_stream", stream_config)
|
|
|
|
assert "test_stream" in context.components["streams"]
|
|
|
|
def test_resolve_reference_local(self):
|
|
"""Test resolving reference from local context."""
|
|
context = InstantiationContext()
|
|
agent_config = {"type": "llm"}
|
|
context.add_component("agent", "local_agent", agent_config)
|
|
|
|
ref = ComponentReference(ref_type="agent", ref_name="local_agent")
|
|
resolved = context.resolve_reference(ref)
|
|
|
|
assert resolved == agent_config
|
|
|
|
def test_resolve_reference_parent(self):
|
|
"""Test resolving reference from parent context."""
|
|
parent = InstantiationContext()
|
|
parent.add_component("agent", "parent_agent", {"type": "tool"})
|
|
|
|
child = InstantiationContext(parent=parent)
|
|
ref = ComponentReference(ref_type="agent", ref_name="parent_agent")
|
|
|
|
resolved = child.resolve_reference(ref)
|
|
|
|
assert resolved is not None
|
|
assert resolved["type"] == "tool"
|
|
|
|
def test_resolve_reference_not_found(self):
|
|
"""Test resolving reference that doesn't exist returns None."""
|
|
context = InstantiationContext()
|
|
ref = ComponentReference(ref_type="agent", ref_name="missing")
|
|
|
|
resolved = context.resolve_reference(ref)
|
|
|
|
assert resolved is None
|
|
|
|
def test_resolve_pending_success(self):
|
|
"""Test resolve_pending when references can be resolved."""
|
|
context = InstantiationContext()
|
|
|
|
# Add a pending reference
|
|
ref = ComponentReference(ref_type="agent", ref_name="deferred")
|
|
context.resolve_reference(ref) # Adds to pending
|
|
|
|
# Now add the component
|
|
context.add_component("agent", "deferred", {"type": "llm"})
|
|
|
|
# Should not raise
|
|
context.resolve_pending()
|
|
|
|
def test_resolve_pending_failure(self):
|
|
"""Test resolve_pending raises error for unresolvable references."""
|
|
context = InstantiationContext()
|
|
|
|
# Add a reference that can't be resolved
|
|
ref = ComponentReference(ref_type="agent", ref_name="missing")
|
|
context.resolve_reference(ref)
|
|
|
|
with pytest.raises(ValueError, match="Cannot resolve references"):
|
|
context.resolve_pending()
|
|
|
|
def test_get_all_components(self):
|
|
"""Test getting all components returns deep copy."""
|
|
context = InstantiationContext()
|
|
context.add_component("agent", "agent1", {"type": "llm"})
|
|
context.add_component("graph", "graph1", {"nodes": {}})
|
|
|
|
all_components = context.get_all_components()
|
|
|
|
assert "agents" in all_components
|
|
assert "graphs" in all_components
|
|
assert "agent1" in all_components["agents"]
|
|
assert "graph1" in all_components["graphs"]
|
|
|
|
# Verify it's a deep copy
|
|
all_components["agents"]["agent1"]["modified"] = True
|
|
assert "modified" not in context.components["agents"]["agent1"]
|
|
|
|
|
|
class ConcreteTemplate(BaseTemplate):
|
|
"""Concrete implementation of BaseTemplate for testing."""
|
|
|
|
def instantiate(self, params, registry, context):
|
|
"""Simple instantiation for testing."""
|
|
filled = self.validate_params(params)
|
|
return self._apply_template_vars(self.definition, filled)
|
|
|
|
|
|
class TestBaseTemplate:
|
|
"""Test cases for BaseTemplate class."""
|
|
|
|
def test_init(self):
|
|
"""Test BaseTemplate initialization."""
|
|
definition = {"type": "llm", "parameters": {}}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
assert template.name == "test"
|
|
assert template.template_type == TemplateType.AGENT
|
|
assert template.definition == definition
|
|
|
|
def test_parse_parameters_dict_format(self):
|
|
"""Test parsing parameters in dict format."""
|
|
definition = {
|
|
"parameters": {
|
|
"param1": {"type": "string", "default": "value1"},
|
|
"param2": {"type": "int", "required": True}
|
|
}
|
|
}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
assert "param1" in template.parameters
|
|
assert "param2" in template.parameters
|
|
assert template.parameters["param1"].type == "string"
|
|
assert template.parameters["param2"].required is True
|
|
|
|
def test_parse_parameters_dict_simple_values(self):
|
|
"""Test parsing parameters with simple default values."""
|
|
definition = {
|
|
"parameters": {
|
|
"param1": "default_value",
|
|
"param2": 42
|
|
}
|
|
}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
assert template.parameters["param1"].default == "default_value"
|
|
assert template.parameters["param2"].default == 42
|
|
|
|
def test_parse_parameters_list_format(self):
|
|
"""Test parsing parameters in list format."""
|
|
definition = {
|
|
"parameters": [
|
|
{"name": "param1", "type": "string"},
|
|
{"name": "param2", "type": "int"}
|
|
]
|
|
}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
assert "param1" in template.parameters
|
|
assert "param2" in template.parameters
|
|
|
|
def test_parse_parameters_list_simple_names(self):
|
|
"""Test parsing parameters as simple list of names."""
|
|
definition = {
|
|
"parameters": ["param1", "param2", "param3"]
|
|
}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
assert "param1" in template.parameters
|
|
assert "param2" in template.parameters
|
|
assert "param3" in template.parameters
|
|
|
|
def test_parse_parameters_no_parameters(self):
|
|
"""Test parsing when no parameters defined."""
|
|
definition = {"type": "llm"}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
assert template.parameters == {}
|
|
|
|
def test_validate_params(self):
|
|
"""Test parameter validation."""
|
|
definition = {
|
|
"parameters": {
|
|
"param1": {"type": "string", "default": "default"},
|
|
"param2": {"type": "int", "required": True}
|
|
}
|
|
}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template.validate_params({"param2": 42})
|
|
|
|
assert result["param1"] == "default"
|
|
assert result["param2"] == 42
|
|
|
|
def test_validate_params_extra_params(self):
|
|
"""Test that extra params are included."""
|
|
definition = {"parameters": {"param1": "default"}}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template.validate_params({"param1": "value", "extra": "included"})
|
|
|
|
assert result["extra"] == "included"
|
|
|
|
def test_apply_template_vars_string_simple(self):
|
|
"""Test applying template vars to simple string."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template._apply_template_vars("{{ name }}", {"name": "test_value"})
|
|
|
|
assert result == "test_value"
|
|
|
|
def test_apply_template_vars_string_no_template(self):
|
|
"""Test string without template syntax."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template._apply_template_vars("plain string", {})
|
|
|
|
assert result == "plain string"
|
|
|
|
def test_apply_template_vars_boolean_true(self):
|
|
"""Test rendering boolean true."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template._apply_template_vars("{{ flag }}", {"flag": "true"})
|
|
|
|
assert result is True
|
|
|
|
def test_apply_template_vars_boolean_false(self):
|
|
"""Test rendering boolean false."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template._apply_template_vars("{{ flag }}", {"flag": "false"})
|
|
|
|
assert result is False
|
|
|
|
def test_apply_template_vars_int(self):
|
|
"""Test rendering integer."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template._apply_template_vars("{{ count }}", {"count": 42})
|
|
|
|
assert result == 42
|
|
|
|
def test_apply_template_vars_float(self):
|
|
"""Test rendering float."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template._apply_template_vars("{{ value }}", {"value": 3.14})
|
|
|
|
assert result == 3.14
|
|
|
|
def test_apply_template_vars_list(self):
|
|
"""Test rendering list."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template._apply_template_vars("{{ items }}", {"items": "[1, 2, 3]"})
|
|
|
|
assert result == [1, 2, 3]
|
|
|
|
def test_apply_template_vars_dict(self):
|
|
"""Test rendering dict."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
result = template._apply_template_vars('{{ data }}', {"data": '{"key": "value"}'})
|
|
|
|
assert result == {"key": "value"}
|
|
|
|
def test_apply_template_vars_dict_recursive(self):
|
|
"""Test applying template vars recursively to dict."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
config = {
|
|
"name": "{{ agent_name }}",
|
|
"nested": {
|
|
"value": "{{ nested_value }}"
|
|
}
|
|
}
|
|
params = {"agent_name": "test_agent", "nested_value": "nested"}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
assert result["name"] == "test_agent"
|
|
assert result["nested"]["value"] == "nested"
|
|
|
|
def test_apply_template_vars_list_items(self):
|
|
"""Test applying template vars to list items."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
config = ["{{ item1 }}", "{{ item2 }}", "static"]
|
|
params = {"item1": "value1", "item2": "value2"}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
assert result == ["value1", "value2", "static"]
|
|
|
|
def test_apply_template_vars_conditional_true(self):
|
|
"""Test conditional template block when condition is true."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
config = {
|
|
"{% if include %}": "included: true"
|
|
}
|
|
params = {"include": True}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
assert result is not None
|
|
|
|
def test_apply_template_vars_conditional_false(self):
|
|
"""Test conditional template block when condition is false."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
config = {
|
|
"{% if include %}": "included: true"
|
|
}
|
|
params = {"include": False}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
assert result is None
|
|
|
|
def test_apply_template_vars_dict_key_templating(self):
|
|
"""Test applying templates to dict keys."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
config = {
|
|
"{{ key_name }}": "value"
|
|
}
|
|
params = {"key_name": "dynamic_key"}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
assert "dynamic_key" in result
|
|
assert result["dynamic_key"] == "value"
|
|
|
|
def test_apply_template_vars_filters_none_values(self):
|
|
"""Test that None values are filtered from dicts."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
config = {
|
|
"keep": "value",
|
|
"remove": None
|
|
}
|
|
params = {}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
assert "keep" in result
|
|
# None values should be filtered out
|
|
assert "remove" not in result or result.get("remove") is None
|
|
|
|
def test_apply_template_vars_rendering_error(self):
|
|
"""Test handling of template rendering with undefined variables."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
# Template with undefined variable renders as empty string in Jinja2
|
|
config = "{{ undefined_var }}"
|
|
params = {}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
# Jinja2 renders undefined vars as empty string by default
|
|
assert result == ""
|
|
|
|
def test_merge_params(self):
|
|
"""Test merging parameter dictionaries."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
base = {"param1": "base1", "param2": "base2"}
|
|
override = {"param2": "override2", "param3": "override3"}
|
|
|
|
result = template._merge_params(base, override)
|
|
|
|
assert result["param1"] == "base1"
|
|
assert result["param2"] == "override2"
|
|
assert result["param3"] == "override3"
|
|
|
|
def test_merge_params_with_template_vars(self):
|
|
"""Test merging params applies template vars to overrides."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
base = {"name": "test"}
|
|
override = {"model": "{{ name }}_model"}
|
|
|
|
result = template._merge_params(base, override)
|
|
|
|
assert result["model"] == "test_model"
|
|
|
|
def test_merge_params_preserves_base(self):
|
|
"""Test that merge doesn't modify base params."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
base = {"param": "value"}
|
|
override = {"param": "new_value"}
|
|
|
|
result = template._merge_params(base, override)
|
|
|
|
assert base["param"] == "value" # Original unchanged
|
|
assert result["param"] == "new_value"
|
|
|
|
def test_apply_template_vars_json_parse_error(self):
|
|
"""Test handling JSON parse error for dict-like strings."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
# String that looks like dict but has really invalid JSON
|
|
config = "{{ data }}"
|
|
params = {"data": "{not json at all}"}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
# Should return as string when JSON parsing fails
|
|
assert isinstance(result, str)
|
|
|
|
def test_apply_template_vars_list_with_none_items(self):
|
|
"""Test that None items are filtered from lists."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
config = ["item1", None, "item2"]
|
|
params = {}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
# None should be filtered out
|
|
assert None not in result
|
|
assert "item1" in result
|
|
assert "item2" in result
|
|
|
|
def test_apply_template_vars_conditional_yaml_parse_error(self):
|
|
"""Test conditional block with YAML parse error."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
# Conditional that renders invalid YAML
|
|
config = {
|
|
"{% if enabled %}": ": invalid yaml :::"
|
|
}
|
|
params = {"enabled": True}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
# Should handle the error gracefully
|
|
assert result is not None
|
|
|
|
def test_apply_template_vars_jinja_exception(self):
|
|
"""Test handling Jinja2 rendering exception."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
# Template that will cause an exception (division by zero)
|
|
config = "{{ 1 / 0 }}"
|
|
params = {}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
# Should return original config on exception
|
|
assert result == config
|
|
|
|
def test_apply_template_vars_number_parsing_error(self):
|
|
"""Test number parsing fallback to string."""
|
|
definition = {}
|
|
template = ConcreteTemplate("test", TemplateType.AGENT, definition)
|
|
|
|
# Template that renders to non-numeric string
|
|
config = "{{ value }}"
|
|
params = {"value": "not_a_number"}
|
|
|
|
result = template._apply_template_vars(config, params)
|
|
|
|
# Should return as string when number parsing fails
|
|
assert result == "not_a_number"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|
|
|