parserPDF / tests /test_main_ui.py
semmyk's picture
initial commit
0fd441a
raw
history blame
6.44 kB
# tests/test_main_ui.py
# run with pytest tests/.
import pytest
from unittest.mock import patch, MagicMock
from pathlib import Path
from main import build_interface # Wait, main imports from ui, but test main logic
from ui.gradio_ui import convert_batch, build_interface, accumulate_files, clear_state, pdf_files_wrap
from utils.logger import get_logger
logger = get_logger("test_main_ui")
@pytest.fixture
def mock_gradio():
with patch('gradio.Blocks') as mock_blocks, \
patch('gradio.Markdown') as mock_md, \
patch('gradio.Accordion') as mock_accordion, \
patch('gradio.Dropdown') as mock_dropdown, \
patch('gradio.Textbox') as mock_textbox, \
patch('gradio.Slider') as mock_slider, \
patch('gradio.Checkbox') as mock_checkbox, \
patch('gradio.Button') as mock_button, \
patch('gradio.File') as mock_file, \
patch('gradio.UploadButton') as mock_upload, \
patch('gradio.State') as mock_state, \
patch('gradio.Tab') as mock_tab, \
patch('gradio.JSON') as mock_json, \
patch('gradio.Files') as mock_files, \
patch('gradio.Gallery') as mock_gallery:
yield {
'Blocks': mock_blocks, 'Markdown': mock_md, 'Accordion': mock_accordion,
'Dropdown': mock_dropdown, 'Textbox': mock_textbox, 'Slider': mock_slider,
'Checkbox': mock_checkbox, 'Button': mock_button, 'File': mock_file,
'UploadButton': mock_upload, 'State': mock_state, 'Tab': mock_tab,
'JSON': mock_json, 'Files': mock_files, 'Gallery': mock_gallery
}
def test_build_interface(mock_gradio):
demo = build_interface()
assert demo is not None
# Verify UI components are created
mock_gradio['Blocks'].assert_called_once_with(title="parserPDF", css=MagicMock())
mock_gradio['Markdown'].assert_called() # Title markdown
mock_gradio['Accordion'].assert_any_call("βš™οΈ LLM Model Settings", open=False)
mock_gradio['Tab'].assert_any_call(" πŸ“„ PDF & HTML ➜ Markdown")
def test_convert_batch_no_files():
result = convert_batch([], 0, "huggingface", "test-model", "fireworks-ai", "", "model-id",
"system", 1024, 0.0, 0.1, False, "token",
"https://router.huggingface.co/v1", "webp", 4, 2, "markdown",
"output_dir", False, None)
assert "No files uploaded" in result[0]
@patch('ui.gradio_ui.login_huggingface')
@patch('ui.gradio_ui.ProcessPoolExecutor')
@patch('ui.gradio_ui.pdf2md_converter.convert_files')
def test_convert_batch_success(mock_convert, mock_pool, mock_login):
mock_result = MagicMock()
mock_convert.return_value = {"filepath": Path("test.md"), "image_path": ["img.jpg"], "markdown": "content"}
mock_pool.return_value.__enter__.return_value.map.return_value = [mock_result]
mock_login.return_value = None
pdf_files = [MagicMock(name="test.pdf")]
result = convert_batch(pdf_files, 1, "huggingface", "test-model", "fireworks-ai", "", "model-id",
"system", 1024, 0.0, 0.1, False, "token",
"https://router.huggingface.co/v1", "webp", 4, 2, "markdown",
"output_dir", False, None)
assert len(result) == 3
assert "test.md" in result[0]
assert "img.jpg" in result[2][0]
mock_pool.assert_called_once()
mock_convert.assert_called_once_with("test.pdf")
@patch('ui.gradio_ui.ProcessPoolExecutor')
def test_convert_batch_pool_error(mock_pool):
mock_pool.side_effect = Exception("Pool error")
pdf_files = [MagicMock(name="test.pdf")]
result = convert_batch(pdf_files, 1, "huggingface", "test-model", "fireworks-ai", "", "model-id",
"system", 1024, 0.0, 0.1, False, "token",
"https://router.huggingface.co/v1", "webp", 4, 2, "markdown",
"output_dir", False, None)
assert "Error during ProcessPoolExecutor" in result[0]
def test_accumulate_files():
# Test initial accumulation
new_files = [MagicMock(name="/tmp/file1.pdf"), MagicMock(name="/tmp/file2.html")]
state = []
updated_state, message = accumulate_files(new_files, state)
assert len(updated_state) == 2
assert "/tmp/file1.pdf" in updated_state
assert "Accumulated 2 file(s)" in message
# Test adding to existing state
new_files2 = [MagicMock(name="/tmp/file3.pdf")]
updated_state2, message2 = accumulate_files(new_files2, updated_state)
assert len(updated_state2) == 3
assert "Accumulated 3 file(s)" in message2
# Test no new files
_, message3 = accumulate_files([], updated_state2)
assert "No new files uploaded" in message3
def test_clear_state():
result = clear_state()
assert len(result) == 4
assert result[0] == [] # cleared file list
assert result[1] == "Files list cleared." # message
assert result[2] == [] # cleared file btn
assert result[3] == [] # cleared dir btn
def test_pdf_files_wrap():
# Single file
single_file = "single.pdf"
wrapped = pdf_files_wrap(single_file)
assert isinstance(wrapped, list)
assert len(wrapped) == 1
assert wrapped[0] == single_file
# List of files
files_list = ["file1.pdf", "file2.html"]
wrapped_list = pdf_files_wrap(files_list)
assert wrapped_list == files_list
# None input
assert pdf_files_wrap(None) == [None]
@patch('ui.gradio_ui.os.chdir')
@patch('ui.gradio_ui.Path')
def test_main_launch(mock_path, mock_chdir):
mock_script_dir = MagicMock()
mock_path.return_value.resolve.return_value.parent = mock_script_dir
mock_chdir.return_value = None
# Test main execution path
with patch('builtins.__name__', '__main__'):
from main import main # Assuming main has a main function, or test the if __name__ logic indirectly
# Since main.py is simple, test the key parts
demo = MagicMock()
with patch('ui.gradio_ui.build_interface', return_value=demo):
with patch('gradio.Interface.launch') as mock_launch:
# Execute main logic
import main
main.main() # If it has main(), or just import runs it
mock_chdir.assert_called_once_with(mock_script_dir)
mock_launch.assert_called_once_with(debug=True, show_error=True)