import base64 import io import os import re import numpy as np import pytest from PIL import Image from .support import ( PyScriptTest, filter_inner_text, filter_page_content, wait_for_render, ) DISPLAY_OUTPUT_ID_PATTERN = r'[id^="py-"]' class TestDisplay(PyScriptTest): def test_simple_display(self): self.pyscript_run( """ print('ciao') from pyscript import display display("hello world") """, timeout=20000, ) node_list = self.page.query_selector_all(DISPLAY_OUTPUT_ID_PATTERN) pattern = r"
hello world
" assert node_list[0].inner_html() == pattern assert len(node_list) == 1 def test_consecutive_display(self): self.pyscript_run( """ from pyscript import display display('hello 1')

hello 2

from pyscript import display display('hello 3') """ ) inner_text = self.page.inner_text("body") lines = inner_text.splitlines() lines = [line for line in filter_page_content(lines)] # remove empty lines assert lines == ["hello 1", "hello 2", "hello 3"] def test_target_attribute(self): self.pyscript_run( """ from pyscript import display display('hello world', target="mydiv")
""" ) mydiv = self.page.locator("#mydiv") assert mydiv.inner_text() == "hello world" def test_consecutive_display_target(self): self.pyscript_run( """ from pyscript import display display('hello 1')

hello in between 1 and 2

