|
| 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() |
0 commit comments