mirror of
https://github.com/pyscript/pyscript.git
synced 2026-02-24 02:01:33 -05:00
[NEXT] Pydom (#1681)
* add pyweb * build * add test file * fix pydom example code * remove old reference to js * temporarily comment out query functions on BaseElement while rearranging code to reuse the same underlying logic accross PyDom and other elements * add temp TODO comment to content as it breaks with template elements * update pydom example to define code on external file * fix name type while renaming document -> dom * add real pydom test files * add classes to dom scope * __len__ to ElementCollection * fix some of the old tests * rename test from test_query_by_class to test_getitem_by_class * change test for read and write multiple elements * add find method to BaseElement * fix remaining tests * add Collection Tests * add equality to Collection * add test for collection style manipulation * fix getter for style property and rename style related attribute from pop to remove * add single element creation test * remove append on BaseElement and add body and head to dom * add test_create_element_child to verify child creation * add children getter property to Element * remove old code * remove more old code, change style attribute from visibility to visible and now default getters on collection to return a list with the value of an attribute for every element in the collection * remove more old code and add possibility to customize test flags via url * add support to pass Js and pydom.Element elements to when decorator * remove methods related to input type of elements until we have a better design for it * rename _element to _js * add test_when decorator with a ElementCollection input * when decorator now supporte pydom.ElementCollection as input * update pyscript.js * remove useless variable from when decorator * remove base.py from pyweb * add nodes for append collection test and add better feedback on successes vs failure * add tests and fix code for support of append Element and ElementCollection * manage access to content attribute when tagname is template * fix comment --------- Co-authored-by: Fabio Pliger <fpliger@anaconda.com>
This commit is contained in:
0
pyscript.core/test/pyscript_dom/tests/__init__.py
Normal file
0
pyscript.core/test/pyscript_dom/tests/__init__.py
Normal file
15
pyscript.core/test/pyscript_dom/tests/conftest.py
Normal file
15
pyscript.core/test/pyscript_dom/tests/conftest.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import pytest
|
||||
from js import document, localStorage
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def before_tests():
|
||||
"""
|
||||
Ensure browser storage is always reset to empty. Remove the app
|
||||
placeholder. Reset the page title.
|
||||
"""
|
||||
localStorage.clear()
|
||||
# app_placeholder = document.querySelector("pyper-app")
|
||||
# if app_placeholder:
|
||||
# app_placeholder.remove()
|
||||
document.querySelector("title").innerText = "Web API PyTest Suite"
|
||||
246
pyscript.core/test/pyscript_dom/tests/test_dom.py
Normal file
246
pyscript.core/test/pyscript_dom/tests/test_dom.py
Normal file
@@ -0,0 +1,246 @@
|
||||
import pytest
|
||||
from pyscript import document, when
|
||||
from unittest import mock
|
||||
|
||||
from pyweb import pydom
|
||||
|
||||
|
||||
class TestDocument:
|
||||
def test__element(self):
|
||||
assert pydom._js == document
|
||||
|
||||
def test_no_parent(self):
|
||||
assert pydom.parent is None
|
||||
|
||||
def test_create_element(self):
|
||||
new_el = pydom.create("div")
|
||||
assert isinstance(new_el, pydom.BaseElement)
|
||||
assert new_el._js.tagName == "DIV"
|
||||
# EXPECT the new element to be associated with the document
|
||||
assert new_el.parent == None
|
||||
|
||||
|
||||
def test_getitem_by_id():
|
||||
# GIVEN an existing element on the page with a known text content
|
||||
id_ = "test_id_selector"
|
||||
txt = "You found test_id_selector"
|
||||
selector = f"#{id_}"
|
||||
# EXPECT the element to be found by id
|
||||
result = pydom[selector]
|
||||
div = result[0]
|
||||
# EXPECT the element text value to match what we expect and what
|
||||
# the JS document.querySelector API would return
|
||||
assert document.querySelector(selector).innerHTML == div.html == txt
|
||||
# EXPECT the results to be of the right types
|
||||
assert isinstance(div, pydom.BaseElement)
|
||||
assert isinstance(result, pydom.ElementCollection)
|
||||
|
||||
|
||||
def test_getitem_by_class():
|
||||
ids = [
|
||||
"test_class_selector",
|
||||
"test_selector_w_children",
|
||||
"test_selector_w_children_child_1",
|
||||
]
|
||||
expected_class = "a-test-class"
|
||||
result = pydom[f".{expected_class}"]
|
||||
div = result[0]
|
||||
|
||||
# EXPECT to find exact number of elements with the class in the page (== 3)
|
||||
assert len(result) == 3
|
||||
|
||||
# EXPECT that all element ids are in the expected list
|
||||
assert [el.id for el in result] == ids
|
||||
|
||||
|
||||
def test_read_n_write_collection_elements():
|
||||
elements = pydom[".multi-elems"]
|
||||
|
||||
for element in elements:
|
||||
assert element.html == f"Content {element.id.replace('#', '')}"
|
||||
|
||||
new_content = "New Content"
|
||||
elements.html = new_content
|
||||
for element in elements:
|
||||
assert element.html == new_content
|
||||
|
||||
|
||||
class TestElement:
|
||||
def test_query(self):
|
||||
# GIVEN an existing element on the page, with at least 1 child element
|
||||
id_ = "test_selector_w_children"
|
||||
parent_div = pydom[f"#{id_}"][0]
|
||||
|
||||
# EXPECT it to be able to query for the first child element
|
||||
div = parent_div.find("div")[0]
|
||||
|
||||
# EXPECT the new element to be associated with the parent
|
||||
assert div.parent == parent_div
|
||||
# EXPECT the new element to be a BaseElement
|
||||
assert isinstance(div, pydom.BaseElement)
|
||||
# EXPECT the div attributes to be == to how they are configured in the page
|
||||
assert div.html == "Child 1"
|
||||
assert div.id == "test_selector_w_children_child_1"
|
||||
|
||||
def test_equality(self):
|
||||
# GIVEN 2 different Elements pointing to the same underlying element
|
||||
id_ = "test_id_selector"
|
||||
selector = f"#{id_}"
|
||||
div = pydom[selector][0]
|
||||
div2 = pydom[selector][0]
|
||||
|
||||
# EXPECT them to be equal
|
||||
assert div == div2
|
||||
# EXPECT them to be different objects
|
||||
assert div is not div2
|
||||
|
||||
# EXPECT their value to always be equal
|
||||
assert div.html == div2.html
|
||||
div.html = "some value"
|
||||
|
||||
assert div.html == div2.html == "some value"
|
||||
|
||||
def test_append_element(self):
|
||||
id_ = "element-append-tests"
|
||||
div = pydom[f"#{id_}"][0]
|
||||
len_children_before = len(div.children)
|
||||
new_el = div.create("p")
|
||||
div.append(new_el)
|
||||
assert len(div.children) == len_children_before + 1
|
||||
assert div.children[-1] == new_el
|
||||
|
||||
def test_append_js_element(self):
|
||||
id_ = "element-append-tests"
|
||||
div = pydom[f"#{id_}"][0]
|
||||
len_children_before = len(div.children)
|
||||
new_el = div.create("p")
|
||||
div.append(new_el._js)
|
||||
assert len(div.children) == len_children_before + 1
|
||||
assert div.children[-1] == new_el
|
||||
|
||||
def test_append_collection(self):
|
||||
id_ = "element-append-tests"
|
||||
div = pydom[f"#{id_}"][0]
|
||||
len_children_before = len(div.children)
|
||||
collection = pydom[".collection"]
|
||||
div.append(collection)
|
||||
assert len(div.children) == len_children_before + len(collection)
|
||||
|
||||
for i in range(len(collection)):
|
||||
assert div.children[-1 - i] == collection[-1 - i]
|
||||
|
||||
def test_read_classes(self):
|
||||
id_ = "test_class_selector"
|
||||
expected_class = "a-test-class"
|
||||
div = pydom[f"#{id_}"][0]
|
||||
assert div.classes == [expected_class]
|
||||
|
||||
def test_add_remove_class(self):
|
||||
id_ = "div-no-classes"
|
||||
classname = "tester-class"
|
||||
div = pydom[f"#{id_}"][0]
|
||||
assert not div.classes
|
||||
div.add_class(classname)
|
||||
same_div = pydom[f"#{id_}"][0]
|
||||
assert div.classes == [classname] == same_div.classes
|
||||
div.remove_class(classname)
|
||||
assert div.classes == [] == same_div.classes
|
||||
|
||||
def test_when_decorator(self):
|
||||
called = False
|
||||
|
||||
just_a_button = pydom["#a-test-button"][0]
|
||||
|
||||
@when("click", just_a_button)
|
||||
def on_click(event):
|
||||
nonlocal called
|
||||
called = True
|
||||
|
||||
# Now let's simulate a click on the button (using the low level JS API)
|
||||
# so we don't risk pydom getting in the way
|
||||
assert not called
|
||||
just_a_button._js.click()
|
||||
|
||||
assert called
|
||||
|
||||
|
||||
class TestCollection:
|
||||
def test_iter_eq_children(self):
|
||||
elements = pydom[".multi-elems"]
|
||||
assert [el for el in elements] == [el for el in elements.children]
|
||||
assert len(elements) == 3
|
||||
|
||||
def test_slices(self):
|
||||
elements = pydom[".multi-elems"]
|
||||
assert elements[0]
|
||||
_slice = elements[:2]
|
||||
assert len(_slice) == 2
|
||||
for i, el in enumerate(_slice):
|
||||
assert el == elements[i]
|
||||
assert elements[:] == elements
|
||||
|
||||
def test_style_rule(self):
|
||||
selector = ".multi-elems"
|
||||
elements = pydom[selector]
|
||||
for el in elements:
|
||||
assert el.style["background-color"] != "red"
|
||||
|
||||
elements.style["background-color"] = "red"
|
||||
|
||||
for i, el in enumerate(pydom[selector]):
|
||||
assert elements[i].style["background-color"] == "red"
|
||||
assert el.style["background-color"] == "red"
|
||||
|
||||
elements.style.remove("background-color")
|
||||
|
||||
for i, el in enumerate(pydom[selector]):
|
||||
assert el.style["background-color"] != "red"
|
||||
assert elements[i].style["background-color"] != "red"
|
||||
|
||||
def test_when_decorator(self):
|
||||
called = False
|
||||
|
||||
buttons_collection = pydom["button"]
|
||||
|
||||
@when("click", buttons_collection)
|
||||
def on_click(event):
|
||||
nonlocal called
|
||||
called = True
|
||||
|
||||
# Now let's simulate a click on the button (using the low level JS API)
|
||||
# so we don't risk pydom getting in the way
|
||||
assert not called
|
||||
for button in buttons_collection:
|
||||
button._js.click()
|
||||
assert called
|
||||
called = False
|
||||
|
||||
|
||||
class TestCreation:
|
||||
def test_create_document_element(self):
|
||||
new_el = pydom.create("div")
|
||||
new_el.id = "new_el_id"
|
||||
assert isinstance(new_el, pydom.BaseElement)
|
||||
assert new_el._js.tagName == "DIV"
|
||||
# EXPECT the new element to be associated with the document
|
||||
assert new_el.parent == None
|
||||
pydom.body.append(new_el)
|
||||
|
||||
assert pydom["#new_el_id"][0].parent == pydom.body
|
||||
|
||||
def test_create_element_child(self):
|
||||
selector = "#element-creation-test"
|
||||
parent_div = pydom[selector][0]
|
||||
|
||||
# Creating an element from another element automatically creates that element
|
||||
# as a child of the original element
|
||||
new_el = parent_div.create(
|
||||
"p", classes=["code-description"], html="Ciao PyScripters!"
|
||||
)
|
||||
|
||||
assert isinstance(new_el, pydom.BaseElement)
|
||||
assert new_el._js.tagName == "P"
|
||||
# EXPECT the new element to be associated with the document
|
||||
assert new_el.parent == parent_div
|
||||
|
||||
assert pydom[selector][0].children[0] == new_el
|
||||
Reference in New Issue
Block a user