Skip to content

Commit

Permalink
Add missing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hansthen committed Jan 18, 2025
1 parent 8b61f79 commit 2b30c5b
Showing 1 changed file with 395 additions and 0 deletions.
395 changes: 395 additions & 0 deletions tests/streamlit/test_streamlit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,395 @@
from __future__ import annotations

from contextlib import contextmanager
from time import sleep

import pytest
from playwright.sync_api import Page, Response, expect

LOCAL_TEST = False

PORT = "8503" if LOCAL_TEST else "8699"


@pytest.fixture(scope="module", autouse=True)
def before_module():
# Run the streamlit app before each module
with run_streamlit():
yield


@pytest.fixture(scope="function", autouse=True)
def before_test(page: Page):
page.goto(f"localhost:{PORT}")
page.set_viewport_size({"width": 2000, "height": 2000})
expect.set_options(timeout=5_000)


# Take screenshot of each page if there are failures for this session
@pytest.fixture(scope="function", autouse=True)
def after_test(page: Page, request):
yield
if request.node.rep_call.failed:
page.screenshot(path=f"screenshot-{request.node.name}.png", full_page=True)


@contextmanager
def run_streamlit():
"""Run the streamlit app at examples/streamlit_app.py on port 8599"""
import subprocess

if LOCAL_TEST:
try:
yield 1
finally:
pass
else:
p = subprocess.Popen(
[
"streamlit",
"run",
"examples/streamlit_app.py",
"--server.port",
PORT,
"--server.headless",
"true",
]
)

sleep(5)

try:
yield 1
finally:
p.kill()


def click_button_or_marker(page: Page, nth: int = 0, locator: str | None = None):
"""For some reason, there's a discrepancy between how the map markers are
selectable locally and on github actions, perhaps related some error in loading
the actual marker images. This tries both ways to select a marker"""

frame = page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]')
if locator is not None:
frame = frame.locator(locator)
try:
frame.get_by_role("button", name="Marker").nth(nth).click(timeout=5_000)
except Exception:
frame.get_by_role("img").nth(nth).click(timeout=5_000)


def test_marker_click(page: Page):
def check_for_404(response: Response):
if not response.ok:
print(response)
print(response.text())
print(response.url)
print(response.status)
raise Exception("404")

page.on("response", check_for_404)

# Check page title
expect(page).to_have_title("streamlit-folium documentation")

expect(page.get_by_text('"last_object_clicked":NULL')).to_be_visible()

# Click marker
try:
click_button_or_marker(page)
except Exception as e:
page.screenshot(path="screenshot-test-marker-click.png", full_page=True)
raise e

expect(page.get_by_text('"last_object_clicked":NULL')).to_be_hidden()


def test_draw(page: Page):
# Test draw support
page.get_by_role("link", name="draw support").click()
# Click again to see if it resolves timeout issues
page.get_by_role("link", name="draw support").click()

expect(page).to_have_title("streamlit-folium documentation: Draw Support")

page.frame_locator(
'internal:attr=[title="streamlit_folium.st_folium"i]'
).get_by_role("link", name="Draw a polygon").click()

# Should be no drawings
expect(page.get_by_text('"all_drawings":NULL')).to_be_visible()

page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').get_by_role(
"link", name="Draw a marker"
).click()
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').locator(
".leaflet-marker-icon"
).first.click()
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').locator(
"#map_div"
).click()

# Should be one item in drawings after having placed a marker
expect(page.get_by_text('"all_drawings":NULL')).to_be_hidden()


def test_limit_data(page: Page):
# Test limit data support
page.get_by_role("link", name="limit data return").click()
# Click again to see if it resolves timeout issues
page.get_by_role("link", name="limit data return").click()

expect(page).to_have_title("streamlit-folium documentation: Limit Data Return")

expect(page.get_by_text('{"last_object_clicked":NULL}')).to_be_visible()

# Click marker
click_button_or_marker(page, 2)

# Have to click a second time for some reason, maybe because it doesn't load right
# away
click_button_or_marker(page, 2)

expect(page.get_by_text('{"last_object_clicked":{"lat":39.96')).to_be_visible()


def test_dual_map(page: Page):
page.get_by_role("link", name="misc examples").click()
# Click again to see if it resolves timeout issues
page.get_by_role("link", name="misc examples").click()

expect(page).to_have_title("streamlit-folium documentation: Misc Examples")

page.locator("label").filter(has_text="Dual map").click()
page.locator("label").filter(has_text="Dual map").click()

# Click marker on left map
try:
click_button_or_marker(page, 0, "#map_div")
click_button_or_marker(page, 0, "#map_div2")
except Exception as e:
page.screenshot(path="screenshot-dual-map.png", full_page=True)
raise e


def test_vector_grid(page: Page):
page.get_by_role("link", name="vector grid").click()
page.get_by_role("link", name="vector grid").click()

expect(page).to_have_title("streamlit-folium documentation: Vector Grid")

page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').locator(
".leaflet-marker-icon"
).click()


def test_tooltip_click(page: Page):
expect(page.get_by_text('"last_object_clicked_tooltip":NULL')).to_be_visible()

# Click marker on map
click_button_or_marker(page)

expect(
page.get_by_text('"last_object_clicked_tooltip":"Liberty Bell"')
).to_be_visible()


