f26d4d8f7f
- Multi-source content aggregation (Bilibili/YouTube/Zhihu) - Smart inbox management with AI quality scoring - Long video chunking analysis (30min+ auto-segmentation) - Topic-based organization - Git auto-sync to Obsidian - Template system with Jinja2 and fallback rendering - CLI commands: subscribe, inbox, process, skip, status, search - Comprehensive test suite with unit and integration tests - Documentation: README.md and SKILL.md Checkpoint 7-8 completed by Agent E
258 lines
8.6 KiB
Python
258 lines
8.6 KiB
Python
"""
|
|
Unit tests for template renderer module.
|
|
"""
|
|
import unittest
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import sys
|
|
sys.path.insert(0, str(Path(__file__).parent.parent / 'src'))
|
|
|
|
from template_renderer import TemplateRenderer, render_content
|
|
from models import Content, ContentType, ContentStatus, ContentAnalysis
|
|
|
|
|
|
class TestTemplateRenderer(unittest.TestCase):
|
|
"""Test TemplateRenderer class."""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures."""
|
|
# Use the actual templates directory
|
|
self.templates_dir = Path(__file__).parent.parent / 'src' / 'templates'
|
|
self.renderer = TemplateRenderer(str(self.templates_dir))
|
|
|
|
def test_initialization(self):
|
|
"""Test renderer initialization."""
|
|
self.assertTrue(self.renderer.templates_dir.exists())
|
|
|
|
def test_get_template_name_video(self):
|
|
"""Test template selection for video content."""
|
|
content = Content(
|
|
id="test_001",
|
|
source="bilibili",
|
|
title="Test Video",
|
|
url="https://example.com",
|
|
duration=600, # 10 minutes
|
|
content_type=ContentType.VIDEO
|
|
)
|
|
|
|
template_name = self.renderer._get_template_name(content)
|
|
self.assertEqual(template_name, 'light_video.md')
|
|
|
|
def test_get_template_name_long_video(self):
|
|
"""Test template selection for long video."""
|
|
content = Content(
|
|
id="test_002",
|
|
source="bilibili",
|
|
title="Long Tutorial",
|
|
url="https://example.com",
|
|
duration=3600, # 60 minutes
|
|
content_type=ContentType.VIDEO
|
|
)
|
|
|
|
template_name = self.renderer._get_template_name(content)
|
|
self.assertEqual(template_name, 'tutorial_video.md')
|
|
|
|
def test_get_template_name_article(self):
|
|
"""Test template selection for article."""
|
|
content = Content(
|
|
id="test_003",
|
|
source="zhihu",
|
|
title="Test Article",
|
|
url="https://example.com",
|
|
content_type=ContentType.ARTICLE
|
|
)
|
|
|
|
template_name = self.renderer._get_template_name(content)
|
|
self.assertEqual(template_name, 'article.md')
|
|
|
|
def test_prepare_context(self):
|
|
"""Test context preparation."""
|
|
content = Content(
|
|
id="test_004",
|
|
source="bilibili",
|
|
title="Test Title",
|
|
url="https://example.com",
|
|
author="Test Author",
|
|
duration=300,
|
|
tags=["python", "tutorial"]
|
|
)
|
|
|
|
context = self.renderer._prepare_context(content)
|
|
|
|
self.assertEqual(context['title'], "Test Title")
|
|
self.assertEqual(context['source'], "bilibili")
|
|
self.assertEqual(context['author'], "Test Author")
|
|
self.assertEqual(context['tags'], ["python", "tutorial"])
|
|
|
|
def test_prepare_context_with_analysis(self):
|
|
"""Test context preparation with analysis data."""
|
|
analysis = ContentAnalysis(
|
|
one_liner="Quick summary",
|
|
prerequisites=["Basic Python"],
|
|
outline=[{"title": "Part 1", "summary": "Introduction"}],
|
|
pitfalls=["Common mistake"],
|
|
practice_advice=["Try this"]
|
|
)
|
|
|
|
content = Content(
|
|
id="test_005",
|
|
source="bilibili",
|
|
title="Test",
|
|
url="https://example.com",
|
|
analysis=analysis
|
|
)
|
|
|
|
context = self.renderer._prepare_context(content)
|
|
|
|
self.assertEqual(context['prerequisites'], ["Basic Python"])
|
|
self.assertEqual(context['outline'], [{"title": "Part 1", "summary": "Introduction"}])
|
|
|
|
def test_render_light_video(self):
|
|
"""Test rendering light video template."""
|
|
content = Content(
|
|
id="test_006",
|
|
source="bilibili",
|
|
title="Quick Tips",
|
|
url="https://example.com",
|
|
author="Creator",
|
|
duration=300,
|
|
tags=["tips", "productivity"]
|
|
)
|
|
content.analysis = ContentAnalysis(
|
|
one_liner="Great productivity tips",
|
|
summary="This video covers essential tips.",
|
|
key_points=["Point 1", "Point 2"],
|
|
quality_score=85
|
|
)
|
|
|
|
result = self.renderer.render(content)
|
|
|
|
self.assertIn("Quick Tips", result)
|
|
self.assertIn("Great productivity tips", result)
|
|
self.assertIn("Point 1", result)
|
|
self.assertIn("#tips", result)
|
|
|
|
def test_render_tutorial_video(self):
|
|
"""Test rendering tutorial video template."""
|
|
content = Content(
|
|
id="test_007",
|
|
source="bilibili",
|
|
title="Python Tutorial",
|
|
url="https://example.com",
|
|
author="PythonMaster",
|
|
duration=3600,
|
|
tags=["python", "programming"]
|
|
)
|
|
content.analysis = ContentAnalysis(
|
|
one_liner="Complete Python guide",
|
|
prerequisites=["Basic programming"],
|
|
outline=[{
|
|
"title": "Introduction",
|
|
"time_range": "00:00-05:00",
|
|
"summary": "Getting started"
|
|
}],
|
|
key_points=["Install Python", "Write first script"],
|
|
pitfalls=["Don't use Python 2"],
|
|
practice_advice=["Practice daily"],
|
|
quality_score=95
|
|
)
|
|
|
|
result = self.renderer.render(content)
|
|
|
|
self.assertIn("Python Tutorial", result)
|
|
self.assertIn("Complete Python guide", result)
|
|
self.assertIn("Basic programming", result)
|
|
|
|
def test_render_article(self):
|
|
"""Test rendering article template."""
|
|
content = Content(
|
|
id="test_008",
|
|
source="zhihu",
|
|
title="Deep Dive Article",
|
|
url="https://zhihu.com/article/test",
|
|
author="Writer",
|
|
content_type=ContentType.ARTICLE,
|
|
tags=["technology", "ai"]
|
|
)
|
|
content.analysis = ContentAnalysis(
|
|
one_liner="Comprehensive analysis",
|
|
summary="Detailed article content.",
|
|
key_points=["Insight 1", "Insight 2"],
|
|
quality_score=90
|
|
)
|
|
|
|
result = self.renderer.render(content)
|
|
|
|
self.assertIn("Deep Dive Article", result)
|
|
self.assertIn("Comprehensive analysis", result)
|
|
|
|
def test_render_to_file(self):
|
|
"""Test rendering to file."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
content = Content(
|
|
id="test_009",
|
|
source="bilibili",
|
|
title="File Test",
|
|
url="https://example.com",
|
|
duration=600
|
|
)
|
|
content.analysis = ContentAnalysis(
|
|
one_liner="Test one-liner",
|
|
key_points=["Point A"]
|
|
)
|
|
|
|
output_path = Path(tmpdir) / "output.md"
|
|
result_path = self.renderer.render_to_file(content, str(output_path))
|
|
|
|
self.assertTrue(Path(result_path).exists())
|
|
content_text = Path(result_path).read_text(encoding='utf-8')
|
|
self.assertIn("File Test", content_text)
|
|
|
|
def test_simple_render_fallback(self):
|
|
"""Test simple rendering fallback (no Jinja2)."""
|
|
template = "Title: {{ title }}, Author: {{ author }}"
|
|
context = {'title': 'Test', 'author': 'User'}
|
|
|
|
result = self.renderer._simple_render(template, context)
|
|
|
|
self.assertIn("Title: Test", result)
|
|
self.assertIn("Author: User", result)
|
|
|
|
def test_simple_render_with_list(self):
|
|
"""Test simple rendering with list values."""
|
|
template = "Tags: {{ tags }}"
|
|
context = {'tags': ['python', 'coding']}
|
|
|
|
result = self.renderer._simple_render(template, context)
|
|
|
|
self.assertIn("Tags: python, coding", result)
|
|
|
|
|
|
class TestRenderContentFunction(unittest.TestCase):
|
|
"""Test render_content convenience function."""
|
|
|
|
def test_render_content(self):
|
|
"""Test convenience function."""
|
|
templates_dir = Path(__file__).parent.parent / 'src' / 'templates'
|
|
content = Content(
|
|
id="test_010",
|
|
source="bilibili",
|
|
title="Convenience Test",
|
|
url="https://example.com",
|
|
duration=300
|
|
)
|
|
content.analysis = ContentAnalysis(
|
|
one_liner="Simple test",
|
|
key_points=["Test point"]
|
|
)
|
|
|
|
result = render_content(content, str(templates_dir))
|
|
|
|
self.assertIn("Convenience Test", result)
|
|
self.assertIn("Simple test", result)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|