зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1587627 - [marionette] Remove `Anon` and `AnonAttribute` strategies from "WebDriver:FindElement" and "WebDriver:FindElements" command. r=webdriver-reviewers,maja_zf
Differential Revision: https://phabricator.services.mozilla.com/D50804 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a5b86e1d96
Коммит
e8f5161a31
|
@ -172,7 +172,6 @@ var whitelist = [
|
|||
// Bug 1356031 (only used by devtools)
|
||||
{ file: "chrome://global/skin/icons/error-16.png" },
|
||||
// Bug 1344267
|
||||
{ file: "chrome://marionette/content/test_anonymous_content.xul" },
|
||||
{ file: "chrome://marionette/content/test_dialog.properties" },
|
||||
{ file: "chrome://marionette/content/test_dialog.xul" },
|
||||
// Bug 1348533
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE dialog [
|
||||
]>
|
||||
|
||||
<dialog id="testDialogAnonymousNode"
|
||||
buttons="accept, cancel"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<bindings id="testBindings" xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<binding id="framebox">
|
||||
<content orient="vertical" mousethrough="never">
|
||||
<xul:browser anonid="content" id="browser" flex="1"
|
||||
context="contentAreaContextMenu"
|
||||
src="test.xul"
|
||||
type="content"/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="iframebox">
|
||||
<content>
|
||||
<xul:box>
|
||||
<xul:iframe anonid="iframe" src="chrome://marionette/content/test.xul"></xul:iframe>
|
||||
</xul:box>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="buttonbox">
|
||||
<content>
|
||||
<xul:box anonid="buttons">
|
||||
<xul:button dlgtype="cancel" class="dialog-button"/>
|
||||
<xul:button dlgtype="accept" class="dialog-button"/>
|
||||
</xul:box>
|
||||
<xul:vbox></xul:vbox>
|
||||
<xul:vbox></xul:vbox>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
||||
|
||||
<hbox id="testAnonymousContentBox"/>
|
||||
<hbox id="container" style="-moz-binding: url('#testBindings');"/>
|
||||
<hbox id="container2" style="-moz-binding: url('#iframebox');"/>
|
||||
<hbox id="container3" style="-moz-binding: url('#buttonbox');"/>
|
||||
|
||||
</dialog>
|
|
@ -85,42 +85,3 @@ Doing the following will work::
|
|||
But this will raise a `NoSuchElementException`::
|
||||
|
||||
client.find_element(By.ID, 'container').find_element(By.ID, 'footer')
|
||||
|
||||
|
||||
Finding Anonymous Nodes
|
||||
-----------------------
|
||||
|
||||
When working in chrome scope, for example manipulating the Firefox user
|
||||
interface, you may run into something called an anonymous node.
|
||||
|
||||
Firefox uses a markup language called XUL_ for its interface. XUL is similar
|
||||
to HTML in that it has a DOM and tags that render controls on the display. One
|
||||
ability of XUL is to create re-useable widgets that are made up out of several
|
||||
smaller XUL elements. These widgets can be bound to the DOM using something
|
||||
called the `XML binding language (XBL)`_.
|
||||
|
||||
The end result is that the DOM sees the widget as a single entity. It doesn't
|
||||
know anything about how that widget is made up. All of the smaller XUL elements
|
||||
that make up the widget are called `anonymous content`_. It is not possible to
|
||||
query such elements using traditional DOM methods like `getElementById`.
|
||||
|
||||
Marionette provides two special strategies used for finding anonymous content.
|
||||
Unlike normal elements, anonymous nodes can only be seen by their parent. So
|
||||
it's necessary to first find the parent element and then search for the
|
||||
anonymous children from there.
|
||||
|
||||
* `anon` - Finds all anonymous children of the element, there is no search term
|
||||
so `None` must be passed in::
|
||||
|
||||
anon_children = client.find_element('id', 'parent').find_elements('anon', None)
|
||||
|
||||
* `anon attribute` - Find an anonymous child based on an attribute. An
|
||||
unofficial convention is for anonymous nodes to have an
|
||||
`anonid` attribute::
|
||||
|
||||
anon_child = client.find_element('id', 'parent').find_element('anon attribute', {'anonid': 'container'})
|
||||
|
||||
|
||||
.. _XUL: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL
|
||||
.. _XML binding language (XBL): https://developer.mozilla.org/en-US/docs/XBL
|
||||
.. _anonymous content: https://developer.mozilla.org/en-US/docs/XBL/XBL_1.0_Reference/Anonymous_Content
|
||||
|
|
|
@ -25,5 +25,3 @@ class By(object):
|
|||
TAG_NAME = "tag name"
|
||||
CLASS_NAME = "class name"
|
||||
CSS_SELECTOR = "css selector"
|
||||
ANON_ATTRIBUTE = "anon attribute"
|
||||
ANON = "anon"
|
||||
|
|
|
@ -1677,9 +1677,9 @@ class Marionette(object):
|
|||
|
||||
:param method: The method to use to locate the element; one of:
|
||||
"id", "name", "class name", "tag name", "css selector",
|
||||
"link text", "partial link text", "xpath", "anon" and "anon
|
||||
attribute". Note that the "name", "link text" and "partial
|
||||
link test" methods are not supported in the chrome DOM.
|
||||
"link text", "partial link text" and "xpath".
|
||||
Note that the "name", "link text" and "partial link test"
|
||||
methods are not supported in the chrome DOM.
|
||||
:param target: The target of the search. For example, if method =
|
||||
"tag", target might equal "div". If method = "id", target would
|
||||
be an element id.
|
||||
|
@ -1707,9 +1707,9 @@ class Marionette(object):
|
|||
|
||||
:param method: The method to use to locate the elements; one
|
||||
of: "id", "name", "class name", "tag name", "css selector",
|
||||
"link text", "partial link text", "xpath", "anon" and "anon
|
||||
attribute". Note that the "name", "link text" and "partial link
|
||||
test" methods are not supported in the chrome DOM.
|
||||
"link text", "partial link text" and "xpath".
|
||||
Note that the "name", "link text" and "partial link test"
|
||||
methods are not supported in the chrome DOM.
|
||||
:param target: The target of the search. For example, if method =
|
||||
"tag", target might equal "div". If method = "id", target would be
|
||||
an element id.
|
||||
|
|
|
@ -26,10 +26,6 @@ element.findByPartialLinkText
|
|||
-----------------------------
|
||||
.. js:autofunction:: element.findByPartialLinkText
|
||||
|
||||
element.findAnonymousNodes
|
||||
----------------------------
|
||||
.. js:autofunction:: element.findAnonymousNodes
|
||||
|
||||
element.findClosest
|
||||
-------------------
|
||||
.. js:autofunction:: element.findClosest
|
||||
|
|
|
@ -97,8 +97,6 @@ const SUPPORTED_STRATEGIES = new Set([
|
|||
element.Strategy.ID,
|
||||
element.Strategy.TagName,
|
||||
element.Strategy.XPath,
|
||||
element.Strategy.Anon,
|
||||
element.Strategy.AnonAttribute,
|
||||
]);
|
||||
|
||||
// Timeout used to abort fullscreen, maximize, and minimize
|
||||
|
@ -1804,37 +1802,6 @@ GeckoDriver.prototype.switchToFrame = async function(cmd) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Check if the frame is XBL anonymous
|
||||
let parent = curWindow.document.getBindingParent(wantedFrame);
|
||||
// Shadow nodes also show up in getAnonymousNodes, we should
|
||||
// ignore them.
|
||||
if (
|
||||
parent &&
|
||||
!(parent.shadowRoot && parent.shadowRoot.contains(wantedFrame))
|
||||
) {
|
||||
const doc = curWindow.document;
|
||||
let anonNodes = [...(doc.getAnonymousNodes(parent) || [])];
|
||||
if (anonNodes.length > 0) {
|
||||
let el = wantedFrame;
|
||||
while (el) {
|
||||
if (anonNodes.indexOf(el) > -1) {
|
||||
curWindow = wantedFrame.contentWindow;
|
||||
this.curFrame = curWindow;
|
||||
if (focus) {
|
||||
this.curFrame.focus();
|
||||
}
|
||||
checkTimer.initWithCallback(
|
||||
checkLoad.bind(this),
|
||||
100,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT
|
||||
);
|
||||
return;
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// else, assume iframe
|
||||
let frames = curWindow.document.getElementsByTagName("iframe");
|
||||
let numFrames = frames.length;
|
||||
|
|
|
@ -82,8 +82,6 @@ element.Strategy = {
|
|||
PartialLinkText: "partial link text",
|
||||
TagName: "tag name",
|
||||
XPath: "xpath",
|
||||
Anon: "anon",
|
||||
AnonAttribute: "anon attribute",
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -329,17 +327,7 @@ element.find = function(container, strategy, selector, opts = {}) {
|
|||
// the following code ought to be moved into findElement
|
||||
// and findElements when bug 1254486 is addressed
|
||||
if (!opts.all && (!foundEls || foundEls.length == 0)) {
|
||||
let msg;
|
||||
switch (strategy) {
|
||||
case element.Strategy.AnonAttribute:
|
||||
msg =
|
||||
"Unable to locate anonymous element: " + JSON.stringify(selector);
|
||||
break;
|
||||
|
||||
default:
|
||||
msg = "Unable to locate element: " + selector;
|
||||
}
|
||||
|
||||
let msg = `Unable to locate element: ${selector}`;
|
||||
reject(new NoSuchElementError(msg));
|
||||
}
|
||||
|
||||
|
@ -361,19 +349,7 @@ function find_(
|
|||
let rootNode = container.shadowRoot || container.frame.document;
|
||||
|
||||
if (!startNode) {
|
||||
switch (strategy) {
|
||||
// For anonymous nodes the start node needs to be of type
|
||||
// DOMElement, which will refer to :root in case of a DOMDocument.
|
||||
case element.Strategy.Anon:
|
||||
case element.Strategy.AnonAttribute:
|
||||
if (rootNode.nodeType == rootNode.DOCUMENT_NODE) {
|
||||
startNode = rootNode.documentElement;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
startNode = rootNode;
|
||||
}
|
||||
startNode = rootNode;
|
||||
}
|
||||
|
||||
let res;
|
||||
|
@ -484,24 +460,6 @@ element.findByPartialLinkText = function(startNode, linkText) {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Find anonymous nodes of <var>node</var>.
|
||||
*
|
||||
* @param {HTMLDocument} document
|
||||
* Root node of the document.
|
||||
* @param {XULElement} node
|
||||
* Where in the DOM hierarchy to begin searching.
|
||||
*
|
||||
* @return {Iterable.<XULElement>}
|
||||
* Iterator over anonymous elements.
|
||||
*/
|
||||
element.findAnonymousNodes = function*(document, node) {
|
||||
let anons = document.getAnonymousNodes(node) || [];
|
||||
for (let node of anons) {
|
||||
yield node;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Filters all hyperlinks that are descendant of <var>startNode</var>
|
||||
* by <var>predicate</var>.
|
||||
|
@ -592,17 +550,6 @@ function findElement(strategy, selector, document, startNode = undefined) {
|
|||
} catch (e) {
|
||||
throw new InvalidSelectorError(`${e.message}: "${selector}"`);
|
||||
}
|
||||
|
||||
case element.Strategy.Anon:
|
||||
return element.findAnonymousNodes(document, startNode).next().value;
|
||||
|
||||
case element.Strategy.AnonAttribute:
|
||||
let attr = Object.keys(selector)[0];
|
||||
return document.getAnonymousElementByAttribute(
|
||||
startNode,
|
||||
attr,
|
||||
selector[attr]
|
||||
);
|
||||
}
|
||||
|
||||
throw new InvalidSelectorError(`No such strategy: ${strategy}`);
|
||||
|
@ -664,21 +611,6 @@ function findElements(strategy, selector, document, startNode = undefined) {
|
|||
case element.Strategy.Selector:
|
||||
return startNode.querySelectorAll(selector);
|
||||
|
||||
case element.Strategy.Anon:
|
||||
return [...element.findAnonymousNodes(document, startNode)];
|
||||
|
||||
case element.Strategy.AnonAttribute:
|
||||
let attr = Object.keys(selector)[0];
|
||||
let el = document.getAnonymousElementByAttribute(
|
||||
startNode,
|
||||
attr,
|
||||
selector[attr]
|
||||
);
|
||||
if (el) {
|
||||
return [el];
|
||||
}
|
||||
return [];
|
||||
|
||||
default:
|
||||
throw new InvalidSelectorError(`No such strategy: ${strategy}`);
|
||||
}
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from marionette_driver.by import By
|
||||
from marionette_driver.errors import NoSuchElementException
|
||||
from marionette_driver.marionette import HTMLElement
|
||||
|
||||
from marionette_harness import MarionetteTestCase, WindowManagerMixin
|
||||
|
||||
|
||||
class TestAnonymousNodes(WindowManagerMixin, MarionetteTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestAnonymousNodes, self).setUp()
|
||||
self.marionette.set_context("chrome")
|
||||
|
||||
url = "chrome://marionette/content/test_anonymous_content.xul"
|
||||
new_window = self.open_chrome_window(url)
|
||||
self.marionette.switch_to_window(new_window)
|
||||
|
||||
def tearDown(self):
|
||||
self.close_all_windows()
|
||||
|
||||
super(TestAnonymousNodes, self).tearDown()
|
||||
|
||||
def test_switch_to_anonymous_frame(self):
|
||||
self.marionette.find_element(By.ID, "testAnonymousContentBox")
|
||||
anon_browser_el = self.marionette.find_element(By.ID, "browser")
|
||||
self.assertTrue("test_anonymous_content.xul" in self.marionette.get_url())
|
||||
self.marionette.switch_to_frame(anon_browser_el)
|
||||
self.assertTrue("test.xul" in self.marionette.get_url())
|
||||
self.marionette.find_element(By.ID, "testXulBox")
|
||||
self.assertRaises(NoSuchElementException,
|
||||
self.marionette.find_element, By.ID, "testAnonymousContentBox")
|
||||
|
||||
def test_switch_to_anonymous_iframe(self):
|
||||
self.marionette.find_element(By.ID, "testAnonymousContentBox")
|
||||
el = self.marionette.find_element(By.ID, "container2")
|
||||
anon_iframe_el = el.find_element(By.ANON_ATTRIBUTE, {"anonid": "iframe"})
|
||||
self.marionette.switch_to_frame(anon_iframe_el)
|
||||
self.assertTrue("test.xul" in self.marionette.get_url())
|
||||
self.marionette.find_element(By.ID, "testXulBox")
|
||||
self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID,
|
||||
"testAnonymousContentBox")
|
||||
|
||||
def test_find_anonymous_element_by_attribute(self):
|
||||
accept_button = (By.ANON_ATTRIBUTE, {"dlgtype": "accept"},)
|
||||
not_existent = (By.ANON_ATTRIBUTE, {"anonid": "notexistent"},)
|
||||
|
||||
# By using the window document element
|
||||
start_node = self.marionette.find_element(By.ID, "container3")
|
||||
button = start_node.find_element(*accept_button)
|
||||
self.assertEquals(HTMLElement, type(button))
|
||||
with self.assertRaises(NoSuchElementException):
|
||||
start_node.find_element(*not_existent)
|
||||
|
||||
def test_find_anonymous_elements_by_attribute(self):
|
||||
dialog_buttons = (By.ANON_ATTRIBUTE, {"anonid": "buttons"},)
|
||||
not_existent = (By.ANON_ATTRIBUTE, {"anonid": "notexistent"},)
|
||||
|
||||
start_node = self.marionette.find_element(By.ID, "container3")
|
||||
buttons = start_node.find_elements(*dialog_buttons)
|
||||
self.assertEquals(1, len(buttons))
|
||||
self.assertEquals(HTMLElement, type(buttons[0]))
|
||||
self.assertListEqual([], start_node.find_elements(*not_existent))
|
||||
|
||||
def test_find_anonymous_children(self):
|
||||
start_node = self.marionette.find_element(By.ID, "container3")
|
||||
self.assertEquals(HTMLElement, type(start_node.find_element(By.ANON, None)))
|
||||
self.assertEquals(3, len(start_node.find_elements(By.ANON, None)))
|
||||
|
||||
frame = self.marionette.find_element(By.ID, "framebox")
|
||||
with self.assertRaises(NoSuchElementException):
|
||||
frame.find_element(By.ANON, None)
|
||||
self.assertListEqual([], frame.find_elements(By.ANON, None))
|
|
@ -34,8 +34,6 @@ expected = fail
|
|||
[test_navigation.py]
|
||||
[test_timeouts.py]
|
||||
|
||||
[test_anonymous_content.py]
|
||||
skip-if = !xbl
|
||||
[test_switch_frame.py]
|
||||
[test_switch_frame_chrome.py]
|
||||
[test_switch_window_chrome.py]
|
||||
|
|
|
@ -40,7 +40,6 @@ marionette.jar:
|
|||
content/transport.js (transport.js)
|
||||
#ifdef ENABLE_TESTS
|
||||
content/test2.xul (chrome/test2.xul)
|
||||
content/test_anonymous_content.xul (chrome/test_anonymous_content.xul)
|
||||
content/test_dialog.dtd (chrome/test_dialog.dtd)
|
||||
content/test_dialog.properties (chrome/test_dialog.properties)
|
||||
content/test_dialog.xul (chrome/test_dialog.xul)
|
||||
|
|
|
@ -157,7 +157,6 @@ reftest.Runner = class {
|
|||
browser = reftestWin.document.createElementNS(XUL_NS, "xul:browser");
|
||||
browser.permanentKey = {};
|
||||
browser.setAttribute("id", "browser");
|
||||
browser.setAttribute("anonid", "initialBrowser");
|
||||
browser.setAttribute("type", "content");
|
||||
browser.setAttribute("primary", "true");
|
||||
if (this.remote) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче