Skip to content

Commit

Permalink
Automate tap action on an element in an iframe (web-platform-tests#17260
Browse files Browse the repository at this point in the history
)
  • Loading branch information
LanWei22 authored and natechapin committed Aug 23, 2019
1 parent e77962a commit 22f38fb
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 13 deletions.
14 changes: 11 additions & 3 deletions tools/webdriver/webdriver/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,12 @@ def perform(self, actions=None):
``ActionSequence.dict``.
"""
body = {"actions": [] if actions is None else actions}
return self.session.send_session_command("POST", "actions", body)
actions = self.session.send_session_command("POST", "actions", body)
"""WebDriver window should be set to the top level window when wptrunner
processes the next event.
"""
self.session.switch_frame(None)
return actions

@command
def release(self):
Expand Down Expand Up @@ -308,8 +313,11 @@ def __init__(self, session):
self.session = session

@command
def css(self, selector, all=True):
return self._find_element("css selector", selector, all)
def css(self, element_selector, frame, all=True):
if (frame != "window"):
self.session.switch_frame(frame)
elements = self._find_element("css selector", element_selector, all)
return elements

def _find_element(self, strategy, selector, all):
route = "elements" if all else "element"
Expand Down
6 changes: 3 additions & 3 deletions tools/wptrunner/wptrunner/executors/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,11 +669,11 @@ def __call__(self, payload):
for action in actionSequence["actions"]:
if (action["type"] == "pointerMove" and
isinstance(action["origin"], dict)):
action["origin"] = self.get_element(action["origin"]["selector"])
action["origin"] = self.get_element(action["origin"]["selector"], action["frame"]["frame"])
self.protocol.action_sequence.send_actions({"actions": actions})

def get_element(self, selector):
element = self.protocol.select.element_by_selector(selector)
def get_element(self, element_selector, frame):
element = self.protocol.select.element_by_selector(element_selector, frame)
return element

class GenerateTestReportAction(object):
Expand Down
3 changes: 3 additions & 0 deletions tools/wptrunner/wptrunner/executors/executormarionette.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ def setup(self):
def elements_by_selector(self, selector):
return self.marionette.find_elements("css selector", selector)

def elements_by_selector_and_frame(self, element_selector, frame):
return self.marionette.find_elements("css selector", element_selector)


class MarionetteClickProtocolPart(ClickProtocolPart):
def setup(self):
Expand Down
3 changes: 3 additions & 0 deletions tools/wptrunner/wptrunner/executors/executorselenium.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ def setup(self):
def elements_by_selector(self, selector):
return self.webdriver.find_elements_by_css_selector(selector)

def elements_by_selector_and_frame(self, element_selector, frame):
return self.webdriver.find_elements_by_css_selector(element_selector)


class SeleniumClickProtocolPart(ClickProtocolPart):
def setup(self):
Expand Down
3 changes: 3 additions & 0 deletions tools/wptrunner/wptrunner/executors/executorwebdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ def setup(self):
def elements_by_selector(self, selector):
return self.webdriver.find.css(selector)

def elements_by_selector_and_frame(self, element_selector, frame):
return self.webdriver.find.css(element_selector, frame)


class WebDriverClickProtocolPart(ClickProtocolPart):
def setup(self):
Expand Down
18 changes: 14 additions & 4 deletions tools/wptrunner/wptrunner/executors/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,15 @@ class SelectorProtocolPart(ProtocolPart):

name = "select"

def element_by_selector(self, selector):
elements = self.elements_by_selector(selector)
def element_by_selector(self, element_selector, frame="window"):
elements = self.elements_by_selector_and_frame(element_selector, frame)
frame_name = "window"
if (frame != "window"):
frame_name = frame.id
if len(elements) == 0:
raise ValueError("Selector '%s' matches no elements" % selector)
raise ValueError("Selector '%s' in frame '%s' matches no elements" % (element_selector, frame_name))
elif len(elements) > 1:
raise ValueError("Selector '%s' matches multiple elements" % selector)
raise ValueError("Selector '%s' in frame '%s' matches multiple elements" % (element_selector, frame_name))
return elements[0]

@abstractmethod
Expand All @@ -251,6 +254,13 @@ def elements_by_selector(self, selector):
:returns: A list of protocol-specific handles to elements"""
pass

@abstractmethod
def elements_by_selector_and_frame(self, element_selector, frame):
"""Select elements matching a CSS selector
:param str selector: The CSS selector
:returns: A list of protocol-specific handles to elements"""
pass


class ClickProtocolPart(ProtocolPart):
"""Protocol part for performing trusted clicks"""
Expand Down
30 changes: 27 additions & 3 deletions tools/wptrunner/wptrunner/testdriver-extra.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,26 @@
}
});

const get_frame = function(element, frame) {
let foundFrame = frame;
let frameDocument = frame == window ? window.document : frame.contentDocument;
if (!frameDocument.contains(element)) {
foundFrame = null;
let frames = document.getElementsByTagName("iframe");
for (let i = 0; i < frames.length; i++) {
if (get_frame(element, frames[i])) {
foundFrame = frames[i];
break;
}
}
}
return foundFrame;
};

const get_selector = function(element) {
let selector;

if (element.id && document.getElementById(element.id) === element) {
if (element.id) {
const id = element.id;

selector = "#";
Expand Down Expand Up @@ -81,8 +97,16 @@
for (let actionSequence of actions) {
if (actionSequence.type == "pointer") {
for (let action of actionSequence.actions) {
if (action.type == "pointerMove" && action.origin instanceof Element) {
action.origin = {selector: get_selector(action.origin)};
// The origin of each action can only be an element or a string of a value "viewport" or "pointer".
if (action.type == "pointerMove" && typeof(action.origin) != 'string') {
let frame = get_frame(action.origin, window);
if (frame != null) {
if (frame == window)
action.frame = {frame: "window"};
else
action.frame = {frame: frame};
action.origin = {selector: get_selector(action.origin)};
}
}
}
}
Expand Down

0 comments on commit 22f38fb

Please sign in to comment.