""" Unit tests for URL generation """ import pytest from unittest.mock import Mock, MagicMock from src.generation.url_generator import generate_slug, generate_urls_for_batch from src.database.models import GeneratedContent, SiteDeployment class TestGenerateSlug: """Tests for generate_slug function""" def test_basic_slug_generation(self): assert generate_slug("How to Fix Your Engine") == "how-to-fix-your-engine" def test_slug_with_numbers(self): assert generate_slug("10 Best SEO Tips for 2024") == "10-best-seo-tips-for-2024" def test_slug_with_special_characters(self): assert generate_slug("C++ Programming Guide") == "c-programming-guide" assert generate_slug("SEO Tips & Tricks!") == "seo-tips-tricks" def test_slug_with_multiple_spaces(self): assert generate_slug("How to Fix") == "how-to-fix" def test_slug_with_leading_trailing_hyphens(self): assert generate_slug("---Title---") == "title" def test_slug_max_length(self): long_title = "a" * 200 slug = generate_slug(long_title, max_length=100) assert len(slug) == 100 def test_empty_string_fallback(self): assert generate_slug("") == "article" assert generate_slug("!!!") == "article" assert generate_slug(" ") == "article" def test_unicode_characters(self): slug = generate_slug("Café Programming Guide") assert "caf" in slug.lower() class TestGenerateUrlsForBatch: """Tests for generate_urls_for_batch function""" def test_url_generation_with_custom_hostname(self): content = Mock(spec=GeneratedContent) content.id = 1 content.title = "How to Fix Engines" content.tier = "tier1" content.site_deployment_id = 10 site = Mock(spec=SiteDeployment) site.id = 10 site.custom_hostname = "www.example.com" site.pull_zone_bcdn_hostname = "example.b-cdn.net" site_repo = Mock() site_repo.get_by_id.return_value = site urls = generate_urls_for_batch([content], site_repo) assert len(urls) == 1 assert urls[0]["content_id"] == 1 assert urls[0]["title"] == "How to Fix Engines" assert urls[0]["url"] == "https://www.example.com/how-to-fix-engines.html" assert urls[0]["tier"] == "tier1" assert urls[0]["slug"] == "how-to-fix-engines" assert urls[0]["hostname"] == "www.example.com" def test_url_generation_with_bcdn_hostname_only(self): content = Mock(spec=GeneratedContent) content.id = 2 content.title = "SEO Guide" content.tier = "tier2" content.site_deployment_id = 20 site = Mock(spec=SiteDeployment) site.id = 20 site.custom_hostname = None site.pull_zone_bcdn_hostname = "mysite123.b-cdn.net" site_repo = Mock() site_repo.get_by_id.return_value = site urls = generate_urls_for_batch([content], site_repo) assert len(urls) == 1 assert urls[0]["url"] == "https://mysite123.b-cdn.net/seo-guide.html" assert urls[0]["hostname"] == "mysite123.b-cdn.net" def test_error_if_missing_site_deployment_id(self): content = Mock(spec=GeneratedContent) content.id = 3 content.title = "Test" content.site_deployment_id = None site_repo = Mock() with pytest.raises(ValueError, match="missing site_deployment_id"): generate_urls_for_batch([content], site_repo) def test_error_if_site_not_found(self): content = Mock(spec=GeneratedContent) content.id = 4 content.title = "Test" content.site_deployment_id = 999 site_repo = Mock() site_repo.get_by_id.return_value = None with pytest.raises(ValueError, match="not found"): generate_urls_for_batch([content], site_repo) def test_fallback_slug_for_empty_title(self): content = Mock(spec=GeneratedContent) content.id = 5 content.title = "!!!" content.tier = "tier1" content.site_deployment_id = 10 site = Mock(spec=SiteDeployment) site.id = 10 site.custom_hostname = "www.example.com" site.pull_zone_bcdn_hostname = "example.b-cdn.net" site_repo = Mock() site_repo.get_by_id.return_value = site urls = generate_urls_for_batch([content], site_repo) assert urls[0]["slug"] == "article-5" assert urls[0]["url"] == "https://www.example.com/article-5.html" def test_multiple_articles(self): content1 = Mock(spec=GeneratedContent) content1.id = 1 content1.title = "Article One" content1.tier = "tier1" content1.site_deployment_id = 10 content2 = Mock(spec=GeneratedContent) content2.id = 2 content2.title = "Article Two" content2.tier = "tier2" content2.site_deployment_id = 20 site1 = Mock(spec=SiteDeployment) site1.id = 10 site1.custom_hostname = "www.site1.com" site1.pull_zone_bcdn_hostname = "site1.b-cdn.net" site2 = Mock(spec=SiteDeployment) site2.id = 20 site2.custom_hostname = None site2.pull_zone_bcdn_hostname = "site2.b-cdn.net" site_repo = Mock() site_repo.get_by_id.side_effect = lambda sid: site1 if sid == 10 else site2 urls = generate_urls_for_batch([content1, content2], site_repo) assert len(urls) == 2 assert urls[0]["url"] == "https://www.site1.com/article-one.html" assert urls[1]["url"] == "https://site2.b-cdn.net/article-two.html"