Content Calendar, Content Gap Analysis, and Content Optimization
This commit is contained in:
185
lib/ai_seo_tools/content_calendar/tests/test_ai_generator.py
Normal file
185
lib/ai_seo_tools/content_calendar/tests/test_ai_generator.py
Normal file
@@ -0,0 +1,185 @@
|
||||
import unittest
|
||||
from typing import Dict, Any
|
||||
|
||||
from ..models.calendar import ContentType
|
||||
from ..core.ai_generator import AIContentGenerator
|
||||
|
||||
class TestAIContentGenerator(unittest.TestCase):
|
||||
"""Test cases for AIContentGenerator."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test cases."""
|
||||
self.generator = AIContentGenerator()
|
||||
self.test_title = "10 Ways to Improve Your SEO Strategy"
|
||||
self.test_content_type = ContentType.BLOG_POST
|
||||
self.test_context = {
|
||||
"website_url": "https://example.com",
|
||||
"target_audience": "digital marketers",
|
||||
"content_goals": ["educate", "generate leads"]
|
||||
}
|
||||
|
||||
def test_generate_headings(self):
|
||||
"""Test heading generation."""
|
||||
headings = self.generator.generate_headings(
|
||||
title=self.test_title,
|
||||
content_type=self.test_content_type,
|
||||
context=self.test_context
|
||||
)
|
||||
|
||||
self.assertIsInstance(headings, list)
|
||||
for heading in headings:
|
||||
self.assertIn('title', heading)
|
||||
self.assertIn('level', heading)
|
||||
self.assertIn('keywords', heading)
|
||||
self.assertIn('summary', heading)
|
||||
|
||||
# Verify heading level
|
||||
self.assertEqual(heading['level'], 1)
|
||||
|
||||
# Verify heading content
|
||||
self.assertIsInstance(heading['title'], str)
|
||||
self.assertIsInstance(heading['keywords'], list)
|
||||
self.assertIsInstance(heading['summary'], str)
|
||||
|
||||
def test_generate_subheadings(self):
|
||||
"""Test subheading generation."""
|
||||
main_heading = {
|
||||
'title': 'Understanding SEO Basics',
|
||||
'level': 1,
|
||||
'keywords': ['SEO', 'basics', 'fundamentals'],
|
||||
'summary': 'Introduction to core SEO concepts'
|
||||
}
|
||||
|
||||
subheadings = self.generator.generate_subheadings(
|
||||
main_heading=main_heading,
|
||||
content_type=self.test_content_type,
|
||||
context=self.test_context
|
||||
)
|
||||
|
||||
self.assertIsInstance(subheadings, list)
|
||||
for subheading in subheadings:
|
||||
self.assertIn('title', subheading)
|
||||
self.assertIn('level', subheading)
|
||||
self.assertIn('keywords', subheading)
|
||||
self.assertIn('summary', subheading)
|
||||
|
||||
# Verify subheading level
|
||||
self.assertEqual(subheading['level'], 2)
|
||||
|
||||
# Verify subheading content
|
||||
self.assertIsInstance(subheading['title'], str)
|
||||
self.assertIsInstance(subheading['keywords'], list)
|
||||
self.assertIsInstance(subheading['summary'], str)
|
||||
|
||||
def test_generate_key_points(self):
|
||||
"""Test key points generation."""
|
||||
key_points = self.generator.generate_key_points(
|
||||
title=self.test_title,
|
||||
content_type=self.test_content_type,
|
||||
context=self.test_context
|
||||
)
|
||||
|
||||
self.assertIsInstance(key_points, list)
|
||||
for point in key_points:
|
||||
self.assertIn('point', point)
|
||||
self.assertIn('importance', point)
|
||||
self.assertIn('supporting_evidence', point)
|
||||
self.assertIn('related_keywords', point)
|
||||
|
||||
# Verify point content
|
||||
self.assertIsInstance(point['point'], str)
|
||||
self.assertIn(point['importance'], ['high', 'medium', 'low'])
|
||||
self.assertIsInstance(point['supporting_evidence'], list)
|
||||
self.assertIsInstance(point['related_keywords'], list)
|
||||
|
||||
def test_generate_content_flow(self):
|
||||
"""Test content flow generation."""
|
||||
outline = {
|
||||
'main_headings': [
|
||||
{
|
||||
'title': 'Introduction',
|
||||
'level': 1,
|
||||
'keywords': ['SEO', 'introduction'],
|
||||
'summary': 'Overview of SEO importance'
|
||||
}
|
||||
],
|
||||
'subheadings': {
|
||||
'Introduction': [
|
||||
{
|
||||
'title': 'What is SEO?',
|
||||
'level': 2,
|
||||
'keywords': ['definition', 'basics'],
|
||||
'summary': 'Basic definition of SEO'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
flow = self.generator.generate_content_flow(
|
||||
title=self.test_title,
|
||||
content_type=self.test_content_type,
|
||||
outline=outline
|
||||
)
|
||||
|
||||
self.assertIsInstance(flow, dict)
|
||||
self.assertIn('introduction', flow)
|
||||
self.assertIn('main_sections', flow)
|
||||
self.assertIn('conclusion', flow)
|
||||
self.assertIn('transitions', flow)
|
||||
self.assertIn('content_pacing', flow)
|
||||
|
||||
# Verify flow content
|
||||
self.assertIsInstance(flow['introduction'], dict)
|
||||
self.assertIsInstance(flow['main_sections'], list)
|
||||
self.assertIsInstance(flow['conclusion'], dict)
|
||||
self.assertIsInstance(flow['transitions'], list)
|
||||
self.assertIsInstance(flow['content_pacing'], dict)
|
||||
|
||||
def test_prompt_creation(self):
|
||||
"""Test prompt creation methods."""
|
||||
# Test heading prompt
|
||||
heading_prompt = self.generator._create_heading_prompt(
|
||||
title=self.test_title,
|
||||
content_type=self.test_content_type,
|
||||
gaps={'opportunities': ['keyword research', 'content optimization']}
|
||||
)
|
||||
self.assertIsInstance(heading_prompt, str)
|
||||
self.assertIn(self.test_title, heading_prompt)
|
||||
self.assertIn(self.test_content_type.value, heading_prompt)
|
||||
|
||||
# Test subheading prompt
|
||||
main_heading = {
|
||||
'title': 'Understanding SEO Basics',
|
||||
'level': 1,
|
||||
'keywords': ['SEO', 'basics'],
|
||||
'summary': 'Introduction to SEO'
|
||||
}
|
||||
subheading_prompt = self.generator._create_subheading_prompt(
|
||||
main_heading=main_heading,
|
||||
content_type=self.test_content_type,
|
||||
context=self.test_context
|
||||
)
|
||||
self.assertIsInstance(subheading_prompt, str)
|
||||
self.assertIn(main_heading['title'], subheading_prompt)
|
||||
|
||||
# Test key points prompt
|
||||
key_points_prompt = self.generator._create_key_points_prompt(
|
||||
title=self.test_title,
|
||||
content_type=self.test_content_type,
|
||||
seo_data={'keywords': ['SEO', 'strategy']},
|
||||
context=self.test_context
|
||||
)
|
||||
self.assertIsInstance(key_points_prompt, str)
|
||||
self.assertIn(self.test_title, key_points_prompt)
|
||||
|
||||
# Test flow prompt
|
||||
flow_prompt = self.generator._create_flow_prompt(
|
||||
title=self.test_title,
|
||||
content_type=self.test_content_type,
|
||||
outline={'main_headings': []}
|
||||
)
|
||||
self.assertIsInstance(flow_prompt, str)
|
||||
self.assertIn(self.test_title, flow_prompt)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
132
lib/ai_seo_tools/content_calendar/tests/test_content_brief.py
Normal file
132
lib/ai_seo_tools/content_calendar/tests/test_content_brief.py
Normal file
@@ -0,0 +1,132 @@
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any
|
||||
|
||||
from ..models.calendar import ContentItem, ContentType, Platform, SEOData
|
||||
from ..core.content_brief import ContentBriefGenerator
|
||||
|
||||
class TestContentBriefGenerator(unittest.TestCase):
|
||||
"""Test cases for ContentBriefGenerator."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test cases."""
|
||||
self.generator = ContentBriefGenerator()
|
||||
self.test_content_item = self._create_test_content_item()
|
||||
|
||||
def _create_test_content_item(self) -> ContentItem:
|
||||
"""Create a test content item."""
|
||||
return ContentItem(
|
||||
id="test-001",
|
||||
title="10 Ways to Improve Your SEO Strategy",
|
||||
description="A comprehensive guide to enhancing your website's SEO performance",
|
||||
content_type=ContentType.BLOG_POST,
|
||||
platforms=[Platform.WEBSITE, Platform.LINKEDIN],
|
||||
publish_date=datetime.now(),
|
||||
seo_data=SEOData(
|
||||
keywords=["SEO", "search engine optimization", "digital marketing"],
|
||||
meta_description="Learn effective SEO strategies to boost your website's visibility",
|
||||
structured_data={}
|
||||
),
|
||||
platform_specs={
|
||||
"website": {
|
||||
"format": "blog post",
|
||||
"min_length": 1500
|
||||
},
|
||||
"linkedin": {
|
||||
"format": "article",
|
||||
"min_length": 800
|
||||
}
|
||||
},
|
||||
context={
|
||||
"website_url": "https://example.com",
|
||||
"target_audience": "digital marketers",
|
||||
"content_goals": ["educate", "generate leads"]
|
||||
}
|
||||
)
|
||||
|
||||
def test_generate_brief(self):
|
||||
"""Test content brief generation."""
|
||||
# Generate brief
|
||||
brief = self.generator.generate_brief(
|
||||
content_item=self.test_content_item,
|
||||
target_audience={
|
||||
"demographics": {
|
||||
"age_range": "25-45",
|
||||
"profession": "digital marketers"
|
||||
},
|
||||
"interests": ["SEO", "content marketing", "digital strategy"],
|
||||
"pain_points": [
|
||||
"low search rankings",
|
||||
"poor content performance",
|
||||
"lack of organic traffic"
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# Verify brief structure
|
||||
self.assertIsInstance(brief, dict)
|
||||
self.assertIn('title', brief)
|
||||
self.assertIn('content_type', brief)
|
||||
self.assertIn('outline', brief)
|
||||
self.assertIn('key_points', brief)
|
||||
self.assertIn('content_flow', brief)
|
||||
self.assertIn('target_audience', brief)
|
||||
self.assertIn('seo_data', brief)
|
||||
self.assertIn('platform_specs', brief)
|
||||
|
||||
# Verify outline structure
|
||||
outline = brief['outline']
|
||||
self.assertIn('main_headings', outline)
|
||||
self.assertIn('subheadings', outline)
|
||||
|
||||
# Verify key points
|
||||
self.assertIsInstance(brief['key_points'], list)
|
||||
|
||||
# Verify content flow
|
||||
flow = brief['content_flow']
|
||||
self.assertIn('introduction', flow)
|
||||
self.assertIn('main_sections', flow)
|
||||
self.assertIn('conclusion', flow)
|
||||
self.assertIn('transitions', flow)
|
||||
self.assertIn('content_pacing', flow)
|
||||
|
||||
def test_generate_brief_without_audience(self):
|
||||
"""Test content brief generation without target audience data."""
|
||||
brief = self.generator.generate_brief(
|
||||
content_item=self.test_content_item
|
||||
)
|
||||
|
||||
self.assertIsInstance(brief, dict)
|
||||
self.assertIn('target_audience', brief)
|
||||
self.assertEqual(brief['target_audience'], {})
|
||||
|
||||
def test_generate_outline(self):
|
||||
"""Test outline generation."""
|
||||
outline = self.generator._generate_outline(self.test_content_item)
|
||||
|
||||
self.assertIsInstance(outline, dict)
|
||||
self.assertIn('main_headings', outline)
|
||||
self.assertIn('subheadings', outline)
|
||||
|
||||
# Verify main headings
|
||||
main_headings = outline['main_headings']
|
||||
self.assertIsInstance(main_headings, list)
|
||||
for heading in main_headings:
|
||||
self.assertIn('title', heading)
|
||||
self.assertIn('level', heading)
|
||||
self.assertIn('keywords', heading)
|
||||
self.assertIn('summary', heading)
|
||||
|
||||
# Verify subheadings
|
||||
subheadings = outline['subheadings']
|
||||
self.assertIsInstance(subheadings, dict)
|
||||
for heading_title, heading_subheadings in subheadings.items():
|
||||
self.assertIsInstance(heading_subheadings, list)
|
||||
for subheading in heading_subheadings:
|
||||
self.assertIn('title', subheading)
|
||||
self.assertIn('level', subheading)
|
||||
self.assertIn('keywords', subheading)
|
||||
self.assertIn('summary', subheading)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,171 @@
|
||||
import unittest
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, Any
|
||||
|
||||
from ..integrations.integration_manager import IntegrationManager
|
||||
|
||||
class TestIntegrationManager(unittest.TestCase):
|
||||
"""Test cases for the IntegrationManager class."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test fixtures."""
|
||||
self.integration_manager = IntegrationManager()
|
||||
self.start_date = datetime.now()
|
||||
self.end_date = self.start_date + timedelta(days=30)
|
||||
self.platforms = ['instagram', 'twitter', 'linkedin', 'blog', 'facebook']
|
||||
self.content_types = ['article', 'social', 'video']
|
||||
self.target_audience = {
|
||||
'age_range': '25-34',
|
||||
'interests': ['technology', 'marketing'],
|
||||
'location': 'global'
|
||||
}
|
||||
self.industry = 'technology'
|
||||
self.keywords = ['AI', 'content marketing', 'social media']
|
||||
|
||||
# Sample content item
|
||||
self.sample_content = {
|
||||
'title': 'The Future of AI in Content Marketing',
|
||||
'content': 'AI is revolutionizing content marketing...',
|
||||
'content_type': 'article',
|
||||
'keywords': ['AI', 'content marketing', 'automation'],
|
||||
'target_audience': self.target_audience,
|
||||
'industry': self.industry
|
||||
}
|
||||
|
||||
def test_create_cross_platform_calendar(self):
|
||||
"""Test creating a cross-platform content calendar."""
|
||||
calendar = self.integration_manager.create_cross_platform_calendar(
|
||||
start_date=self.start_date,
|
||||
end_date=self.end_date,
|
||||
platforms=self.platforms,
|
||||
content_types=self.content_types,
|
||||
target_audience=self.target_audience,
|
||||
industry=self.industry,
|
||||
keywords=self.keywords
|
||||
)
|
||||
|
||||
# Check basic structure
|
||||
self.assertIn('base_calendar', calendar)
|
||||
self.assertIn('platform_calendars', calendar)
|
||||
self.assertIn('metadata', calendar)
|
||||
|
||||
# Check platform calendars
|
||||
platform_calendars = calendar['platform_calendars']
|
||||
self.assertEqual(len(platform_calendars), len(self.platforms))
|
||||
|
||||
for platform in self.platforms:
|
||||
self.assertIn(platform, platform_calendars)
|
||||
platform_calendar = platform_calendars[platform]
|
||||
self.assertIn('content_items', platform_calendar)
|
||||
self.assertIn('metadata', platform_calendar)
|
||||
|
||||
def test_adapt_calendar_for_platform(self):
|
||||
"""Test adapting calendar for a specific platform."""
|
||||
# Create base calendar
|
||||
calendar = self.integration_manager.create_cross_platform_calendar(
|
||||
start_date=self.start_date,
|
||||
end_date=self.end_date,
|
||||
platforms=[self.platforms[0]], # Test with just Instagram
|
||||
content_types=self.content_types,
|
||||
target_audience=self.target_audience,
|
||||
industry=self.industry,
|
||||
keywords=self.keywords
|
||||
)
|
||||
|
||||
# Get platform calendar
|
||||
platform_calendar = calendar['platform_calendars'][self.platforms[0]]
|
||||
|
||||
# Check structure
|
||||
self.assertIn('content_items', platform_calendar)
|
||||
self.assertIn('metadata', platform_calendar)
|
||||
|
||||
# Check content items
|
||||
for item in platform_calendar['content_items']:
|
||||
self.assertIn('original_item', item)
|
||||
self.assertIn('adapted_content', item)
|
||||
self.assertIn('platform_specifics', item)
|
||||
|
||||
def test_adapt_content_item(self):
|
||||
"""Test adapting a content item for a platform."""
|
||||
adapted_item = self.integration_manager._adapt_content_item(
|
||||
item=self.sample_content,
|
||||
platform='instagram'
|
||||
)
|
||||
|
||||
# Check structure
|
||||
self.assertIsNotNone(adapted_item)
|
||||
self.assertIn('original_item', adapted_item)
|
||||
self.assertIn('adapted_content', adapted_item)
|
||||
self.assertIn('platform_specifics', adapted_item)
|
||||
|
||||
# Check content adaptation
|
||||
adapted_content = adapted_item['adapted_content']
|
||||
self.assertIn('captions', adapted_content)
|
||||
self.assertIn('hashtags', adapted_content)
|
||||
self.assertIn('media_suggestions', adapted_content)
|
||||
|
||||
def test_get_platform_suggestions(self):
|
||||
"""Test getting platform-specific suggestions."""
|
||||
suggestions = self.integration_manager.get_platform_suggestions(
|
||||
content=self.sample_content,
|
||||
platforms=self.platforms
|
||||
)
|
||||
|
||||
# Check structure
|
||||
self.assertEqual(len(suggestions), len(self.platforms))
|
||||
|
||||
for platform in self.platforms:
|
||||
self.assertIn(platform, suggestions)
|
||||
platform_suggestions = suggestions[platform]
|
||||
self.assertIsInstance(platform_suggestions, dict)
|
||||
|
||||
def test_validate_platform_content(self):
|
||||
"""Test validating content for a platform."""
|
||||
validation = self.integration_manager.validate_platform_content(
|
||||
content=self.sample_content,
|
||||
platform='instagram'
|
||||
)
|
||||
|
||||
# Check structure
|
||||
self.assertIn('platform', validation)
|
||||
self.assertIn('is_valid', validation)
|
||||
self.assertIn('specifications', validation)
|
||||
|
||||
# Check validation result
|
||||
self.assertIsInstance(validation['is_valid'], bool)
|
||||
|
||||
def test_optimize_cross_platform_content(self):
|
||||
"""Test optimizing content for multiple platforms."""
|
||||
optimized = self.integration_manager.optimize_cross_platform_content(
|
||||
content=self.sample_content,
|
||||
platforms=self.platforms
|
||||
)
|
||||
|
||||
# Check structure
|
||||
self.assertEqual(len(optimized), len(self.platforms))
|
||||
|
||||
for platform in self.platforms:
|
||||
self.assertIn(platform, optimized)
|
||||
platform_optimized = optimized[platform]
|
||||
self.assertIsInstance(platform_optimized, dict)
|
||||
|
||||
def test_error_handling(self):
|
||||
"""Test error handling with invalid inputs."""
|
||||
# Test with invalid platform
|
||||
with self.assertRaises(Exception):
|
||||
self.integration_manager.validate_platform_content(
|
||||
content=self.sample_content,
|
||||
platform='invalid_platform'
|
||||
)
|
||||
|
||||
# Test with invalid content
|
||||
invalid_content = {'title': 'Invalid Content'}
|
||||
validation = self.integration_manager.validate_platform_content(
|
||||
content=invalid_content,
|
||||
platform='instagram'
|
||||
)
|
||||
self.assertFalse(validation['is_valid'])
|
||||
self.assertIn('error', validation)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,186 @@
|
||||
import unittest
|
||||
from typing import Dict, Any
|
||||
from datetime import datetime
|
||||
|
||||
from ..integrations.platform_adapters import UnifiedPlatformAdapter
|
||||
|
||||
class TestUnifiedPlatformAdapter(unittest.TestCase):
|
||||
"""Test cases for the UnifiedPlatformAdapter."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test cases."""
|
||||
self.adapter = UnifiedPlatformAdapter()
|
||||
self.test_content = {
|
||||
'title': 'Test Content',
|
||||
'content': 'This is a test content for platform adaptation.',
|
||||
'keywords': ['test', 'content', 'platform'],
|
||||
'tone': 'professional',
|
||||
'cta': 'Learn More',
|
||||
'audience': 'For All',
|
||||
'language': 'English',
|
||||
'industry': 'technology',
|
||||
'word_count': 1000
|
||||
}
|
||||
|
||||
def test_adapt_instagram_content(self):
|
||||
"""Test Instagram content adaptation."""
|
||||
adapted_content = self.adapter.adapt_content(
|
||||
content=self.test_content,
|
||||
platform='instagram'
|
||||
)
|
||||
|
||||
self.assertIsInstance(adapted_content, dict)
|
||||
self.assertIn('captions', adapted_content)
|
||||
self.assertIn('hashtags', adapted_content)
|
||||
self.assertIn('media_suggestions', adapted_content)
|
||||
self.assertIn('platform_specific', adapted_content)
|
||||
|
||||
def test_adapt_twitter_content(self):
|
||||
"""Test Twitter content adaptation."""
|
||||
adapted_content = self.adapter.adapt_content(
|
||||
content=self.test_content,
|
||||
platform='twitter'
|
||||
)
|
||||
|
||||
self.assertIsInstance(adapted_content, dict)
|
||||
self.assertIn('tweets', adapted_content)
|
||||
self.assertIn('thread_structure', adapted_content)
|
||||
self.assertIn('media_suggestions', adapted_content)
|
||||
self.assertIn('platform_specific', adapted_content)
|
||||
|
||||
def test_adapt_linkedin_content(self):
|
||||
"""Test LinkedIn content adaptation."""
|
||||
adapted_content = self.adapter.adapt_content(
|
||||
content=self.test_content,
|
||||
platform='linkedin'
|
||||
)
|
||||
|
||||
self.assertIsInstance(adapted_content, dict)
|
||||
self.assertIn('post', adapted_content)
|
||||
self.assertIn('engagement_optimization', adapted_content)
|
||||
self.assertIn('media_suggestions', adapted_content)
|
||||
self.assertIn('platform_specific', adapted_content)
|
||||
|
||||
def test_adapt_blog_content(self):
|
||||
"""Test blog content adaptation."""
|
||||
adapted_content = self.adapter.adapt_content(
|
||||
content=self.test_content,
|
||||
platform='blog'
|
||||
)
|
||||
|
||||
self.assertIsInstance(adapted_content, dict)
|
||||
self.assertIn('post', adapted_content)
|
||||
self.assertIn('seo_optimization', adapted_content)
|
||||
self.assertIn('media_suggestions', adapted_content)
|
||||
self.assertIn('platform_specific', adapted_content)
|
||||
|
||||
def test_adapt_facebook_content(self):
|
||||
"""Test Facebook content adaptation."""
|
||||
adapted_content = self.adapter.adapt_content(
|
||||
content=self.test_content,
|
||||
platform='facebook'
|
||||
)
|
||||
|
||||
self.assertIsInstance(adapted_content, dict)
|
||||
self.assertIn('post', adapted_content)
|
||||
self.assertIn('engagement_optimization', adapted_content)
|
||||
self.assertIn('media_suggestions', adapted_content)
|
||||
self.assertIn('platform_specific', adapted_content)
|
||||
|
||||
def test_validate_content(self):
|
||||
"""Test content validation."""
|
||||
# Test valid content
|
||||
self.assertTrue(
|
||||
self.adapter.validate_content(
|
||||
self.test_content,
|
||||
'instagram'
|
||||
)
|
||||
)
|
||||
|
||||
# Test invalid content (missing required fields)
|
||||
invalid_content = {
|
||||
'title': 'Test Content',
|
||||
'content': 'This is a test content.'
|
||||
}
|
||||
self.assertFalse(
|
||||
self.adapter.validate_content(
|
||||
invalid_content,
|
||||
'instagram'
|
||||
)
|
||||
)
|
||||
|
||||
def test_unsupported_platform(self):
|
||||
"""Test handling of unsupported platform."""
|
||||
with self.assertRaises(ValueError):
|
||||
self.adapter.adapt_content(
|
||||
content=self.test_content,
|
||||
platform='unsupported_platform'
|
||||
)
|
||||
|
||||
def test_content_adaptation_with_context(self):
|
||||
"""Test content adaptation with additional context."""
|
||||
context = {
|
||||
'target_audience': 'professionals',
|
||||
'campaign_goals': ['awareness', 'engagement'],
|
||||
'brand_voice': 'authoritative'
|
||||
}
|
||||
|
||||
adapted_content = self.adapter.adapt_content(
|
||||
content=self.test_content,
|
||||
platform='linkedin',
|
||||
context=context
|
||||
)
|
||||
|
||||
self.assertIsInstance(adapted_content, dict)
|
||||
self.assertIn('post', adapted_content)
|
||||
self.assertIn('engagement_optimization', adapted_content)
|
||||
|
||||
def test_error_handling(self):
|
||||
"""Test error handling in content adaptation."""
|
||||
# Test with invalid content structure
|
||||
invalid_content = {
|
||||
'title': 123, # Invalid type
|
||||
'content': None # Missing required field
|
||||
}
|
||||
|
||||
adapted_content = self.adapter.adapt_content(
|
||||
content=invalid_content,
|
||||
platform='blog'
|
||||
)
|
||||
|
||||
self.assertIn('error', adapted_content)
|
||||
|
||||
def test_platform_specs(self):
|
||||
"""Test platform specifications."""
|
||||
specs = self.adapter.platform_specs
|
||||
|
||||
# Check Instagram specs
|
||||
self.assertIn('instagram', specs)
|
||||
self.assertIn('max_caption_length', specs['instagram'])
|
||||
self.assertIn('max_hashtags', specs['instagram'])
|
||||
self.assertIn('required_fields', specs['instagram'])
|
||||
|
||||
# Check Twitter specs
|
||||
self.assertIn('twitter', specs)
|
||||
self.assertIn('max_tweet_length', specs['twitter'])
|
||||
self.assertIn('max_thread_length', specs['twitter'])
|
||||
self.assertIn('required_fields', specs['twitter'])
|
||||
|
||||
# Check LinkedIn specs
|
||||
self.assertIn('linkedin', specs)
|
||||
self.assertIn('max_post_length', specs['linkedin'])
|
||||
self.assertIn('required_fields', specs['linkedin'])
|
||||
|
||||
# Check blog specs
|
||||
self.assertIn('blog', specs)
|
||||
self.assertIn('min_word_count', specs['blog'])
|
||||
self.assertIn('max_word_count', specs['blog'])
|
||||
self.assertIn('required_fields', specs['blog'])
|
||||
|
||||
# Check Facebook specs
|
||||
self.assertIn('facebook', specs)
|
||||
self.assertIn('max_post_length', specs['facebook'])
|
||||
self.assertIn('required_fields', specs['facebook'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
132
lib/ai_seo_tools/content_calendar/tests/test_seo_optimizer.py
Normal file
132
lib/ai_seo_tools/content_calendar/tests/test_seo_optimizer.py
Normal file
@@ -0,0 +1,132 @@
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any
|
||||
|
||||
from ..integrations.seo_optimizer import SEOOptimizer
|
||||
|
||||
class TestSEOOptimizer(unittest.TestCase):
|
||||
"""Test cases for the SEOOptimizer class."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test fixtures."""
|
||||
self.seo_optimizer = SEOOptimizer()
|
||||
|
||||
# Sample content for testing
|
||||
self.sample_content = {
|
||||
'title': 'The Future of AI in Content Marketing',
|
||||
'content': 'AI is revolutionizing content marketing...',
|
||||
'keywords': ['AI', 'content marketing', 'automation'],
|
||||
'author': 'John Doe',
|
||||
'publish_date': datetime.now().isoformat(),
|
||||
'description': 'An in-depth look at AI in content marketing',
|
||||
'image_url': 'https://example.com/image.jpg',
|
||||
'url': 'https://example.com/article'
|
||||
}
|
||||
|
||||
# Sample calendar for testing
|
||||
self.sample_calendar = {
|
||||
'metadata': {
|
||||
'start_date': datetime.now().isoformat(),
|
||||
'end_date': datetime.now().isoformat(),
|
||||
'platforms': ['blog', 'social'],
|
||||
'content_types': ['article']
|
||||
},
|
||||
'content_items': [self.sample_content]
|
||||
}
|
||||
|
||||
def test_optimize_content(self):
|
||||
"""Test content optimization."""
|
||||
optimized = self.seo_optimizer.optimize_content(
|
||||
content=self.sample_content,
|
||||
content_type='article',
|
||||
language='English',
|
||||
search_intent='Informational Intent'
|
||||
)
|
||||
|
||||
# Check structure
|
||||
self.assertIn('original_content', optimized)
|
||||
self.assertIn('seo_optimized', optimized)
|
||||
|
||||
# Check SEO elements
|
||||
seo_elements = optimized['seo_optimized']
|
||||
self.assertIn('title', seo_elements)
|
||||
self.assertIn('meta_description', seo_elements)
|
||||
self.assertIn('structured_data', seo_elements)
|
||||
self.assertIn('keywords', seo_elements)
|
||||
|
||||
def test_optimize_title(self):
|
||||
"""Test title optimization."""
|
||||
titles = self.seo_optimizer._optimize_title(
|
||||
title=self.sample_content['title'],
|
||||
keywords=self.sample_content['keywords'],
|
||||
content_type='article',
|
||||
language='English',
|
||||
search_intent='Informational Intent'
|
||||
)
|
||||
|
||||
# Check titles
|
||||
self.assertIsInstance(titles, list)
|
||||
self.assertTrue(len(titles) > 0)
|
||||
|
||||
def test_generate_meta_description(self):
|
||||
"""Test meta description generation."""
|
||||
descriptions = self.seo_optimizer._generate_meta_description(
|
||||
keywords=self.sample_content['keywords'],
|
||||
content_type='article',
|
||||
language='English',
|
||||
search_intent='Informational Intent'
|
||||
)
|
||||
|
||||
# Check descriptions
|
||||
self.assertIsInstance(descriptions, list)
|
||||
self.assertTrue(len(descriptions) > 0)
|
||||
|
||||
def test_generate_structured_data(self):
|
||||
"""Test structured data generation."""
|
||||
structured_data = self.seo_optimizer._generate_structured_data(
|
||||
content=self.sample_content,
|
||||
content_type='article'
|
||||
)
|
||||
|
||||
# Check structured data
|
||||
self.assertIsNotNone(structured_data)
|
||||
|
||||
def test_optimize_calendar_content(self):
|
||||
"""Test calendar content optimization."""
|
||||
optimized_calendar = self.seo_optimizer.optimize_calendar_content(
|
||||
calendar=self.sample_calendar,
|
||||
content_type='article',
|
||||
language='English',
|
||||
search_intent='Informational Intent'
|
||||
)
|
||||
|
||||
# Check structure
|
||||
self.assertIn('metadata', optimized_calendar)
|
||||
self.assertIn('content_items', optimized_calendar)
|
||||
|
||||
# Check content items
|
||||
self.assertTrue(len(optimized_calendar['content_items']) > 0)
|
||||
for item in optimized_calendar['content_items']:
|
||||
self.assertIn('original_content', item)
|
||||
self.assertIn('seo_optimized', item)
|
||||
|
||||
def test_error_handling(self):
|
||||
"""Test error handling with invalid inputs."""
|
||||
# Test with invalid content
|
||||
invalid_content = {'title': 'Invalid Content'}
|
||||
optimized = self.seo_optimizer.optimize_content(
|
||||
content=invalid_content,
|
||||
content_type='article'
|
||||
)
|
||||
self.assertIn('error', optimized)
|
||||
|
||||
# Test with invalid calendar
|
||||
invalid_calendar = {'metadata': {}}
|
||||
optimized_calendar = self.seo_optimizer.optimize_calendar_content(
|
||||
calendar=invalid_calendar,
|
||||
content_type='article'
|
||||
)
|
||||
self.assertIn('error', optimized_calendar)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user