mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-20 10:47:35 -05:00
* Added microsoft channel and playwright as dependency * Added test-setup to run * Basic tests for each example in examples/index.html * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update test_webgl_raycaster_index.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update test_folium.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update test_folium.py * Update test_folium.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update test_bokeh.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Whitelisting assertion statements in test files * Updated bare execept statements with ImportError * Flake8 compliance * Updated message * Removed 'make test-setup' * Removed @echo from make test * Uncommented Toga test * Removed __test_all__.py file * Removing unnecessary files * Removed individual test files * conftest.py with all data for running tests * Consolidated test file * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixed pre-commit flake8 issues * flake8 issue * add playwright installation to setup * Testing parameterization and webserver to serve examples locally * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Flake8 compliance * More flake8 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Michael Verhulst <michael@terminallabs.com> Co-authored-by: Fabio Pliger <fabio.pliger@gmail.com>
204 lines
6.1 KiB
Python
204 lines
6.1 KiB
Python
"""Each example requires the same three tests:
|
|
|
|
- Test that the initial markup loads properly (currently done by testing the <title>
|
|
tag's content)
|
|
- Testing that pyodide is loading properly
|
|
- Testing that the page contains appropriate content after rendering
|
|
|
|
The single function iterates through the examples, instantiates one playwright browser
|
|
session per example, and runs all three of each example's tests in that same browser
|
|
session.
|
|
"""
|
|
|
|
import math
|
|
import re
|
|
import time
|
|
from urllib.parse import urljoin
|
|
|
|
import pytest
|
|
from playwright.sync_api import sync_playwright
|
|
|
|
MAX_TEST_TIME = 30 # Number of seconds allowed for checking a testing condition
|
|
TEST_TIME_INCREMENT = 0.25 # 1/4 second, the length of each iteration
|
|
TEST_ITERATIONS = math.ceil(
|
|
MAX_TEST_TIME / TEST_TIME_INCREMENT
|
|
) # 120 iters of 1/4 second
|
|
|
|
# Content that is displayed in the page while pyodide loads
|
|
LOADING_MESSAGES = [
|
|
"Loading runtime...",
|
|
"Runtime created...",
|
|
"Initializing components...",
|
|
"Initializing scripts...",
|
|
]
|
|
|
|
EXAMPLES = [
|
|
"altair",
|
|
"bokeh",
|
|
"bokeh_interactive",
|
|
"d3",
|
|
"folium",
|
|
"hello_world",
|
|
"matplotlib",
|
|
"numpy_canvas_fractals",
|
|
"panel",
|
|
"panel_deckgl",
|
|
"panel_kmeans",
|
|
"panel_stream",
|
|
"repl",
|
|
"repl2",
|
|
"simple_clock",
|
|
"todo",
|
|
"todo_pylist",
|
|
"toga_freedom",
|
|
"webgl_raycaster_index",
|
|
]
|
|
|
|
TEST_PARAMS = {
|
|
"altair": {
|
|
"file": "altair.html",
|
|
"pattern": '<canvas.*?class=\\"marks\\".*?>',
|
|
"title": "Altair",
|
|
},
|
|
"bokeh": {
|
|
"file": "bokeh.html",
|
|
"pattern": '<div.*class=\\"bk\\".*>',
|
|
"title": "Bokeh Example",
|
|
},
|
|
"bokeh_interactive": {
|
|
"file": "bokeh_interactive.html",
|
|
"pattern": '<div.*?class=\\"bk\\".*?>',
|
|
"title": "Bokeh Example",
|
|
},
|
|
"d3": {
|
|
"file": "d3.html",
|
|
"pattern": "<svg.*?>",
|
|
"title": "d3: JavaScript & PyScript visualizations side-by-side",
|
|
},
|
|
"folium": {"file": "folium.html", "pattern": "<iframe srcdoc=", "title": "Folium"},
|
|
"hello_world": {
|
|
"file": "hello_world.html",
|
|
"pattern": "\\d+/\\d+/\\d+, \\d+:\\d+:\\d+",
|
|
"title": "PyScript Hello World",
|
|
},
|
|
"matplotlib": {
|
|
"file": "matplotlib.html",
|
|
"pattern": "<img src=['\"]data:image",
|
|
"title": "Matplotlib",
|
|
},
|
|
"numpy_canvas_fractals": {
|
|
"file": "numpy_canvas_fractals.html",
|
|
"pattern": "<div.*?id=['\"](mandelbrot|julia|newton)['\"].*?>",
|
|
"title": "Visualization of Mandelbrot, Julia and "
|
|
"Newton sets with NumPy and HTML5 canvas",
|
|
},
|
|
"panel": {
|
|
"file": "panel.html",
|
|
"pattern": "<div.*?class=['\"]bk-root['\"].*?>",
|
|
"title": "Panel Example",
|
|
},
|
|
"panel_deckgl": {
|
|
"file": "panel_deckgl.html",
|
|
"pattern": "<div.*?class=['\"]bk-root['\"].*?>",
|
|
"title": "PyScript/Panel DeckGL Demo",
|
|
},
|
|
"panel_kmeans": {
|
|
"file": "panel_kmeans.html",
|
|
"pattern": "<div.*?class=['\"]bk-root['\"].*?>",
|
|
"title": "Pyscript/Panel KMeans Demo",
|
|
},
|
|
"panel_stream": {
|
|
"file": "panel_stream.html",
|
|
"pattern": "<div.*?class=['\"]bk-root['\"].*?>",
|
|
"title": "PyScript/Panel Streaming Demo",
|
|
},
|
|
"repl": {"file": "repl.html", "pattern": "<py-repl.*?>", "title": "REPL"},
|
|
"repl2": {
|
|
"file": "repl2.html",
|
|
"pattern": "<py-repl.*?>",
|
|
"title": "Custom REPL Example",
|
|
},
|
|
"simple_clock": {
|
|
"file": "simple_clock.html",
|
|
"pattern": "\\d+/\\d+/\\d+, \\d+:\\d+:\\d+",
|
|
"title": "Simple Clock Demo",
|
|
},
|
|
"todo": {
|
|
"file": "todo.html",
|
|
"pattern": "<input.*?id=['\"]new-task-content['\"].*?>",
|
|
"title": "Todo App",
|
|
},
|
|
"todo_pylist": {
|
|
"file": "todo-pylist.html",
|
|
"pattern": "<input.*?id=['\"]new-task-content['\"].*?>",
|
|
"title": "Todo App",
|
|
},
|
|
"toga_freedom": {
|
|
"file": "toga/freedom.html",
|
|
"pattern": "<(main|div).*?id=['\"]toga_\\d+['\"].*?>",
|
|
"title": ["Loading...", "Freedom Units"],
|
|
},
|
|
"webgl_raycaster_index": {
|
|
"file": "webgl/raycaster/index.html",
|
|
"pattern": "<canvas.*?>",
|
|
"title": "Raycaster",
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize("example", EXAMPLES)
|
|
def test_examples(example, http_server):
|
|
|
|
base_url = http_server
|
|
example_path = urljoin(base_url, TEST_PARAMS[example]["file"])
|
|
|
|
# Invoke playwright
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch()
|
|
page = browser.new_page()
|
|
page.goto(example_path)
|
|
|
|
# STEP 1: Check page title proper initial loading of the example page
|
|
|
|
expected_title = TEST_PARAMS[example]["title"]
|
|
if isinstance(expected_title, list):
|
|
# One example's title changes so expected_title is a list of possible
|
|
# titles in that case
|
|
assert page.title() in expected_title # nosec
|
|
else:
|
|
assert page.title() == expected_title # nosec
|
|
|
|
# STEP 2: Test that pyodide is loading via messages displayed during loading
|
|
|
|
pyodide_loading = False # Flag to be set to True when condition met
|
|
|
|
for _ in range(TEST_ITERATIONS):
|
|
time.sleep(TEST_TIME_INCREMENT)
|
|
content = page.text_content("*")
|
|
for message in LOADING_MESSAGES:
|
|
if message in content:
|
|
pyodide_loading = True
|
|
if pyodide_loading:
|
|
break
|
|
|
|
assert pyodide_loading # nosec
|
|
|
|
# STEP 3:
|
|
# Assert that rendering inserts data into the page as expected: search the
|
|
# DOM from within the timing loop for a string that is not present in the
|
|
# initial markup but should appear by way of rendering
|
|
|
|
re_sub_content = re.compile(TEST_PARAMS[example]["pattern"])
|
|
py_rendered = False # Flag to be set to True when condition met
|
|
|
|
for _ in range(TEST_ITERATIONS):
|
|
time.sleep(TEST_TIME_INCREMENT)
|
|
content = page.inner_html("*")
|
|
if re_sub_content.search(content):
|
|
py_rendered = True
|
|
break
|
|
|
|
assert py_rendered # nosec
|
|
|
|
browser.close()
|