def test_popup_text(page: Page):
page.get_by_role("link", name="simple popup").click()
page.get_by_role("link", name="simple popup").click()

expect(page.get_by_text("Popup: None")).to_be_visible()
expect(page.get_by_text("Tooltip: None")).to_be_visible()

click_button_or_marker(page)

try:
expect(page.get_by_text("Popup: Popup!")).to_be_visible()
expect(page.get_by_text("Tooltip: Tooltip!")).to_be_visible()
except Exception as e:
page.screenshot(path="screenshot-popup.png")
raise e


def test_return_on_hover(page: Page):
page.get_by_role("link", name="simple popup").click()
page.get_by_role("link", name="simple popup").click()

expect(page.get_by_text("Popup: None")).to_be_visible()
expect(page.get_by_text("Tooltip: None")).to_be_visible()

page.get_by_text("Return on hover?").click()

click_button_or_marker(page, 1)

try:
expect(page.get_by_text("Popup: Popup 2!")).to_be_visible()
expect(page.get_by_text("Tooltip: Tooltip 2!")).to_be_visible()
except Exception as e:
page.screenshot(path="screenshot-popup2.png")
raise e


def test_responsiveness(page: Page):
page.get_by_role("link", name="responsive").click()
page.get_by_role("link", name="responsive").click()

page.set_viewport_size({"width": 500, "height": 3000})

try:
initial_bbox = (
page.frame_locator("iframe").nth(2).locator("#map_div").bounding_box()
)
except Exception as e:
page.screenshot(path="screenshot-responsive.png", full_page=True)
raise e

page.set_viewport_size({"width": 1000, "height": 3000})

sleep(1)

new_bbox = page.query_selector_all("iframe")[2].bounding_box()

print(initial_bbox)
print(new_bbox)

assert initial_bbox is not None

assert new_bbox is not None

assert new_bbox["width"] > initial_bbox["width"] + 300

# Check that the iframe is reasonably tall, which makes sure it hasn't failed to
# render at all
assert new_bbox["height"] > 100

page.set_viewport_size({"width": 2000, "height": 2000})


def test_geojson_styles(page: Page):
page.get_by_role("link", name="geojson styles").click()
page.get_by_role("link", name="geojson styles").click()

page.get_by_text("Show generated code").click()
expect(page.get_by_text('"fillOpacity"')).to_be_visible()


def test_grouped_layer_control(page: Page):
page.get_by_role("link", name="grouped layer control").click()
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').locator(
"label"
).filter(has_text="g2").click()
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').get_by_label(
"g2"
).check()


def test_geojson_popup(page: Page):
page.get_by_role("link", name="geojson popup").click()

expect(page.get_by_text("AttributeError")).to_be_hidden()


@pytest.mark.skip(reason="too flaky")
def test_dynamic_feature_group_update(page: Page):
page.get_by_role("link", name="dynamic updates").click()
page.get_by_text("Show generated code").click()

# Test showing only Parcel layer
page.get_by_test_id("stRadio").get_by_text("Parcels").click()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"] >> nth=1')
.locator("path")
.first
).to_be_visible()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"] >> nth=1')
.get_by_role("img")
.locator("svg")
).to_be_hidden()
expect(
page.get_by_text('"fillColor"')
).to_be_visible() # fillColor only present in parcel style
expect(
page.get_by_text('"dashArray"')
).to_be_hidden() # dashArray only present in building style

# Test showing only Building layer
page.get_by_test_id("stRadio").get_by_text("Buildings").click()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"] >> nth=1')
.locator("path")
.first
).to_be_visible()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"] >> nth=1')
.get_by_role("img")
.locator("svg")
).to_be_hidden()
expect(page.get_by_text("fillColor")).to_be_hidden()
expect(page.get_by_text("dashArray")).to_be_visible()

# Test showing no layers
page.get_by_test_id("stRadio").get_by_text("None").click()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"] >> nth=1')
.get_by_role("img")
.locator("svg")
).to_be_hidden()
expect(page.get_by_text("fillColor")).to_be_hidden()
expect(page.get_by_text("dashArray")).to_be_hidden()

# Test showing both layers
page.get_by_test_id("stRadio").get_by_text("Both").click()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"] >> nth=1')
.locator("path")
.first
).to_be_visible()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"] >> nth=1')
.locator("path")
.nth(1)
).to_be_visible()
expect(page.get_by_text("fillColor")).to_be_visible()
expect(page.get_by_text("dashArray")).to_be_visible()


def test_layer_control_dynamic_update(page: Page):
page.get_by_role("link", name="dynamic layer control").click()
# page.get_by_text("Show generated code").click()

page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').get_by_text(
"Parcels"
).click()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').get_by_text(
"Parcels"
)
).not_to_be_checked()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]')
.get_by_role("img")
.locator("svg")
).to_be_hidden()
expect(page.get_by_text("dashArray")).to_be_hidden()

page.get_by_test_id("stRadio").get_by_text("Both").click()
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').get_by_text(
"Parcels"
).click()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').get_by_text(
"Parcels"
)
).not_to_be_checked()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]').get_by_text(
"Buildings"
)
).to_be_checked()
expect(
page.frame_locator('iframe[title="streamlit_folium\\.st_folium"]')
.get_by_role("img")
.locator("path")
).to_be_visible()

0 comments on commit 2b30c5b

Please sign in to comment.