from pyscript import display display('hello 2', target="second") from pyscript import display display('hello 3') """ ) inner_text = self.page.inner_text("body") lines = inner_text.splitlines() lines = [line for line in filter_page_content(lines)] # remove empty lines assert lines == ["hello 1", "hello in between 1 and 2", "hello 2", "hello 3"] def test_multiple_display_calls_same_tag(self): self.pyscript_run( """ from pyscript import display display('hello') display('world') """ ) tag = self.page.locator("py-script") lines = tag.inner_text().splitlines() assert lines == ["hello", "world"] def test_implicit_target_from_a_different_tag(self): self.pyscript_run( """ from pyscript import display def say_hello(): display('hello') from pyscript import display say_hello() """ ) py1 = self.page.locator("#py1") py2 = self.page.locator("#py2") assert py1.inner_text() == "" assert py2.inner_text() == "hello" def test_no_explicit_target(self): self.pyscript_run( """ from pyscript import display def display_hello(error): display('hello world') """ ) self.page.locator("button").click() text = self.page.locator("py-script").text_content() assert "hello world" in text def test_explicit_target_pyscript_tag(self): self.pyscript_run( """ from pyscript import display def display_hello(): display('hello', target='second-pyscript-tag') display_hello() """ ) text = self.page.locator("id=second-pyscript-tag").inner_text() assert text == "hello" def test_explicit_target_on_button_tag(self): self.pyscript_run( """ from pyscript import display def display_hello(error): display('hello', target='my-button') """ ) self.page.locator("text=Click me").click() text = self.page.locator("id=my-button").inner_text() assert "hello" in text def test_explicit_different_target_from_call(self): self.pyscript_run( """ from pyscript import display def display_hello(): display('hello', target='second-pyscript-tag') print('nothing to see here') display_hello() """ ) text = self.page.locator("id=second-pyscript-tag").all_inner_texts() assert "hello" in text def test_append_true(self): self.pyscript_run( """ from pyscript import display display('hello world', append=True) """ ) node_list = self.page.query_selector_all(DISPLAY_OUTPUT_ID_PATTERN) pattern = r"
hello world
" assert node_list[0].inner_html() == pattern assert len(node_list) == 1 def test_append_false(self): self.pyscript_run( """ from pyscript import display display('hello world', append=False) """ ) inner_html = self.page.content() pattern = r'hello world' assert re.search(pattern, inner_html) def test_display_multiple_values(self): self.pyscript_run( """ from pyscript import display hello = 'hello' world = 'world' display(hello, world) """ ) inner_text = self.page.inner_text("html") assert inner_text == "hello\nworld" def test_display_multiple_append_false(self): self.pyscript_run( """ from pyscript import display display('hello', append=False) display('world', append=False) """ ) inner_html = self.page.content() pattern = r'world' assert re.search(pattern, inner_html) # TODO: this is a display.py issue to fix when append=False is used # do not use the first element, just clean up and then append # remove the # display comment once that's done def test_display_multiple_append_false_with_target(self): self.pyscript_run( """
""" ) innerhtml = self.page.locator("id=circle-div").inner_html() assert ( innerhtml == '' # noqa: E501 ) assert self.console.error.lines == [] def test_display_list_dict_tuple(self): self.pyscript_run( """ from pyscript import display l = ['A', 1, '!'] d = {'B': 2, 'List': l} t = ('C', 3, '!') display(l, d, t) """ ) inner_text = self.page.inner_text("html") filtered_inner_text = filter_inner_text(inner_text) print(filtered_inner_text) assert ( filtered_inner_text == "['A', 1, '!']\n{'B': 2, 'List': ['A', 1, '!']}\n('C', 3, '!')" ) def test_display_should_escape(self): self.pyscript_run( """ from pyscript import display display("

hello world

")
""" ) # out = self.page.locator("py-script > div") node_list = self.page.query_selector_all(DISPLAY_OUTPUT_ID_PATTERN) node_list[0] # assert out.inner_html() == html.escape("

hello world

") # assert out.inner_text() == "

hello world

" @pytest.mark.skip("FIXME: HTML has been removed from pyscript") def test_display_HTML(self): self.pyscript_run( """ from pyscript import display, HTML display(HTML("

hello world

"))
""" ) # out = self.page.locator("py-script > div") node_list = self.page.query_selector_all(DISPLAY_OUTPUT_ID_PATTERN) node_list[0] # assert out.inner_html() == "

hello world

" # assert out.inner_text() == "hello world" @pytest.mark.skip( "FIX TEST: Works correctly in Chrome, but fails in TEST with the error:\n\n" "It's likely that the Test framework injections in config are causing" "this error." ) def test_image_display(self): self.pyscript_run( """ packages = ["matplotlib"] from pyscript import display import matplotlib.pyplot as plt xpoints = [3, 6, 9] ypoints = [1, 2, 3] plt.plot(xpoints, ypoints) display(plt) """ ) wait_for_render(self.page, "*", " from pyscript import display import js print('print from python') js.console.log('print from js') js.console.error('error from js'); """ ) inner_html = self.page.content() assert re.search("", inner_html) console_text = self.console.all.lines assert "print from python" in console_text assert "print from js" in console_text assert "error from js" in console_text def test_text_HTML_and_console_output(self): self.pyscript_run( """ from pyscript import display import js display('this goes to the DOM') print('print from python') js.console.log('print from js') js.console.error('error from js'); """ ) inner_text = self.page.inner_text("py-script") assert inner_text == "this goes to the DOM" assert self.console.log.lines[-2:] == [ "print from python", "print from js", ] print(self.console.error.lines) assert self.console.error.lines[-1] == "error from js" def test_console_line_break(self): self.pyscript_run( """ print('1print\\n2print') print('1console\\n2console') """ ) console_text = self.console.all.lines assert console_text.index("1print") == (console_text.index("2print") - 1) assert console_text.index("1console") == (console_text.index("2console") - 1) @pytest.mark.skip( "FIX TEST: Works correctly in Chrome, but fails in TEST with the error:\n\n" "It's likely that the Test framework injections in config are causing" "this error." ) def test_image_renders_correctly(self): """This is just a sanity check to make sure that images are rendered correctly.""" buffer = io.BytesIO() img = Image.new("RGB", (4, 4), color=(0, 0, 0)) img.save(buffer, format="PNG") b64_img = base64.b64encode(buffer.getvalue()).decode("utf-8") expected_img_src = f"data:image/png;charset=utf-8;base64,{b64_img}" self.pyscript_run( """ packages = ["pillow"]
from pyscript import display from PIL import Image img = Image.new("RGB", (4, 4), color=(0, 0, 0)) display(img, target='img-target', append=False) """ ) rendered_img_src = self.page.locator("img").get_attribute("src") assert rendered_img_src == expected_img_src