-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tests for proposed WebDriver Shadow DOM support (#27132)
- Loading branch information
Showing
13 changed files
with
837 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
Find, | ||
Frame, | ||
Session, | ||
ShadowRoot, | ||
Timeouts, | ||
Window) | ||
from .error import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import pytest | ||
|
||
@pytest.fixture | ||
def get_shadow_page(inline): | ||
def get_shadow_page(shadow_content): | ||
return inline(""" | ||
<custom-shadow-element></custom-shadow-element> | ||
<script> | ||
customElements.define('custom-shadow-element', | ||
class extends HTMLElement {{ | ||
constructor() {{ | ||
super(); | ||
this.attachShadow({{mode: 'open'}}).innerHTML = ` | ||
{{ {0} }} | ||
`; | ||
}} | ||
}}); | ||
</script>""".format(shadow_content)) | ||
return get_shadow_page |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import pytest | ||
|
||
from webdriver.transport import Response | ||
|
||
from tests.support.asserts import assert_error, assert_same_element, assert_success | ||
|
||
|
||
def find_element(session, shadow_id, using, value): | ||
return session.transport.send( | ||
"POST", "session/{session_id}/shadow/{shadow_id}/element".format( | ||
session_id=session.session_id, | ||
shadow_id=shadow_id), | ||
{"using": using, "value": value}) | ||
|
||
|
||
def test_null_parameter_value(session, http, get_shadow_page): | ||
session.url = get_shadow_page("<div><a href=# id=linkText>full link text</a></div>") | ||
custom_element = session.find.css("custom-shadow-element", all=False) | ||
shadow_root = custom_element.shadow_root | ||
|
||
path = "/session/{session_id}/shadow/{shadow_id}/element".format( | ||
session_id=session.session_id, shadow_id=shadow_root.id) | ||
with http.post(path, None) as response: | ||
assert_error(Response.from_http(response), "invalid argument") | ||
|
||
|
||
def test_no_top_browsing_context(session, closed_window): | ||
response = find_element(session, "notReal", "css selector", "foo") | ||
assert_error(response, "no such window") | ||
|
||
|
||
def test_no_browsing_context(session, closed_frame): | ||
response = find_element(session, "notReal", "css selector", "foo") | ||
assert_error(response, "no such window") | ||
|
||
|
||
@pytest.mark.parametrize("using", ["a", True, None, 1, [], {}]) | ||
def test_invalid_using_argument(session, using): | ||
# Step 1 - 2 | ||
response = find_element(session, "notReal", using, "value") | ||
assert_error(response, "invalid argument") | ||
|
||
|
||
@pytest.mark.parametrize("value", [None, [], {}]) | ||
def test_invalid_selector_argument(session, value): | ||
# Step 3 - 4 | ||
response = find_element(session, "notReal", "css selector", value) | ||
assert_error(response, "invalid argument") | ||
|
||
|
||
def test_detached_shadow_root(session, get_shadow_page): | ||
session.url = get_shadow_page("<div><input type='checkbox'/></div>") | ||
custom_element = session.find.css("custom-shadow-element", all=False) | ||
shadow_root = custom_element.shadow_root | ||
session.refresh() | ||
|
||
response = find_element(session, shadow_root.id, "css", "input") | ||
assert_error(response, "detached shadow root") | ||
|
||
|
||
def test_found_element_equivalence(session, get_shadow_page): | ||
session.url = get_shadow_page("<div><input type='checkbox'/></div>") | ||
custom_element = session.find.css("custom-shadow-element", all=False) | ||
expected = session.execute_script("return arguments[0].shadowRoot.querySelector('input')", | ||
args=(custom_element,)) | ||
shadow_root = custom_element.shadow_root | ||
response = find_element(session, shadow_root.id, "css", "input") | ||
value = assert_success(response) | ||
assert_same_element(session, value, expected) | ||
|
||
|
||
@pytest.mark.parametrize("using,value", | ||
[("css selector", "#linkText"), | ||
("link text", "full link text"), | ||
("partial link text", "link text"), | ||
("tag name", "a"), | ||
("xpath", "//a")]) | ||
def test_find_element(session, get_shadow_page, using, value): | ||
# Step 8 - 9 | ||
session.url = get_shadow_page("<div><a href=# id=linkText>full link text</a></div>") | ||
custom_element = session.find.css("custom-shadow-element", all=False) | ||
expected = session.execute_script("return arguments[0].shadowRoot.querySelector('#linkText')", | ||
args=(custom_element,)) | ||
shadow_root = custom_element.shadow_root | ||
response = find_element(session, shadow_root.id, using, value) | ||
assert_success(response) | ||
assert_same_element(session, value, expected) | ||
|
||
|
||
@pytest.mark.parametrize("document,value", [ | ||
("<a href=#>link text</a>", "link text"), | ||
("<a href=#> link text </a>", "link text"), | ||
("<a href=#>link<br>text</a>", "link\ntext"), | ||
("<a href=#>link&text</a>", "link&text"), | ||
("<a href=#>LINK TEXT</a>", "LINK TEXT"), | ||
("<a href=# style='text-transform: uppercase'>link text</a>", "LINK TEXT"), | ||
]) | ||
def test_find_element_link_text(session, get_shadow_page, document, value): | ||
# Step 8 - 9 | ||
session.url = get_shadow_page("<div>{0}</div>".format(document)) | ||
custom_element = session.find.css("custom-shadow-element", all=False) | ||
expected = session.execute_script("return arguments[0].shadowRoot.querySelectorAll('a')[0]", | ||
args=(custom_element,)) | ||
shadow_root = custom_element.shadow_root | ||
|
||
response = find_element(session, shadow_root.id, "link text", value) | ||
assert_success(response) | ||
assert_same_element(session, value, expected) | ||
|
||
|
||
@pytest.mark.parametrize("document,value", [ | ||
("<a href=#>partial link text</a>", "link"), | ||
("<a href=#> partial link text </a>", "link"), | ||
("<a href=#>partial link text</a>", "k t"), | ||
("<a href=#>partial link<br>text</a>", "k\nt"), | ||
("<a href=#>partial link&text</a>", "k&t"), | ||
("<a href=#>PARTIAL LINK TEXT</a>", "LINK"), | ||
("<a href=# style='text-transform: uppercase'>partial link text</a>", "LINK"), | ||
]) | ||
def test_find_element_partial_link_text(session, get_shadow_page, document, value): | ||
# Step 8 - 9 | ||
session.url = get_shadow_page("<div>{0}</div>".format(document)) | ||
custom_element = session.find.css("custom-shadow-element", all=False) | ||
expected = session.execute_script("return arguments[0].shadowRoot.querySelectorAll('a')[0]", | ||
args=(custom_element,)) | ||
shadow_root = custom_element.shadow_root | ||
|
||
response = find_element(session, shadow_root.id, "partial link text", value) | ||
assert_success(response) | ||
assert_same_element(session, value, expected) | ||
|
||
|
||
@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")]) | ||
def test_no_element(session, get_shadow_page, using, value): | ||
# Step 8 - 9 | ||
session.url = get_shadow_page("<div></div>") | ||
custom_element = session.find.css("custom-shadow-element", all=False) | ||
shadow_root = custom_element.shadow_root | ||
|
||
response = find_element(session, shadow_root.id, using, value) | ||
assert_error(response, "no such element") |
129 changes: 129 additions & 0 deletions
129
webdriver/tests/find_element_from_shadow_root/user_prompts.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# META: timeout=long | ||
|
||
import pytest | ||
|
||
from tests.support.asserts import ( | ||
assert_error, | ||
assert_same_element, | ||
assert_success, | ||
assert_dialog_handled, | ||
) | ||
|
||
|
||
def find_element(session, shadow_id, using, value): | ||
return session.transport.send( | ||
"POST", "session/{session_id}/shadow/{shadow_id}/element".format( | ||
session_id=session.session_id, | ||
element_id=shadow_id), | ||
{"using": using, "value": value}) | ||
|
||
|
||
@pytest.fixture | ||
def check_user_prompt_closed_without_exception(session, create_dialog, get_shadow_page): | ||
def check_user_prompt_closed_without_exception(dialog_type, retval): | ||
session.url = get_shadow_page("<div><p>bar</p><div>") | ||
outer_element = session.find.css("custom-shadow-element", all=False) | ||
shadow_root = outer_element.shadow_root | ||
inner_element = session.execute_script("return arguments[0].shadowRoot.querySelector('p')", | ||
args=(outer_element,)) | ||
|
||
create_dialog(dialog_type, text=dialog_type) | ||
|
||
response = find_element(session, shadow_root.id, "css selector", "p") | ||
value = assert_success(response) | ||
|
||
assert_dialog_handled(session, expected_text=dialog_type, expected_retval=retval) | ||
|
||
assert_same_element(session, value, inner_element) | ||
|
||
return check_user_prompt_closed_without_exception | ||
|
||
|
||
@pytest.fixture | ||
def check_user_prompt_closed_with_exception(session, create_dialog, get_shadow_page): | ||
def check_user_prompt_closed_with_exception(dialog_type, retval): | ||
session.url = get_shadow_page("<div><p>bar</p><div>") | ||
outer_element = session.find.css("custom-shadow-element", all=False) | ||
shadow_root = outer_element.shadow_root | ||
|
||
create_dialog(dialog_type, text=dialog_type) | ||
|
||
response = find_element(session, shadow_root.id, "css selector", "p") | ||
assert_error(response, "unexpected alert open") | ||
|
||
assert_dialog_handled(session, expected_text=dialog_type, expected_retval=retval) | ||
|
||
return check_user_prompt_closed_with_exception | ||
|
||
|
||
@pytest.fixture | ||
def check_user_prompt_not_closed_but_exception(session, create_dialog, get_shadow_page): | ||
def check_user_prompt_not_closed_but_exception(dialog_type): | ||
session.url = get_shadow_page("<div><p>bar</p><div>") | ||
outer_element = session.find.css("custom-shadow-element", all=False) | ||
shadow_root = outer_element.shadow_root | ||
|
||
create_dialog(dialog_type, text=dialog_type) | ||
|
||
response = find_element(session, shadow_root.id, "css selector", "p") | ||
assert_error(response, "unexpected alert open") | ||
|
||
assert session.alert.text == dialog_type | ||
session.alert.dismiss() | ||
|
||
return check_user_prompt_not_closed_but_exception | ||
|
||
|
||
@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"}) | ||
@pytest.mark.parametrize("dialog_type, retval", [ | ||
("alert", None), | ||
("confirm", True), | ||
("prompt", ""), | ||
]) | ||
def test_accept(check_user_prompt_closed_without_exception, dialog_type, retval): | ||
check_user_prompt_closed_without_exception(dialog_type, retval) | ||
|
||
|
||
@pytest.mark.capabilities({"unhandledPromptBehavior": "accept and notify"}) | ||
@pytest.mark.parametrize("dialog_type, retval", [ | ||
("alert", None), | ||
("confirm", True), | ||
("prompt", ""), | ||
]) | ||
def test_accept_and_notify(check_user_prompt_closed_with_exception, dialog_type, retval): | ||
check_user_prompt_closed_with_exception(dialog_type, retval) | ||
|
||
|
||
@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"}) | ||
@pytest.mark.parametrize("dialog_type, retval", [ | ||
("alert", None), | ||
("confirm", False), | ||
("prompt", None), | ||
]) | ||
def test_dismiss(check_user_prompt_closed_without_exception, dialog_type, retval): | ||
check_user_prompt_closed_without_exception(dialog_type, retval) | ||
|
||
|
||
@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss and notify"}) | ||
@pytest.mark.parametrize("dialog_type, retval", [ | ||
("alert", None), | ||
("confirm", False), | ||
("prompt", None), | ||
]) | ||
def test_dismiss_and_notify(check_user_prompt_closed_with_exception, dialog_type, retval): | ||
check_user_prompt_closed_with_exception(dialog_type, retval) | ||
|
||
|
||
@pytest.mark.capabilities({"unhandledPromptBehavior": "ignore"}) | ||
@pytest.mark.parametrize("dialog_type", ["alert", "confirm", "prompt"]) | ||
def test_ignore(check_user_prompt_not_closed_but_exception, dialog_type): | ||
check_user_prompt_not_closed_but_exception(dialog_type) | ||
|
||
|
||
@pytest.mark.parametrize("dialog_type, retval", [ | ||
("alert", None), | ||
("confirm", False), | ||
("prompt", None), | ||
]) | ||
def test_default(check_user_prompt_closed_with_exception, dialog_type, retval): | ||
check_user_prompt_closed_with_exception(dialog_type, retval) |
Oops, something went wrong.