Skip to main content
Glama

basic-memory

test_template_loader.py8.04 kB
"""Tests for the template loader functionality.""" import datetime import pytest from pathlib import Path from basic_memory.api.template_loader import TemplateLoader @pytest.fixture def temp_template_dir(tmpdir): """Create a temporary directory for test templates.""" template_dir = tmpdir.mkdir("templates").mkdir("prompts") return template_dir @pytest.fixture def custom_template_loader(temp_template_dir): """Return a TemplateLoader instance with a custom template directory.""" return TemplateLoader(str(temp_template_dir)) @pytest.fixture def simple_template(temp_template_dir): """Create a simple test template.""" template_path = temp_template_dir / "simple.hbs" template_path.write_text("Hello, {{name}}!", encoding="utf-8") return "simple.hbs" @pytest.mark.asyncio async def test_render_simple_template(custom_template_loader, simple_template): """Test rendering a simple template.""" context = {"name": "World"} result = await custom_template_loader.render(simple_template, context) assert result == "Hello, World!" @pytest.mark.asyncio async def test_template_cache(custom_template_loader, simple_template): """Test that templates are cached.""" context = {"name": "World"} # First render, should load template await custom_template_loader.render(simple_template, context) # Check that template is in cache assert simple_template in custom_template_loader.template_cache # Modify the template file - shouldn't affect the cached version template_path = Path(custom_template_loader.template_dir) / simple_template template_path.write_text("Goodbye, {{name}}!", encoding="utf-8") # Second render, should use cached template result = await custom_template_loader.render(simple_template, context) assert result == "Hello, World!" # Clear cache and render again - should use updated template custom_template_loader.clear_cache() assert simple_template not in custom_template_loader.template_cache result = await custom_template_loader.render(simple_template, context) assert result == "Goodbye, World!" @pytest.mark.asyncio async def test_date_helper(custom_template_loader, temp_template_dir): # Test date helper date_path = temp_template_dir / "date.hbs" date_path.write_text("{{date timestamp}}", encoding="utf-8") date_result = await custom_template_loader.render( "date.hbs", {"timestamp": datetime.datetime(2023, 1, 1, 12, 30)} ) assert "2023-01-01" in date_result @pytest.mark.asyncio async def test_default_helper(custom_template_loader, temp_template_dir): # Test default helper default_path = temp_template_dir / "default.hbs" default_path.write_text("{{default null 'default-value'}}", encoding="utf-8") default_result = await custom_template_loader.render("default.hbs", {"null": None}) assert default_result == "default-value" @pytest.mark.asyncio async def test_capitalize_helper(custom_template_loader, temp_template_dir): # Test capitalize helper capitalize_path = temp_template_dir / "capitalize.hbs" capitalize_path.write_text("{{capitalize 'test'}}", encoding="utf-8") capitalize_result = await custom_template_loader.render("capitalize.hbs", {}) assert capitalize_result == "Test" @pytest.mark.asyncio async def test_size_helper(custom_template_loader, temp_template_dir): # Test size helper size_path = temp_template_dir / "size.hbs" size_path.write_text("{{size collection}}", encoding="utf-8") size_result = await custom_template_loader.render("size.hbs", {"collection": [1, 2, 3]}) assert size_result == "3" @pytest.mark.asyncio async def test_json_helper(custom_template_loader, temp_template_dir): # Test json helper json_path = temp_template_dir / "json.hbs" json_path.write_text("{{json data}}", encoding="utf-8") json_result = await custom_template_loader.render("json.hbs", {"data": {"key": "value"}}) assert json_result == '{"key": "value"}' @pytest.mark.asyncio async def test_less_than_helper(custom_template_loader, temp_template_dir): # Test lt (less than) helper lt_path = temp_template_dir / "lt.hbs" lt_path.write_text("{{#if_cond (lt 2 3)}}true{{else}}false{{/if_cond}}", encoding="utf-8") lt_result = await custom_template_loader.render("lt.hbs", {}) assert lt_result == "true" @pytest.mark.asyncio async def test_file_not_found(custom_template_loader): """Test that FileNotFoundError is raised when a template doesn't exist.""" with pytest.raises(FileNotFoundError): await custom_template_loader.render("non_existent_template.hbs", {}) @pytest.mark.asyncio async def test_extension_handling(custom_template_loader, temp_template_dir): """Test that template extensions are handled correctly.""" # Create template with .hbs extension template_path = temp_template_dir / "test_extension.hbs" template_path.write_text("Template with extension: {{value}}", encoding="utf-8") # Test accessing with full extension result = await custom_template_loader.render("test_extension.hbs", {"value": "works"}) assert result == "Template with extension: works" # Test accessing without extension result = await custom_template_loader.render("test_extension", {"value": "also works"}) assert result == "Template with extension: also works" # Test accessing with wrong extension gets converted template_path = temp_template_dir / "liquid_template.hbs" template_path.write_text("Liquid template: {{value}}", encoding="utf-8") result = await custom_template_loader.render("liquid_template.liquid", {"value": "converted"}) assert result == "Liquid template: converted" @pytest.mark.asyncio async def test_dedent_helper(custom_template_loader, temp_template_dir): """Test the dedent helper for text blocks.""" dedent_path = temp_template_dir / "dedent.hbs" # Create a template with indented text blocks template_content = """Before {{#dedent}} This is indented text with nested indentation that should be dedented while preserving relative indentation {{/dedent}} After""" dedent_path.write_text(template_content, encoding="utf-8") # Render the template result = await custom_template_loader.render("dedent.hbs", {}) # Print the actual output for debugging print(f"Dedent helper result: {repr(result)}") # Check that the indentation is properly removed assert "This is indented text" in result assert "with nested indentation" in result assert "that should be dedented" in result assert "while preserving relative indentation" in result assert "Before" in result assert "After" in result # Check that relative indentation is preserved assert result.find("with nested indentation") > result.find("This is indented text") @pytest.mark.asyncio async def test_nested_dedent_helper(custom_template_loader, temp_template_dir): """Test the dedent helper with nested content.""" dedent_path = temp_template_dir / "nested_dedent.hbs" # Create a template with nested indented blocks template_content = """ {{#each items}} {{#dedent}} --- Item {{this}} Details for item {{this}} - Indented detail 1 - Indented detail 2 {{/dedent}} {{/each}}""" dedent_path.write_text(template_content, encoding="utf-8") # Render the template result = await custom_template_loader.render("nested_dedent.hbs", {"items": [1, 2]}) # Print the actual output for debugging print(f"Actual result: {repr(result)}") # Use a more flexible assertion that checks individual components # instead of exact string matching assert "--- Item 1" in result assert "Details for item 1" in result assert "- Indented detail 1" in result assert "--- Item 2" in result assert "Details for item 2" in result assert "- Indented detail 2" in result

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/basicmachines-co/basic-memory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server