mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-12-30 02:31:20 +01:00
373 lines
9.0 KiB
Python
373 lines
9.0 KiB
Python
import pytest
|
|
from qtpy.QtPdf import QPdfDocument
|
|
from qtpy.QtPdfWidgets import QPdfView
|
|
|
|
from bec_widgets.widgets.utility.pdf_viewer.pdf_viewer import PdfViewerWidget
|
|
|
|
from .client_mocks import mocked_client
|
|
|
|
|
|
@pytest.fixture
|
|
def pdf_viewer_widget(qtbot, mocked_client):
|
|
"""Create a PDF viewer widget for testing."""
|
|
widget = PdfViewerWidget(client=mocked_client)
|
|
qtbot.addWidget(widget)
|
|
qtbot.waitExposed(widget)
|
|
yield widget
|
|
widget.cleanup()
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_pdf_file(tmpdir):
|
|
"""Create a minimal 3-page PDF file for testing."""
|
|
pdf_content = b"""%PDF-1.4
|
|
1 0 obj
|
|
<< /Type /Catalog /Pages 2 0 R >>
|
|
endobj
|
|
2 0 obj
|
|
<< /Type /Pages /Kids [3 0 R 5 0 R 7 0 R] /Count 3 >>
|
|
endobj
|
|
|
|
3 0 obj
|
|
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R >>
|
|
endobj
|
|
4 0 obj
|
|
<< /Length 44 >>
|
|
stream
|
|
BT /F1 12 Tf 100 700 Td (Page 1) Tj ET
|
|
endstream
|
|
endobj
|
|
|
|
5 0 obj
|
|
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 6 0 R >>
|
|
endobj
|
|
6 0 obj
|
|
<< /Length 44 >>
|
|
stream
|
|
BT /F1 12 Tf 100 700 Td (Page 2) Tj ET
|
|
endstream
|
|
endobj
|
|
|
|
7 0 obj
|
|
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 8 0 R >>
|
|
endobj
|
|
8 0 obj
|
|
<< /Length 44 >>
|
|
stream
|
|
BT /F1 12 Tf 100 700 Td (Page 3) Tj ET
|
|
endstream
|
|
endobj
|
|
|
|
9 0 obj
|
|
<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>
|
|
endobj
|
|
|
|
xref
|
|
0 10
|
|
0000000000 65535 f
|
|
0000000010 00000 n
|
|
0000000060 00000 n
|
|
0000000125 00000 n
|
|
0000000205 00000 n
|
|
0000000282 00000 n
|
|
0000000362 00000 n
|
|
0000000439 00000 n
|
|
0000000519 00000 n
|
|
0000000596 00000 n
|
|
trailer
|
|
<< /Size 10 /Root 1 0 R >>
|
|
startxref
|
|
675
|
|
%%EOF
|
|
"""
|
|
|
|
pdf_path = tmpdir.join("test_3page.pdf")
|
|
pdf_path.write_binary(pdf_content)
|
|
return str(pdf_path)
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_pdf_file_2(tmpdir):
|
|
"""Create a second minimal temporary PDF file for testing."""
|
|
# Create a minimal PDF content for testing
|
|
pdf_content = b"""%PDF-1.4
|
|
1 0 obj
|
|
<<
|
|
/Type /Catalog
|
|
/Pages 2 0 R
|
|
>>
|
|
endobj
|
|
2 0 obj
|
|
<<
|
|
/Type /Pages
|
|
/Kids [3 0 R]
|
|
/Count 1
|
|
>>
|
|
endobj
|
|
3 0 obj
|
|
<<
|
|
/Type /Page
|
|
/Parent 2 0 R
|
|
/MediaBox [0 0 612 792]
|
|
/Resources <<
|
|
/Font <<
|
|
/F1 <<
|
|
/Type /Font
|
|
/Subtype /Type1
|
|
/BaseFont /Helvetica
|
|
>>
|
|
>>
|
|
>>
|
|
/Contents 4 0 R
|
|
>>
|
|
endobj
|
|
4 0 obj
|
|
<<
|
|
/Length 44
|
|
>>stream
|
|
BT
|
|
/F1 12 Tf
|
|
100 700 Td
|
|
(Second Test PDF) Tj
|
|
ET
|
|
endstream
|
|
endobj
|
|
xref
|
|
0 5
|
|
0000000000 65535 f
|
|
0000000009 00000 n
|
|
0000000058 00000 n
|
|
0000000115 00000 n
|
|
0000000307 00000 n
|
|
trailer
|
|
<<
|
|
/Size 5
|
|
/Root 1 0 R
|
|
>>
|
|
startxref
|
|
398
|
|
%%EOF"""
|
|
# Create temporary PDF file using tmpdir
|
|
pdf_file = tmpdir.join("test2.pdf")
|
|
pdf_file.write_binary(pdf_content)
|
|
return str(pdf_file)
|
|
|
|
|
|
def test_initialization(pdf_viewer_widget: PdfViewerWidget):
|
|
"""Test that the widget initializes correctly."""
|
|
widget = pdf_viewer_widget
|
|
|
|
# Check basic widget setup
|
|
assert widget is not None
|
|
assert hasattr(widget, "pdf_view")
|
|
assert hasattr(widget, "toolbar")
|
|
assert hasattr(widget, "_pdf_document")
|
|
|
|
# Check initial state
|
|
assert widget._current_file_path is None
|
|
assert widget._page_spacing == 5
|
|
assert widget._side_margins == 10
|
|
|
|
# Check PDF view setup
|
|
assert isinstance(widget.pdf_view, QPdfView)
|
|
assert widget.pdf_view.zoomMode() == QPdfView.ZoomMode.FitToWidth
|
|
|
|
# Check PDF document setup
|
|
assert isinstance(widget._pdf_document, QPdfDocument)
|
|
|
|
|
|
def test_toolbar_setup(pdf_viewer_widget: PdfViewerWidget):
|
|
"""Test that toolbar is set up with all expected actions."""
|
|
widget = pdf_viewer_widget
|
|
toolbar = widget.toolbar
|
|
|
|
# Check that all expected actions exist
|
|
expected_actions = [
|
|
"open_file",
|
|
"zoom_in",
|
|
"zoom_out",
|
|
"fit_width",
|
|
"fit_page",
|
|
"reset_zoom",
|
|
"continuous_scroll",
|
|
"prev_page",
|
|
"next_page",
|
|
"page_jump",
|
|
]
|
|
|
|
for action_name in expected_actions:
|
|
assert toolbar.components.exists(action_name), f"Action {action_name} not found"
|
|
|
|
|
|
def test_load_pdf_file(qtbot, pdf_viewer_widget: PdfViewerWidget, temp_pdf_file, temp_pdf_file_2):
|
|
"""Test loading a PDF file into the viewer."""
|
|
widget = pdf_viewer_widget
|
|
|
|
# Load the temporary PDF file
|
|
widget.load_pdf(temp_pdf_file)
|
|
qtbot.wait(100) # Wait for loading
|
|
|
|
# Check that the document is loaded
|
|
assert widget._pdf_document.status() == QPdfDocument.Status.Ready
|
|
assert widget._pdf_document.pageCount() > 0
|
|
assert widget._current_file_path == temp_pdf_file
|
|
|
|
# Load a second PDF file to test reloading
|
|
widget.load_pdf(temp_pdf_file_2)
|
|
qtbot.wait(100) # Wait for loading
|
|
|
|
# Check that the new document is loaded
|
|
assert widget._pdf_document.status() == QPdfDocument.Status.Ready
|
|
assert widget._pdf_document.pageCount() > 0
|
|
assert widget._current_file_path == temp_pdf_file_2
|
|
|
|
assert widget.current_file_path == temp_pdf_file_2
|
|
|
|
widget.current_file_path = temp_pdf_file
|
|
qtbot.wait(100) # Wait for loading
|
|
assert widget.current_file_path == temp_pdf_file
|
|
|
|
|
|
def test_load_invalid_pdf_file(qtbot, pdf_viewer_widget: PdfViewerWidget, tmpdir):
|
|
"""Test loading an invalid PDF file into the viewer."""
|
|
widget = pdf_viewer_widget
|
|
|
|
# Try to open a non-existent file
|
|
invalid_pdf_file = tmpdir.join("non_existent.pdf")
|
|
|
|
# Attempt to load the invalid PDF file
|
|
with pytest.raises(FileNotFoundError):
|
|
widget.load_pdf(str(invalid_pdf_file), _override_slot_params={"raise_error": True})
|
|
|
|
|
|
def test_page_navigation(qtbot, pdf_viewer_widget: PdfViewerWidget, temp_pdf_file):
|
|
"""Test page navigation functionality."""
|
|
widget = pdf_viewer_widget
|
|
|
|
# Load the temporary PDF file
|
|
with qtbot.waitSignal(widget.document_ready, timeout=2000):
|
|
widget.load_pdf(temp_pdf_file)
|
|
|
|
# Check initial page
|
|
assert widget.current_page == 1
|
|
total_pages = widget._pdf_document.pageCount()
|
|
assert total_pages >= 1
|
|
|
|
# Navigate to next page
|
|
widget.next_page()
|
|
qtbot.wait(300)
|
|
assert widget.current_page == 2
|
|
|
|
# Navigate to previous page
|
|
widget.previous_page()
|
|
qtbot.wait(300)
|
|
assert widget.current_page == 1
|
|
|
|
# Jump to last page
|
|
widget.jump_to_page(total_pages)
|
|
qtbot.wait(300)
|
|
assert widget.current_page == total_pages
|
|
|
|
widget.jump_to_page(1)
|
|
qtbot.wait(300)
|
|
assert widget.current_page == 1
|
|
|
|
widget.jump_to_page(2)
|
|
qtbot.wait(300)
|
|
assert widget.current_page == 2
|
|
|
|
widget.go_to_last_page()
|
|
qtbot.wait(300)
|
|
assert widget.current_page == total_pages
|
|
|
|
widget.go_to_first_page()
|
|
qtbot.wait(300)
|
|
assert widget.current_page == 1
|
|
|
|
widget.page_input.setText(str(total_pages + 10))
|
|
widget.page_input.returnPressed.emit()
|
|
qtbot.wait(100)
|
|
assert widget.current_page == total_pages
|
|
|
|
|
|
def test_zoom_controls(qtbot, pdf_viewer_widget: PdfViewerWidget, temp_pdf_file):
|
|
"""Test zoom in, zoom out, fit width, fit page, and reset zoom functionality."""
|
|
widget = pdf_viewer_widget
|
|
|
|
# Load the temporary PDF file
|
|
with qtbot.waitSignal(widget.document_ready, timeout=2000):
|
|
widget.load_pdf(temp_pdf_file)
|
|
|
|
# Initial zoom mode should be FitToWidth
|
|
assert widget.pdf_view.zoomMode() == QPdfView.ZoomMode.FitToWidth
|
|
|
|
# Zoom in
|
|
initial_zoom = widget.pdf_view.zoomFactor()
|
|
widget.zoom_in()
|
|
qtbot.wait(100)
|
|
assert widget.pdf_view.zoomFactor() > initial_zoom
|
|
|
|
# Zoom out
|
|
zoom_after_in = widget.pdf_view.zoomFactor()
|
|
widget.zoom_out()
|
|
qtbot.wait(100)
|
|
assert widget.pdf_view.zoomFactor() < zoom_after_in
|
|
|
|
# Fit to page
|
|
widget.fit_to_page()
|
|
qtbot.wait(100)
|
|
assert widget.pdf_view.zoomMode() == QPdfView.ZoomMode.FitInView
|
|
|
|
# Fit to width
|
|
widget.fit_to_width()
|
|
qtbot.wait(100)
|
|
assert widget.pdf_view.zoomMode() == QPdfView.ZoomMode.FitToWidth
|
|
|
|
# Reset zoom
|
|
widget.reset_zoom()
|
|
qtbot.wait(100)
|
|
assert widget.pdf_view.zoomMode() == QPdfView.ZoomMode.Custom
|
|
|
|
|
|
def test_page_spacing_and_margins(qtbot, pdf_viewer_widget: PdfViewerWidget, temp_pdf_file):
|
|
"""Test setting page spacing and side margins."""
|
|
widget = pdf_viewer_widget
|
|
|
|
# Load the temporary PDF file
|
|
with qtbot.waitSignal(widget.document_ready, timeout=2000):
|
|
widget.load_pdf(temp_pdf_file)
|
|
|
|
# Set and verify page spacing
|
|
widget.page_spacing = 20
|
|
assert widget.page_spacing == 20
|
|
|
|
# Set and verify side margins
|
|
widget.side_margins = 30
|
|
assert widget.side_margins == 30
|
|
|
|
|
|
def test_toggle_continuous_scroll(qtbot, pdf_viewer_widget: PdfViewerWidget, temp_pdf_file):
|
|
"""Test toggling continuous scroll mode."""
|
|
widget = pdf_viewer_widget
|
|
|
|
# Load the temporary PDF file
|
|
with qtbot.waitSignal(widget.document_ready, timeout=2000):
|
|
widget.load_pdf(temp_pdf_file)
|
|
|
|
# Initial mode should be single page
|
|
assert widget.pdf_view.pageMode() == QPdfView.PageMode.SinglePage
|
|
|
|
# Toggle to continuous scroll
|
|
widget.toggle_continuous_scroll(True)
|
|
qtbot.wait(100)
|
|
assert widget.pdf_view.pageMode() == QPdfView.PageMode.MultiPage
|
|
|
|
# Toggle back to single page
|
|
widget.toggle_continuous_scroll(False)
|
|
qtbot.wait(100)
|
|
assert widget.pdf_view.pageMode() == QPdfView.PageMode.SinglePage
|
|
|
|
widget.jump_to_page(2)
|
|
qtbot.wait(100)
|
|
assert widget.current_page == 2
|