Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions streamlit_pdf_viewer/frontend/src/PdfViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ export default {

const handleResize = async () => {
if (isRendering.value) return;
// Skip render if container is hidden (e.g., inactive Streamlit tab)
if (pdfContainer.value && pdfContainer.value.clientWidth === 0) return;
isRendering.value = true;
try {
const binaryDataUrl = `data:application/pdf;base64,${props.args.binary}`;
Expand Down Expand Up @@ -464,15 +466,29 @@ export default {

const debouncedHandleResize = debounce(handleResize, 200);

let lastContainerWidth = 0;
const resizeObserver = new ResizeObserver((entries) => {
const entry = entries[0];
const newWidth = entry.contentRect.width;
if (lastContainerWidth === 0 && newWidth > 0) {
debouncedHandleResize();
}
lastContainerWidth = newWidth;
});

onMounted(() => {
debouncedHandleResize();
window.addEventListener("resize", debouncedHandleResize);
document.addEventListener('click', handleClickOutside);
if (pdfContainer.value) {
resizeObserver.observe(pdfContainer.value);
}
});

onUnmounted(() => {
window.removeEventListener("resize", debouncedHandleResize);
document.removeEventListener('click', handleClickOutside);
resizeObserver.disconnect();
});

return {
Expand Down
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import pytest
from pathlib import Path
from typing import Generator, Any, Dict
from playwright.sync_api import Browser, BrowserContext, Page
from playwright.sync_api import Browser, BrowserContext, Page, expect

from tests import ROOT_DIRECTORY
from tests.e2e_utils import StreamlitRunner
Expand Down Expand Up @@ -143,7 +143,7 @@ def default_go_to_app(page: Page, default_streamlit_app: StreamlitRunner):
"""Navigate to the default streamlit app and wait for it to load."""
page.goto(default_streamlit_app.server_url)
# Wait for app to load
page.get_by_role("img", name="Running...").is_hidden()
expect(page.get_by_role("img", name="Running...")).not_to_be_visible()


@pytest.fixture(autouse=True, scope="module")
Expand All @@ -164,4 +164,4 @@ def go_to_app(page: Page, streamlit_app: StreamlitRunner):
"""
page.goto(streamlit_app.server_url)
# Wait for app to load
page.get_by_role("img", name="Running...").is_hidden()
expect(page.get_by_role("img", name="Running...")).not_to_be_visible()
2 changes: 1 addition & 1 deletion tests/e2e_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def is_server_running(self, timeout: int = 30) -> bool:
if response.text == "ok":
return True
time.sleep(3)
if time.time() - start_time > 60 * timeout:
if time.time() - start_time > timeout:
return False

@property
Expand Down
8 changes: 3 additions & 5 deletions tests/test_accessibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,9 @@ def test_accessibility_high_contrast_mode(page: Page):
}
""")

page.wait_for_timeout(1000)

iframe_components = page.locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]')
expect(iframe_components).to_have_count(1)

# Check that the viewer is still visible and functional in high contrast
iframe_frame = page.frame_locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]').nth(0)
pdf_viewer = iframe_frame.locator('div[id="pdfViewer"]')
Expand All @@ -109,8 +107,8 @@ def test_accessibility_responsive_text_sizing(page: Page):

for viewport in viewports:
page.set_viewport_size(viewport)
page.wait_for_timeout(1000)
page.wait_for_timeout(500)

iframe_components = page.locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]')
expect(iframe_components).to_have_count(1)

Expand Down
2 changes: 1 addition & 1 deletion tests/test_alignment_center.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def streamlit_app():
def go_to_app(page: Page, streamlit_app: StreamlitRunner):
page.goto(streamlit_app.server_url)
# Wait for app to load
page.get_by_role("img", name="Running...").is_hidden()
expect(page.get_by_role("img", name="Running...")).not_to_be_visible()


def test_should_render_with_center_alignment(page: Page):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_alignment_left.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def streamlit_app():
def go_to_app(page: Page, streamlit_app: StreamlitRunner):
page.goto(streamlit_app.server_url)
# Wait for app to load
page.get_by_role("img", name="Running...").is_hidden()
expect(page.get_by_role("img", name="Running...")).not_to_be_visible()


def test_should_render_with_left_alignment(page: Page):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_alignment_right.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def streamlit_app():
def go_to_app(page: Page, streamlit_app: StreamlitRunner):
page.goto(streamlit_app.server_url)
# Wait for app to load
page.get_by_role("img", name="Running...").is_hidden()
expect(page.get_by_role("img", name="Running...")).not_to_be_visible()


def test_should_render_with_right_alignment(page: Page):
Expand Down
3 changes: 0 additions & 3 deletions tests/test_browser_compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ def test_basic_pdf_viewer_compatibility(page: Page):
@pytest.mark.compatibility
def test_pdf_viewer_renders_correctly(page: Page):
"""Test that PDF viewer renders correctly across browsers."""
# Wait for content to load
page.wait_for_timeout(3000)

# Check that the PDF viewer is present
iframe_components = page.locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]')
expect(iframe_components).to_have_count(1)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_edge_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ def test_edge_case_viewport_resize(page: Page):

for viewport in viewports:
page.set_viewport_size(viewport)
page.wait_for_timeout(1000)
page.wait_for_timeout(500)

# Check that all viewers remain functional
for i in range(1):
iframe_frame = page.frame_locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]').nth(i)
Expand Down
54 changes: 0 additions & 54 deletions tests/test_error_handling.py

This file was deleted.

85 changes: 3 additions & 82 deletions tests/test_interactive_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,94 +6,15 @@
def test_zoom_controls_visibility(page: Page):
"""Test that zoom controls are visible and functional."""
expect(page.get_by_text("Test PDF Viewer with auto zoom (fit to width)")).to_be_visible()

