first
This commit is contained in:
637
backend/tests/test_export_service.py
Normal file
637
backend/tests/test_export_service.py
Normal file
@@ -0,0 +1,637 @@
|
||||
"""
|
||||
Tool_OCR - Export Service Unit Tests
|
||||
Tests for app/services/export_service.py
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import json
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
from datetime import datetime
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from app.services.export_service import ExportService, ExportError
|
||||
from app.models.ocr import FileStatus
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def export_service():
|
||||
"""Create an ExportService instance"""
|
||||
return ExportService()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_ocr_result(temp_dir):
|
||||
"""Create a mock OCRResult with markdown file"""
|
||||
# Create mock markdown file
|
||||
md_file = temp_dir / "test_result.md"
|
||||
md_file.write_text("# Test Document\n\nThis is test content.", encoding="utf-8")
|
||||
|
||||
# Create mock result
|
||||
result = Mock()
|
||||
result.id = 1
|
||||
result.markdown_path = str(md_file)
|
||||
result.json_path = None
|
||||
result.detected_language = "zh"
|
||||
result.total_text_regions = 10
|
||||
result.average_confidence = 0.95
|
||||
result.layout_data = {"elements": [{"type": "text"}]}
|
||||
result.images_metadata = []
|
||||
|
||||
# Mock file
|
||||
result.file = Mock()
|
||||
result.file.id = 1
|
||||
result.file.original_filename = "test.png"
|
||||
result.file.file_format = "png"
|
||||
result.file.file_size = 1024
|
||||
result.file.processing_time = 2.5
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_db():
|
||||
"""Create a mock database session"""
|
||||
return Mock()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestExportServiceInit:
|
||||
"""Test ExportService initialization"""
|
||||
|
||||
def test_init(self, export_service):
|
||||
"""Test export service initialization"""
|
||||
assert export_service is not None
|
||||
assert export_service.pdf_generator is not None
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestApplyFilters:
|
||||
"""Test filter application"""
|
||||
|
||||
def test_apply_filters_confidence_threshold(self, export_service):
|
||||
"""Test confidence threshold filter"""
|
||||
result1 = Mock()
|
||||
result1.average_confidence = 0.95
|
||||
result1.file = Mock()
|
||||
result1.file.original_filename = "test1.png"
|
||||
|
||||
result2 = Mock()
|
||||
result2.average_confidence = 0.75
|
||||
result2.file = Mock()
|
||||
result2.file.original_filename = "test2.png"
|
||||
|
||||
result3 = Mock()
|
||||
result3.average_confidence = 0.85
|
||||
result3.file = Mock()
|
||||
result3.file.original_filename = "test3.png"
|
||||
|
||||
results = [result1, result2, result3]
|
||||
filters = {"confidence_threshold": 0.80}
|
||||
|
||||
filtered = export_service.apply_filters(results, filters)
|
||||
|
||||
assert len(filtered) == 2
|
||||
assert result1 in filtered
|
||||
assert result3 in filtered
|
||||
assert result2 not in filtered
|
||||
|
||||
def test_apply_filters_filename_pattern(self, export_service):
|
||||
"""Test filename pattern filter"""
|
||||
result1 = Mock()
|
||||
result1.average_confidence = 0.95
|
||||
result1.file = Mock()
|
||||
result1.file.original_filename = "invoice_2024.png"
|
||||
|
||||
result2 = Mock()
|
||||
result2.average_confidence = 0.95
|
||||
result2.file = Mock()
|
||||
result2.file.original_filename = "receipt.png"
|
||||
|
||||
results = [result1, result2]
|
||||
filters = {"filename_pattern": "invoice"}
|
||||
|
||||
filtered = export_service.apply_filters(results, filters)
|
||||
|
||||
assert len(filtered) == 1
|
||||
assert result1 in filtered
|
||||
|
||||
def test_apply_filters_language(self, export_service):
|
||||
"""Test language filter"""
|
||||
result1 = Mock()
|
||||
result1.detected_language = "zh"
|
||||
result1.average_confidence = 0.95
|
||||
result1.file = Mock()
|
||||
result1.file.original_filename = "chinese.png"
|
||||
|
||||
result2 = Mock()
|
||||
result2.detected_language = "en"
|
||||
result2.average_confidence = 0.95
|
||||
result2.file = Mock()
|
||||
result2.file.original_filename = "english.png"
|
||||
|
||||
results = [result1, result2]
|
||||
filters = {"language": "zh"}
|
||||
|
||||
filtered = export_service.apply_filters(results, filters)
|
||||
|
||||
assert len(filtered) == 1
|
||||
assert result1 in filtered
|
||||
|
||||
def test_apply_filters_combined(self, export_service):
|
||||
"""Test multiple filters combined"""
|
||||
result1 = Mock()
|
||||
result1.detected_language = "zh"
|
||||
result1.average_confidence = 0.95
|
||||
result1.file = Mock()
|
||||
result1.file.original_filename = "invoice_chinese.png"
|
||||
|
||||
result2 = Mock()
|
||||
result2.detected_language = "zh"
|
||||
result2.average_confidence = 0.75
|
||||
result2.file = Mock()
|
||||
result2.file.original_filename = "invoice_low.png"
|
||||
|
||||
result3 = Mock()
|
||||
result3.detected_language = "en"
|
||||
result3.average_confidence = 0.95
|
||||
result3.file = Mock()
|
||||
result3.file.original_filename = "invoice_english.png"
|
||||
|
||||
results = [result1, result2, result3]
|
||||
filters = {
|
||||
"confidence_threshold": 0.80,
|
||||
"language": "zh",
|
||||
"filename_pattern": "invoice"
|
||||
}
|
||||
|
||||
filtered = export_service.apply_filters(results, filters)
|
||||
|
||||
assert len(filtered) == 1
|
||||
assert result1 in filtered
|
||||
|
||||
def test_apply_filters_no_filters(self, export_service):
|
||||
"""Test with no filters applied"""
|
||||
results = [Mock(), Mock(), Mock()]
|
||||
filtered = export_service.apply_filters(results, {})
|
||||
|
||||
assert len(filtered) == len(results)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestExportToTXT:
|
||||
"""Test TXT export"""
|
||||
|
||||
def test_export_to_txt_basic(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test basic TXT export"""
|
||||
output_path = temp_dir / "output.txt"
|
||||
|
||||
result_path = export_service.export_to_txt([mock_ocr_result], output_path)
|
||||
|
||||
assert result_path.exists()
|
||||
content = result_path.read_text(encoding="utf-8")
|
||||
assert "Test Document" in content
|
||||
assert "test content" in content
|
||||
|
||||
def test_export_to_txt_with_line_numbers(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test TXT export with line numbers"""
|
||||
output_path = temp_dir / "output.txt"
|
||||
formatting = {"add_line_numbers": True}
|
||||
|
||||
result_path = export_service.export_to_txt(
|
||||
[mock_ocr_result],
|
||||
output_path,
|
||||
formatting=formatting
|
||||
)
|
||||
|
||||
content = result_path.read_text(encoding="utf-8")
|
||||
assert "|" in content # Line number separator
|
||||
|
||||
def test_export_to_txt_with_metadata(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test TXT export with metadata headers"""
|
||||
output_path = temp_dir / "output.txt"
|
||||
formatting = {"include_metadata": True}
|
||||
|
||||
result_path = export_service.export_to_txt(
|
||||
[mock_ocr_result],
|
||||
output_path,
|
||||
formatting=formatting
|
||||
)
|
||||
|
||||
content = result_path.read_text(encoding="utf-8")
|
||||
assert "文件:" in content
|
||||
assert "test.png" in content
|
||||
assert "信心度:" in content
|
||||
|
||||
def test_export_to_txt_with_grouping(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test TXT export with file grouping"""
|
||||
output_path = temp_dir / "output.txt"
|
||||
formatting = {"group_by_filename": True}
|
||||
|
||||
result_path = export_service.export_to_txt(
|
||||
[mock_ocr_result, mock_ocr_result],
|
||||
output_path,
|
||||
formatting=formatting
|
||||
)
|
||||
|
||||
content = result_path.read_text(encoding="utf-8")
|
||||
assert "-" * 80 in content # Separator
|
||||
|
||||
def test_export_to_txt_missing_markdown(self, export_service, temp_dir):
|
||||
"""Test TXT export with missing markdown file"""
|
||||
result = Mock()
|
||||
result.id = 1
|
||||
result.markdown_path = "/nonexistent/path.md"
|
||||
result.file = Mock()
|
||||
result.file.original_filename = "test.png"
|
||||
|
||||
output_path = temp_dir / "output.txt"
|
||||
|
||||
# Should not fail, just skip the file
|
||||
result_path = export_service.export_to_txt([result], output_path)
|
||||
assert result_path.exists()
|
||||
|
||||
def test_export_to_txt_creates_parent_directories(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test that export creates necessary parent directories"""
|
||||
output_path = temp_dir / "subdir" / "output.txt"
|
||||
|
||||
result_path = export_service.export_to_txt([mock_ocr_result], output_path)
|
||||
|
||||
assert result_path.exists()
|
||||
assert result_path.parent.exists()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestExportToJSON:
|
||||
"""Test JSON export"""
|
||||
|
||||
def test_export_to_json_basic(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test basic JSON export"""
|
||||
output_path = temp_dir / "output.json"
|
||||
|
||||
result_path = export_service.export_to_json([mock_ocr_result], output_path)
|
||||
|
||||
assert result_path.exists()
|
||||
data = json.loads(result_path.read_text(encoding="utf-8"))
|
||||
|
||||
assert "export_time" in data
|
||||
assert data["total_files"] == 1
|
||||
assert len(data["results"]) == 1
|
||||
assert data["results"][0]["filename"] == "test.png"
|
||||
assert data["results"][0]["average_confidence"] == 0.95
|
||||
|
||||
def test_export_to_json_with_layout(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test JSON export with layout data"""
|
||||
output_path = temp_dir / "output.json"
|
||||
|
||||
result_path = export_service.export_to_json(
|
||||
[mock_ocr_result],
|
||||
output_path,
|
||||
include_layout=True
|
||||
)
|
||||
|
||||
data = json.loads(result_path.read_text(encoding="utf-8"))
|
||||
assert "layout_data" in data["results"][0]
|
||||
|
||||
def test_export_to_json_without_layout(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test JSON export without layout data"""
|
||||
output_path = temp_dir / "output.json"
|
||||
|
||||
result_path = export_service.export_to_json(
|
||||
[mock_ocr_result],
|
||||
output_path,
|
||||
include_layout=False
|
||||
)
|
||||
|
||||
data = json.loads(result_path.read_text(encoding="utf-8"))
|
||||
assert "layout_data" not in data["results"][0]
|
||||
|
||||
def test_export_to_json_multiple_results(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test JSON export with multiple results"""
|
||||
output_path = temp_dir / "output.json"
|
||||
|
||||
result_path = export_service.export_to_json(
|
||||
[mock_ocr_result, mock_ocr_result],
|
||||
output_path
|
||||
)
|
||||
|
||||
data = json.loads(result_path.read_text(encoding="utf-8"))
|
||||
assert data["total_files"] == 2
|
||||
assert len(data["results"]) == 2
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestExportToExcel:
|
||||
"""Test Excel export"""
|
||||
|
||||
def test_export_to_excel_basic(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test basic Excel export"""
|
||||
output_path = temp_dir / "output.xlsx"
|
||||
|
||||
result_path = export_service.export_to_excel([mock_ocr_result], output_path)
|
||||
|
||||
assert result_path.exists()
|
||||
df = pd.read_excel(result_path)
|
||||
assert len(df) == 1
|
||||
assert "文件名" in df.columns
|
||||
assert df.iloc[0]["文件名"] == "test.png"
|
||||
|
||||
def test_export_to_excel_with_confidence(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test Excel export with confidence scores"""
|
||||
output_path = temp_dir / "output.xlsx"
|
||||
|
||||
result_path = export_service.export_to_excel(
|
||||
[mock_ocr_result],
|
||||
output_path,
|
||||
include_confidence=True
|
||||
)
|
||||
|
||||
df = pd.read_excel(result_path)
|
||||
assert "平均信心度" in df.columns
|
||||
|
||||
def test_export_to_excel_without_processing_time(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test Excel export without processing time"""
|
||||
output_path = temp_dir / "output.xlsx"
|
||||
|
||||
result_path = export_service.export_to_excel(
|
||||
[mock_ocr_result],
|
||||
output_path,
|
||||
include_processing_time=False
|
||||
)
|
||||
|
||||
df = pd.read_excel(result_path)
|
||||
assert "處理時間(秒)" not in df.columns
|
||||
|
||||
def test_export_to_excel_long_content_truncation(self, export_service, temp_dir):
|
||||
"""Test that long content is truncated in Excel"""
|
||||
# Create result with long content
|
||||
md_file = temp_dir / "long.md"
|
||||
md_file.write_text("x" * 2000, encoding="utf-8")
|
||||
|
||||
result = Mock()
|
||||
result.id = 1
|
||||
result.markdown_path = str(md_file)
|
||||
result.detected_language = "zh"
|
||||
result.total_text_regions = 10
|
||||
result.average_confidence = 0.95
|
||||
result.file = Mock()
|
||||
result.file.original_filename = "long.png"
|
||||
result.file.file_format = "png"
|
||||
result.file.file_size = 1024
|
||||
result.file.processing_time = 1.0
|
||||
|
||||
output_path = temp_dir / "output.xlsx"
|
||||
result_path = export_service.export_to_excel([result], output_path)
|
||||
|
||||
df = pd.read_excel(result_path)
|
||||
content = df.iloc[0]["提取內容"]
|
||||
assert "..." in content
|
||||
assert len(content) <= 1004 # 1000 + "..."
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestExportToMarkdown:
|
||||
"""Test Markdown export"""
|
||||
|
||||
def test_export_to_markdown_combined(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test combined Markdown export"""
|
||||
output_path = temp_dir / "combined.md"
|
||||
|
||||
result_path = export_service.export_to_markdown(
|
||||
[mock_ocr_result],
|
||||
output_path,
|
||||
combine=True
|
||||
)
|
||||
|
||||
assert result_path.exists()
|
||||
assert result_path.is_file()
|
||||
content = result_path.read_text(encoding="utf-8")
|
||||
assert "test.png" in content
|
||||
assert "Test Document" in content
|
||||
|
||||
def test_export_to_markdown_separate(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test separate Markdown export"""
|
||||
output_dir = temp_dir / "markdown_files"
|
||||
|
||||
result_path = export_service.export_to_markdown(
|
||||
[mock_ocr_result],
|
||||
output_dir,
|
||||
combine=False
|
||||
)
|
||||
|
||||
assert result_path.exists()
|
||||
assert result_path.is_dir()
|
||||
files = list(result_path.glob("*.md"))
|
||||
assert len(files) == 1
|
||||
|
||||
def test_export_to_markdown_multiple_files(self, export_service, mock_ocr_result, temp_dir):
|
||||
"""Test Markdown export with multiple files"""
|
||||
output_path = temp_dir / "combined.md"
|
||||
|
||||
result_path = export_service.export_to_markdown(
|
||||
[mock_ocr_result, mock_ocr_result],
|
||||
output_path,
|
||||
combine=True
|
||||
)
|
||||
|
||||
content = result_path.read_text(encoding="utf-8")
|
||||
assert content.count("---") >= 1 # Separators
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestExportToPDF:
|
||||
"""Test PDF export"""
|
||||
|
||||
@patch.object(ExportService, '__init__', lambda self: None)
|
||||
def test_export_to_pdf_success(self, mock_ocr_result, temp_dir):
|
||||
"""Test successful PDF export"""
|
||||
from app.services.pdf_generator import PDFGenerator
|
||||
|
||||
service = ExportService()
|
||||
service.pdf_generator = Mock(spec=PDFGenerator)
|
||||
service.pdf_generator.generate_pdf = Mock(return_value=temp_dir / "output.pdf")
|
||||
|
||||
output_path = temp_dir / "output.pdf"
|
||||
|
||||
result_path = service.export_to_pdf(mock_ocr_result, output_path)
|
||||
|
||||
service.pdf_generator.generate_pdf.assert_called_once()
|
||||
call_kwargs = service.pdf_generator.generate_pdf.call_args[1]
|
||||
assert call_kwargs["css_template"] == "default"
|
||||
|
||||
@patch.object(ExportService, '__init__', lambda self: None)
|
||||
def test_export_to_pdf_with_custom_template(self, mock_ocr_result, temp_dir):
|
||||
"""Test PDF export with custom CSS template"""
|
||||
from app.services.pdf_generator import PDFGenerator
|
||||
|
||||
service = ExportService()
|
||||
service.pdf_generator = Mock(spec=PDFGenerator)
|
||||
service.pdf_generator.generate_pdf = Mock(return_value=temp_dir / "output.pdf")
|
||||
|
||||
output_path = temp_dir / "output.pdf"
|
||||
|
||||
service.export_to_pdf(mock_ocr_result, output_path, css_template="academic")
|
||||
|
||||
call_kwargs = service.pdf_generator.generate_pdf.call_args[1]
|
||||
assert call_kwargs["css_template"] == "academic"
|
||||
|
||||
@patch.object(ExportService, '__init__', lambda self: None)
|
||||
def test_export_to_pdf_missing_markdown(self, temp_dir):
|
||||
"""Test PDF export with missing markdown file"""
|
||||
from app.services.pdf_generator import PDFGenerator
|
||||
|
||||
result = Mock()
|
||||
result.id = 1
|
||||
result.markdown_path = None
|
||||
result.file = Mock()
|
||||
|
||||
service = ExportService()
|
||||
service.pdf_generator = Mock(spec=PDFGenerator)
|
||||
|
||||
output_path = temp_dir / "output.pdf"
|
||||
|
||||
with pytest.raises(ExportError) as exc_info:
|
||||
service.export_to_pdf(result, output_path)
|
||||
|
||||
assert "not found" in str(exc_info.value).lower()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestGetExportFormats:
|
||||
"""Test getting available export formats"""
|
||||
|
||||
def test_get_export_formats(self, export_service):
|
||||
"""Test getting export formats"""
|
||||
formats = export_service.get_export_formats()
|
||||
|
||||
assert isinstance(formats, dict)
|
||||
assert "txt" in formats
|
||||
assert "json" in formats
|
||||
assert "excel" in formats
|
||||
assert "markdown" in formats
|
||||
assert "pdf" in formats
|
||||
assert "zip" in formats
|
||||
|
||||
# Check descriptions are in Chinese
|
||||
for desc in formats.values():
|
||||
assert isinstance(desc, str)
|
||||
assert len(desc) > 0
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestApplyExportRule:
|
||||
"""Test export rule application"""
|
||||
|
||||
def test_apply_export_rule_success(self, export_service, mock_db):
|
||||
"""Test applying export rule"""
|
||||
# Create mock rule
|
||||
rule = Mock()
|
||||
rule.id = 1
|
||||
rule.config_json = {
|
||||
"filters": {
|
||||
"confidence_threshold": 0.80
|
||||
}
|
||||
}
|
||||
|
||||
mock_db.query.return_value.filter.return_value.first.return_value = rule
|
||||
|
||||
# Create mock results
|
||||
result1 = Mock()
|
||||
result1.average_confidence = 0.95
|
||||
result1.file = Mock()
|
||||
result1.file.original_filename = "test1.png"
|
||||
|
||||
result2 = Mock()
|
||||
result2.average_confidence = 0.70
|
||||
result2.file = Mock()
|
||||
result2.file.original_filename = "test2.png"
|
||||
|
||||
results = [result1, result2]
|
||||
|
||||
filtered = export_service.apply_export_rule(mock_db, results, rule_id=1)
|
||||
|
||||
assert len(filtered) == 1
|
||||
assert result1 in filtered
|
||||
|
||||
def test_apply_export_rule_not_found(self, export_service, mock_db):
|
||||
"""Test applying non-existent rule"""
|
||||
mock_db.query.return_value.filter.return_value.first.return_value = None
|
||||
|
||||
with pytest.raises(ExportError) as exc_info:
|
||||
export_service.apply_export_rule(mock_db, [], rule_id=999)
|
||||
|
||||
assert "not found" in str(exc_info.value).lower()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestEdgeCases:
|
||||
"""Test edge cases and error handling"""
|
||||
|
||||
def test_export_to_txt_empty_results(self, export_service, temp_dir):
|
||||
"""Test TXT export with empty results list"""
|
||||
output_path = temp_dir / "output.txt"
|
||||
|
||||
result_path = export_service.export_to_txt([], output_path)
|
||||
|
||||
assert result_path.exists()
|
||||
content = result_path.read_text(encoding="utf-8")
|
||||
assert content == ""
|
||||
|
||||
def test_export_to_json_empty_results(self, export_service, temp_dir):
|
||||
"""Test JSON export with empty results list"""
|
||||
output_path = temp_dir / "output.json"
|
||||
|
||||
result_path = export_service.export_to_json([], output_path)
|
||||
|
||||
data = json.loads(result_path.read_text(encoding="utf-8"))
|
||||
assert data["total_files"] == 0
|
||||
assert len(data["results"]) == 0
|
||||
|
||||
def test_export_with_unicode_content(self, export_service, temp_dir):
|
||||
"""Test export with Unicode/Chinese content"""
|
||||
md_file = temp_dir / "chinese.md"
|
||||
md_file.write_text("# 測試文檔\n\n這是中文內容。", encoding="utf-8")
|
||||
|
||||
result = Mock()
|
||||
result.id = 1
|
||||
result.markdown_path = str(md_file)
|
||||
result.json_path = None
|
||||
result.detected_language = "zh"
|
||||
result.total_text_regions = 10
|
||||
result.average_confidence = 0.95
|
||||
result.layout_data = None # Use None instead of Mock for JSON serialization
|
||||
result.images_metadata = None # Use None instead of Mock
|
||||
result.file = Mock()
|
||||
result.file.id = 1
|
||||
result.file.original_filename = "中文測試.png"
|
||||
result.file.file_format = "png"
|
||||
result.file.file_size = 1024
|
||||
result.file.processing_time = 1.0
|
||||
|
||||
# Test TXT export
|
||||
txt_path = temp_dir / "output.txt"
|
||||
export_service.export_to_txt([result], txt_path)
|
||||
assert "測試文檔" in txt_path.read_text(encoding="utf-8")
|
||||
|
||||
# Test JSON export
|
||||
json_path = temp_dir / "output.json"
|
||||
export_service.export_to_json([result], json_path)
|
||||
data = json.loads(json_path.read_text(encoding="utf-8"))
|
||||
assert data["results"][0]["filename"] == "中文測試.png"
|
||||
|
||||
def test_apply_filters_with_none_values(self, export_service):
|
||||
"""Test filters with None values in results"""
|
||||
result = Mock()
|
||||
result.average_confidence = None
|
||||
result.detected_language = None
|
||||
result.file = Mock()
|
||||
result.file.original_filename = "test.png"
|
||||
|
||||
filters = {"confidence_threshold": 0.80}
|
||||
|
||||
filtered = export_service.apply_filters([result], filters)
|
||||
|
||||
# Should filter out result with None confidence
|
||||
assert len(filtered) == 0
|
||||
Reference in New Issue
Block a user