diff --git a/tests/test_processors/test_download.py b/tests/test_processors/test_download.py new file mode 100644 index 0000000..63860db --- /dev/null +++ b/tests/test_processors/test_download.py @@ -0,0 +1,127 @@ +"""Tests for DownloadProcessor and DownloadInput/DownloadOutput schemas. + +Test coverage: +- DownloadInput schema validation +- DownloadOutput schema validation +- DownloadProcessor metadata fetching +- DownloadProcessor content downloading +- DownloadProcessor state recording +""" + +import pytest +from datetime import datetime +from unittest.mock import AsyncMock, MagicMock, patch +from pathlib import Path + +from kb_pipeline.schemas import DownloadInput, DownloadOutput + + +class TestDownloadInputSchema: + """Tests for DownloadInput schema validation.""" + + def test_schema_download_input_validates_required_fields(self): + """Test 1: DownloadInput validates required fields""" + # Test with all required fields + input_data = DownloadInput( + content_id="BV1xx", + platform="bilibili", + content_dir="/tmp/content", + content_type="video" + ) + assert input_data.content_id == "BV1xx" + assert input_data.platform == "bilibili" + assert input_data.content_dir == "/tmp/content" + assert input_data.content_type == "video" + + def test_schema_download_input_requires_content_dir(self): + """DownloadInput should require content_dir""" + with pytest.raises(Exception): # ValidationError from pydantic + DownloadInput( + content_id="BV1xx", + platform="bilibili", + content_type="video" + # Missing content_dir + ) + + def test_schema_download_input_requires_content_type(self): + """DownloadInput should require content_type""" + with pytest.raises(Exception): # ValidationError from pydantic + DownloadInput( + content_id="BV1xx", + platform="bilibili", + content_dir="/tmp/content" + # Missing content_type + ) + + +class TestDownloadOutputSchema: + """Tests for DownloadOutput schema validation.""" + + def test_schema_download_output_validates_required_fields(self): + """Test 2: DownloadOutput validates required fields""" + output = DownloadOutput( + success=True, + metadata_file="/tmp/content/bilibili_BV1xx_metadata.json", + content_file="/tmp/content/bilibili_BV1xx_content.md", + title="Test Video", + author="Test Author" + ) + assert output.success is True + assert output.metadata_file == "/tmp/content/bilibili_BV1xx_metadata.json" + assert output.content_file == "/tmp/content/bilibili_BV1xx_content.md" + assert output.title == "Test Video" + assert output.author == "Test Author" + assert output.duration is None # Optional field + + def test_schema_download_output_handles_video_content_type(self): + """Test 3: DownloadOutput handles video content type with duration""" + output = DownloadOutput( + success=True, + metadata_file="/tmp/content/bilibili_BV1xx_metadata.json", + content_file="", # Video content handled by ASR + title="Test Video", + author="Test Author", + duration=300 # 5 minutes + ) + assert output.success is True + assert output.duration == 300 + assert output.content_file == "" + + def test_schema_download_output_handles_article_content_type(self): + """Test 3: DownloadOutput handles article content type without duration""" + output = DownloadOutput( + success=True, + metadata_file="/tmp/content/bilibili_CV123_metadata.json", + content_file="/tmp/content/bilibili_CV123_content.md", + title="Test Article", + author="Test Author", + duration=None # Articles don't have duration + ) + assert output.success is True + assert output.duration is None + assert output.content_file == "/tmp/content/bilibili_CV123_content.md" + + def test_schema_download_output_handles_zhihu_answer(self): + """Test 3: DownloadOutput handles Zhihu answer content type""" + output = DownloadOutput( + success=True, + metadata_file="/tmp/content/zhihu_123456_metadata.json", + content_file="/tmp/content/zhihu_123456_content.md", + title="Test Answer", + author="Test Author" + ) + assert output.success is True + assert "zhihu" in output.metadata_file + + def test_schema_download_output_handles_failure(self): + """DownloadOutput should handle failure case""" + output = DownloadOutput( + success=False, + error_message="Network error", + metadata_file="", + content_file="", + title="", + author="" + ) + assert output.success is False + assert output.error_message == "Network error"