diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 6117295bdd1d..83afc9b5d8d1 100755 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -2967,7 +2967,7 @@ var BrowserOnClick = { anchorTarget.classList.contains("newtab-link")) { event.preventDefault(); let where = whereToOpenLink(event, false, false); - openLinkIn(anchorTarget.href, where, { charset: ownerDoc.characterSet }); + openLinkIn(anchorTarget.href, where, { charset: ownerDoc.characterSet, referrerURI: ownerDoc.documentURIObject }); } }, @@ -7248,8 +7248,9 @@ var gIdentityHandler = { label.textContent = aPermission.label; let img = document.createElement("image"); + let isBlocked = (aPermission.state == SitePermissions.BLOCK) ? " blocked" : ""; img.setAttribute("class", - "identity-popup-permission-icon " + aPermission.id + "-icon"); + "identity-popup-permission-icon " + aPermission.id + "-icon" + isBlocked); let container = document.createElement("hbox"); container.setAttribute("align", "center"); diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index dfc3b15b6049..560fba5164b5 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1764,12 +1764,10 @@ {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - @FIREFOX_VERSION@ - @FIREFOX_VERSION@ + @MOZ_APP_VERSION@ + @MOZ_APP_MAXVERSION@ diff --git a/browser/extensions/e10srollout/moz.build b/browser/extensions/e10srollout/moz.build index ec3348926911..8232da717dca 100644 --- a/browser/extensions/e10srollout/moz.build +++ b/browser/extensions/e10srollout/moz.build @@ -4,6 +4,9 @@ # 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/. +DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] +DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION'] + FINAL_TARGET_FILES.features['e10srollout@mozilla.org'] += [ 'bootstrap.js' ] diff --git a/browser/extensions/flyweb/install.rdf.in b/browser/extensions/flyweb/install.rdf.in index d5a32270d85b..f4f7ed6e8b05 100644 --- a/browser/extensions/flyweb/install.rdf.in +++ b/browser/extensions/flyweb/install.rdf.in @@ -19,8 +19,8 @@ {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - @FIREFOX_VERSION@ - @FIREFOX_VERSION@ + @MOZ_APP_VERSION@ + @MOZ_APP_MAXVERSION@ diff --git a/browser/extensions/flyweb/moz.build b/browser/extensions/flyweb/moz.build index 0528eb6c990d..6bf4ffcf7459 100644 --- a/browser/extensions/flyweb/moz.build +++ b/browser/extensions/flyweb/moz.build @@ -4,6 +4,9 @@ # 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/. +DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] +DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION'] + FINAL_TARGET_FILES.features['flyweb@mozilla.org'] += [ 'bootstrap.js' ] diff --git a/browser/extensions/pocket/install.rdf.in b/browser/extensions/pocket/install.rdf.in index 3e5b4fcdf7f8..4e390e68b744 100644 --- a/browser/extensions/pocket/install.rdf.in +++ b/browser/extensions/pocket/install.rdf.in @@ -19,8 +19,8 @@ {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - @FIREFOX_VERSION@ - @FIREFOX_VERSION@ + @MOZ_APP_VERSION@ + @MOZ_APP_MAXVERSION@ diff --git a/browser/extensions/pocket/moz.build b/browser/extensions/pocket/moz.build index 80e38b8fabd1..eb6cb964ffa1 100644 --- a/browser/extensions/pocket/moz.build +++ b/browser/extensions/pocket/moz.build @@ -4,6 +4,9 @@ # 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/. +DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] +DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION'] + DIRS += ['locales'] FINAL_TARGET_FILES.features['firefox@getpocket.com'] += [ diff --git a/browser/extensions/webcompat/install.rdf.in b/browser/extensions/webcompat/install.rdf.in index 0a19006b98a9..2cdc6921fb42 100644 --- a/browser/extensions/webcompat/install.rdf.in +++ b/browser/extensions/webcompat/install.rdf.in @@ -19,8 +19,8 @@ {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - @FIREFOX_VERSION@ - @FIREFOX_VERSION@ + @MOZ_APP_VERSION@ + @MOZ_APP_MAXVERSION@ diff --git a/browser/extensions/webcompat/moz.build b/browser/extensions/webcompat/moz.build index b2a6227cbd99..1e2d727b3f0e 100644 --- a/browser/extensions/webcompat/moz.build +++ b/browser/extensions/webcompat/moz.build @@ -4,6 +4,9 @@ # 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/. +DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] +DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION'] + FINAL_TARGET_FILES.features['webcompat@mozilla.org'] += [ 'bootstrap.js' ] diff --git a/browser/themes/shared/glyphs.svg b/browser/themes/shared/glyphs.svg index ee771d03c5fc..41eb84e14ef5 100644 --- a/browser/themes/shared/glyphs.svg +++ b/browser/themes/shared/glyphs.svg @@ -3,25 +3,69 @@ - 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/. --> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/themes/shared/notification-icons.inc.css b/browser/themes/shared/notification-icons.inc.css index 6c9fe93e25d5..609d21035c24 100644 --- a/browser/themes/shared/notification-icons.inc.css +++ b/browser/themes/shared/notification-icons.inc.css @@ -112,6 +112,10 @@ list-style-image: url(chrome://browser/skin/glyphs.svg#desktop-notification); } +.desktop-notification-icon.blocked { + list-style-image: url(chrome://browser/skin/glyphs.svg#desktop-notification-blocked); +} + .geo-icon { %ifdef XP_MACOSX list-style-image: url(chrome://browser/skin/glyphs.svg#geo-osx); @@ -122,6 +126,16 @@ %endif } +.geo-icon.blocked { +%ifdef XP_MACOSX + list-style-image: url(chrome://browser/skin/glyphs.svg#geo-osx-blocked); +%elif defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT) + list-style-image: url(chrome://browser/skin/glyphs.svg#geo-linux-blocked); +%else + list-style-image: url(chrome://browser/skin/glyphs.svg#geo-windows-blocked); +%endif +} + .popup-notification-icon[popupid="geolocation"] { %ifdef XP_MACOSX list-style-image: url(chrome://browser/skin/glyphs.svg#geo-osx); @@ -137,6 +151,10 @@ list-style-image: url(chrome://browser/skin/glyphs.svg#indexedDB); } +.indexedDB-icon.blocked { + list-style-image: url(chrome://browser/skin/glyphs.svg#indexedDB-blocked); +} + .login-icon { list-style-image: url(chrome://browser/skin/glyphs.svg#login); } @@ -158,12 +176,20 @@ list-style-image: url(chrome://browser/skin/glyphs.svg#camera); } +.camera-icon.blocked { + list-style-image: url(chrome://browser/skin/glyphs.svg#camera-blocked); +} + /* The first selector is used by socialchat.xml (bug 1275558). */ .webRTC-sharingMicrophone-notification-icon, .microphone-icon { list-style-image: url(chrome://browser/skin/glyphs.svg#microphone); } +.microphone-icon.blocked { + list-style-image: url(chrome://browser/skin/glyphs.svg#microphone-blocked); +} + .popup-notification-icon[popupid="webRTC-shareMicrophone"], .popup-notification-icon[popupid="webRTC-sharingMicrophone"] { list-style-image: url(chrome://browser/skin/glyphs.svg#microphone-detailed); @@ -175,11 +201,20 @@ list-style-image: url(chrome://browser/skin/glyphs.svg#screen); } +.screen-icon.blocked { + list-style-image: url(chrome://browser/skin/glyphs.svg#screen-blocked); +} + .popup-notification-icon[popupid="pointerLock"], .pointerLock-icon { list-style-image: url(chrome://browser/skin/glyphs.svg#pointerLock); } +.pointerLock-icon.blocked { + list-style-image: url(chrome://browser/skin/glyphs.svg#pointerLock-blocked); +} + +/* This icon has a block sign in it, so we don't need a blocked version. */ .popup-icon { list-style-image: url("chrome://browser/skin/glyphs.svg#popup"); } diff --git a/dom/animation/test/chrome/test_animation_observers.html b/dom/animation/test/chrome/test_animation_observers.html index b137996f6e8c..17b2d03e5360 100644 --- a/dom/animation/test/chrome/test_animation_observers.html +++ b/dom/animation/test/chrome/test_animation_observers.html @@ -1540,12 +1540,13 @@ addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() { yield await_frame(); assert_records([], "records after assigning same value"); - anim.currentTime = 500 * MS_PER_SEC; + anim.currentTime = anim.effect.timing.duration * 2; + anim.finish(); yield await_frame(); assert_records([{ added: [], changed: [], removed: [anim] }], "records after animation end"); - anim.effect.timing.duration = 1000 * MS_PER_SEC; + anim.effect.timing.duration = anim.effect.timing.duration * 3; yield await_frame(); assert_records([{ added: [anim], changed: [], removed: [] }], "records after animation restarted"); diff --git a/testing/marionette/element.js b/testing/marionette/element.js index 1d1c4e3b5b23..8cb8becc1de2 100644 --- a/testing/marionette/element.js +++ b/testing/marionette/element.js @@ -296,46 +296,99 @@ function find_(container, strategy, selector, searchFn, opts) { } /** - * Find a value by XPATH + * Find a single element by XPath expression. * - * @param nsIDOMElement root - * Document root - * @param string value - * XPATH search string - * @param nsIDOMElement node - * start node + * @param {DOMElement} root + * Document root + * @param {DOMElement} startNode + * Where in the DOM hiearchy to begin searching. + * @param {string} expr + * XPath search expression. * - * @return nsIDOMElement - * returns the found element + * @return {DOMElement} + * First element matching expression. */ -function findByXPath(root, value, node) { - return root.evaluate(value, node, null, - Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; -} +element.findByXPath = function(root, startNode, expr) { + let iter = root.evaluate(expr, startNode, null, + Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null) + return iter.singleNodeValue; +}; /** - * Find values by XPATH + * Find elements by XPath expression. * - * @param nsIDOMElement root - * Document root - * @param string value - * XPATH search string - * @param nsIDOMElement node - * start node + * @param {DOMElement} root + * Document root. + * @param {DOMElement} startNode + * Where in the DOM hierarchy to begin searching. + * @param {string} expr + * XPath search expression. * - * @return object - * returns a list of found nsIDOMElements + * @return {Array.} + * Sequence of found elements matching expression. */ -function findByXPathAll(root, value, node) { - let values = root.evaluate(value, node, null, - Ci.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null); - let elements = []; - let element = values.iterateNext(); - while (element) { - elements.push(element); - element = values.iterateNext(); +element.findByXPathAll = function(root, startNode, expr) { + let rv = []; + let iter = root.evaluate(expr, startNode, null, + Ci.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE, null); + let el = iter.iterateNext(); + while (el) { + rv.push(el); + el = iter.iterateNext(); } - return elements; + return rv; +}; + +/** + * Find all hyperlinks dscendant of |node| which link text is |s|. + * + * @param {DOMElement} node + * Where in the DOM hierarchy to being searching. + * @param {string} s + * Link text to search for. + * + * @return {Array.} + * Sequence of link elements which text is |s|. + */ +element.findByLinkText = function(node, s) { + return filterLinks(node, link => link.text === s); +}; + +/** + * Find all hyperlinks descendant of |node| which link text contains |s|. + * + * @param {DOMElement} node + * Where in the DOM hierachy to begin searching. + * @param {string} s + * Link text to search for. + * + * @return {Array.} + * Sequence of link elements which text containins |s|. + */ +element.findByPartialLinkText = function(node, s) { + return filterLinks(node, link => link.text.indexOf(s) != -1); +}; + +/** + * Filters all hyperlinks that are descendant of |node| by |predicate|. + * + * @param {DOMElement} node + * Where in the DOM hierarchy to begin searching. + * @param {function(DOMAnchorElement): boolean} predicate + * Function that determines if given link should be included in + * return value or filtered away. + * + * @return {Array.} + * Sequence of link elements matching |predicate|. + */ +function filterLinks(node, predicate) { + let rv = []; + for (let link of node.getElementsByTagName("a")) { + if (predicate(link)) { + rv.push(link); + } + } + return rv; } /** @@ -364,13 +417,13 @@ function findElement(using, value, rootNode, startNode) { if (startNode.getElementById) { return startNode.getElementById(value); } - return findByXPath(rootNode, `.//*[@id="${value}"]`, startNode); + return element.findByXPath(rootNode, startNode, `.//*[@id="${value}"]`); case element.Strategy.Name: if (startNode.getElementsByName) { return startNode.getElementsByName(value)[0]; } - return findByXPath(rootNode, `.//*[@name="${value}"]`, startNode); + return element.findByXPath(rootNode, startNode, `.//*[@name="${value}"]`); case element.Strategy.ClassName: // works for >= Firefox 3 @@ -381,24 +434,23 @@ function findElement(using, value, rootNode, startNode) { return startNode.getElementsByTagName(value)[0]; case element.Strategy.XPath: - return findByXPath(rootNode, value, startNode); + return element.findByXPath(rootNode, startNode, value); - // TODO(ato): Rewrite this, it's hairy: case element.Strategy.LinkText: - case element.Strategy.PartialLinkText: - let el; - let allLinks = startNode.getElementsByTagName("A"); - for (let i = 0; i < allLinks.length && !el; i++) { - let text = allLinks[i].text; - if (using == element.Strategy.PartialLinkText) { - if (text.indexOf(value) != -1) { - el = allLinks[i]; - } - } else if (text == value) { - el = allLinks[i]; + for (let link of startNode.getElementsByTagName("a")) { + if (link.text === value) { + return link; } } - return el; + break; + + case element.Strategy.PartialLinkText: + for (let link of startNode.getElementsByTagName("a")) { + if (link.text.indexOf(value) != -1) { + return link; + } + } + break; case element.Strategy.Selector: try { @@ -446,13 +498,13 @@ function findElements(using, value, rootNode, startNode) { // fall through case element.Strategy.XPath: - return findByXPathAll(rootNode, value, startNode); + return element.findByXPathAll(rootNode, startNode, value); case element.Strategy.Name: if (startNode.getElementsByName) { return startNode.getElementsByName(value); } - return findByXPathAll(rootNode, `.//*[@name="${value}"]`, startNode); + return element.findByXPathAll(rootNode, startNode, `.//*[@name="${value}"]`); case element.Strategy.ClassName: return startNode.getElementsByClassName(value); @@ -461,20 +513,10 @@ function findElements(using, value, rootNode, startNode) { return startNode.getElementsByTagName(value); case element.Strategy.LinkText: + return element.findByLinkText(startNode, value); + case element.Strategy.PartialLinkText: - let els = []; - let allLinks = startNode.getElementsByTagName("A"); - for (let i = 0; i < allLinks.length; i++) { - let text = allLinks[i].text; - if (using == element.Strategy.PartialLinkText) { - if (text.indexOf(value) != -1) { - els.push(allLinks[i]); - } - } else if (text == value) { - els.push(allLinks[i]); - } - } - return els; + return element.findByPartialLinkText(startNode, value); case element.Strategy.Selector: return startNode.querySelectorAll(value); diff --git a/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py b/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py new file mode 100644 index 000000000000..d8557ace8454 --- /dev/null +++ b/testing/marionette/harness/marionette/tests/unit/test_element_retrieval.py @@ -0,0 +1,466 @@ +# 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/. + +import re +import urllib + +from marionette import MarionetteTestCase, skip +from marionette_driver.marionette import HTMLElement +from marionette_driver.by import By +from marionette_driver.errors import NoSuchElementException, InvalidSelectorException + + +def inline(doc, doctype="html"): + if doctype == "html": + return "data:text/html;charset=utf-8,%s" % urllib.quote(doc) + elif doctype == "xhtml": + return "data:application/xhtml+xml,%s" % urllib.quote( +r""" + + + XHTML might be the future + + + + %s + +""" % doc) + + +id_html = inline("

", doctype="html") +id_xhtml = inline('

', doctype="xhtml") +parent_child_html = inline("

", doctype="html") +parent_child_xhtml = inline('

', doctype="xhtml") +children_html = inline("

foo

bar

", doctype="html") +children_xhtml = inline("

foo

bar

", doctype="xhtml") +class_html = inline("

", doctype="html") +class_xhtml = inline('

', doctype="xhtml") +name_html = inline("

", doctype="html") +name_xhtml = inline('

', doctype="xhtml") +link_html = inline("

foo bar", doctype="html") +link_xhtml = inline('

foo bar

', doctype="xhtml") + + +class TestFindElementHTML(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_search_timeout(0) + + def test_id(self): + self.marionette.navigate(id_html) + expected = self.marionette.execute_script("return document.querySelector('p')") + found = self.marionette.find_element(By.ID, "foo") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(expected, found) + + def test_child_element(self): + self.marionette.navigate(parent_child_html) + parent = self.marionette.find_element(By.ID, "parent") + child = self.marionette.find_element(By.ID, "child") + found = parent.find_element(By.TAG_NAME, "p") + self.assertEqual(found.tag_name, "p") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(child, found) + + def test_tag_name(self): + self.marionette.navigate(children_html) + el = self.marionette.execute_script("return document.querySelector('p')") + found = self.marionette.find_element(By.TAG_NAME, "p") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_class_name(self): + self.marionette.navigate(class_html) + el = self.marionette.execute_script("return document.querySelector('.foo')") + found = self.marionette.find_element(By.CLASS_NAME, "foo") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_by_name(self): + self.marionette.navigate(name_html) + el = self.marionette.execute_script("return document.querySelector('[name=foo]')") + found = self.marionette.find_element(By.NAME, "foo") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_css_selector(self): + self.marionette.navigate(children_html) + el = self.marionette.execute_script("return document.querySelector('p')") + found = self.marionette.find_element(By.CSS_SELECTOR, "p") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_invalid_css_selector_should_throw(self): + with self.assertRaises(InvalidSelectorException): + self.marionette.find_element(By.CSS_SELECTOR, "#") + + def test_link_text(self): + self.marionette.navigate(link_html) + el = self.marionette.execute_script("return document.querySelector('a')") + found = self.marionette.find_element(By.LINK_TEXT, "foo bar") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_partial_link_text(self): + self.marionette.navigate(link_html) + el = self.marionette.execute_script("return document.querySelector('a')") + found = self.marionette.find_element(By.PARTIAL_LINK_TEXT, "foo") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_xpath(self): + self.marionette.navigate(id_html) + el = self.marionette.execute_script("return document.querySelector('#foo')") + found = self.marionette.find_element(By.XPATH, "id('foo')") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_not_found(self): + self.marionette.set_search_timeout(0) + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CLASS_NAME, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CSS_SELECTOR, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.LINK_TEXT, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.NAME, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.PARTIAL_LINK_TEXT, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese") + + def test_not_found_implicit_wait(self): + self.marionette.set_search_timeout(50) + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CLASS_NAME, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CSS_SELECTOR, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.LINK_TEXT, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.NAME, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.PARTIAL_LINK_TEXT, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese") + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese") + + def test_not_found(self): + self.marionette.set_search_timeout(0) + self.marionette.navigate(id_html) + el = self.marionette.find_element(By.ID, "foo") + self.assertRaises(NoSuchElementException, el.find_element, By.CLASS_NAME, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.CSS_SELECTOR, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.ID, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.LINK_TEXT, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.NAME, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.PARTIAL_LINK_TEXT, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.TAG_NAME, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.XPATH, "cheese") + + def test_not_found_implicit_wait(self): + self.marionette.set_search_timeout(50) + self.marionette.navigate(id_html) + el = self.marionette.find_element(By.ID, "foo") + self.assertRaises(NoSuchElementException, el.find_element, By.CLASS_NAME, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.CSS_SELECTOR, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.ID, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.LINK_TEXT, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.NAME, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.PARTIAL_LINK_TEXT, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.TAG_NAME, "cheese") + self.assertRaises(NoSuchElementException, el.find_element, By.XPATH, "cheese") + + def test_css_selector_scope_doesnt_start_at_rootnode(self): + self.marionette.navigate(parent_child_html) + el = self.marionette.find_element(By.ID, "child") + parent = self.marionette.find_element(By.ID, "parent") + found = parent.find_element(By.CSS_SELECTOR, "p") + self.assertEqual(el, found) + + def test_unknown_selector(self): + with self.assertRaises(InvalidSelectorException): + self.marionette.find_elements("foo", "bar") + + def test_element_id_is_valid_uuid(self): + self.marionette.navigate(id_html) + el = self.marionette.find_element(By.TAG_NAME, "p") + uuid_regex = re.compile('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') + self.assertIsNotNone(re.search(uuid_regex, el.id), + 'UUID for the WebElement is not valid. ID is {}'\ + .format(el.id)) + + def test_invalid_xpath_selector(self): + with self.assertRaises(InvalidSelectorException): + self.marionette.find_element(By.XPATH, "count(//input)") + with self.assertRaises(InvalidSelectorException): + parent = self.marionette.execute_script("return document.documentElement") + parent.find_element(By.XPATH, "count(//input)") + + def test_invalid_css_selector(self): + with self.assertRaises(InvalidSelectorException): + self.marionette.find_element(By.CSS_SELECTOR, "") + with self.assertRaises(InvalidSelectorException): + parent = self.marionette.execute_script("return document.documentElement") + parent.find_element(By.CSS_SELECTOR, "") + + def test_finding_active_element_returns_element(self): + self.marionette.navigate(id_html) + active = self.marionette.execute_script("return document.activeElement") + self.assertEqual(active, self.marionette.get_active_element()) + + +class TestFindElementXHTML(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_search_timeout(0) + + def test_id(self): + self.marionette.navigate(id_xhtml) + expected = self.marionette.execute_script("return document.querySelector('p')") + found = self.marionette.find_element(By.ID, "foo") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(expected, found) + + def test_child_element(self): + self.marionette.navigate(parent_child_xhtml) + parent = self.marionette.find_element(By.ID, "parent") + child = self.marionette.find_element(By.ID, "child") + found = parent.find_element(By.TAG_NAME, "p") + self.assertEqual(found.tag_name, "p") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(child, found) + + def test_tag_name(self): + self.marionette.navigate(children_xhtml) + el = self.marionette.execute_script("return document.querySelector('p')") + found = self.marionette.find_element(By.TAG_NAME, "p") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_class_name(self): + self.marionette.navigate(class_xhtml) + el = self.marionette.execute_script("return document.querySelector('.foo')") + found = self.marionette.find_element(By.CLASS_NAME, "foo") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_by_name(self): + self.marionette.navigate(name_xhtml) + el = self.marionette.execute_script("return document.querySelector('[name=foo]')") + found = self.marionette.find_element(By.NAME, "foo") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_css_selector(self): + self.marionette.navigate(children_xhtml) + el = self.marionette.execute_script("return document.querySelector('p')") + found = self.marionette.find_element(By.CSS_SELECTOR, "p") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_link_text(self): + self.marionette.navigate(link_xhtml) + el = self.marionette.execute_script("return document.querySelector('a')") + found = self.marionette.find_element(By.LINK_TEXT, "foo bar") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_partial_link_text(self): + self.marionette.navigate(link_xhtml) + el = self.marionette.execute_script("return document.querySelector('a')") + found = self.marionette.find_element(By.PARTIAL_LINK_TEXT, "foo") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_xpath(self): + self.marionette.navigate(id_xhtml) + el = self.marionette.execute_script("return document.querySelector('#foo')") + found = self.marionette.find_element(By.XPATH, "id('foo')") + self.assertIsInstance(found, HTMLElement) + self.assertEqual(el, found) + + def test_css_selector_scope_does_not_start_at_rootnode(self): + self.marionette.navigate(parent_child_xhtml) + el = self.marionette.find_element(By.ID, "child") + parent = self.marionette.find_element(By.ID, "parent") + found = parent.find_element(By.CSS_SELECTOR, "p") + self.assertEqual(el, found) + + def test_active_element(self): + self.marionette.navigate(id_xhtml) + active = self.marionette.execute_script("return document.activeElement") + self.assertEqual(active, self.marionette.get_active_element()) + + +class TestFindElementsHTML(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_search_timeout(0) + + def assertItemsIsInstance(self, items, typ): + for item in items: + self.assertIsInstance(item, typ) + + def test_child_elements(self): + self.marionette.navigate(children_html) + parent = self.marionette.find_element(By.TAG_NAME, "div") + children = self.marionette.find_elements(By.TAG_NAME, "p") + found = parent.find_elements(By.TAG_NAME, "p") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(found, children) + + def test_tag_name(self): + self.marionette.navigate(children_html) + els = self.marionette.execute_script("return document.querySelectorAll('p')") + found = self.marionette.find_elements(By.TAG_NAME, "p") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_class_name(self): + self.marionette.navigate(class_html) + els = self.marionette.execute_script("return document.querySelectorAll('.foo')") + found = self.marionette.find_elements(By.CLASS_NAME, "foo") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_by_name(self): + self.marionette.navigate(name_html) + els = self.marionette.execute_script("return document.querySelectorAll('[name=foo]')") + found = self.marionette.find_elements(By.NAME, "foo") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_css_selector(self): + self.marionette.navigate(children_html) + els = self.marionette.execute_script("return document.querySelectorAll('p')") + found = self.marionette.find_elements(By.CSS_SELECTOR, "p") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_invalid_css_selector_should_throw(self): + with self.assertRaises(InvalidSelectorException): + self.marionette.find_elements(By.CSS_SELECTOR, "#") + + def test_link_text(self): + self.marionette.navigate(link_html) + els = self.marionette.execute_script("return document.querySelectorAll('a')") + found = self.marionette.find_elements(By.LINK_TEXT, "foo bar") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_partial_link_text(self): + self.marionette.navigate(link_html) + els = self.marionette.execute_script("return document.querySelectorAll('a')") + found = self.marionette.find_elements(By.PARTIAL_LINK_TEXT, "foo") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_xpath(self): + self.marionette.navigate(children_html) + els = self.marionette.execute_script("return document.querySelectorAll('p')") + found = self.marionette.find_elements(By.XPATH, ".//p") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_css_selector_scope_doesnt_start_at_rootnode(self): + self.marionette.navigate(parent_child_html) + els = self.marionette.find_elements(By.ID, "child") + parent = self.marionette.find_element(By.ID, "parent") + found = parent.find_elements(By.CSS_SELECTOR, "p") + self.assertSequenceEqual(els, found) + + def test_unknown_selector(self): + with self.assertRaises(InvalidSelectorException): + self.marionette.find_element("foo", "bar") + + def test_element_id_is_valid_uuid(self): + self.marionette.navigate(id_html) + els = self.marionette.find_elements(By.TAG_NAME, "p") + uuid_regex = re.compile('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') + self.assertIsNotNone(re.search(uuid_regex, els[0].id), + 'UUID for the WebElement is not valid. ID is {}'\ + .format(els[0].id)) + + def test_invalid_xpath_selector(self): + with self.assertRaises(InvalidSelectorException): + self.marionette.find_elements(By.XPATH, "count(//input)") + with self.assertRaises(InvalidSelectorException): + parent = self.marionette.execute_script("return document.documentElement") + parent.find_elements(By.XPATH, "count(//input)") + + def test_invalid_css_selector(self): + with self.assertRaises(InvalidSelectorException): + self.marionette.find_elements(By.CSS_SELECTOR, "") + with self.assertRaises(InvalidSelectorException): + parent = self.marionette.execute_script("return document.documentElement") + parent.find_elements(By.CSS_SELECTOR, "") + + +class TestFindElementsXHTML(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_search_timeout(0) + + def assertItemsIsInstance(self, items, typ): + for item in items: + self.assertIsInstance(item, typ) + + def test_child_elements(self): + self.marionette.navigate(children_xhtml) + parent = self.marionette.find_element(By.TAG_NAME, "div") + children = self.marionette.find_elements(By.TAG_NAME, "p") + found = parent.find_elements(By.TAG_NAME, "p") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(found, children) + + def test_tag_name(self): + self.marionette.navigate(children_xhtml) + els = self.marionette.execute_script("return document.querySelectorAll('p')") + found = self.marionette.find_elements(By.TAG_NAME, "p") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_class_name(self): + self.marionette.navigate(class_xhtml) + els = self.marionette.execute_script("return document.querySelectorAll('.foo')") + found = self.marionette.find_elements(By.CLASS_NAME, "foo") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_by_name(self): + self.marionette.navigate(name_xhtml) + els = self.marionette.execute_script("return document.querySelectorAll('[name=foo]')") + found = self.marionette.find_elements(By.NAME, "foo") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_css_selector(self): + self.marionette.navigate(children_xhtml) + els = self.marionette.execute_script("return document.querySelectorAll('p')") + found = self.marionette.find_elements(By.CSS_SELECTOR, "p") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_link_text(self): + self.marionette.navigate(link_xhtml) + els = self.marionette.execute_script("return document.querySelectorAll('a')") + found = self.marionette.find_elements(By.LINK_TEXT, "foo bar") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_partial_link_text(self): + self.marionette.navigate(link_xhtml) + els = self.marionette.execute_script("return document.querySelectorAll('a')") + found = self.marionette.find_elements(By.PARTIAL_LINK_TEXT, "foo") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + @skip("XHTML namespace not yet supported") + def test_xpath(self): + self.marionette.navigate(children_xhtml) + els = self.marionette.execute_script("return document.querySelectorAll('p')") + found = self.marionette.find_elements(By.XPATH, "//xhtml:p") + self.assertItemsIsInstance(found, HTMLElement) + self.assertSequenceEqual(els, found) + + def test_css_selector_scope_doesnt_start_at_rootnode(self): + self.marionette.navigate(parent_child_xhtml) + els = self.marionette.find_elements(By.ID, "child") + parent = self.marionette.find_element(By.ID, "parent") + found = parent.find_elements(By.CSS_SELECTOR, "p") + self.assertSequenceEqual(els, found) diff --git a/testing/marionette/harness/marionette/tests/unit/test_findelement.py b/testing/marionette/harness/marionette/tests/unit/test_findelement.py deleted file mode 100644 index c5578d169e4e..000000000000 --- a/testing/marionette/harness/marionette/tests/unit/test_findelement.py +++ /dev/null @@ -1,209 +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/. - -import re - -from marionette import MarionetteTestCase -from marionette_driver.marionette import HTMLElement -from marionette_driver.by import By -from marionette_driver.errors import NoSuchElementException, InvalidSelectorException - - -class TestElements(MarionetteTestCase): - def setUp(self): - MarionetteTestCase.setUp(self) - self.marionette.set_search_timeout(0) - url = self.marionette.absolute_url("test.html") - self.marionette.navigate(url) - - def test_id(self): - el = self.marionette.execute_script("return window.document.getElementById('mozLink');") - found_el = self.marionette.find_element(By.ID, "mozLink") - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_child_element(self): - el = self.marionette.find_element(By.ID, "divLink") - div = self.marionette.find_element(By.ID, "testDiv") - found_el = div.find_element(By.TAG_NAME, "a") - self.assertEqual("a", found_el.tag_name) - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_child_elements(self): - el = self.marionette.find_element(By.ID, "divLink2") - div = self.marionette.find_element(By.ID, "testDiv") - found_els = div.find_elements(By.TAG_NAME, "a") - self.assertTrue(el.id in [found_el.id for found_el in found_els]) - - def test_tag_name(self): - el = self.marionette.execute_script("return window.document.getElementsByTagName('body')[0];") - found_el = self.marionette.find_element(By.TAG_NAME, "body") - self.assertEqual('body', found_el.tag_name) - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - found_el = self.marionette.find_elements(By.TAG_NAME, "body")[0] - self.assertEqual('body', found_el.tag_name) - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_class_name(self): - el = self.marionette.execute_script("return window.document.getElementsByClassName('linkClass')[0];") - found_el = self.marionette.find_element(By.CLASS_NAME, "linkClass") - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - found_el = self.marionette.find_elements(By.CLASS_NAME, "linkClass")[0] - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_by_name(self): - el = self.marionette.execute_script("return window.document.getElementsByName('myInput')[0];") - found_el = self.marionette.find_element(By.NAME, "myInput") - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - found_el = self.marionette.find_elements(By.NAME, "myInput")[0] - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_css_selector(self): - el = self.marionette.execute_script("return window.document.getElementById('testh1');") - found_el = self.marionette.find_element(By.CSS_SELECTOR, "h1") - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - found_el = self.marionette.find_elements(By.CSS_SELECTOR, "h1")[0] - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_invalid_css_selector_should_throw(self): - with self.assertRaises(InvalidSelectorException): - self.marionette.find_element(By.CSS_SELECTOR, "#") - - def test_link_text(self): - el = self.marionette.execute_script("return window.document.getElementById('mozLink');") - found_el = self.marionette.find_element(By.LINK_TEXT, "Click me!") - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - found_el = self.marionette.find_elements(By.LINK_TEXT, "Click me!")[0] - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_partial_link_text(self): - el = self.marionette.execute_script("return window.document.getElementById('mozLink');") - found_el = self.marionette.find_element(By.PARTIAL_LINK_TEXT, "Click m") - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - found_el = self.marionette.find_elements(By.PARTIAL_LINK_TEXT, "Click m")[0] - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_xpath(self): - el = self.marionette.execute_script("return window.document.getElementById('mozLink');") - found_el = self.marionette.find_element(By.XPATH, "id('mozLink')") - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - found_el = self.marionette.find_elements(By.XPATH, "id('mozLink')")[0] - self.assertEqual(HTMLElement, type(found_el)) - self.assertEqual(el, found_el) - - def test_not_found(self): - self.marionette.set_search_timeout(0) - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CLASS_NAME, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CSS_SELECTOR, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.LINK_TEXT, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.NAME, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.PARTIAL_LINK_TEXT, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese") - - def test_not_found_implicit_wait(self): - self.marionette.set_search_timeout(50) - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CLASS_NAME, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.CSS_SELECTOR, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.LINK_TEXT, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.NAME, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.PARTIAL_LINK_TEXT, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.TAG_NAME, "cheese") - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.XPATH, "cheese") - - def test_timeout_element(self): - button = self.marionette.find_element(By.ID, "createDivButton") - button.click() - self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, "newDiv") - self.assertTrue(True, self.marionette.set_search_timeout(8000)) - self.assertEqual(HTMLElement, type(self.marionette.find_element(By.ID, "newDiv"))) - - def test_timeout_elements(self): - button = self.marionette.find_element(By.ID, "createDivButton") - button.click() - self.assertEqual(len(self.marionette.find_elements(By.ID, "newDiv")), 0) - self.assertTrue(True, self.marionette.set_search_timeout(8000)) - self.assertEqual(len(self.marionette.find_elements(By.ID, "newDiv")), 1) - - def test_css_selector_scope_doesnt_start_at_rootnode(self): - el = self.marionette.find_element(By.ID, "mozLink") - nav_el = self.marionette.find_element(By.ID, "testDiv") - found_els = nav_el.find_elements(By.CSS_SELECTOR, "a") - self.assertFalse(el.id in [found_el.id for found_el in found_els]) - - def test_finding_active_element_returns_element(self): - body = self.marionette.find_element(By.TAG_NAME, "body") - self.assertEqual(body, self.marionette.get_active_element()) - - def test_unknown_selector(self): - with self.assertRaises(InvalidSelectorException): - self.marionette.find_element("foo", "bar") - - def test_element_id_is_valid_uuid(self): - el = self.marionette.find_element(By.TAG_NAME, "body") - uuid_regex = re.compile('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$') - self.assertIsNotNone(re.search(uuid_regex, el.id), - 'UUID for the WebElement is not valid. ID is {}'\ - .format(el.id)) - - def test_should_find_elements_by_link_text(self): - url = self.marionette.absolute_url("nestedElements.html") - self.marionette.navigate(url) - element = self.marionette.find_element(By.NAME, "div1") - children = element.find_elements(By.LINK_TEXT, "hello world") - self.assertEqual(len(children), 2) - self.assertEqual("link1", children[0].get_attribute("name")) - self.assertEqual("link2", children[1].get_attribute("name")) - - def test_should_throw_invalidselectorexception_when_invalid_xPath_in_driver_find_element(self): - url = self.marionette.absolute_url("formPage.html") - self.marionette.navigate(url) - self.assertRaises(InvalidSelectorException, self.marionette.find_element, By.XPATH, "count(//input)") - - def test_should_throw_invalidselectorexception_when_invalid_xpath_in_driver_find_elements(self): - url = self.marionette.absolute_url("formPage.html") - self.marionette.navigate(url) - self.assertRaises(InvalidSelectorException, self.marionette.find_elements, By.XPATH, "count(//input)") - - def test_should_throw_invalidselectorexception_when_invalid_xpath_in_element_find_element(self): - url = self.marionette.absolute_url("formPage.html") - self.marionette.navigate(url) - body = self.marionette.find_element(By.TAG_NAME, "body") - self.assertRaises(InvalidSelectorException, body.find_element, By.XPATH, "count(//input)") - - def test_should_throw_invalidselectorexception_when_invalid_xpath_in_element_find_elements(self): - url = self.marionette.absolute_url("formPage.html") - self.marionette.navigate(url) - body = self.marionette.find_element(By.TAG_NAME, "body") - self.assertRaises(InvalidSelectorException, body.find_elements, By.XPATH, "count(//input)") - - def test_should_throw_invalidselectorexception_when_css_is_empty_in_driver_find_element(self): - self.assertRaises(InvalidSelectorException, self.marionette.find_element, By.CSS_SELECTOR, "") - - def test_should_throw_invalidselectorexception_when_css_is_empty_in_driver_find_elements(self): - self.assertRaises(InvalidSelectorException, self.marionette.find_elements, By.CSS_SELECTOR, "") - - def test_should_throw_invalidselectorexception_when_css_is_empty_in_element_find_element(self): - body = self.marionette.find_element(By.TAG_NAME, "body") - self.assertRaises(InvalidSelectorException, body.find_element, By.CSS_SELECTOR, "") - - def test_should_throw_invalidselectorexception_when_css_is_empty_in_element_find_elements(self): - body = self.marionette.find_element(By.TAG_NAME, "body") - self.assertRaises(InvalidSelectorException, body.find_elements, By.CSS_SELECTOR, "") diff --git a/testing/marionette/harness/marionette/tests/unit/unit-tests.ini b/testing/marionette/harness/marionette/tests/unit/unit-tests.ini index 24ffa195f09c..4be59268b564 100644 --- a/testing/marionette/harness/marionette/tests/unit/unit-tests.ini +++ b/testing/marionette/harness/marionette/tests/unit/unit-tests.ini @@ -39,7 +39,7 @@ skip-if = buildapp == 'b2g' [test_execute_async_script.py] [test_execute_script.py] [test_simpletest_fail.js] -[test_findelement.py] +[test_element_retrieval.py] [test_findelement_chrome.py] skip-if = buildapp == 'b2g' diff --git a/toolkit/components/telemetry/TelemetrySession.jsm b/toolkit/components/telemetry/TelemetrySession.jsm index f70856f256b2..9d530e844bc1 100644 --- a/toolkit/components/telemetry/TelemetrySession.jsm +++ b/toolkit/components/telemetry/TelemetrySession.jsm @@ -1258,7 +1258,6 @@ var Impl = { simpleMeasurements: simpleMeasurements, histograms: protect(() => this.getHistograms(isSubsession, clearSubsession)), keyedHistograms: protect(() => this.getKeyedHistograms(isSubsession, clearSubsession)), - scalars: protect(() => this.getScalars(isSubsession, clearSubsession)), }; // Add extended set measurements common to chrome & content processes @@ -1273,6 +1272,13 @@ var Impl = { return payloadObj; } + // Set the scalars for the parent process. + payloadObj.processes = { + parent: { + scalars: protect(() => this.getScalars(isSubsession, clearSubsession)), + } + }; + // Additional payload for chrome process. payloadObj.info = info; diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js index 3a7610cb8be0..e8f43b4e68cd 100644 --- a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js +++ b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js @@ -242,13 +242,14 @@ function checkPayloadInfo(data) { Assert.ok(data.timezoneOffset <= 12*60, "The timezone must be in a valid range."); } -function checkScalars(payload) { +function checkScalars(processes) { // Check that the scalars section is available in the ping payload. - Assert.ok("scalars" in payload, "The scalars section must be available in the payload."); - Assert.equal(typeof payload.scalars, "object", "The scalars entry must be an object."); + const parentProcess = processes.parent; + Assert.ok("scalars" in parentProcess, "The scalars section must be available in the parent process."); + Assert.equal(typeof parentProcess.scalars, "object", "The scalars entry must be an object."); // Check that we have valid scalar entries. - const scalars = payload.scalars; + const scalars = parentProcess.scalars; for (let name in scalars) { Assert.equal(typeof name, "string", "Scalar names must be strings."); // Check if the value is of a supported type. @@ -403,7 +404,9 @@ function checkPayload(payload, reason, successfulPings, savedPings) { }; Assert.deepEqual(expected_keyed_count, keyedHistograms[TELEMETRY_TEST_KEYED_COUNT]); - checkScalars(payload); + Assert.ok("processes" in payload, "The payload must have a processes section."); + Assert.ok("parent" in payload.processes, "There must be at least a parent process."); + checkScalars(payload.processes); } function writeStringToFile(file, contents) { @@ -608,25 +611,25 @@ add_task(function* test_checkSubsessionScalars() { const TEST_SCALARS = [ UINT_SCALAR, STRING_SCALAR ]; for (let name of TEST_SCALARS) { // Scalar must be reported in subsession pings (e.g. main). - Assert.ok(name in subsession.scalars, + Assert.ok(name in subsession.processes.parent.scalars, name + " must be reported in a subsession ping."); } // No scalar must be reported in classic pings (e.g. saved-session). - Assert.ok(Object.keys(classic.scalars).length == 0, + Assert.ok(Object.keys(classic.processes.parent.scalars).length == 0, "Scalars must not be reported in a classic ping."); // And make sure that we're getting the right values in the // subsession ping. - Assert.equal(subsession.scalars[UINT_SCALAR], expectedUint, + Assert.equal(subsession.processes.parent.scalars[UINT_SCALAR], expectedUint, UINT_SCALAR + " must contain the expected value."); - Assert.equal(subsession.scalars[STRING_SCALAR], expectedString, + Assert.equal(subsession.processes.parent.scalars[STRING_SCALAR], expectedString, STRING_SCALAR + " must contain the expected value."); // Since we cleared the subsession in the last getPayload(), check that // breaking subsessions clears the scalars. subsession = TelemetrySession.getPayload("environment-change"); for (let name of TEST_SCALARS) { - Assert.ok(!(name in subsession.scalars), + Assert.ok(!(name in subsession.processes.parent.scalars), name + " must be cleared with the new subsession."); } @@ -636,9 +639,9 @@ add_task(function* test_checkSubsessionScalars() { Telemetry.scalarSet(UINT_SCALAR, expectedUint); Telemetry.scalarSet(STRING_SCALAR, expectedString); subsession = TelemetrySession.getPayload("environment-change"); - Assert.equal(subsession.scalars[UINT_SCALAR], expectedUint, + Assert.equal(subsession.processes.parent.scalars[UINT_SCALAR], expectedUint, UINT_SCALAR + " must contain the expected value."); - Assert.equal(subsession.scalars[STRING_SCALAR], expectedString, + Assert.equal(subsession.processes.parent.scalars[STRING_SCALAR], expectedString, STRING_SCALAR + " must contain the expected value."); }); diff --git a/toolkit/content/aboutTelemetry.js b/toolkit/content/aboutTelemetry.js index 1d05f492f80e..8685b037eb5f 100644 --- a/toolkit/content/aboutTelemetry.js +++ b/toolkit/content/aboutTelemetry.js @@ -1559,7 +1559,11 @@ var Scalars = { let scalarsSection = document.getElementById("scalars"); removeAllChildNodes(scalarsSection); - let scalars = aPayload.scalars; + if (!aPayload.processes || !aPayload.processes.parent) { + return; + } + + let scalars = aPayload.processes.parent.scalars; const hasData = scalars && Object.keys(scalars).length > 0; setHasData("scalars-section", hasData); if (!hasData) {