Bug 1080764 - Add 'anon' and 'anon attribute' search strategies to marionette.find_element(), r=AutomatedTester

The 'anon' search strategy maps directly to nsIXULDocument.getAnonymousNodes() whereas the 'anon attribute'
strategy maps to nsIXULDocument.getAnonymousElementByAttribute(). These strategies are needed for clients who
wish to find and manipulate anonymous content, typically found in the Firefox chrome. For more details, see:
https://developer.mozilla.org/en-US/docs/XBL/XBL_1.0_Reference/Anonymous_Content

--HG--
rename : testing/marionette/client/marionette/tests/unit/test_switch_anonymous_content.py => testing/marionette/client/marionette/tests/unit/test_anonymous_content.py
This commit is contained in:
Andrew Halberstadt 2014-10-28 17:37:24 -04:00
parent 4aba8d9b17
commit 9386537f22
4 changed files with 74 additions and 19 deletions

View File

@ -1281,14 +1281,15 @@ class Marionette(object):
NoSuchElementException will be raised.
: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" and "xpath". Note that the methods supported in
the chrome dom are only "id", "class name", "tag name" and "xpath".
"name", "class name", "tag name", "css selector", "link text",
"partial link text", "xpath", "anon" and "anon attribute".
Note that the "name", "css selector", "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.
"tag", target might equal "div". If method = "id", target would be
an element id.
:param id: If specified, search for elements only inside the element
with the specified id.
with the specified id.
'''
kwargs = { 'value': target, 'using': method }
if id:
@ -1307,14 +1308,15 @@ class Marionette(object):
time set by set_search_timeout().
: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" and "xpath". Note that the methods supported in
the chrome dom are only "id", "class name", "tag name" and "xpath".
"id", "name", "class name", "tag name", "css selector", "link text",
"partial link text", "xpath", "anon" and "anon attribute".
Note that the "name", "css selector", "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.
"tag", target might equal "div". If method = "id", target would be
an element id.
:param id: If specified, search for elements only inside the element
with the specified id.
with the specified id.
'''
kwargs = { 'value': target, 'using': method }
if id:

View File

@ -2,10 +2,13 @@
# 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 marionette import HTMLElement
from marionette_test import MarionetteTestCase
from errors import JavascriptException, NoSuchElementException
from errors import NoSuchElementException
from expected import element_present
from wait import Wait
class TestSwitchFrameChrome(MarionetteTestCase):
class TestAnonymousContent(MarionetteTestCase):
def setUp(self):
MarionetteTestCase.setUp(self)
self.marionette.set_context("chrome")
@ -20,7 +23,7 @@ class TestSwitchFrameChrome(MarionetteTestCase):
self.marionette.switch_to_window(self.win)
MarionetteTestCase.tearDown(self)
def test_switch(self):
def test_switch_to_anonymous_frame(self):
self.marionette.find_element("id", "testAnonymousContentBox")
anon_browser_el = self.marionette.find_element("id", "browser")
self.assertTrue("test_anonymous_content.xul" in self.marionette.get_url())
@ -28,3 +31,22 @@ class TestSwitchFrameChrome(MarionetteTestCase):
self.assertTrue("test.xul" in self.marionette.get_url())
self.marionette.find_element("id", "testXulBox")
self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "testAnonymousContentBox")
def test_find_anonymous_element_by_attribute(self):
el = Wait(self.marionette).until(element_present("id", "dia"))
self.assertEquals(HTMLElement, type(el.find_element("anon attribute", {"anonid": "buttons"})))
self.assertEquals(1, len(el.find_elements("anon attribute", {"anonid": "buttons"})))
with self.assertRaises(NoSuchElementException):
el.find_element("anon attribute", {"anonid": "nonexistent"})
self.assertEquals([], el.find_elements("anon attribute", {"anonid": "nonexistent"}))
def test_find_anonymous_children(self):
el = Wait(self.marionette).until(element_present("id", "dia"))
self.assertEquals(HTMLElement, type(el.find_element("anon", None)))
self.assertEquals(2, len(el.find_elements("anon", None)))
el = self.marionette.find_element("id", "framebox")
with self.assertRaises(NoSuchElementException):
el.find_element("anon", None)
self.assertEquals([], el.find_elements("anon", None))

View File

@ -87,7 +87,7 @@ browser = false
[test_simpletest_chrome.js]
[test_simpletest_timeout.js]
[test_specialpowers.py]
[test_switch_anonymous_content.py]
[test_anonymous_content.py]
[test_switch_frame.py]
b2g = false
skip-if = os == "win" # Bug 1078237

View File

@ -20,7 +20,9 @@ this.EXPORTED_SYMBOLS = [
"LINK_TEXT",
"PARTIAL_LINK_TEXT",
"TAG",
"XPATH"
"XPATH",
"ANON",
"ANON_ATTRIBUTE"
];
const DOCUMENT_POSITION_DISCONNECTED = 1;
@ -36,6 +38,8 @@ this.LINK_TEXT = "link text";
this.PARTIAL_LINK_TEXT = "partial link text";
this.TAG = "tag name";
this.XPATH = "xpath";
this.ANON= "anon";
this.ANON_ATTRIBUTE = "anon attribute";
function ElementException(msg, num, stack) {
this.message = msg;
@ -46,7 +50,7 @@ function ElementException(msg, num, stack) {
this.ElementManager = function ElementManager(notSupported) {
this.seenItems = {};
this.timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
this.elementStrategies = [CLASS_NAME, SELECTOR, ID, NAME, LINK_TEXT, PARTIAL_LINK_TEXT, TAG, XPATH];
this.elementStrategies = [CLASS_NAME, SELECTOR, ID, NAME, LINK_TEXT, PARTIAL_LINK_TEXT, TAG, XPATH, ANON, ANON_ATTRIBUTE];
for (let i = 0; i < notSupported.length; i++) {
this.elementStrategies.splice(this.elementStrategies.indexOf(notSupported[i]), 1);
}
@ -309,7 +313,14 @@ ElementManager.prototype = {
return;
} else {
if (!searchTimeout || new Date().getTime() - startTime > searchTimeout) {
on_error("Unable to locate element: " + values.value, 7, null, command_id);
// Format message depending on strategy if necessary
let message = "Unable to locate element: " + values.value;
if (values.using == ANON) {
message = "Unable to locate anonymous children";
} else if (values.using == ANON_ATTRIBUTE) {
message = "Unable to locate anonymous element: " + JSON.stringify(values.value);
}
on_error(message, 7, null, command_id);
} else {
values.time = startTime;
this.timer.initWithCallback(this.find.bind(this, win, values,
@ -419,6 +430,16 @@ ElementManager.prototype = {
case SELECTOR:
element = startNode.querySelector(value);
break;
case ANON:
element = rootNode.getAnonymousNodes(startNode);
if (element != null) {
element = element[0];
}
break;
case ANON_ATTRIBUTE:
let attr = Object.keys(value)[0];
element = rootNode.getAnonymousElementByAttribute(startNode, attr, value[attr]);
break;
default:
throw new ElementException("No such strategy", 500, null);
}
@ -476,6 +497,16 @@ ElementManager.prototype = {
case SELECTOR:
elements = Array.slice(startNode.querySelectorAll(value));
break;
case ANON:
elements = rootNode.getAnonymousNodes(startNode) || [];
break;
case ANON_ATTRIBUTE:
let attr = Object.keys(value)[0];
let el = rootNode.getAnonymousElementByAttribute(startNode, attr, value[attr]);
if (el != null) {
elements = [el];
}
break;
default:
throw new ElementException("No such strategy", 500, null);
}