""" Unit tests for template service """ import pytest import json from pathlib import Path from unittest.mock import Mock, MagicMock, patch, mock_open from src.templating.service import TemplateService from src.database.models import GeneratedContent, SiteDeployment @pytest.fixture def mock_content_repo(): return Mock() @pytest.fixture def mock_site_deployment_repo(): return Mock() @pytest.fixture def template_service(mock_content_repo): return TemplateService(content_repo=mock_content_repo) @pytest.fixture def mock_site_deployment(): deployment = Mock(spec=SiteDeployment) deployment.id = 1 deployment.custom_hostname = "test.example.com" deployment.site_name = "Test Site" return deployment class TestGetAvailableTemplates: def test_returns_list_of_template_names(self, template_service): """Test that available templates are returned""" templates = template_service.get_available_templates() assert isinstance(templates, list) assert len(templates) >= 4 assert "basic" in templates assert "modern" in templates assert "classic" in templates assert "minimal" in templates def test_templates_are_sorted(self, template_service): """Test that templates are returned in sorted order""" templates = template_service.get_available_templates() assert templates == sorted(templates) class TestLoadTemplate: def test_load_valid_template(self, template_service): """Test loading a valid template""" template_content = template_service.load_template("basic") assert isinstance(template_content, str) assert len(template_content) > 0 assert "" in template_content assert "{{ title }}" in template_content assert "{{ content }}" in template_content def test_load_all_templates(self, template_service): """Test that all templates can be loaded""" for template_name in ["basic", "modern", "classic", "minimal"]: template_content = template_service.load_template(template_name) assert len(template_content) > 0 def test_template_caching(self, template_service): """Test that templates are cached after first load""" template_service.load_template("basic") assert "basic" in template_service._template_cache cached_content = template_service._template_cache["basic"] loaded_content = template_service.load_template("basic") assert cached_content == loaded_content def test_load_nonexistent_template(self, template_service): """Test that loading nonexistent template raises error""" with pytest.raises(FileNotFoundError) as exc_info: template_service.load_template("nonexistent") assert "nonexistent" in str(exc_info.value) assert "not found" in str(exc_info.value).lower() class TestSelectTemplateForContent: def test_select_random_when_no_site_deployment(self, template_service): """Test random selection when site_deployment_id is None""" template_name = template_service.select_template_for_content( site_deployment_id=None, site_deployment_repo=None ) available_templates = template_service.get_available_templates() assert template_name in available_templates @patch('src.templating.service.get_config') def test_use_existing_mapping( self, mock_get_config, template_service, mock_site_deployment, mock_site_deployment_repo ): """Test using existing template mapping from config""" mock_config = Mock() mock_config.templates.mappings = { "test.example.com": "modern" } mock_get_config.return_value = mock_config mock_site_deployment_repo.get_by_id.return_value = mock_site_deployment template_name = template_service.select_template_for_content( site_deployment_id=1, site_deployment_repo=mock_site_deployment_repo ) assert template_name == "modern" mock_site_deployment_repo.get_by_id.assert_called_once_with(1) @patch('src.templating.service.get_config') @patch('builtins.open', new_callable=mock_open) @patch('pathlib.Path.exists', return_value=True) def test_create_new_mapping( self, mock_exists, mock_file, mock_get_config, template_service, mock_site_deployment, mock_site_deployment_repo ): """Test creating new mapping when hostname not in config""" mock_config = Mock() mock_config.templates.mappings = {} mock_get_config.return_value = mock_config mock_file.return_value.read.return_value = json.dumps({ "templates": {"default": "basic", "mappings": {}} }) mock_site_deployment_repo.get_by_id.return_value = mock_site_deployment template_name = template_service.select_template_for_content( site_deployment_id=1, site_deployment_repo=mock_site_deployment_repo ) available_templates = template_service.get_available_templates() assert template_name in available_templates class TestFormatContent: def test_format_with_basic_template(self, template_service): """Test formatting content with basic template""" content = "
Test paragraph.
" title = "Test Article" meta = "Test meta description" formatted = template_service.format_content( content=content, title=title, meta_description=meta, template_name="basic" ) assert "" in formatted assert "Test Article" in formatted assert "Test meta description" in formatted assert "Test paragraph.
" in formatted def test_format_with_all_templates(self, template_service): """Test formatting with all available templates""" content = "Content.
" title = "Title" meta = "Description" for template_name in ["basic", "modern", "classic", "minimal"]: formatted = template_service.format_content( content=content, title=title, meta_description=meta, template_name=template_name ) assert len(formatted) > 0 assert "Title" in formatted assert "Description" in formatted assert content in formatted def test_html_escaping_in_title(self, template_service): """Test that HTML is escaped in title""" content = "Content
" title = "Title with " meta = "Description" formatted = template_service.format_content( content=content, title=title, meta_description=meta, template_name="basic" ) assert "<script>" in formatted assert "