# Check that all three PDF viewers are present
iframe_components = page.locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]')
expect(iframe_components).to_have_count(1)
Comment on lines 10 to 12

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update stale inline comment about iframe count.

Line 10 says “all three PDF viewers,” but Line 12 asserts a count of 1. Please align the comment with the actual expectation to avoid confusion during future maintenance.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_interactive_features.py` around lines 10 - 12, Update the
misleading inline comment to match the actual assertion: change the comment
referencing “all three PDF viewers” to reflect that the test expects a single
PDF viewer. Locate the test variable iframe_components and the locator
'iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]' in
tests/test_interactive_features.py and revise the comment above that assertion
so it accurately describes expect(iframe_components).to_have_count(1).


# Test the first viewer (with zoom controls)
iframe_frame = page.frame_locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]').nth(0)

# Check for zoom controls
zoom_controls = iframe_frame.locator('button.zoom-button, .zoom-controls, [class*="zoom"]')
# Note: The exact selector depends on your frontend implementation
# This is a flexible approach that looks for common zoom control patterns
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated


@pytest.mark.skip(reason="Test expects 3 PDF viewers with different zoom levels (1.0, 2.0, 0.5) but the test app example_zoom_auto.py only contains 1 PDF viewer with auto zoom. Test app content doesn't match test expectations.")
@pytest.mark.interactive
def test_different_zoom_levels_render(page: Page):
"""Test that different zoom levels render correctly."""
iframe_components = page.locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]')

# Test each viewer with different zoom levels
for i in range(3):
iframe_frame = page.frame_locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]').nth(i)

# Check that each PDF container is visible
pdf_container = iframe_frame.locator('div[id="pdfContainer"]')
expect(pdf_container).to_be_visible()

# Check that each PDF viewer has content
pdf_viewer = iframe_frame.locator('div[id="pdfViewer"]')
expect(pdf_viewer).to_be_visible()

# Check for canvas elements (rendered PDF content)
canvas_elements = pdf_viewer.locator("canvas")
expect(canvas_elements).to_have_count(1) # At least one canvas per viewer


@pytest.mark.skip(reason="Test expects 3 PDF viewers with different zoom levels (1.0, 2.0, 0.5) to compare canvas sizes, but the test app example_zoom_auto.py only contains 1 PDF viewer with auto zoom. Cannot test zoom level differences without multiple viewers.")
@pytest.mark.interactive
def test_zoom_level_differences(page: Page):
"""Test that different zoom levels produce visually different results."""
iframe_components = page.locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]')

# Get the first viewer (zoom level 1.0)
iframe_frame_1 = page.frame_locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]').nth(0)
canvas_1 = iframe_frame_1.locator("canvas").first
canvas_1_box = canvas_1.bounding_box()

# Get the second viewer (zoom level 2.0)
iframe_frame_2 = page.frame_locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]').nth(1)
canvas_2 = iframe_frame_2.locator("canvas").first
canvas_2_box = canvas_2.bounding_box()

# Get the third viewer (zoom level 0.5)
iframe_frame_3 = page.frame_locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]').nth(2)
canvas_3 = iframe_frame_3.locator("canvas").first
canvas_3_box = canvas_3.bounding_box()

# The canvases should have different sizes due to different zoom levels
# High zoom (2.0) should be larger than normal zoom (1.0)
# Low zoom (0.5) should be smaller than normal zoom (1.0)
assert canvas_2_box['width'] > canvas_1_box['width'], "High zoom should produce larger canvas"
assert canvas_3_box['width'] < canvas_1_box['width'], "Low zoom should produce smaller canvas"


@pytest.mark.skip(reason="Test expects 3 PDF viewers to test responsiveness, but the test app example_zoom_auto.py only contains 1 PDF viewer. Cannot test multiple viewer responsiveness with single viewer.")
@pytest.mark.interactive
def test_interactive_features_responsiveness(page: Page):
"""Test that interactive features remain responsive."""
# Wait for all content to load
page.wait_for_timeout(3000)

iframe_components = page.locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]')
expect(iframe_components).to_have_count(1)

# Test that all viewers are interactive
for i in range(3):
iframe_frame = page.frame_locator('iframe[title="streamlit_pdf_viewer.streamlit_pdf_viewer"]').nth(i)

# Check that the PDF viewer is interactive (has content)
pdf_viewer = iframe_frame.locator('div[id="pdfViewer"]')
expect(pdf_viewer).to_be_visible()

# Check for canvas elements that indicate rendered content
canvas = pdf_viewer.locator("canvas").first
expect(canvas).to_be_visible()

# Verify the canvas has reasonable dimensions
canvas_box = canvas.bounding_box()
assert canvas_box['width'] > 0, f"Canvas {i} should have positive width"
assert canvas_box['height'] > 0, f"Canvas {i} should have positive height"
2 changes: 1 addition & 1 deletion tests/test_invalid_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def streamlit_app():
def go_to_app(page: Page, streamlit_app: StreamlitRunner):
page.goto(streamlit_app.server_url)
# Wait for app to load
page.get_by_role("img", name="Running...").is_hidden()
expect(page.get_by_role("img", name="Running...")).not_to_be_visible()


def test_should_fail_rendering(page: Page):
Expand Down
84 changes: 0 additions & 84 deletions tests/test_multiple_instances.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_page_separator_disabled.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def streamlit_app():
def go_to_app(page: Page, streamlit_app: StreamlitRunner):
page.goto(streamlit_app.server_url)
# Wait for app to load
page.get_by_role("img", name="Running...").is_hidden()
expect(page.get_by_role("img", name="Running...")).not_to_be_visible()


def test_should_render_with_page_separators_disabled(page: Page):
Expand Down
Loading
Loading