""" Tests for prompt templates and PromptLoader module. Task 1: Test prompt template files exist with variable placeholders. Task 2: Test PromptLoader loads and renders templates correctly. """ import pytest from pathlib import Path # Path to prompts directory PROMPTS_DIR = Path(__file__).parent.parent / "src" / "gsd_openclaw" / "prompts" class TestPromptTemplatesExist: """Test that prompt template files exist and contain variable placeholders.""" def test_context_recovery_template_exists(self): """context_recovery.md template exists.""" template_path = PROMPTS_DIR / "context_recovery.md" assert template_path.exists(), f"Template not found: {template_path}" def test_command_mapping_template_exists(self): """command_mapping.md template exists.""" template_path = PROMPTS_DIR / "command_mapping.md" assert template_path.exists(), f"Template not found: {template_path}" def test_error_recovery_template_exists(self): """error_recovery.md template exists.""" template_path = PROMPTS_DIR / "error_recovery.md" assert template_path.exists(), f"Template not found: {template_path}" def test_templates_contain_variable_placeholders(self): """All templates contain {{variable}} placeholders.""" template_files = [ PROMPTS_DIR / "context_recovery.md", PROMPTS_DIR / "command_mapping.md", PROMPTS_DIR / "error_recovery.md", ] for template_path in template_files: content = template_path.read_text(encoding='utf-8') # Check for at least one {{variable}} pattern assert "{{" in content and "}}" in content, \ f"Template {template_path.name} has no {{variable}} placeholders" class TestPromptLoader: """Test PromptLoader class for loading and rendering templates.""" def test_render_substitutes_variables(self): """PromptLoader.render substitutes variables correctly.""" from gsd_openclaw.prompt_loader import PromptLoader loader = PromptLoader(PROMPTS_DIR) result = loader.render( "context_recovery", project_name="test-project", last_active_at="2026-03-11", current_phase="Phase 1", command_count="5", last_output_snapshot="Last output" ) assert "test-project" in result assert "{{project_name}}" not in result def test_render_handles_missing_variables(self): """PromptLoader.render leaves missing variables as literal {{variable}}.""" from gsd_openclaw.prompt_loader import PromptLoader loader = PromptLoader(PROMPTS_DIR) # Render with only partial variables - missing ones should remain as {{var}} result = loader.render( "context_recovery", project_name="test-project" # Missing: last_active_at, current_phase, etc. ) # Should have substituted project_name assert "test-project" in result # Missing variables should remain as {{variable}} assert "{{last_active_at}}" in result or "{{current_phase}}" in result def test_render_raises_for_missing_template(self): """PromptLoader.render raises FileNotFoundError for missing template.""" from gsd_openclaw.prompt_loader import PromptLoader loader = PromptLoader(PROMPTS_DIR) with pytest.raises(FileNotFoundError, match="Template not found"): loader.render("nonexistent_template") def test_get_returns_raw_template_content(self): """PromptLoader.get returns raw template content (cached).""" from gsd_openclaw.prompt_loader import PromptLoader loader = PromptLoader(PROMPTS_DIR) content = loader.get("context_recovery") assert isinstance(content, str) assert "{{project_name}}" in content assert len(content) > 0 def test_get_caches_template(self): """PromptLoader caches templates after first load.""" from gsd_openclaw.prompt_loader import PromptLoader loader = PromptLoader(PROMPTS_DIR) # First load content1 = loader.get("context_recovery") # Second load (should be from cache) content2 = loader.get("context_recovery") # Should be the same object (cached) assert content1 == content2 assert "context_recovery" in loader._cache def test_default_template_dir(self): """PromptLoader uses default prompts directory when none specified.""" from gsd_openclaw.prompt_loader import PromptLoader loader = PromptLoader() expected_dir = Path(__file__).parent.parent / "src" / "gsd_openclaw" / "prompts" assert loader.template_dir == expected_dir