Skip to content

Commit

Permalink
Add more unit and integration tests (#773)
Browse files Browse the repository at this point in the history
* Add unit tests for pyloader and pytitle

* Add more unit tests for pyrepl, pybox and pyinputbox

* Add more tests for pyscript and pyconfig

* White space

* Fix d3 tests and improve more examples test

* Update matplotlib test

* Add numpy to dependencies

* Address Madhur comments

* Update test name
  • Loading branch information
FabioRosado committed Sep 26, 2022
1 parent d033ab0 commit b674515
Show file tree
Hide file tree
Showing 12 changed files with 482 additions and 53 deletions.
4 changes: 2 additions & 2 deletions examples/d3.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@
<script type="importmap">
{
"imports": {
"d3": "https://cdn.skypack.dev/d3@7"
"d3": "https://cdn.skypack.dev/pin/d3@v7.6.1-1Q0NZ0WZnbYeSjDusJT3/mode=imports,min/optimized/d3.js"
}
}
</script>

<script type="module">
import * as d3 from "https://cdn.skypack.dev/d3@7";
import * as d3 from "https://cdn.skypack.dev/pin/d3@v7.6.1-1Q0NZ0WZnbYeSjDusJT3/mode=imports,min/optimized/d3.js";

const fruits = [
{name: "🍊", count: 21},
Expand Down
2 changes: 2 additions & 0 deletions pyscriptjs/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ dependencies:
- isort
- codespell
- pre-commit
- pillow
- numpy

- pip:
- playwright
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
98 changes: 90 additions & 8 deletions pyscriptjs/tests/integration/test_zz_examples.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import base64
import io
import math
import os
import re
import time

import numpy as np
import pytest
from PIL import Image

from .support import ROOT, PyScriptTest

Expand Down Expand Up @@ -80,7 +85,6 @@ def test_altair(self):
wait_for_render(self.page, "*", '<canvas.*?class=\\"marks\\".*?>')
save_as_png_link = self.page.locator("text=Save as PNG")
see_source_link = self.page.locator("text=View Source")

# These shouldn't be visible since we didn't click the menu
assert not save_as_png_link.is_visible()
assert not see_source_link.is_visible()
Expand All @@ -105,32 +109,66 @@ def test_bokeh_interactive(self):
assert self.page.title() == "Bokeh Example"
wait_for_render(self.page, "*", '<div.*?class=\\"bk\\".*?>')

@pytest.mark.xfail(reason="Flaky test #759")
def test_d3(self):
# XXX improve this test
self.goto("examples/d3.html")
self.wait_for_pyscript()
assert (
self.page.title() == "d3: JavaScript & PyScript visualizations side-by-side"
)
wait_for_render(self.page, "*", "<svg.*?>")
assert "PyScript version" in self.page.content()
pyscript_chart = self.page.wait_for_selector("#py")

# Let's simply assert that the text of the chart is as expected which
# means that the chart rendered successfully and with the right text
assert "🍊21\n🍇13\n🍏8\n🍌5\n🍐3\n🍋2\n🍎1\n🍉1" in pyscript_chart.inner_text()

def test_folium(self):
# XXX improve this test
self.goto("examples/folium.html")
self.wait_for_pyscript()
assert self.page.title() == "Folium"
wait_for_render(self.page, "*", "<iframe srcdoc=")

# We need to look into the iframe first
iframe = self.page.frame_locator("iframe")

# Just checking that legend was rendered correctly
legend = iframe.locator("#legend")
assert "Unemployment Rate (%)" in legend.inner_html()

# Let's check that the zoom buttons are rendered and clickable
# Note: if element is not clickable it will timeout
zoom_in = iframe.locator("[aria-label='Zoom in']")
assert "+" in zoom_in.inner_text()
zoom_in.click()
zoom_out = iframe.locator("[aria-label='Zoom out']")
assert "−" in zoom_out.inner_text()
zoom_out.click()

def test_matplotlib(self):
# XXX improve this test
self.goto("examples/matplotlib.html")
self.wait_for_pyscript()
assert self.page.title() == "Matplotlib"
wait_for_render(self.page, "*", "<img src=['\"]data:image")
# The image is being rended using base64, lets fetch its source
# and replace everything but the actual base64 string.\
img_src = (
self.page.wait_for_selector("img")
.get_attribute("src")
.replace("data:image/png;charset=utf-8;base64,", "")
)
# Finally, let's get the np array from the previous data
img_data = np.asarray(Image.open(io.BytesIO(base64.b64decode(img_src))))
with Image.open(
os.path.join(os.path.dirname(__file__), "test_assets", "tripcolor.png"),
) as image:
ref_data = np.asarray(image)
# Now that we have both images data as a numpy array
# let's confirm that they are the same
deviation = np.mean(np.abs(img_data - ref_data))
assert deviation == 0.0

def test_numpy_canvas_fractals(self):
# XXX improve this test
self.goto("examples/numpy_canvas_fractals.html")
self.wait_for_pyscript()
assert (
Expand All @@ -141,12 +179,57 @@ def test_numpy_canvas_fractals(self):
self.page, "*", "<div.*?id=['\"](mandelbrot|julia|newton)['\"].*?>"
)

# Assert that we get the title and canvas for each element
mandelbrot = self.page.wait_for_selector("#mandelbrot")
assert "Mandelbrot set" in mandelbrot.inner_text()
assert "<canvas" in mandelbrot.inner_html()

julia = self.page.wait_for_selector("#julia")
assert "Julia set" in julia.inner_text()
assert "<canvas" in julia.inner_html()

newton = self.page.wait_for_selector("#newton")
assert "Newton set" in newton.inner_text()
assert "<canvas" in newton.inner_html()

# Confirm that all fieldsets are rendered correctly
poly = newton.wait_for_selector("#poly")
assert poly.input_value() == "z**3 - 2*z + 2"

coef = newton.wait_for_selector("#coef")
assert coef.input_value() == "1"

# Let's now change some x/y values to confirm that they
# are editable (is it the best way to test this?)
x0 = newton.wait_for_selector("#x0")
y0 = newton.wait_for_selector("#y0")

x0.fill("50")
assert x0.input_value() == "50"
y0.fill("-25")
assert y0.input_value() == "-25"

# This was the first computation with the default values
assert self.console.log.lines[-2] == "Computing Newton set ..."
# Confirm that changing the input values, triggered a new computation
assert self.console.log.lines[-1] == "Computing Newton set ..."

def test_panel(self):
# XXX improve this test
self.goto("examples/panel.html")
self.wait_for_pyscript()
assert self.page.title() == "Panel Example"
wait_for_render(self.page, "*", "<div.*?class=['\"]bk-root['\"].*?>")
slider_title = self.page.wait_for_selector(".bk-slider-title")
assert slider_title.inner_text() == "Amplitude: 0"

slider_result = self.page.wait_for_selector(".bk-clearfix")
assert slider_result.inner_text() == "Amplitude is: 0"

amplitude_bar = self.page.wait_for_selector(".noUi-connects")
amplitude_bar.click()

# Let's confirm that slider title changed
assert slider_title.inner_text() == "Amplitude: 5"

def test_panel_deckgl(self):
# XXX improve this test
Expand Down Expand Up @@ -190,7 +273,6 @@ def test_repl(self):
)
assert second_repl_result.text_content() == "4"

@pytest.mark.xfail(reason="Test seems flaky")
def test_repl2(self):
self.goto("examples/repl2.html")
self.wait_for_pyscript()
Expand Down
25 changes: 25 additions & 0 deletions pyscriptjs/tests/unit/pybox.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { jest } from "@jest/globals"

import { PyBox } from "../../src/components/pybox"

customElements.define('py-box', PyBox)

describe('PyBox', () => {
let instance: PyBox;

beforeEach(() => {
instance = new PyBox();
})

it('PyBox instantiates correctly', async () => {
expect(instance).toBeInstanceOf(PyBox)
})

it("test connectedCallback creates pybox div", async () => {
expect(instance.innerHTML).toBe("")
instance.connectedCallback()

expect(instance.innerHTML).toBe('<div class=\"py-box\"></div>')
})

})
2 changes: 1 addition & 1 deletion pyscriptjs/tests/unit/pybutton.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('PyButton', () => {
expect(instance).toBeInstanceOf(PyButton);
});

it('confirm that runAfterRuntimeInitialized is called', async () => {
it('confirm that runAfterRuntimeInitialized is called', async () => {
const mockedRunAfterRuntimeInitialized = jest
.spyOn(instance, 'runAfterRuntimeInitialized')
.mockImplementation(jest.fn());
Expand Down

0 comments on commit b674515

Please sign in to comment.