Skip to content

Commit 7edca16

Browse files
committed
Add sample playwright tests for folium
First try: just do the draw plugin.
1 parent c1210ce commit 7edca16

30 files changed

+961
-4
lines changed

.github/workflows/save_versions.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Save package versions
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
run:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout Folium
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Micromamba env
18+
uses: mamba-org/setup-micromamba@v2
19+
with:
20+
environment-name: TEST
21+
create-args: >-
22+
python=3
23+
--file requirements.txt
24+
--file requirements-dev.txt
25+
26+
- name: Install folium from source
27+
shell: bash -l {0}
28+
run: |
29+
python -m pip install -e . --no-deps --force-reinstall
30+
31+
- name: Create versions.txt
32+
shell: bash -l {0}
33+
run: |
34+
conda list > /tmp/versions.txt
35+
chromium --version >> /tmp/versions.txt
36+
37+
- name: Save versions.txt
38+
if: always()
39+
uses: actions/upload-artifact@v4
40+
with:
41+
name: versions.txt
42+
path: /tmp/versions.txt
43+
fail-on-empty: false

.github/workflows/test_code.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,10 @@ jobs:
3535
- name: Install folium from source
3636
run: python -m pip install -e . --no-deps --force-reinstall
3737

38+
- name: Install pixelmatch
39+
shell: bash -l {0}
40+
run: |
41+
pip install pixelmatch
42+
3843
- name: Code tests
39-
run: python -m pytest -vv --ignore=tests/selenium
44+
run: python -m pytest -vv --ignore=tests/selenium --ignore=tests/playwright --ignore=tests/snapshots

.github/workflows/test_latest_branca.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ jobs:
3333
run: |
3434
micromamba remove branca --yes --force
3535
python -m pip install git+https://github.com/python-visualization/branca.git
36-
python -m pytest -vv --ignore=tests/selenium
36+
python -m pytest -vv --ignore=tests/selenium --ignore=tests/playwright --ignore=tests/snapshots

.github/workflows/test_snapshots.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Run Snapshot Tests
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
run:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout Folium
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Micromamba env
18+
uses: mamba-org/setup-micromamba@v2
19+
with:
20+
environment-name: TEST
21+
create-args: >-
22+
python=3
23+
--file requirements.txt
24+
--file requirements-dev.txt
25+
26+
- name: Install pytest plugins and pixelmatch
27+
shell: bash -l {0}
28+
run: |
29+
pip install pixelmatch pytest-github-actions-annotate-failures pytest-rerunfailures
30+
31+
- name: Install folium from source
32+
shell: bash -l {0}
33+
run: |
34+
python -m pip install -e . --no-deps --force-reinstall
35+
36+
- name: Test with pytest
37+
shell: bash -l {0}
38+
run: |
39+
python -m pytest tests/snapshots -s --junit-xml=test-results.xml
40+
41+
- name: Surface failing tests
42+
if: always()
43+
uses: pmeier/pytest-results-action@main
44+
with:
45+
path: test-results.xml
46+
fail-on-empty: false
47+
48+
- name: Upload screenshots
49+
if: failure()
50+
uses: actions/upload-artifact@v4
51+
with:
52+
name: screenshots
53+
path: |
54+
/tmp/screenshot_*_*.png
55+
/tmp/folium_map_*.html

.github/workflows/test_streamlit_folium.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
shell: bash -l {0}
6767
run: |
6868
cd streamlit_folium
69-
pytest tests/test_frontend.py --browser chromium -s --reruns 3 --junit-xml=test-results.xml
69+
pytest tests/test_frontend.py --browser chromium -s --reruns 5 --junit-xml=test-results.xml
7070
7171
- name: Surface failing tests
7272
if: always()

