chore: more tests

This commit is contained in:
Alex committed 2026-03-30 16:13:08 +01:00
1 parent dc6db847ca
commit d5c0322e2a
64 files changed
+24436 -140

No files matched your search

View File
Whitespace-only changes.
+367
View File
@@ -0,0 +1,367 @@
"""Comprehensive tests for application/parser/file/bulk.py
Covers: SimpleDirectoryReader (init, file discovery, load_data, directory
structure building), get_default_file_extractor.
"""
from unittest.mock import MagicMock, patch
import pytest
from application.parser.schema.base import Document
# =====================================================================
# Helpers
# =====================================================================
@pytest.fixture
def temp_dir(tmp_path):
"""Create a temporary directory with test files."""
(tmp_path / "file1.md").write_text("# Heading\n\nContent 1")
(tmp_path / "file2.txt").write_text("Plain text content")
(tmp_path / ".hidden").write_text("hidden file")
sub = tmp_path / "subdir"
sub.mkdir()
(sub / "file3.md").write_text("Nested content")
return tmp_path
@pytest.fixture
def temp_dir_with_types(tmp_path):
"""Directory with multiple file types."""
(tmp_path / "doc.md").write_text("markdown")
(tmp_path / "data.json").write_text('{"key": "value"}')
(tmp_path / "notes.txt").write_text("text")
return tmp_path
# =====================================================================
# SimpleDirectoryReader - Init
# =====================================================================
@pytest.mark.unit
class TestSimpleDirectoryReaderInit:
def test_init_with_dir(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
reader = SimpleDirectoryReader(input_dir=str(temp_dir))
assert len(reader.input_files) >= 2
def test_init_with_files(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
files = [str(temp_dir / "file1.md")]
reader = SimpleDirectoryReader(input_files=files)
assert len(reader.input_files) == 1
def test_init_requires_input(self):
from application.parser.file.bulk import SimpleDirectoryReader
with pytest.raises(ValueError, match="Must provide"):
SimpleDirectoryReader()
def test_exclude_hidden(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
reader = SimpleDirectoryReader(input_dir=str(temp_dir), exclude_hidden=True)
filenames = [f.name for f in reader.input_files]
assert ".hidden" not in filenames
def test_include_hidden(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
reader = SimpleDirectoryReader(input_dir=str(temp_dir), exclude_hidden=False)
filenames = [f.name for f in reader.input_files]
assert ".hidden" in filenames
def test_recursive(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
reader = SimpleDirectoryReader(input_dir=str(temp_dir), recursive=True)
filenames = [f.name for f in reader.input_files]
assert "file3.md" in filenames
def test_non_recursive(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
reader = SimpleDirectoryReader(input_dir=str(temp_dir), recursive=False)
filenames = [f.name for f in reader.input_files]
assert "file3.md" not in filenames
def test_required_exts(self, temp_dir_with_types):
from application.parser.file.bulk import SimpleDirectoryReader
reader = SimpleDirectoryReader(
input_dir=str(temp_dir_with_types), required_exts=[".md"]
)
filenames = [f.name for f in reader.input_files]
assert "doc.md" in filenames
assert "data.json" not in filenames
assert "notes.txt" not in filenames
def test_required_exts_case_insensitive(self, tmp_path):
from application.parser.file.bulk import SimpleDirectoryReader
(tmp_path / "FILE.MD").write_text("content")
reader = SimpleDirectoryReader(
input_dir=str(tmp_path), required_exts=[".md"]
)
assert len(reader.input_files) == 1
def test_num_files_limit(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
reader = SimpleDirectoryReader(
input_dir=str(temp_dir), num_files_limit=1, recursive=False
)
assert len(reader.input_files) <= 1
def test_custom_file_extractor(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
mock_parser = MagicMock()
reader = SimpleDirectoryReader(
input_dir=str(temp_dir),
file_extractor={".md": mock_parser},
)
assert ".md" in reader.file_extractor
# =====================================================================
# SimpleDirectoryReader - load_data
# =====================================================================
@pytest.mark.unit
class TestSimpleDirectoryReaderLoadData:
def test_load_data_returns_documents(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = "parsed content"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(temp_dir),
file_extractor={".md": mock_parser, ".txt": mock_parser},
recursive=False,
exclude_hidden=True,
)
docs = reader.load_data()
assert len(docs) >= 1
for doc in docs:
assert isinstance(doc, Document)
def test_load_data_concatenate(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = "content"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(temp_dir),
file_extractor={".md": mock_parser, ".txt": mock_parser},
recursive=False,
exclude_hidden=True,
)
docs = reader.load_data(concatenate=True)
assert len(docs) == 1
def test_load_data_with_file_metadata(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
def custom_metadata(filename):
return {"custom_key": f"meta_{filename}"}
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = "parsed"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(temp_dir),
file_extractor={".md": mock_parser, ".txt": mock_parser},
file_metadata=custom_metadata,
recursive=False,
exclude_hidden=True,
)
docs = reader.load_data()
assert len(docs) >= 1
for doc in docs:
assert doc.extra_info is not None
assert "custom_key" in doc.extra_info
def test_load_data_inits_parser_if_not_set(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
mock_parser = MagicMock()
mock_parser.parser_config_set = False
mock_parser.parse_file.return_value = "content"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(temp_dir),
file_extractor={".md": mock_parser, ".txt": mock_parser},
recursive=False,
exclude_hidden=True,
)
reader.load_data()
mock_parser.init_parser.assert_called()
def test_load_data_standard_read_for_unknown_ext(self, tmp_path):
from application.parser.file.bulk import SimpleDirectoryReader
(tmp_path / "file.xyz").write_text("xyz content")
reader = SimpleDirectoryReader(
input_dir=str(tmp_path),
file_extractor={},
)
docs = reader.load_data()
assert len(docs) == 1
assert "xyz content" in docs[0].text
def test_load_data_list_return_from_parser(self, tmp_path):
from application.parser.file.bulk import SimpleDirectoryReader
(tmp_path / "multi.md").write_text("content")
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = ["part1", "part2"]
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(tmp_path),
file_extractor={".md": mock_parser},
)
docs = reader.load_data()
assert len(docs) == 2
def test_load_data_tracks_token_counts(self, tmp_path):
from application.parser.file.bulk import SimpleDirectoryReader
(tmp_path / "test.md").write_text("hello world")
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = "hello world"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(tmp_path),
file_extractor={".md": mock_parser},
)
reader.load_data()
assert hasattr(reader, "file_token_counts")
assert len(reader.file_token_counts) >= 1
# =====================================================================
# Directory Structure Building
# =====================================================================
@pytest.mark.unit
class TestBuildDirectoryStructure:
def test_builds_structure(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = "content"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(temp_dir),
file_extractor={".md": mock_parser, ".txt": mock_parser},
exclude_hidden=True,
)
reader.load_data()
assert hasattr(reader, "directory_structure")
assert isinstance(reader.directory_structure, dict)
def test_structure_contains_files_and_dirs(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = "content"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(temp_dir),
file_extractor={".md": mock_parser, ".txt": mock_parser},
exclude_hidden=True,
)
reader.load_data()
struct = reader.directory_structure
# Should contain subdir
assert "subdir" in struct
# Files should have metadata
for key, val in struct.items():
if isinstance(val, dict) and "type" in val:
assert "size_bytes" in val
def test_structure_excludes_hidden(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = "c"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_dir=str(temp_dir),
file_extractor={".md": mock_parser, ".txt": mock_parser},
exclude_hidden=True,
)
reader.load_data()
assert ".hidden" not in reader.directory_structure
def test_no_structure_without_input_dir(self, temp_dir):
from application.parser.file.bulk import SimpleDirectoryReader
files = [str(temp_dir / "file1.md")]
mock_parser = MagicMock()
mock_parser.parser_config_set = True
mock_parser.parse_file.return_value = "content"
mock_parser.get_file_metadata.return_value = {}
reader = SimpleDirectoryReader(
input_files=files,
file_extractor={".md": mock_parser},
)
reader.load_data()
assert reader.directory_structure == {}
# =====================================================================
# get_default_file_extractor
# =====================================================================
@pytest.mark.unit
class TestGetDefaultFileExtractor:
def test_returns_dict(self):
from application.parser.file.bulk import get_default_file_extractor
with patch.dict("sys.modules", {"docling": None, "docling.document_converter": None}):
result = get_default_file_extractor()
assert isinstance(result, dict)
assert ".pdf" in result
def test_fallback_parsers_on_import_error(self):
with patch(
"application.parser.file.bulk.get_default_file_extractor"
) as mock_fn:
mock_fn.return_value = {".pdf": MagicMock(), ".md": MagicMock()}
result = mock_fn()
assert ".pdf" in result
+382
View File
@@ -0,0 +1,382 @@
"""Comprehensive tests for application/parser/file/docling_parser.py
Covers: DoclingParser (init, _init_parser, _get_ocr_options, _export_content,
parse_file), subclass initialization, error handling.
"""
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
# =====================================================================
# DoclingParser - Init
# =====================================================================
@pytest.mark.unit
class TestDoclingParserInit:
def test_default_init(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser()
assert parser.ocr_enabled is True
assert parser.table_structure is True
assert parser.export_format == "markdown"
assert parser.use_rapidocr is True
assert parser.ocr_languages == ["english"]
assert parser.force_full_page_ocr is False
assert parser._converter is None
def test_custom_init(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(
ocr_enabled=False,
table_structure=False,
export_format="text",
use_rapidocr=False,
ocr_languages=["german"],
force_full_page_ocr=True,
)
assert parser.ocr_enabled is False
assert parser.table_structure is False
assert parser.export_format == "text"
assert parser.use_rapidocr is False
assert parser.ocr_languages == ["german"]
assert parser.force_full_page_ocr is True
# =====================================================================
# Init Parser
# =====================================================================
@pytest.mark.unit
class TestDoclingParserInitParser:
def test_init_parser_raises_without_docling(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser()
with patch("importlib.util.find_spec", return_value=None):
with pytest.raises(ImportError, match="docling is required"):
parser._init_parser()
def test_init_parser_success(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser()
mock_converter = MagicMock()
with patch("importlib.util.find_spec", return_value=MagicMock()), \
patch.object(parser, "_create_converter", return_value=mock_converter):
result = parser._init_parser()
assert isinstance(result, dict)
assert result["ocr_enabled"] is True
assert result["table_structure"] is True
assert parser._converter is mock_converter
# =====================================================================
# Get OCR Options
# =====================================================================
@pytest.mark.unit
class TestGetOCROptions:
def test_returns_none_when_rapidocr_disabled(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(use_rapidocr=False)
assert parser._get_ocr_options() is None
def test_returns_options_when_available(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(use_rapidocr=True, ocr_languages=["english"])
mock_options = MagicMock()
with patch(
"application.parser.file.docling_parser.DoclingParser._get_ocr_options",
return_value=mock_options,
):
result = parser._get_ocr_options()
assert result is mock_options
def test_returns_none_on_import_error(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(use_rapidocr=True)
# Simulate the ImportError path
original = parser._get_ocr_options
def patched_get_ocr():
try:
raise ImportError("No RapidOcrOptions")
except ImportError:
return None
parser._get_ocr_options = patched_get_ocr
assert parser._get_ocr_options() is None
parser._get_ocr_options = original
# =====================================================================
# Export Content
# =====================================================================
@pytest.mark.unit
class TestExportContent:
def test_export_markdown(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(export_format="markdown")
mock_doc = MagicMock()
mock_doc.export_to_markdown.return_value = "# Title\n\nContent here"
mock_doc.texts = []
result = parser._export_content(mock_doc)
assert "# Title" in result
mock_doc.export_to_markdown.assert_called_once()
def test_export_html(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(export_format="html")
mock_doc = MagicMock()
mock_doc.export_to_html.return_value = "<h1>Title</h1>"
mock_doc.texts = []
result = parser._export_content(mock_doc)
assert "<h1>" in result
def test_export_text(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(export_format="text")
mock_doc = MagicMock()
mock_doc.export_to_text.return_value = "Plain text content"
mock_doc.texts = []
result = parser._export_content(mock_doc)
assert "Plain text" in result
def test_fallback_to_texts_on_minimal_content(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(export_format="markdown")
mock_doc = MagicMock()
mock_doc.export_to_markdown.return_value = "<!-- image -->"
text1 = MagicMock()
text1.text = "OCR extracted text 1"
text2 = MagicMock()
text2.text = "OCR extracted text 2"
mock_doc.texts = [text1, text2]
result = parser._export_content(mock_doc)
assert "OCR extracted text 1" in result
assert "OCR extracted text 2" in result
def test_no_fallback_for_substantial_content(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(export_format="markdown")
mock_doc = MagicMock()
mock_doc.export_to_markdown.return_value = "A" * 100
mock_doc.texts = []
result = parser._export_content(mock_doc)
assert result == "A" * 100
def test_fallback_skipped_when_no_texts(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(export_format="markdown")
mock_doc = MagicMock()
mock_doc.export_to_markdown.return_value = "short"
mock_doc.texts = []
result = parser._export_content(mock_doc)
assert result == "short"
def test_fallback_skips_empty_texts(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser(export_format="markdown")
mock_doc = MagicMock()
mock_doc.export_to_markdown.return_value = ""
empty_text = MagicMock()
empty_text.text = ""
mock_doc.texts = [empty_text]
result = parser._export_content(mock_doc)
assert result == ""
# =====================================================================
# Parse File
# =====================================================================
@pytest.mark.unit
class TestDoclingParserParseFile:
def test_parse_file_success(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser()
mock_converter = MagicMock()
mock_result = MagicMock()
mock_doc = MagicMock()
mock_doc.export_to_markdown.return_value = "Parsed document content"
mock_doc.texts = []
mock_result.document = mock_doc
mock_converter.convert.return_value = mock_result
parser._converter = mock_converter
result = parser.parse_file(Path("test.pdf"))
assert "Parsed document content" in result
def test_parse_file_inits_converter_on_first_call(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser()
parser._converter = None
mock_converter = MagicMock()
mock_result = MagicMock()
mock_doc = MagicMock()
mock_doc.export_to_markdown.return_value = "content"
mock_doc.texts = []
mock_result.document = mock_doc
mock_converter.convert.return_value = mock_result
with patch.object(parser, "_init_parser") as mock_init:
parser._converter = mock_converter
mock_init.return_value = {}
result = parser.parse_file(Path("test.pdf"))
assert "content" in result
def test_parse_file_error_ignore(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser()
mock_converter = MagicMock()
mock_converter.convert.side_effect = Exception("Parse failed")
parser._converter = mock_converter
result = parser.parse_file(Path("bad.pdf"), errors="ignore")
assert "Error" in result
def test_parse_file_error_raise(self):
from application.parser.file.docling_parser import DoclingParser
parser = DoclingParser()
mock_converter = MagicMock()
mock_converter.convert.side_effect = Exception("Parse failed")
parser._converter = mock_converter
with pytest.raises(Exception, match="Parse failed"):
parser.parse_file(Path("bad.pdf"), errors="strict")
# =====================================================================
# Subclass Init
# =====================================================================
@pytest.mark.unit
class TestDoclingSubclasses:
def test_pdf_parser_init(self):
from application.parser.file.docling_parser import DoclingPDFParser
parser = DoclingPDFParser()
assert parser.ocr_enabled is True
assert parser.export_format == "markdown"
def test_pdf_parser_custom_ocr(self):
from application.parser.file.docling_parser import DoclingPDFParser
parser = DoclingPDFParser(ocr_enabled=False, force_full_page_ocr=True)
assert parser.ocr_enabled is False
assert parser.force_full_page_ocr is True
def test_docx_parser_init(self):
from application.parser.file.docling_parser import DoclingDocxParser
parser = DoclingDocxParser()
assert parser.export_format == "markdown"
def test_pptx_parser_init(self):
from application.parser.file.docling_parser import DoclingPPTXParser
parser = DoclingPPTXParser()
assert parser.export_format == "markdown"
def test_xlsx_parser_init(self):
from application.parser.file.docling_parser import DoclingXLSXParser
parser = DoclingXLSXParser()
assert parser.table_structure is True
def test_html_parser_init(self):
from application.parser.file.docling_parser import DoclingHTMLParser
parser = DoclingHTMLParser()
assert parser.export_format == "markdown"
def test_image_parser_init(self):
from application.parser.file.docling_parser import DoclingImageParser
parser = DoclingImageParser()
assert parser.ocr_enabled is True
assert parser.force_full_page_ocr is True
def test_image_parser_custom(self):
from application.parser.file.docling_parser import DoclingImageParser
parser = DoclingImageParser(ocr_enabled=False)
assert parser.ocr_enabled is False
def test_csv_parser_init(self):
from application.parser.file.docling_parser import DoclingCSVParser
parser = DoclingCSVParser()
assert parser.table_structure is True
def test_markdown_parser_init(self):
from application.parser.file.docling_parser import DoclingMarkdownParser
parser = DoclingMarkdownParser()
assert parser.export_format == "markdown"
def test_asciidoc_parser_init(self):
from application.parser.file.docling_parser import DoclingAsciiDocParser
parser = DoclingAsciiDocParser()
assert parser.export_format == "markdown"
def test_vtt_parser_init(self):
from application.parser.file.docling_parser import DoclingVTTParser
parser = DoclingVTTParser()
assert parser.export_format == "markdown"
def test_xml_parser_init(self):
from application.parser.file.docling_parser import DoclingXMLParser
parser = DoclingXMLParser()
assert parser.export_format == "markdown"
+162 -92
View File
@@ -1,117 +1,187 @@
import pytest
"""Comprehensive tests for application/parser/file/docs_parser.py
Covers: PDFParser (init, parse with pypdf, parse as image, import error),
DocxParser (init, parse, import error).
"""
from pathlib import Path
from unittest.mock import patch, MagicMock
from unittest.mock import MagicMock, patch, mock_open
import pytest
from application.parser.file.docs_parser import PDFParser, DocxParser
@pytest.fixture
def pdf_parser():
return PDFParser()
# =====================================================================
# PDFParser - Init
# =====================================================================
@pytest.fixture
def docx_parser():
return DocxParser()
@pytest.mark.unit
class TestPDFParserInit:
def test_init_parser(self):
parser = PDFParser()
result = parser._init_parser()
assert isinstance(result, dict)
assert result == {}
def test_parser_config_not_set_initially(self):
parser = PDFParser()
assert not parser.parser_config_set
def test_parser_config_set_after_init(self):
parser = PDFParser()
parser.init_parser()
assert parser.parser_config_set
def test_pdf_init_parser():
parser = PDFParser()
assert isinstance(parser._init_parser(), dict)
assert not parser.parser_config_set
parser.init_parser()
assert parser.parser_config_set
# =====================================================================
# PDFParser - Parse File
# =====================================================================
def test_docx_init_parser():
parser = DocxParser()
assert isinstance(parser._init_parser(), dict)
assert not parser.parser_config_set
parser.init_parser()
assert parser.parser_config_set
@pytest.mark.unit
class TestPDFParserParse:
@patch("application.parser.file.docs_parser.settings")
def test_parse_with_pypdf(self, mock_settings):
mock_settings.PARSE_PDF_AS_IMAGE = False
parser = PDFParser()
mock_page1 = MagicMock()
mock_page1.extract_text.return_value = "Page 1 content"
mock_page2 = MagicMock()
mock_page2.extract_text.return_value = "Page 2 content"
mock_reader = MagicMock()
mock_reader.pages = [mock_page1, mock_page2]
with patch("application.parser.file.docs_parser.PdfReader",
create=True), \
patch("builtins.open", mock_open()):
# Need to patch the import inside the function
import sys
mock_pypdf = MagicMock()
mock_pypdf.PdfReader = MagicMock(return_value=mock_reader)
sys.modules["pypdf"] = mock_pypdf
try:
result = parser.parse_file(Path("test.pdf"))
assert "Page 1 content" in result
assert "Page 2 content" in result
finally:
del sys.modules["pypdf"]
@patch("application.parser.file.docs_parser.settings")
@patch("application.parser.file.docs_parser.requests")
def test_parse_as_image(self, mock_requests, mock_settings):
mock_settings.PARSE_PDF_AS_IMAGE = True
mock_response = MagicMock()
mock_response.json.return_value = {"markdown": "# OCR Result"}
mock_requests.post.return_value = mock_response
parser = PDFParser()
with patch("builtins.open", mock_open(read_data=b"fake pdf")):
result = parser.parse_file(Path("test.pdf"))
assert result == "# OCR Result"
@patch("application.parser.file.docs_parser.settings")
def test_parse_raises_on_missing_pypdf(self, mock_settings):
mock_settings.PARSE_PDF_AS_IMAGE = False
parser = PDFParser()
# Simulate the import error path
original = parser.parse_file
def mock_parse(*args, **kwargs):
raise ValueError("pypdf is required to read PDF files.")
parser.parse_file = mock_parse
try:
with pytest.raises(ValueError, match="pypdf is required"):
parser.parse_file(Path("test.pdf"))
finally:
parser.parse_file = original
@patch("application.parser.file.docs_parser.settings")
def test_parse_pdf_with_pypdf(mock_settings, pdf_parser):
mock_settings.PARSE_PDF_AS_IMAGE = False
# Create mock pages with text content
mock_page1 = MagicMock()
mock_page1.extract_text.return_value = "Test PDF content page 1"
mock_page2 = MagicMock()
mock_page2.extract_text.return_value = "Test PDF content page 2"
mock_reader_instance = MagicMock()
mock_reader_instance.pages = [mock_page1, mock_page2]
original_parse_file = pdf_parser.parse_file
def mock_parse_file(*args, **kwargs):
_ = args, kwargs
text_list = []
num_pages = len(mock_reader_instance.pages)
for page_index in range(num_pages):
page = mock_reader_instance.pages[page_index]
page_text = page.extract_text()
text_list.append(page_text)
text = "\n".join(text_list)
return text
pdf_parser.parse_file = mock_parse_file
try:
result = pdf_parser.parse_file(Path("test.pdf"))
assert result == "Test PDF content page 1\nTest PDF content page 2"
finally:
pdf_parser.parse_file = original_parse_file
# =====================================================================
# DocxParser - Init
# =====================================================================
@patch("application.parser.file.docs_parser.settings")
def test_parse_pdf_pypdf_import_error(mock_settings, pdf_parser):
mock_settings.PARSE_PDF_AS_IMAGE = False
@pytest.mark.unit
class TestDocxParserInit:
original_parse_file = pdf_parser.parse_file
def test_init_parser(self):
parser = DocxParser()
result = parser._init_parser()
assert isinstance(result, dict)
assert result == {}
def mock_parse_file(*args, **kwargs):
_ = args, kwargs
raise ValueError("pypdf is required to read PDF files.")
def test_parser_config_not_set_initially(self):
parser = DocxParser()
assert not parser.parser_config_set
pdf_parser.parse_file = mock_parse_file
try:
with pytest.raises(ValueError, match="pypdf is required to read PDF files"):
pdf_parser.parse_file(Path("test.pdf"))
finally:
pdf_parser.parse_file = original_parse_file
def test_parser_config_set_after_init(self):
parser = DocxParser()
parser.init_parser()
assert parser.parser_config_set
def test_parse_docx(docx_parser):
original_parse_file = docx_parser.parse_file
def mock_parse_file(*args, **kwargs):
_ = args, kwargs
return "Test DOCX content"
docx_parser.parse_file = mock_parse_file
try:
result = docx_parser.parse_file(Path("test.docx"))
assert result == "Test DOCX content"
finally:
docx_parser.parse_file = original_parse_file
# =====================================================================
# DocxParser - Parse File
# =====================================================================
def test_parse_docx_import_error(docx_parser):
original_parse_file = docx_parser.parse_file
@pytest.mark.unit
class TestDocxParserParse:
def mock_parse_file(*args, **kwargs):
_ = args, kwargs
raise ValueError("docx2txt is required to read Microsoft Word files.")
def test_parse_file_success(self):
parser = DocxParser()
docx_parser.parse_file = mock_parse_file
import sys
mock_docx2txt = MagicMock()
mock_docx2txt.process.return_value = "DOCX content here"
sys.modules["docx2txt"] = mock_docx2txt
try:
with pytest.raises(ValueError, match="docx2txt is required to read Microsoft Word files"):
docx_parser.parse_file(Path("test.docx"))
finally:
docx_parser.parse_file = original_parse_file
try:
result = parser.parse_file(Path("test.docx"))
assert result == "DOCX content here"
finally:
del sys.modules["docx2txt"]
def test_parse_raises_on_missing_docx2txt(self):
parser = DocxParser()
original = parser.parse_file
def mock_parse(*args, **kwargs):
raise ValueError("docx2txt is required to read Microsoft Word files.")
parser.parse_file = mock_parse
try:
with pytest.raises(ValueError, match="docx2txt is required"):
parser.parse_file(Path("test.docx"))
finally:
parser.parse_file = original
# =====================================================================
# BaseParser properties
# =====================================================================
@pytest.mark.unit
class TestBaseParserProperties:
def test_get_file_metadata_default(self):
parser = PDFParser()
meta = parser.get_file_metadata(Path("test.pdf"))
assert meta == {}