Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
d8b1c10
Create test_selenium.py
Conengmo Apr 26, 2020
1d33726
Update requirements-dev.txt
Conengmo Apr 26, 2020
494ce94
Update .gitignore
Conengmo Apr 26, 2020
2a4901b
Try activating on Travis
Conengmo Apr 26, 2020
1136a31
Fix notebook errors
Conengmo Apr 26, 2020
1cd351d
Enable chrome?
Conengmo Apr 26, 2020
27d1c50
Update .travis.yml
Conengmo Apr 26, 2020
2c2a646
Update .travis.yml
Conengmo Apr 26, 2020
d0285ee
Update .travis.yml
Conengmo Apr 26, 2020
a05143d
Update .travis.yml
Conengmo Apr 26, 2020
da09432
Update .travis.yml
Conengmo Apr 26, 2020
e17ecba
Simple selenium + chromedriver test
Conengmo Apr 28, 2020
856af1a
Update test_selenium.py
Conengmo Apr 28, 2020
7281335
Update .travis.yml
Conengmo Apr 28, 2020
140a84d
Update test_selenium.py
Conengmo Apr 28, 2020
ff867e0
Update test_selenium.py
Conengmo Apr 28, 2020
70d5ec0
Update test_selenium.py
Conengmo Apr 28, 2020
bac1425
Update test_selenium.py
Conengmo Apr 28, 2020
f21cac9
Update .travis.yml
Conengmo Apr 28, 2020
27ae4d5
Update .travis.yml
Conengmo Apr 28, 2020
b063eaa
Update .travis.yml
Conengmo Apr 28, 2020
dafc78b
Update .travis.yml
Conengmo Apr 28, 2020
5ca73cc
Update .travis.yml
Conengmo Apr 28, 2020
a059761
Update .travis.yml
Conengmo Apr 28, 2020
4f93c1f
Update .travis.yml
Conengmo Apr 28, 2020
f9efd48
Update test_selenium.py
Conengmo Apr 28, 2020
29286a5
notebook tests
Conengmo Apr 29, 2020
bf1a935
Update .travis.yml
Conengmo Apr 29, 2020
581cb03
Try some other settings
Conengmo Apr 30, 2020
b3c7335
other settings
Conengmo Apr 30, 2020
9f9770d
other settings
Conengmo Apr 30, 2020
a289e2e
Split notebook iframes into html pages
Conengmo May 1, 2020
c40cca0
Update test_selenium.py
Conengmo May 1, 2020
a456ddd
Update test_selenium.py
Conengmo May 1, 2020
5379cee
don't run execute in place
Conengmo May 1, 2020
0f8773c
Update .travis.yml
Conengmo May 2, 2020
11cd83f
Simplify
Conengmo May 9, 2020
8f843c2
Stop using seleniumbase
Conengmo May 9, 2020
fabef6b
Update .travis.yml
Conengmo May 9, 2020
dd23da8
Increase timeout
Conengmo May 9, 2020
4eca61f
Close alert
Conengmo May 9, 2020
ee065ef
remove dummy test
Conengmo May 9, 2020
1d9301f
Wait until alert, close it
Conengmo May 9, 2020
bd0f7d1
Skip problem with alert
Conengmo May 9, 2020
3831aea
stickler
Conengmo May 9, 2020
e51587b
Update CONTRIBUTING.md
Conengmo May 9, 2020
6455e0c
docstring
Conengmo May 9, 2020
5dbb4df
Reuse driver instance
Conengmo May 9, 2020
6ceae59
Reuse driver instance
Conengmo May 9, 2020
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
2 changes: 1 addition & 1 deletion .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ install:

test_script:
- pip install -e . --no-deps --force-reinstall
- pytest -n 2 -rxXs tests
- pytest -n 2 -rxXs tests --ignore=tests/selenium
6 changes: 3 additions & 3 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ The basic workflow for contributing is:
pip install -r requirements.txt
pip install -r requirements-dev.txt
```
6. Install Firefox, download [geckodriver](https://github.com/mozilla/geckodriver/releases)
and put it in the PATH.
6. Install Chrome, download [chromedriver](https://sites.google.com/a/chromium.org/chromedriver/) and put it in the PATH.
7. Make changes to your local copy of the folium repository
8. Make sure the tests pass:
* in the repository folder do `pip install -e . --no-deps` (needed for notebook tests)
* run `python -m pytest tests`
* run `flake8 folium --max-line-length=120`
* run `python -m pytest tests --ignore=tests/selenium`
* run `python -m pytest tests/selenium`
* resolve all errors
9. Commit those changes
```
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ examples/results/*
/_mac/*.xml
/inspection/*.xml
geckodriver.log
geckodriver.exe
geckodriver.tar.gz
geckodriver/
chromedriver.exe
chromedriver/
miniconda.sh
latest_logs/
*.nbconvert.ipynb
24 changes: 21 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ env:

addons:
firefox: latest
# chrome addon fails to install

env:
global:
Expand All @@ -21,6 +22,8 @@ matrix:
env: PY=3.7
- name: notebooks-code
env: PY=3.7
- name: selenium
env: PY=3.7
- name: latest-branca
env: PY=3.7
- name: docs
Expand Down Expand Up @@ -54,7 +57,18 @@ before_install:
mkdir geckodriver
tar -xzf geckodriver.tar.gz -C geckodriver
export PATH=$PATH:$PWD/geckodriver

# Install Chrome
- |
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb
sudo apt-get install -y -f
# sudo dpkg -i google-chrome-stable_current_amd64.deb
# Install chromedriver
- |
wget https://chromedriver.storage.googleapis.com/$(curl https://chromedriver.storage.googleapis.com/LATEST_RELEASE)/chromedriver_linux64.zip -O chromedriver.zip
mkdir chromedriver
unzip chromedriver.zip -d chromedriver
export PATH=$PATH:$PWD/chromedriver

# Test source distribution.
install:
Expand All @@ -72,13 +86,13 @@ script:
fi

- if [[ $TRAVIS_JOB_NAME == 'default' ]]; then
pytest /tmp -vv --ignore=tests/notebooks/test_notebooks.py ;
pytest /tmp -vv --ignore=/tmp/tests/selenium ;
fi

- if [[ $TRAVIS_JOB_NAME == 'latest-branca' ]]; then
conda uninstall branca ;
pip install git+https://github.com/python-visualization/branca.git ;
pytest /tmp -vv --ignore=tests/notebooks/test_notebooks.py ;
pytest /tmp -vv --ignore=/tmp/tests/selenium ;
fi

- if [[ $TRAVIS_JOB_NAME == 'notebooks-conding-standard' ]]; then
Expand All @@ -91,6 +105,10 @@ script:
pytest --nbval-lax /tmp/examples ;
fi

- if [[ $TRAVIS_JOB_NAME == 'selenium' ]]; then
pytest /tmp/tests/selenium -vv ;
fi

# Docs
- |
if [[ $TRAVIS_JOB_NAME == 'docs' ]]; then
Expand Down
47 changes: 11 additions & 36 deletions examples/GeodedeticImageOverlay.ipynb

Large diffs are not rendered by default.

64 changes: 32 additions & 32 deletions examples/Plugins.ipynb

Large diffs are not rendered by default.

67 changes: 33 additions & 34 deletions examples/Quickstart.ipynb

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions examples/SmoothFactor.ipynb

Large diffs are not rendered by default.

118 changes: 19 additions & 99 deletions examples/TilesExample.ipynb

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions examples/plugin-PolyLineOffset.ipynb

Large diffs are not rendered by default.

123 changes: 123 additions & 0 deletions tests/selenium/test_selenium.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@

import base64
import glob
from html.parser import HTMLParser
import os
import subprocess

import nbconvert
import pytest
from selenium.webdriver import Chrome, ChromeOptions
from selenium.common.exceptions import UnexpectedAlertPresentException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import visibility_of_element_located


def create_driver():
"""Create a Selenium WebDriver instance."""
options = ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--disable-gpu')
options.add_argument('--headless')
driver = Chrome(options=options)
return driver


@pytest.fixture(scope='module')
def driver():
"""Pytest fixture that yields a Selenium WebDriver instance"""
driver = create_driver()
try:
yield driver
finally:
driver.quit()


def clean_window(driver):
# open new tab
driver.execute_script('window.open();')
# close old tab
driver.close()
# switch to new tab
driver.switch_to.window(driver.window_handles[0])


def find_notebooks():
"""Return a list of filenames of the example notebooks."""
path = os.path.dirname(__file__)
pattern = os.path.join(path, '..', '..', 'examples', '*.ipynb')
files = glob.glob(pattern)
files = [f for f in files if not f.endswith('.nbconvert.ipynb')]
if files:
return files
else:
raise IOError('Could not find the notebooks')


@pytest.mark.parametrize('filepath', find_notebooks())
def test_notebook(filepath, driver):
for filepath_html in get_notebook_html(filepath):
clean_window(driver)
driver.get('file://' + filepath_html)
wait = WebDriverWait(driver, timeout=10)
map_is_visible = visibility_of_element_located((By.CSS_SELECTOR, '.folium-map'))
try:
assert wait.until(map_is_visible)
except UnexpectedAlertPresentException:
# in Plugins.ipynb we get an alert about geolocation permission
# for some reason it cannot be closed or avoided, so just ignore it
print('skipping', filepath_html, 'because of alert')
continue
logs = driver.get_log('browser')
for log in logs:
if log['level'] == 'SEVERE':
msg = ' '.join(log['message'].split()[2:])
raise RuntimeError('Javascript error: "{}".'.format(msg))


def get_notebook_html(filepath_notebook, execute=True):
"""Store iframes from a notebook in html files, remove them when done."""
if execute:
subprocess.run([
'jupyter', 'nbconvert', '--to', 'notebook', '--execute', filepath_notebook,
])
filepath_notebook = filepath_notebook.replace('.ipynb', '.nbconvert.ipynb')

html_exporter = nbconvert.HTMLExporter()
html_exporter.template_file = 'basic'
body, _ = html_exporter.from_filename(filepath_notebook)

parser = IframeParser()
parser.feed(body)
iframes = parser.iframes

for i, iframe in enumerate(iframes):
filepath_html = filepath_notebook.replace('.ipynb', '.{}.html'.format(i))
filepath_html = os.path.abspath(filepath_html)
with open(filepath_html, 'wb') as f:
f.write(iframe)
try:
yield filepath_html
finally:
os.remove(filepath_html)


class IframeParser(HTMLParser):
"""Extract the iframes from an html page."""

def __init__(self):
super().__init__()
self.iframes = []

def handle_starttag(self, tag, attrs):
if tag == 'iframe':
attrs = dict(attrs)
if 'data-html' in attrs:
html_base64 = attrs['data-html']
else: # legacy, can be removed when all notebooks have `data-html`.
src = attrs['src']
html_base64 = src.split(',')[-1]
html_bytes = base64.b64decode(html_base64)
self.iframes.append(html_bytes)