.pre-commit-config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ repos:
99
- id: debug-statements
1010
- id: end-of-file-fixer
1111
- id: check-docstring-first
12+
exclude: ^examples/streamlit
1213
- id: check-added-large-files
14+
args: ['--maxkb=1024']
1315
- id: requirements-txt-fixer
1416
- id: file-contents-sorter
1517
files: requirements-dev.txt

.streamlit/config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[server]
2+
enableStaticServing = true

examples/streamlit/main.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import streamlit as st
2+
3+
st.logo("https://python-visualization.github.io/folium/latest/_static/folium_logo.png")
4+
st.title("Python data, leaflet.js maps")
5+
6+
"""
7+
Folium builds on the data wrangling strengths of the Python ecosystem
8+
and the mapping strengths of the Leaflet.js library.
9+
10+
Manipulate your data in Python, then visualize it in a Leaflet map via
11+
Folium."""
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import streamlit as st
2+
3+
st.set_page_config(
4+
page_title="streamlit-folium documentation: Draw Support",
5+
page_icon=":pencil:",
6+
layout="wide",
7+
)
8+
9+
"""
10+
# streamlit-folium: Draw Support
11+
12+
Folium supports some of the [most popular leaflet
13+
plugins](https://python-visualization.github.io/folium/plugins.html). In this example,
14+
we can add the
15+
[`Draw`](https://python-visualization.github.io/folium/plugins.html#folium.plugins.Draw)
16+
plugin to our map, which allows for drawing geometric shapes on the map.
17+
18+
When a shape is drawn on the map, the coordinates that represent that shape are passed
19+
back as a geojson feature via the `all_drawings` and `last_active_drawing` data fields.
20+
21+
Draw something below to see the return value back to Streamlit!
22+
"""
23+
24+
with st.echo(code_location="below"):
25+
import streamlit as st
26+
from streamlit_folium import st_folium
27+
28+
import folium
29+
from folium.plugins import Draw
30+
31+
m = folium.Map(location=[39.949610, -75.150282], zoom_start=5, png_enabled=True)
32+
items = folium.FeatureGroup()
33+
marker = folium.Marker(location=[38, -83]).add_to(items)
34+
items.add_to(m)
35+
36+
Draw(export=False, feature_group=items, show_geometry_on_click=False).add_to(m)
37+
38+
c1, c2 = st.columns(2)
39+
with c1:
40+
output = st_folium(m, width=700, height=500)
41+
42+
with c2:
43+
st.write(output)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import json
2+
3+
import streamlit as st
4+
from streamlit_folium import st_folium
5+
6+
import folium
7+
8+
st.set_page_config(layout="wide")
9+
10+
geojson = """
11+
{"type": "FeatureCollection",
12+
"features": [
13+
{"id": "0", "type": "Feature", "properties": {"foo": 0},
14+
"geometry": {"type": "Point", "coordinates": [0.0, 0.0]}
15+
},
16+
{"id": "1", "type": "Feature", "properties": {"foo": 1},
17+
"geometry": {"type": "MultiPoint", "coordinates": [[1.0, 1.0]]}},
18+
{"id": "2", "type": "Feature",
19+
"properties": {"foo": 2}, "geometry": {"type": "MultiPoint", "coordinates":
20+
[[2.0, 2.0]]}}, {"id": "3", "type": "Feature", "properties": {"foo": 3},
21+
"geometry": {"type": "MultiPoint", "coordinates": [[3.0, 3.0]]}}, {"id": "4",
22+
"type": "Feature", "properties": {"foo": 4}, "geometry": {"type":
23+
"MultiPoint", "coordinates": [[4.0, 4.0]]}}]}"""
24+
25+
geojson = json.loads(geojson)
26+
27+
on_each_feature = folium.JsCode(
28+
"""
29+
(feature, layer) => {
30+
layer.bindPopup("hello world");
31+
}
32+
"""
33+
)
34+
m = folium.Map(
35+
zoom_start=5,
36+
location=(0, 0),
37+
)
38+
folium.GeoJson(
39+
geojson, on_each_feature=on_each_feature, marker=folium.CircleMarker(radius=20)
40+
).add_to(m)
41+
42+
st_folium(m, width=700, height=500)
43+
# st_folium(m, width=700, height=500, returned_objects=[])
44+
45+
html = m.get_root().render()
46+
st.code(html)
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import io
2+
3+
import branca
4+
import geopandas
5+
import pandas as pd
6+
import requests
7+
import streamlit as st
8+
from streamlit_folium import st_folium
9+
10+
import folium
11+
12+
st.set_page_config(layout="wide")
13+
14+
response = requests.get(
15+
"https://gist.githubusercontent.com/tvpmb/4734703/raw/"
16+
"b54d03154c339ed3047c66fefcece4727dfc931a/US%2520State%2520List"
17+
)
18+
abbrs = pd.read_json(io.StringIO(response.text))
19+
20+
income = pd.read_csv(
21+
"https://raw.githubusercontent.com/pri-data/50-states/master/data/income-counties-states-national.csv",
22+
dtype={"fips": str},
23+
)
24+
income["income-2015"] = pd.to_numeric(income["income-2015"], errors="coerce")
25+
26+
data = requests.get(
27+
"https://raw.githubusercontent.com/python-visualization/folium-example-data/main/us_states.json"
28+
).json()
29+
30+
states = geopandas.GeoDataFrame.from_features(data, crs="EPSG:4326")
31+
statesmerge = states.merge(abbrs, how="left", left_on="name", right_on="name")
32+
statesmerge["geometry"] = statesmerge.geometry.simplify(0.05)
33+
34+
statesmerge["medianincome"] = statesmerge.merge(
35+
income.groupby("state")["income-2015"].median(),
36+
how="left",
37+
left_on="alpha-2",
38+
right_on="state",
39+
)["income-2015"]
40+
statesmerge["change"] = statesmerge.merge(
41+
income.groupby("state")["change"].median(),
42+
how="left",
43+
left_on="alpha-2",
44+
right_on="state",
45+
)["change"]
46+
47+
statesmerge["empty"] = None
48+
49+
colormap = branca.colormap.LinearColormap(
50+
vmin=statesmerge["change"].quantile(0.0),
51+
vmax=statesmerge["change"].quantile(1),
52+
colors=["red", "orange", "lightblue", "green", "darkgreen"],
53+
caption="State Level Median County Household Income (%)",
54+
)
55+
56+
m = folium.Map(location=[35.3, -97.6], zoom_start=4)
57+
58+
popup = folium.GeoJsonPopup(
59+
fields=["name", "change"],
60+
aliases=["State", "% Change"],
61+
localize=True,
62+
labels=True,
63+
style="background-color: yellow;",
64+
)
65+
66+
tooltip = folium.GeoJsonTooltip(
67+
fields=["name", "medianincome", "change", "empty"],
68+
aliases=["State:", "2015 Median Income(USD):", "Median % Change:", "empty"],
69+
localize=True,
70+
sticky=False,
71+
labels=True,
72+
style="""
73+
background-color: #F0EFEF;
74+
border: 2px solid black;
75+
border-radius: 3px;
76+
box-shadow: 3px;
77+
""",
78+
max_width=800,
79+
)
80+
81+
g = folium.GeoJson(
82+
statesmerge,
83+
style_function=lambda x: {
84+
"fillColor": (
85+
colormap(x["properties"]["change"])
86+
if x["properties"]["change"] is not None
87+
else "transparent"
88+
),
89+
"color": "black",
90+
"fillOpacity": 0.4,
91+
},
92+
tooltip=tooltip,
93+
popup=popup,
94+
).add_to(m)
95+
96+
colormap.add_to(m)
97+
98+
html = m.get_root().render()
99+
st_folium(m, width=700, height=500)
100+
101+
st.code(html)

0 commit comments

Comments
 (0)