The all-new, pyscript.web (ignore the branch name :) ) (#2129)

* Minor cleanups: move all Element classes to bottom of module.

* Commenting.

* Commenting.

* Commenting.

* Group dunder methods.

* Don't cache the element's parent.

* Remove style type check until we decide whether or not to add for classes too.

* Add ability to register/unregister element classes.

* Implement __iter__ for container elements.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Minor renaming to make it clear when we have an Element instance vs an actual DOM element.

* remove duplication: added Element.get_tag_name

* Commenting.

* Allow Element.append to 1) use *args, 2) accept iterables

* Remove iterable check - inteferes with js proxies.

* Don't use *args, so it quacks more like a list ;)

* Element.append take 2 :)

* Remove unused code.

* Move to web.py with a page object!

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Added 'page.title' too :)

* Add __getitem__ as a shortcut for page.find

* Add Element.__getitem__ to be consistent

* Make __getitem__ consistent for Page, Element and ElementCollection.

* Docstringing.

* Docstringing.

* Docstringing/commenting.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix select.add (revert InnerHTML->html)

* Commenting.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Hand-edit some of the AI :)

* Rename ElementCollection.children -> ElementCollection.elements

* Remove unnecessary guard.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Martin
2024-08-01 03:36:57 -06:00
committed by GitHub
parent d47fb58ede
commit 999897df12
6 changed files with 496 additions and 453 deletions

View File

