[wdspec] Add proper support for tests to use WebFrame and WebWindow.
Differential Revision: https://phabricator.services.mozilla.com/D191434
bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1274251
gecko-commit: 92a611eda6b1ad91ec74242b49baad374910a4a6
gecko-reviewers: webdriver-reviewers, jdescottes
diff --git a/tools/webdriver/webdriver/__init__.py b/tools/webdriver/webdriver/__init__.py
index a817514..dfd264f 100644
--- a/tools/webdriver/webdriver/__init__.py
+++ b/tools/webdriver/webdriver/__init__.py
@@ -2,13 +2,14 @@
from .client import (
Cookies,
- Element,
Find,
- Frame,
Session,
ShadowRoot,
Timeouts,
- Window)
+ WebElement,
+ WebFrame,
+ WebWindow,
+)
from .error import (
ElementNotSelectableException,
ElementNotVisibleException,
diff --git a/tools/webdriver/webdriver/client.py b/tools/webdriver/webdriver/client.py
index f33fc34..e41df7f 100644
--- a/tools/webdriver/webdriver/client.py
+++ b/tools/webdriver/webdriver/client.py
@@ -295,9 +295,7 @@
return ActionSequence(self.session, *args, **kwargs)
-class Window:
- identifier = "window-fcc6-11e5-b4f8-330a88ab9d7f"
-
+class BrowserWindow:
def __init__(self, session):
self.session = session
@@ -372,59 +370,6 @@
def fullscreen(self):
return self.session.send_session_command("POST", "window/fullscreen")
- @classmethod
- def from_json(cls, json, session):
- uuid = json[Window.identifier]
- return cls(uuid, session)
-
-
-class Frame:
- identifier = "frame-075b-4da1-b6ba-e579c2d3230a"
-
- def __init__(self, session):
- self.session = session
-
- @classmethod
- def from_json(cls, json, session):
- uuid = json[Frame.identifier]
- return cls(uuid, session)
-
-
-class ShadowRoot:
- identifier = "shadow-6066-11e4-a52e-4f735466cecf"
-
- def __init__(self, session, id):
- """
- Construct a new shadow root representation.
-
- :param id: Shadow root UUID which must be unique across
- all browsing contexts.
- :param session: Current ``webdriver.Session``.
- """
- self.id = id
- self.session = session
-
- @classmethod
- def from_json(cls, json, session):
- uuid = json[ShadowRoot.identifier]
- return cls(session, uuid)
-
- def send_shadow_command(self, method, uri, body=None):
- url = f"shadow/{self.id}/{uri}"
- return self.session.send_session_command(method, url, body)
-
- @command
- def find_element(self, strategy, selector):
- body = {"using": strategy,
- "value": selector}
- return self.send_shadow_command("POST", "element", body)
-
- @command
- def find_elements(self, strategy, selector):
- body = {"using": strategy,
- "value": selector}
- return self.send_shadow_command("POST", "elements", body)
-
class Find:
def __init__(self, session):
@@ -512,7 +457,7 @@
self.extension_cls = extension
self.timeouts = Timeouts(self)
- self.window = Window(self)
+ self.window = BrowserWindow(self)
self.find = Find(self)
self.alert = UserPrompt(self)
self.actions = Actions(self)
@@ -795,7 +740,44 @@
def screenshot(self):
return self.send_session_command("GET", "screenshot")
-class Element:
+
+class ShadowRoot:
+ identifier = "shadow-6066-11e4-a52e-4f735466cecf"
+
+ def __init__(self, session, id):
+ """
+ Construct a new shadow root representation.
+
+ :param id: Shadow root UUID which must be unique across
+ all browsing contexts.
+ :param session: Current ``webdriver.Session``.
+ """
+ self.id = id
+ self.session = session
+
+ @classmethod
+ def from_json(cls, json, session):
+ uuid = json[ShadowRoot.identifier]
+ return cls(session, uuid)
+
+ def send_shadow_command(self, method, uri, body=None):
+ url = f"shadow/{self.id}/{uri}"
+ return self.session.send_session_command(method, url, body)
+
+ @command
+ def find_element(self, strategy, selector):
+ body = {"using": strategy,
+ "value": selector}
+ return self.send_shadow_command("POST", "element", body)
+
+ @command
+ def find_elements(self, strategy, selector):
+ body = {"using": strategy,
+ "value": selector}
+ return self.send_shadow_command("POST", "elements", body)
+
+
+class WebElement:
"""
Representation of a web element.
@@ -818,12 +800,12 @@
return "<%s %s>" % (self.__class__.__name__, self.id)
def __eq__(self, other):
- return (isinstance(other, Element) and self.id == other.id and
+ return (isinstance(other, WebElement) and self.id == other.id and
self.session == other.session)
@classmethod
def from_json(cls, json, session):
- uuid = json[Element.identifier]
+ uuid = json[WebElement.identifier]
return cls(session, uuid)
def send_element_command(self, method, uri, body=None):
@@ -902,3 +884,42 @@
@command
def property(self, name):
return self.send_element_command("GET", "property/%s" % name)
+
+class WebFrame:
+ identifier = "frame-075b-4da1-b6ba-e579c2d3230a"
+
+ def __init__(self, session, id):
+ self.id = id
+ self.session = session
+
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__, self.id)
+
+ def __eq__(self, other):
+ return (isinstance(other, WebFrame) and self.id == other.id and
+ self.session == other.session)
+
+ @classmethod
+ def from_json(cls, json, session):
+ uuid = json[WebFrame.identifier]
+ return cls(session, uuid)
+
+
+class WebWindow:
+ identifier = "window-fcc6-11e5-b4f8-330a88ab9d7f"
+
+ def __init__(self, session, id):
+ self.id = id
+ self.session = session
+
+ def __repr__(self):
+ return "<%s %s>" % (self.__class__.__name__, self.id)
+
+ def __eq__(self, other):
+ return (isinstance(other, WebWindow) and self.id == other.id and
+ self.session == other.session)
+
+ @classmethod
+ def from_json(cls, json, session):
+ uuid = json[WebWindow.identifier]
+ return cls(session, uuid)
diff --git a/tools/webdriver/webdriver/protocol.py b/tools/webdriver/webdriver/protocol.py
index 1972c3f..d6c89af2 100644
--- a/tools/webdriver/webdriver/protocol.py
+++ b/tools/webdriver/webdriver/protocol.py
@@ -16,14 +16,14 @@
def default(self, obj):
if isinstance(obj, (list, tuple)):
return [self.default(x) for x in obj]
- elif isinstance(obj, webdriver.Element):
- return {webdriver.Element.identifier: obj.id}
- elif isinstance(obj, webdriver.Frame):
- return {webdriver.Frame.identifier: obj.id}
- elif isinstance(obj, webdriver.Window):
- return {webdriver.Frame.identifier: obj.id}
+ elif isinstance(obj, webdriver.WebElement):
+ return {webdriver.WebElement.identifier: obj.id}
+ elif isinstance(obj, webdriver.WebFrame):
+ return {webdriver.WebFrame.identifier: obj.id}
elif isinstance(obj, webdriver.ShadowRoot):
return {webdriver.ShadowRoot.identifier: obj.id}
+ elif isinstance(obj, webdriver.WebWindow):
+ return {webdriver.WebWindow.identifier: obj.id}
return super().default(obj)
@@ -36,14 +36,14 @@
def object_hook(self, payload):
if isinstance(payload, (list, tuple)):
return [self.object_hook(x) for x in payload]
- elif isinstance(payload, dict) and webdriver.Element.identifier in payload:
- return webdriver.Element.from_json(payload, self.session)
- elif isinstance(payload, dict) and webdriver.Frame.identifier in payload:
- return webdriver.Frame.from_json(payload, self.session)
- elif isinstance(payload, dict) and webdriver.Window.identifier in payload:
- return webdriver.Window.from_json(payload, self.session)
+ elif isinstance(payload, dict) and webdriver.WebElement.identifier in payload:
+ return webdriver.WebElement.from_json(payload, self.session)
+ elif isinstance(payload, dict) and webdriver.WebFrame.identifier in payload:
+ return webdriver.WebFrame.from_json(payload, self.session)
elif isinstance(payload, dict) and webdriver.ShadowRoot.identifier in payload:
return webdriver.ShadowRoot.from_json(payload, self.session)
+ elif isinstance(payload, dict) and webdriver.WebWindow.identifier in payload:
+ return webdriver.WebWindow.from_json(payload, self.session)
elif isinstance(payload, dict):
return {k: self.object_hook(v) for k, v in payload.items()}
return payload
diff --git a/tools/webdriver/webdriver/transport.py b/tools/webdriver/webdriver/transport.py
index e1e16bd..ca1ff74 100644
--- a/tools/webdriver/webdriver/transport.py
+++ b/tools/webdriver/webdriver/transport.py
@@ -102,9 +102,9 @@
Transports messages (commands and responses) over the WebDriver
wire protocol.
- Complex objects, such as ``webdriver.Element``, ``webdriver.Frame``,
- and ``webdriver.Window`` are by default not marshaled to enable
- use of `session.transport.send` in WPT tests::
+ Complex objects, such as ``webdriver.ShadowRoot``, ``webdriver.WebElement``,
+ ``webdriver.WebFrame``, and ``webdriver.WebWindow`` are by default not
+ marshaled to enable use of `session.transport.send` in WPT tests::
session = webdriver.Session("127.0.0.1", 4444)
response = transport.send("GET", "element/active", None)
@@ -180,17 +180,17 @@
"""
Send a command to the remote.
- The request `body` must be JSON serialisable unless a
+ The request `body` must be JSON serializable unless a
custom `encoder` has been provided. This means complex
- objects such as ``webdriver.Element``, ``webdriver.Frame``,
- and `webdriver.Window`` are not automatically made
- into JSON. This behaviour is, however, provided by
+ objects such as ``webdriver.ShadowRoot``, ``webdriver.WebElement``,
+ ``webdriver.WebFrame``, and `webdriver.Window`` are not automatically
+ made into JSON. This behavior is, however, provided by
``webdriver.protocol.Encoder``, should you want it.
Similarly, the response body is returned au natural
as plain JSON unless a `decoder` that converts web
element references to ``webdriver.Element`` is provided.
- Use ``webdriver.protocol.Decoder`` to achieve this behaviour.
+ Use ``webdriver.protocol.Decoder`` to achieve this behavior.
The client will attempt to use persistent HTTP connections.
@@ -211,7 +211,7 @@
describing the HTTP response received from the remote end.
:raises ValueError: If `body` or the response body are not
- JSON serialisable.
+ JSON serializable.
"""
if body is None and method == "POST":
body = {}
diff --git a/webdriver/tests/bidi/script/classic_interop/node_shared_id.py b/webdriver/tests/bidi/script/classic_interop/node_shared_id.py
index 82b39b4..aeb2bc4 100644
--- a/webdriver/tests/bidi/script/classic_interop/node_shared_id.py
+++ b/webdriver/tests/bidi/script/classic_interop/node_shared_id.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element, ShadowRoot
+from webdriver import ShadowRoot, WebElement
from webdriver.bidi.modules.script import ContextTarget
pytestmark = pytest.mark.asyncio
@@ -51,7 +51,7 @@
assert nodeType == ELEMENT_NODE
# Use element reference from WebDriver BiDi in WebDriver classic
- node = Element(current_session, result["sharedId"])
+ node = WebElement(current_session, result["sharedId"])
nodeType = current_session.execute_script(
"""return arguments[0].nodeType""", args=(node,)
)
diff --git a/webdriver/tests/classic/element_clear/clear.py b/webdriver/tests/classic/element_clear/clear.py
index 9b0d7f2..22c07b6 100644
--- a/webdriver/tests/classic/element_clear/clear.py
+++ b/webdriver/tests/classic/element_clear/clear.py
@@ -1,7 +1,7 @@
# META: timeout=long
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import (
assert_element_has_focus,
@@ -45,7 +45,7 @@
def test_no_top_browsing_context(session, closed_window):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_clear(session, element)
assert_error(response, "no such window")
@@ -59,14 +59,14 @@
def test_no_browsing_context(session, closed_frame):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_clear(session, element)
assert_error(response, "no such window")
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_clear(session, element)
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/element_click/click.py b/webdriver/tests/classic/element_click/click.py
index 3c3f7d7..61acc92 100644
--- a/webdriver/tests/classic/element_click/click.py
+++ b/webdriver/tests/classic/element_click/click.py
@@ -1,5 +1,5 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
@@ -21,7 +21,7 @@
def test_no_top_browsing_context(session, closed_window):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_click(session, element)
assert_error(response, "no such window")
@@ -35,14 +35,14 @@
def test_no_browsing_context(session, closed_frame):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_click(session, element)
assert_error(response, "no such window")
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_click(session, element)
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/element_click/events.py b/webdriver/tests/classic/element_click/events.py
index 30f2dfa..5e80b52 100644
--- a/webdriver/tests/classic/element_click/events.py
+++ b/webdriver/tests/classic/element_click/events.py
@@ -1,4 +1,4 @@
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_success
from tests.support.helpers import filter_dict
diff --git a/webdriver/tests/classic/element_send_keys/send_keys.py b/webdriver/tests/classic/element_send_keys/send_keys.py
index 281c7ad..92002f2 100644
--- a/webdriver/tests/classic/element_send_keys/send_keys.py
+++ b/webdriver/tests/classic/element_send_keys/send_keys.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from webdriver.transport import Response
from tests.support.asserts import assert_error, assert_success
@@ -34,7 +34,7 @@
def test_no_top_browsing_context(session, closed_window):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_send_keys(session, element, "foo")
assert_error(response, "no such window")
@@ -48,14 +48,14 @@
def test_no_browsing_context(session, closed_frame):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_send_keys(session, element, "foo")
assert_error(response, "no such window")
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = element_send_keys(session, element, "foo")
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/execute_async_script/arguments.py b/webdriver/tests/classic/execute_async_script/arguments.py
index ead6e0c..81b30de 100644
--- a/webdriver/tests/classic/execute_async_script/arguments.py
+++ b/webdriver/tests/classic/execute_async_script/arguments.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver.client import Element, Frame, ShadowRoot, Window
+from webdriver.client import ShadowRoot, WebElement, WebFrame, WebWindow
from tests.support.asserts import assert_error, assert_success
from . import execute_async_script
@@ -54,8 +54,8 @@
assert actual[1] == value
-def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+def test_no_such_element_with_unknown_id(session):
+ element = WebElement(session, "foo")
result = execute_async_script(session, """
arguments[1](true);
@@ -101,7 +101,7 @@
assert_error(result, "no such element")
-def test_no_such_shadow_root_with_unknown_shadow_root(session):
+def test_no_such_shadow_root_with_unknown_id(session):
shadow_root = ShadowRoot(session, "foo")
result = execute_async_script(session, """
@@ -159,18 +159,47 @@
assert_error(result, "stale element reference")
-@pytest.mark.parametrize("expression, expected_type, expected_class", [
- ("window.frames[0]", Frame, "Frame"),
- ("document.querySelector('div')", Element, "HTMLDivElement"),
- ("document.querySelector('custom-element').shadowRoot", ShadowRoot, "ShadowRoot"),
- ("window", Window, "Window")
+@pytest.mark.parametrize("type", [WebFrame, WebWindow], ids=["frame", "window"])
+@pytest.mark.parametrize("value", [None, False, 42, [], {}])
+def test_invalid_argument_for_window_with_invalid_type(session, type, value):
+ reference = type(session, value)
+
+ result = execute_async_script(session, "arguments[1](true)", args=(reference,))
+ assert_error(result, "invalid argument")
+
+
+def test_no_such_window_for_window_with_invalid_value(session, get_test_page):
+ session.url = get_test_page()
+
+ result = execute_async_script(session, "arguments[0]([window, window.frames[0]]);")
+ [window, frame] = assert_success(result)
+
+ assert isinstance(window, WebWindow)
+ assert isinstance(frame, WebFrame)
+
+ window_reference = WebWindow(session, frame.id)
+ frame_reference = WebFrame(session, window.id)
+
+ for reference in [window_reference, frame_reference]:
+ result = execute_async_script(session, "arguments[1](true)", args=(reference,))
+ assert_error(result, "no such window")
+
+
+@pytest.mark.parametrize("expression, expected_type", [
+ ("window.frames[0]", WebFrame),
+ ("document.querySelector('div')", WebElement),
+ ("document.querySelector('custom-element').shadowRoot", ShadowRoot),
+ ("window", WebWindow)
], ids=["frame", "node", "shadow-root", "window"])
-def test_element_reference(session, get_test_page, expression, expected_type, expected_class):
+def test_element_reference(session, get_test_page, expression, expected_type):
session.url = get_test_page(as_frame=False)
result = execute_async_script(session, f"arguments[0]({expression})")
reference = assert_success(result)
assert isinstance(reference, expected_type)
- result = execute_async_script(session, "arguments[1](arguments[0].constructor.name)", [reference])
- assert_success(result, expected_class)
+ result = execute_async_script(session, f"""
+ let resolve = arguments[1];
+ resolve(arguments[0] == {expression})
+ """, [reference])
+ assert_success(result, True)
diff --git a/webdriver/tests/classic/execute_async_script/execute_async.py b/webdriver/tests/classic/execute_async_script/execute_async.py
index 42cf4aa..3c8cc62 100644
--- a/webdriver/tests/classic/execute_async_script/execute_async.py
+++ b/webdriver/tests/classic/execute_async_script/execute_async.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from webdriver.error import NoSuchAlertException
from webdriver.transport import Response
@@ -16,12 +16,12 @@
def test_no_top_browsing_context(session, closed_window):
- response = execute_async_script(session, "argument[0](1);")
+ response = execute_async_script(session, "arguments[0](1);")
assert_error(response, "no such window")
def test_no_browsing_context(session, closed_frame):
- response = execute_async_script(session, "argument[0](1);")
+ response = execute_async_script(session, "arguments[0](1);")
assert_error(response, "no such window")
diff --git a/webdriver/tests/classic/execute_async_script/node.py b/webdriver/tests/classic/execute_async_script/node.py
index 53abda4..2f1bf75 100644
--- a/webdriver/tests/classic/execute_async_script/node.py
+++ b/webdriver/tests/classic/execute_async_script/node.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver.client import Element, Frame, ShadowRoot, Window
+from webdriver.client import ShadowRoot, WebElement
from tests.support.asserts import assert_error, assert_success
from . import execute_async_script
@@ -59,11 +59,9 @@
@pytest.mark.parametrize("expression, expected_type", [
- ("window.frames[0]", Frame),
- ("document.querySelector('div')", Element),
+ ("document.querySelector('div')", WebElement),
("document.querySelector('custom-element').shadowRoot", ShadowRoot),
- ("window", Window),
-], ids=["frame", "node", "shadow-root", "window"])
+], ids=["element", "shadow-root"])
def test_element_reference(session, get_test_page, expression, expected_type):
session.url = get_test_page()
@@ -81,7 +79,7 @@
(""" document"""),
(""" document.doctype"""),
], ids=["attribute", "text", "cdata", "processing_instruction", "comment", "document", "doctype"])
-def test_non_element_nodes(session, inline, expression):
+def test_not_supported_nodes(session, inline, expression):
session.url = inline(PAGE_DATA)
result = execute_async_script(session, f"arguments[0]({expression})")
diff --git a/webdriver/tests/classic/execute_async_script/window.py b/webdriver/tests/classic/execute_async_script/window.py
new file mode 100644
index 0000000..f79bfdf
--- /dev/null
+++ b/webdriver/tests/classic/execute_async_script/window.py
@@ -0,0 +1,33 @@
+import pytest
+
+from webdriver.client import WebFrame, WebWindow
+
+from tests.support.asserts import assert_success
+from . import execute_async_script
+
+
+@pytest.mark.parametrize("expression, expected_type", [
+ ("window.frames[0]", WebFrame),
+ ("window", WebWindow),
+], ids=["frame", "window"])
+def test_web_reference(session, get_test_page, expression, expected_type):
+ session.url = get_test_page()
+
+ result = execute_async_script(session, f"arguments[0]({expression})")
+ reference = assert_success(result)
+
+ assert isinstance(reference, expected_type)
+
+ if isinstance(reference, WebWindow):
+ assert reference.id in session.handles
+ else:
+ assert reference.id not in session.handles
+
+
+def test_window_open(session):
+ result = execute_async_script(
+ session, "window.foo = window.open(); arguments[0](window.foo);")
+ reference = assert_success(result)
+
+ assert isinstance(reference, WebWindow)
+ assert reference.id in session.handles
diff --git a/webdriver/tests/classic/execute_script/arguments.py b/webdriver/tests/classic/execute_script/arguments.py
index b8657ce..ab5c523 100644
--- a/webdriver/tests/classic/execute_script/arguments.py
+++ b/webdriver/tests/classic/execute_script/arguments.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver.client import Element, Frame, ShadowRoot, Window
+from webdriver.client import ShadowRoot, WebElement, WebFrame, WebWindow
from tests.support.asserts import assert_error, assert_success
from . import execute_script
@@ -46,8 +46,8 @@
assert actual[1] == value
-def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+def test_no_such_element_with_unknown_id(session):
+ element = WebElement(session, "foo")
result = execute_script(session, "return true;", args=[element])
assert_error(result, "no such element")
@@ -87,7 +87,7 @@
assert_error(result, "no such element")
-def test_no_such_shadow_root_with_unknown_shadow_root(session):
+def test_no_such_shadow_root_with_unknown_id(session):
shadow_root = ShadowRoot(session, "foo")
result = execute_script(session, "return true;", args=[shadow_root])
@@ -147,18 +147,44 @@
assert_error(result, "stale element reference")
-@pytest.mark.parametrize("expression, expected_type, expected_class", [
- ("window.frames[0]", Frame, "Frame"),
- ("document.querySelector('div')", Element, "HTMLDivElement"),
- ("document.querySelector('custom-element').shadowRoot", ShadowRoot, "ShadowRoot"),
- ("window", Window, "Window")
+@pytest.mark.parametrize("type", [WebFrame, WebWindow], ids=["frame", "window"])
+@pytest.mark.parametrize("value", [None, False, 42, [], {}])
+def test_invalid_argument_for_window_with_invalid_type(session, type, value):
+ reference = type(session, value)
+
+ result = execute_script(session, "return true", args=(reference,))
+ assert_error(result, "invalid argument")
+
+
+def test_no_such_window_for_window_with_invalid_value(session, get_test_page):
+ session.url = get_test_page()
+
+ result = execute_script(session, "return [window, window.frames[0]];")
+ [window, frame] = assert_success(result)
+
+ assert isinstance(window, WebWindow)
+ assert isinstance(frame, WebFrame)
+
+ window_reference = WebWindow(session, frame.id)
+ frame_reference = WebFrame(session, window.id)
+
+ for reference in [window_reference, frame_reference]:
+ result = execute_script(session, "return true", args=(reference,))
+ assert_error(result, "no such window")
+
+
+@pytest.mark.parametrize("expression, expected_type", [
+ ("window.frames[0]", WebFrame),
+ ("document.querySelector('div')", WebElement),
+ ("document.querySelector('custom-element').shadowRoot", ShadowRoot),
+ ("window", WebWindow)
], ids=["frame", "node", "shadow-root", "window"])
-def test_element_reference(session, get_test_page, expression, expected_type, expected_class):
+def test_element_reference(session, get_test_page, expression, expected_type):
session.url = get_test_page(as_frame=False)
result = execute_script(session, f"return {expression}")
reference = assert_success(result)
assert isinstance(reference, expected_type)
- result = execute_script(session, "return arguments[0].constructor.name", [reference])
- assert_success(result, expected_class)
+ result = execute_script(session, f"return arguments[0] == {expression}", [reference])
+ assert_success(result, True)
diff --git a/webdriver/tests/classic/execute_script/execute.py b/webdriver/tests/classic/execute_script/execute.py
index fbccc98..15ac1d0 100644
--- a/webdriver/tests/classic/execute_script/execute.py
+++ b/webdriver/tests/classic/execute_script/execute.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from webdriver.error import NoSuchAlertException
from webdriver.transport import Response
diff --git a/webdriver/tests/classic/execute_script/json_serialize_windowproxy.py b/webdriver/tests/classic/execute_script/json_serialize_windowproxy.py
deleted file mode 100644
index 8e76fed..0000000
--- a/webdriver/tests/classic/execute_script/json_serialize_windowproxy.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import json
-
-from tests.support.asserts import assert_success
-from . import execute_script
-
-_window_id = "window-fcc6-11e5-b4f8-330a88ab9d7f"
-_frame_id = "frame-075b-4da1-b6ba-e579c2d3230a"
-
-
-def test_initial_window(session):
- # non-auxiliary top-level browsing context
- response = execute_script(session, "return window;")
- raw_json = assert_success(response)
-
- obj = json.loads(raw_json)
- assert len(obj) == 1
- assert _window_id in obj
- handle = obj[_window_id]
- assert handle in session.window_handles
-
-
-def test_window_open(session):
- # auxiliary browsing context
- session.execute_script("window.foo = window.open()")
-
- response = execute_script(session, "return window.foo;")
- raw_json = assert_success(response)
-
- obj = json.loads(raw_json)
- assert len(obj) == 1
- assert _window_id in obj
- handle = obj[_window_id]
- assert handle in session.window_handles
-
-
-def test_frame(session):
- # nested browsing context
- append = """
- window.frame = document.createElement('iframe');
- document.body.appendChild(frame);
- """
- session.execute_script(append)
-
- response = execute_script(session, "return frame.contentWindow;")
- raw_json = assert_success(response)
-
- obj = json.loads(raw_json)
- assert len(obj) == 1
- assert _frame_id in obj
- handle = obj[_frame_id]
- assert handle not in session.window_handles
diff --git a/webdriver/tests/classic/execute_script/node.py b/webdriver/tests/classic/execute_script/node.py
index caf8598..61cf346 100644
--- a/webdriver/tests/classic/execute_script/node.py
+++ b/webdriver/tests/classic/execute_script/node.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver.client import Element, Frame, ShadowRoot, Window
+from webdriver.client import WebElement, ShadowRoot
from tests.support.asserts import assert_error, assert_success
from . import execute_script
@@ -58,12 +58,10 @@
@pytest.mark.parametrize("expression, expected_type", [
- ("window.frames[0]", Frame),
- ("document.querySelector('div')", Element),
+ ("document.querySelector('div')", WebElement),
("document.querySelector('custom-element').shadowRoot", ShadowRoot),
- ("window", Window),
-], ids=["frame", "node", "shadow-root", "window"])
-def test_element_reference(session, get_test_page, expression, expected_type):
+], ids=["element", "shadow-root"])
+def test_web_reference(session, get_test_page, expression, expected_type):
session.url = get_test_page()
result = execute_script(session, f"return {expression}")
@@ -80,7 +78,7 @@
(""" document"""),
(""" document.doctype"""),
], ids=["attribute", "text", "cdata", "processing_instruction", "comment", "document", "doctype"])
-def test_non_element_nodes(session, inline, expression):
+def test_not_supported_nodes(session, inline, expression):
session.url = inline(PAGE_DATA)
result = execute_script(session, f"return {expression}")
diff --git a/webdriver/tests/classic/execute_script/window.py b/webdriver/tests/classic/execute_script/window.py
new file mode 100644
index 0000000..9ab45d7
--- /dev/null
+++ b/webdriver/tests/classic/execute_script/window.py
@@ -0,0 +1,87 @@
+import pytest
+
+from webdriver.client import WebFrame, WebWindow
+
+from tests.support.asserts import assert_success
+from . import execute_script
+
+
+@pytest.mark.parametrize("expression, expected_type", [
+ ("window.frames[0]", WebFrame),
+ ("window", WebWindow),
+], ids=["frame", "window"])
+def test_web_reference(session, get_test_page, expression, expected_type):
+ session.url = get_test_page()
+
+ result = execute_script(session, f"return {expression}")
+ reference = assert_success(result)
+
+ assert isinstance(reference, expected_type)
+
+ if isinstance(reference, WebWindow):
+ assert reference.id in session.handles
+ else:
+ assert reference.id not in session.handles
+
+
+@pytest.mark.parametrize("expression, expected_type", [
+ ("window.frames[0]", WebFrame),
+ ("window", WebWindow),
+], ids=["frame", "window"])
+def test_web_reference_in_array(session, get_test_page, expression, expected_type):
+ session.url = get_test_page()
+
+ result = execute_script(session, f"return [{expression}]")
+ value = assert_success(result)
+
+ assert isinstance(value[0], expected_type)
+
+ if isinstance(value[0], WebWindow):
+ assert value[0].id in session.handles
+ else:
+ assert value[0].id not in session.handles
+
+
+@pytest.mark.parametrize("expression, expected_type", [
+ ("window.frames[0]", WebFrame),
+ ("window", WebWindow),
+], ids=["frame", "window"])
+def test_web_reference_in_object(session, get_test_page, expression, expected_type):
+ session.url = get_test_page()
+
+ result = execute_script(session, f"""return {{"ref": {expression}}}""")
+ reference = assert_success(result)
+
+ assert isinstance(reference["ref"], expected_type)
+
+ if isinstance(reference["ref"], WebWindow):
+ assert reference["ref"].id in session.handles
+ else:
+ assert reference["ref"].id not in session.handles
+
+
+def test_window_open(session):
+ result = execute_script(session, "window.foo = window.open(); return window.foo;")
+ reference = assert_success(result)
+
+ assert isinstance(reference, WebWindow)
+ assert reference.id in session.handles
+
+
+def test_same_id_after_cross_origin_navigation(session, get_test_page):
+ params = {"pipe": "header(Cross-Origin-Opener-Policy,same-origin)"}
+
+ first_page = get_test_page(parameters=params, protocol="https")
+ second_page = get_test_page(parameters=params, protocol="https", domain="alt")
+
+ session.url = first_page
+
+ result = execute_script(session, "return window")
+ window_before = assert_success(result)
+
+ session.url = second_page
+
+ result = execute_script(session, "return window")
+ window_after = assert_success(result)
+
+ assert window_before == window_after
diff --git a/webdriver/tests/classic/find_element_from_shadow_root/find.py b/webdriver/tests/classic/find_element_from_shadow_root/find.py
index 3f1b64a..c658152 100644
--- a/webdriver/tests/classic/find_element_from_shadow_root/find.py
+++ b/webdriver/tests/classic/find_element_from_shadow_root/find.py
@@ -1,5 +1,5 @@
import pytest
-from webdriver.client import Element, ShadowRoot
+from webdriver.client import WebElement, ShadowRoot
from webdriver.transport import Response
from tests.support.asserts import assert_error, assert_same_element, assert_success
@@ -174,7 +174,7 @@
result = find_element(session, shadow_root.id, using, value)
value = assert_success(result)
- element = Element.from_json(value, session)
+ element = WebElement.from_json(value, session)
assert element.text == expected_text
@@ -243,5 +243,5 @@
result = find_element(session, nested_shadow_root.id, "css selector", "#linkText")
value = assert_success(result)
- element = Element.from_json(value, session)
+ element = WebElement.from_json(value, session)
assert element.text == expected_text
diff --git a/webdriver/tests/classic/find_elements_from_shadow_root/find.py b/webdriver/tests/classic/find_elements_from_shadow_root/find.py
index ffdaa7e..188fff2 100644
--- a/webdriver/tests/classic/find_elements_from_shadow_root/find.py
+++ b/webdriver/tests/classic/find_elements_from_shadow_root/find.py
@@ -1,5 +1,5 @@
import pytest
-from webdriver.client import Element, ShadowRoot
+from webdriver.client import WebElement, ShadowRoot
from webdriver.transport import Response
from tests.support.asserts import assert_error, assert_same_element, assert_success
@@ -177,7 +177,7 @@
assert len(value) == 1
- element = Element.from_json(value[0], session)
+ element = WebElement.from_json(value[0], session)
assert element.text == expected_text
@@ -256,5 +256,5 @@
assert len(value) == 1
- element = Element.from_json(value[0], session)
+ element = WebElement.from_json(value[0], session)
assert element.text == expected_text
diff --git a/webdriver/tests/classic/get_computed_label/get.py b/webdriver/tests/classic/get_computed_label/get.py
index 0dc00a4..e023b79 100644
--- a/webdriver/tests/classic/get_computed_label/get.py
+++ b/webdriver/tests/classic/get_computed_label/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from webdriver.error import NoSuchAlertException
from tests.support.asserts import assert_error, assert_success
@@ -19,7 +19,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
result = get_computed_label(session, element.id)
assert_error(result, "no such element")
diff --git a/webdriver/tests/classic/get_computed_role/get.py b/webdriver/tests/classic/get_computed_role/get.py
index 51b6a8b..1b84896 100644
--- a/webdriver/tests/classic/get_computed_role/get.py
+++ b/webdriver/tests/classic/get_computed_role/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from webdriver.error import NoSuchAlertException
from tests.support.asserts import assert_error, assert_success
@@ -19,7 +19,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
result = get_computed_role(session, element.id)
assert_error(result, "no such element")
diff --git a/webdriver/tests/classic/get_element_attribute/get.py b/webdriver/tests/classic/get_element_attribute/get.py
index 375f250..0fcfd00 100644
--- a/webdriver/tests/classic/get_element_attribute/get.py
+++ b/webdriver/tests/classic/get_element_attribute/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
@@ -30,7 +30,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = get_element_attribute(session, element.id, "id")
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/get_element_css_value/get.py b/webdriver/tests/classic/get_element_css_value/get.py
index 6f0a8a5..1f6f571 100644
--- a/webdriver/tests/classic/get_element_css_value/get.py
+++ b/webdriver/tests/classic/get_element_css_value/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
@@ -34,7 +34,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = get_element_css_value(session, element.id, "display")
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/get_element_property/get.py b/webdriver/tests/classic/get_element_property/get.py
index bb63481..12d48a3 100644
--- a/webdriver/tests/classic/get_element_property/get.py
+++ b/webdriver/tests/classic/get_element_property/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element, Frame, ShadowRoot, Window
+from webdriver import WebElement, WebFrame, ShadowRoot, WebWindow
from tests.support.asserts import assert_error, assert_same_element, assert_success
@@ -31,7 +31,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = get_element_property(session, element.id, "id")
assert_error(response, "no such element")
@@ -165,10 +165,10 @@
@pytest.mark.parametrize("js_web_reference,py_web_reference", [
- ("element", Element),
- ("frame", Frame),
+ ("element", WebElement),
+ ("frame", WebFrame),
("shadowRoot", ShadowRoot),
- ("window", Window),
+ ("window", WebWindow),
])
def test_web_reference(session, get_test_page, js_web_reference, py_web_reference):
session.url = get_test_page()
diff --git a/webdriver/tests/classic/get_element_rect/get.py b/webdriver/tests/classic/get_element_rect/get.py
index 942f119..959ccc4 100644
--- a/webdriver/tests/classic/get_element_rect/get.py
+++ b/webdriver/tests/classic/get_element_rect/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
from tests.support.helpers import element_rect
@@ -34,7 +34,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = get_element_rect(session, element.id)
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/get_element_shadow_root/get.py b/webdriver/tests/classic/get_element_shadow_root/get.py
index d9adde0..25e68c1 100644
--- a/webdriver/tests/classic/get_element_shadow_root/get.py
+++ b/webdriver/tests/classic/get_element_shadow_root/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_same_element, assert_success
@@ -30,7 +30,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = get_shadow_root(session, element.id)
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/get_element_tag_name/get.py b/webdriver/tests/classic/get_element_tag_name/get.py
index 3bb03d7..d8bb3ac 100644
--- a/webdriver/tests/classic/get_element_tag_name/get.py
+++ b/webdriver/tests/classic/get_element_tag_name/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
@@ -30,7 +30,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = get_element_tag_name(session, element.id)
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/get_element_text/get.py b/webdriver/tests/classic/get_element_text/get.py
index e8d559c..2a2363c 100644
--- a/webdriver/tests/classic/get_element_text/get.py
+++ b/webdriver/tests/classic/get_element_text/get.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
@@ -30,7 +30,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = get_element_text(session, element.id)
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/is_element_enabled/enabled.py b/webdriver/tests/classic/is_element_enabled/enabled.py
index fccff38..24fc85f 100644
--- a/webdriver/tests/classic/is_element_enabled/enabled.py
+++ b/webdriver/tests/classic/is_element_enabled/enabled.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
@@ -33,7 +33,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = is_element_enabled(session, element.id)
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/is_element_selected/selected.py b/webdriver/tests/classic/is_element_selected/selected.py
index 1fb5b9c..bf650de 100644
--- a/webdriver/tests/classic/is_element_selected/selected.py
+++ b/webdriver/tests/classic/is_element_selected/selected.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
@@ -49,7 +49,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = is_element_selected(session, element.id)
assert_error(response, "no such element")
diff --git a/webdriver/tests/classic/take_element_screenshot/screenshot.py b/webdriver/tests/classic/take_element_screenshot/screenshot.py
index ea4cc29..fdc0d65 100644
--- a/webdriver/tests/classic/take_element_screenshot/screenshot.py
+++ b/webdriver/tests/classic/take_element_screenshot/screenshot.py
@@ -1,6 +1,6 @@
import pytest
-from webdriver import Element
+from webdriver import WebElement
from tests.support.asserts import assert_error, assert_success
from tests.support.image import png_dimensions
@@ -33,7 +33,7 @@
def test_no_such_element_with_invalid_value(session):
- element = Element(session, "foo")
+ element = WebElement(session, "foo")
response = take_element_screenshot(session, element.id)
assert_error(response, "no such element")
diff --git a/webdriver/tests/support/asserts.py b/webdriver/tests/support/asserts.py
index 04bd199..9d31ff7 100644
--- a/webdriver/tests/support/asserts.py
+++ b/webdriver/tests/support/asserts.py
@@ -1,7 +1,7 @@
import imghdr
from base64 import decodebytes
-from webdriver import Element, NoSuchAlertException, WebDriverException
+from webdriver import NoSuchAlertException, WebDriverException, WebElement
# WebDriver specification ID: dfn-error-response-data
@@ -148,17 +148,17 @@
def assert_same_element(session, a, b):
"""Verify that two element references describe the same element."""
if isinstance(a, dict):
- assert Element.identifier in a, "Actual value does not describe an element"
- a_id = a[Element.identifier]
- elif isinstance(a, Element):
+ assert WebElement.identifier in a, "Actual value does not describe an element"
+ a_id = a[WebElement.identifier]
+ elif isinstance(a, WebElement):
a_id = a.id
else:
raise AssertionError("Actual value is not a dictionary or web element")
if isinstance(b, dict):
- assert Element.identifier in b, "Expected value does not describe an element"
- b_id = b[Element.identifier]
- elif isinstance(b, Element):
+ assert WebElement.identifier in b, "Expected value does not describe an element"
+ b_id = b[WebElement.identifier]
+ elif isinstance(b, WebElement):
b_id = b.id
else:
raise AssertionError("Expected value is not a dictionary or web element")