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:
Henrik Skupin 2019-10-28 18:31:17 +00:00
Родитель a5b86e1d96
Коммит e8f5161a31
12 изменённых файлов: 8 добавлений и 286 удалений

Просмотреть файл

@ -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) {