@@ -1,13 +1,11 @@
from pyscript import document, when
from pyscript.web import dom
from pyscript.web import elements as el
from pyscript.web.elements import ElementCollection
from pyscript.web import Element, ElementCollection, div, p, page
class TestDocument:
def test__element(self):
assert dom.body._dom_element == document.body
assert dom.head._dom_element == document.head
assert page.body._dom_element == document.body
assert page.head._dom_element == document.head
def test_getitem_by_id():
@@ -16,13 +14,13 @@ def test_getitem_by_id():
txt = "You found test_id_selector"
selector = f"#{id_}"
# EXPECT the element to be found by id
result = dom.find(selector)
result = page.find(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.innerHTML == txt
# EXPECT the results to be of the right types
assert isinstance(div, el.Element)
assert isinstance(div, Element)
assert isinstance(result, ElementCollection)
@@ -33,8 +31,7 @@ def test_getitem_by_class():
"test_selector_w_children_child_1",
]
expected_class = "a-test-class"
result = dom.find(f".{expected_class}")
div = result[0]
result = page.find(f".{expected_class}")
# EXPECT to find exact number of elements with the class in the page (== 3)
assert len(result) == 3
@@ -44,7 +41,7 @@ def test_getitem_by_class():
def test_read_n_write_collection_elements():
elements = dom.find(".multi-elems")
elements = page.find(".multi-elems")
for element in elements:
assert element.innerHTML == f"Content {element.id.replace('#', '')}"
@@ -59,15 +56,15 @@ 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 = dom.find(f"#{id_}")[0]
parent_div = page.find(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 el.Element
assert isinstance(div, el.Element)
# EXPECT the new element to be an Element
assert isinstance(div, Element)
# EXPECT the div attributes to be == to how they are configured in the page
assert div.innerHTML == "Child 1"
assert div.id == "test_selector_w_children_child_1"
@@ -76,8 +73,8 @@ class TestElement:
# GIVEN 2 different Elements pointing to the same underlying element
id_ = "test_id_selector"
selector = f"#{id_}"
div = dom.find(selector)[0]
div2 = dom.find(selector)[0]
div = page.find(selector)[0]
div2 = page.find(selector)[0]
# EXPECT them to be equal
assert div == div2
@@ -92,27 +89,27 @@ class TestElement:
def test_append_element(self):
id_ = "element-append-tests"
div = dom.find(f"#{id_}")[0]
div = page.find(f"#{id_}")[0]
len_children_before = len(div.children)
new_el = el.p("new element")
new_el = p("new element")
div.append(new_el)
assert len(div.children) == len_children_before + 1
assert div.children[-1] == new_el
def test_append_dom_element_element(self):
id_ = "element-append-tests"
div = dom.find(f"#{id_}")[0]
div = page.find(f"#{id_}")[0]
len_children_before = len(div.children)
new_el = el.p("new element")
new_el = p("new element")
div.append(new_el._dom_element)
assert len(div.children) == len_children_before + 1
assert div.children[-1] == new_el
def test_append_collection(self):
id_ = "element-append-tests"
div = dom.find(f"#{id_}")[0]
div = page.find(f"#{id_}")[0]
len_children_before = len(div.children)
collection = dom.find(".collection")
collection = page.find(".collection")
div.append(collection)
assert len(div.children) == len_children_before + len(collection)
@@ -122,16 +119,16 @@ class TestElement:
def test_read_classes(self):
id_ = "test_class_selector"
expected_class = "a-test-class"
div = dom.find(f"#{id_}")[0]
div = page.find(f"#{id_}")[0]
assert div.classes == [expected_class]
def test_add_remove_class(self):
id_ = "div-no-classes"
classname = "tester-class"
div = dom.find(f"#{id_}")[0]
div = page.find(f"#{id_}")[0]
assert not div.classes
div.classes.add(classname)
same_div = dom.find(f"#{id_}")[0]
same_div = page.find(f"#{id_}")[0]
assert div.classes == [classname] == same_div.classes
div.classes.remove(classname)
assert div.classes == [] == same_div.classes
@@ -139,7 +136,7 @@ class TestElement:
def test_when_decorator(self):
called = False
just_a_button = dom.find("#a-test-button")[0]
just_a_button = page.find("#a-test-button")[0]
@when("click", just_a_button)
def on_click(event):
@@ -155,7 +152,7 @@ class TestElement:
def test_inner_html_attribute(self):
# GIVEN an existing element on the page with a known empty text content
div = dom.find("#element_attribute_tests")[0]
div = page.find("#element_attribute_tests")[0]
# WHEN we set the html attribute
div.innerHTML = "<b>New Content</b>"
@@ -167,7 +164,7 @@ class TestElement:
def test_text_attribute(self):
# GIVEN an existing element on the page with a known empty text content
div = dom.find("#element_attribute_tests")[0]
div = page.find("#element_attribute_tests")[0]
# WHEN we set the html attribute
div.textContent = "<b>New Content</b>"
@@ -184,12 +181,12 @@ class TestElement:
class TestCollection:
def test_iter_eq_children(self):
elements = dom.find(".multi-elems")
assert [el for el in elements] == [el for el in elements.children]
elements = page.find(".multi-elems")
assert [el for el in elements] == [el for el in elements.elements]
assert len(elements) == 3
def test_slices(self):
elements = dom.find(".multi-elems")
elements = page.find(".multi-elems")
assert elements[0]
_slice = elements[:2]
assert len(_slice) == 2
@@ -199,26 +196,26 @@ class TestCollection:
def test_style_rule(self):
selector = ".multi-elems"
elements = dom.find(selector)
elements = page.find(selector)
for el in elements:
assert el.style["background-color"] != "red"
elements.style["background-color"] = "red"
for i, el in enumerate(dom.find(selector)):
for i, el in enumerate(page.find(selector)):
assert elements[i].style["background-color"] == "red"
assert el.style["background-color"] == "red"
elements.style.remove("background-color")
for i, el in enumerate(dom.find(selector)):
for i, el in enumerate(page.find(selector)):
assert el.style["background-color"] != "red"
assert elements[i].style["background-color"] != "red"
def test_when_decorator(self):
called = False
buttons_collection = dom.find("button")
buttons_collection = page.find("button")
@when("click", buttons_collection)
def on_click(event):
@@ -236,34 +233,33 @@ class TestCollection:
class TestCreation:
def test_create_document_element(self):
# TODO: This test should probably be removed since it's testing the elements module
new_el = el.div("new element")
# TODO: This test should probably be removed since it's testing the elements
# module.
new_el = div("new element")
new_el.id = "new_el_id"
assert isinstance(new_el, el.Element)
assert isinstance(new_el, Element)
assert new_el._dom_element.tagName == "DIV"
# EXPECT the new element to be associated with the document
assert new_el.parent == None
dom.body.append(new_el)
assert new_el.parent is None
page.body.append(new_el)
assert dom.find("#new_el_id")[0].parent == dom.body
assert page.find("#new_el_id")[0].parent == page.body
def test_create_element_child(self):
selector = "#element-creation-test"
parent_div = dom.find(selector)[0]
parent_div = page.find(selector)[0]
# Creating an element from another element automatically creates that element
# as a child of the original element
new_el = el.p(
"a div", classes=["code-description"], innerHTML="Ciao PyScripters!"
)
new_el = p("a div", classes=["code-description"], innerHTML="Ciao PyScripters!")
parent_div.append(new_el)
assert isinstance(new_el, el.Element)
assert isinstance(new_el, Element)
assert new_el._dom_element.tagName == "P"
# EXPECT the new element to be associated with the document
assert new_el.parent == parent_div
assert dom.find(selector)[0].children[0] == new_el
assert page.find(selector)[0].children[0] == new_el
class TestInput:
@@ -277,7 +273,7 @@ class TestInput:
def test_value(self):
for id_ in self.input_ids:
expected_type = id_.split("_")[-1]
result = dom.find(f"#{id_}")
result = page.find(f"#{id_}")
input_el = result[0]
assert input_el._dom_element.type == expected_type
assert input_el.value == f"Content {id_}" == input_el._dom_element.value
@@ -295,7 +291,7 @@ class TestInput:
def test_set_value_collection(self):
for id_ in self.input_ids:
input_el = dom.find(f"#{id_}")
input_el = page.find(f"#{id_}")
assert input_el.value[0] == f"Content {id_}" == input_el[0].value
@@ -308,30 +304,30 @@ class TestInput:
# actually on the class. Maybe a job for __setattr__?
#
# def test_element_without_value(self):
# result = dom.find(f"#tests-terminal"][0]
# result = page.find(f"#tests-terminal"][0]
# with pytest.raises(AttributeError):
# result.value = "some value"
#
# def test_element_without_value_via_collection(self):
# result = dom.find(f"#tests-terminal"]
# result = page.find(f"#tests-terminal"]
# with pytest.raises(AttributeError):
# result.value = "some value"
class TestSelect:
def test_select_options_iter(self):
select = dom.find(f"#test_select_element_w_options")[0]
select = page.find(f"#test_select_element_w_options")[0]
for i, option in enumerate(select.options, 1):
assert option.value == f"{i}"
assert option.innerHTML == f"Option {i}"
def test_select_options_len(self):
select = dom.find(f"#test_select_element_w_options")[0]
select = page.find(f"#test_select_element_w_options")[0]
assert len(select.options) == 2
def test_select_options_clear(self):
select = dom.find(f"#test_select_element_to_clear")[0]
select = page.find(f"#test_select_element_to_clear")[0]
assert len(select.options) == 3
select.options.clear()
@@ -340,7 +336,7 @@ class TestSelect:
def test_select_element_add(self):
# GIVEN the existing select element with no options
select = dom.find(f"#test_select_element")[0]
select = page.find(f"#test_select_element")[0]
# EXPECT the select element to have no options
assert len(select.options) == 0
@@ -431,7 +427,7 @@ class TestSelect:
def test_select_options_remove(self):
# GIVEN the existing select element with 3 options
select = dom.find(f"#test_select_element_to_remove")[0]
select = page.find(f"#test_select_element_to_remove")[0]
# EXPECT the select element to have 3 options
assert len(select.options) == 4
@@ -453,7 +449,7 @@ class TestSelect:
def test_select_get_selected_option(self):
# GIVEN the existing select element with one selected option
select = dom.find(f"#test_select_element_w_options")[0]
select = page.find(f"#test_select_element_w_options")[0]
# WHEN we get the selected option
selected_option = select.options.selected