Skip to content

Commit 9480351

Browse files
test: add render test with pyppeteer - chromium based
1 parent 6c82eb8 commit 9480351

File tree

4 files changed

+69
-1
lines changed

4 files changed

+69
-1
lines changed

.github/workflows/main.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,9 @@ jobs:
6969
conda activate voila-tests
7070
VOILA_TEST_DEBUG=1 VOILA_TEST_XEUS_CLING=1 py.test tests/ --async-test-timeout=240
7171
voila --help # Making sure we can run `voila --help`
72+
- name: Upload artifacts (from test failures)
73+
uses: actions/upload-artifact@v1
74+
if: failed()
75+
with:
76+
name: artifacts
77+
path: artifacts

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,9 @@ def get_data_files():
388388
'pytest<4',
389389
'pytest-tornado',
390390
'matplotlib',
391-
'ipywidgets'
391+
'ipywidgets',
392+
'pyppeteer2', # pyppeteer is not maintained
393+
'pillow'
392394
]
393395
},
394396
'url': 'https://github.com/voila-dashboards/voila',

tests/app/render_test.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# test if it renders in chromium
2+
import asyncio
3+
import pytest
4+
from pathlib import Path
5+
import shutil
6+
import os
7+
8+
from PIL import Image, ImageDraw, ImageChops
9+
import pyppeteer
10+
11+
artifact_path = Path('artifacts')
12+
artifact_path.mkdir(exist_ok=True)
13+
14+
15+
async def compare(element, name):
16+
base_dir = Path('tests/notebooks/screenshots/')
17+
base_dir.mkdir(exist_ok=True)
18+
test_path = base_dir / f'{name}_testrun.png'
19+
truth_path = base_dir / f'{name}_truth.png'
20+
if not truth_path.exists():
21+
# on initial run, we just save it
22+
await element.screenshot({'path': str(truth_path)})
23+
else:
24+
await element.screenshot({'path': str(test_path)})
25+
truth = Image.open(truth_path)
26+
test = Image.open(test_path)
27+
diff = ImageChops.difference(truth, test)
28+
try:
29+
assert truth.size == test.size
30+
assert not diff.getbbox(), 'Visual difference'
31+
except: # noqa
32+
diff_path = artifact_path / f'{name}_diff.png'
33+
diff.convert('RGB').save(diff_path)
34+
shutil.copy(test_path, artifact_path)
35+
shutil.copy(truth_path, artifact_path)
36+
if diff.getbbox():
37+
marked_path = artifact_path / f'{name}_marked.png'
38+
marked = truth.copy()
39+
draw = ImageDraw.Draw(marked)
40+
draw.rectangle(diff.getbbox(), outline='red')
41+
marked.convert('RGB').save(marked_path)
42+
raise
43+
44+
45+
@pytest.mark.gen_test
46+
async def test_render(http_client, base_url, voila_app):
47+
options = dict(headless=False, devtools=True) if os.environ.get('VOILA_TEST_DEBUG_VISUAL', False) else {}
48+
browser = await pyppeteer.launch(options=options)
49+
page = await browser.newPage()
50+
await page.goto(base_url)
51+
el = await page.querySelector('.jp-OutputArea-output')
52+
try:
53+
await compare(el, 'print')
54+
except: # noqa
55+
if os.environ.get('VOILA_TEST_DEBUG_VISUAL', False):
56+
# may want to add --async-test-timeout=60 to pytest arguments
57+
print("Waiting for 60 second for visual inspection (hit ctrl-c to break)")
58+
await asyncio.sleep(60)
59+
finally:
60+
await browser.close()
1.18 KB
Loading

0 commit comments

Comments
 (0)