From 524588210fbec0025a25135875fd0012b148049e Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Tue, 5 Dec 2017 13:25:09 +0100 Subject: [PATCH] Bug 1381519 - Find element for (partial) link text has to use rendered content. r=ato To retrieve links via "link text" or "partial link text" the rendered content of the element has to be used. This can be the case for CSS transformations like "uppercase". MozReview-Commit-ID: fxaHEuWnbf --HG-- extra : rebase_source : 9336a5ede468046e06f065f401a461dde5848a18 --- testing/marionette/element.js | 10 ++- .../tests/unit/test_element_retrieval.py | 74 ------------------- testing/web-platform/meta/MANIFEST.json | 32 +++++--- .../tests/element_retrieval/find_element.py | 36 ++++++++- .../find_element_from_element.py | 39 +++++++++- .../tests/element_retrieval/find_elements.py | 55 ++++++++++++-- .../find_elements_from_element.py | 50 ++++++++++++- 7 files changed, 197 insertions(+), 99 deletions(-) diff --git a/testing/marionette/element.js b/testing/marionette/element.js index 5adca276deb3..738fc8ac0a4c 100644 --- a/testing/marionette/element.js +++ b/testing/marionette/element.js @@ -441,7 +441,8 @@ element.findByXPathAll = function* (document, startNode, expression) { * Sequence of link elements which text is s. */ element.findByLinkText = function(startNode, linkText) { - return filterLinks(startNode, link => link.text.trim() === linkText); + return filterLinks(startNode, + link => atom.getElementText(link).trim() === linkText); }; /** @@ -458,7 +459,8 @@ element.findByLinkText = function(startNode, linkText) { * linkText. */ element.findByPartialLinkText = function(startNode, linkText) { - return filterLinks(startNode, link => link.text.includes(linkText)); + return filterLinks(startNode, + link => atom.getElementText(link).includes(linkText)); }; /** @@ -551,7 +553,7 @@ function findElement(strategy, selector, document, startNode = undefined) { case element.Strategy.LinkText: for (let link of startNode.getElementsByTagName("a")) { - if (link.text.trim() === selector) { + if (atom.getElementText(link).trim() === selector) { return link; } } @@ -559,7 +561,7 @@ function findElement(strategy, selector, document, startNode = undefined) { case element.Strategy.PartialLinkText: for (let link of startNode.getElementsByTagName("a")) { - if (link.text.includes(selector)) { + if (atom.getElementText(link).includes(selector)) { return link; } } diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_element_retrieval.py b/testing/marionette/harness/marionette_harness/tests/unit/test_element_retrieval.py index 7d7d9c73de90..1988f5c27a5a 100644 --- a/testing/marionette/harness/marionette_harness/tests/unit/test_element_retrieval.py +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_element_retrieval.py @@ -42,9 +42,6 @@ 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_html_with_trailing_space = inline("

a link with a trailing space ") -link_xhtml = inline('

foo bar

', doctype="xhtml") class TestFindElementHTML(MarionetteTestCase): @@ -100,27 +97,6 @@ class TestFindElementHTML(MarionetteTestCase): 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_link_text_with_trailing_space(self): - self.marionette.navigate(link_html_with_trailing_space) - el = self.marionette.execute_script("return document.querySelector('a')") - found = self.marionette.find_element(By.LINK_TEXT, "a link with a trailing space") - 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')") @@ -264,20 +240,6 @@ class TestFindElementXHTML(MarionetteTestCase): 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')") @@ -347,28 +309,6 @@ class TestFindElementsHTML(MarionetteTestCase): 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_link_text_with_trailing_space(self): - self.marionette.navigate(link_html_with_trailing_space) - els = self.marionette.execute_script("return document.querySelectorAll('a')") - found = self.marionette.find_elements(By.LINK_TEXT, "a link with a trailing space") - 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')") @@ -455,20 +395,6 @@ class TestFindElementsXHTML(MarionetteTestCase): 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) diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json index 36c838fe5b5f..aed1b245929a 100644 --- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -366460,6 +366460,12 @@ {} ] ], + "xhr/xmlhttprequest-closing-worker.html": [ + [ + "/xhr/xmlhttprequest-closing-worker.html", + {} + ] + ], "xhr/xmlhttprequest-eventtarget.htm": [ [ "/xhr/xmlhttprequest-eventtarget.htm", @@ -500894,27 +500900,27 @@ "testharness" ], "css/css-scoping/shadow-disabled-sheet-001.html": [ - "a3ddf0fe7fa422f5e712b8771669be76b0e3a798", + "3de2d23c1b3339b964ec2c009832a3207a3b9dc4", "reftest" ], "css/css-scoping/shadow-fallback-dynamic-001.html": [ - "062c99df18077a0205d0170d641b1d1e61199657", + "741cd9e29067a4634aa5beb6bd06afa540895d22", "reftest" ], "css/css-scoping/shadow-fallback-dynamic-002.html": [ - "2f66c8bca48c2ce5c9e82c5d67b152e2d143f4c6", + "e9a0d8178387901404030dde1b7ae7b2842f2eca", "reftest" ], "css/css-scoping/shadow-fallback-dynamic-003.html": [ - "f054b0974277fbee38a96a26559c9a15400266db", + "0b75fadbaee366349576e2d6f3ca8d6a49069f66", "reftest" ], "css/css-scoping/shadow-fallback-dynamic-004.html": [ - "fc33527eaaa7711ecb2c7cd9523e793bce2503f2", + "71dcc60c4ff59690927c1575fff2eecf85ee558f", "reftest" ], "css/css-scoping/shadow-fallback-dynamic-005.html": [ - "46d78b6d6931505bbc4bfc2f83e2bd0bac0d3472", + "ab3c3d205e59df800ba5b4217245b83685521c31", "reftest" ], "css/css-scoping/shadow-root-insert-into-document.html": [ @@ -593514,19 +593520,19 @@ "support" ], "webdriver/tests/element_retrieval/find_element.py": [ - "699b97bd31eed625e2f0bed145aaf94c3e646853", + "8c9ed3ac2169f4b65a2e172a6e77b9586d83afa2", "wdspec" ], "webdriver/tests/element_retrieval/find_element_from_element.py": [ - "34f356f2579391289edb31adf5b4d4eb88ffc643", + "ecb74fc793a35481e2aa2456544b8b8f32d08546", "wdspec" ], "webdriver/tests/element_retrieval/find_elements.py": [ - "284ae53c5c94d02fb46b26dcd70af02d7917e7b4", + "fa8c2de1ffd12432bf14368b9c72000567ab8d20", "wdspec" ], "webdriver/tests/element_retrieval/find_elements_from_element.py": [ - "b062b9f044268f0d9e092def81afae1277a91cd8", + "6099bab098d03c0ac17134014b0acaf0b977731a", "wdspec" ], "webdriver/tests/element_retrieval/get_active_element.py": [ @@ -594658,7 +594664,7 @@ "testharness" ], "websockets/Create-on-worker-shutdown.html": [ - "75112264efdc3b310f4ba2ab4517b7608aacf2f2", + "213d7b23d154b930cc20985c2a86509fcdc09a9a", "testharness" ], "websockets/Create-protocol-with-space.htm": [ @@ -601509,6 +601515,10 @@ "a67d1876d6245fb94d60a937b633c87c51a04d21", "testharness" ], + "xhr/xmlhttprequest-closing-worker.html": [ + "2e12b49aca2dc3908837b6b419c92cb890e60e3f", + "testharness" + ], "xhr/xmlhttprequest-eventtarget.htm": [ "40c886f79399108db3ded8a23848905dcf9e0862", "testharness" diff --git a/testing/web-platform/tests/webdriver/tests/element_retrieval/find_element.py b/testing/web-platform/tests/webdriver/tests/element_retrieval/find_element.py index 454e3c38bdcc..dddb28cb333f 100644 --- a/testing/web-platform/tests/webdriver/tests/element_retrieval/find_element.py +++ b/testing/web-platform/tests/webdriver/tests/element_retrieval/find_element.py @@ -51,6 +51,39 @@ def test_find_element(session, using, value): assert_success(response) +@pytest.mark.parametrize("document,value", [ + ("link text", "link text"), + (" link text ", "link text"), + ("link
text
", "link\ntext"), + ("link&text", "link&text"), + ("LINK TEXT", "LINK TEXT"), + ("link text", "LINK TEXT"), +]) +def test_find_element_link_text(session, document, value): + # Step 8 - 9 + session.url = inline(document) + + response = find_element(session, "link text", value) + assert_success(response) + + +@pytest.mark.parametrize("document,value", [ + ("partial link text", "link"), + (" partial link text ", "link"), + ("partial link text", "k t"), + ("partial link
text
", "k\nt"), + ("partial link&text", "k&t"), + ("PARTIAL LINK TEXT", "LINK"), + ("partial link text", "LINK"), +]) +def test_find_element_partial_link_text(session, document, value): + # Step 8 - 9 + session.url = inline(document) + + response = find_element(session, "partial link text", value) + assert_success(response) + + @pytest.mark.parametrize("using,value", [("css selector", "#wontExist")]) def test_no_element(session, using, value): # Step 8 - 9 @@ -65,7 +98,8 @@ def test_no_element(session, using, value): ("tag name", "a"), ("xpath", "//*[name()='a']")]) def test_xhtml_namespace(session, using, value): - session.url = inline("""full link text""", doctype="xhtml") + session.url = inline("""full link text""", + doctype="xhtml") expected = session.execute_script("return document.links[0]") response = find_element(session, using, value) diff --git a/testing/web-platform/tests/webdriver/tests/element_retrieval/find_element_from_element.py b/testing/web-platform/tests/webdriver/tests/element_retrieval/find_element_from_element.py index d79d512a13c5..39dee1a3b994 100644 --- a/testing/web-platform/tests/webdriver/tests/element_retrieval/find_element_from_element.py +++ b/testing/web-platform/tests/webdriver/tests/element_retrieval/find_element_from_element.py @@ -31,7 +31,6 @@ def test_closed_context(session, create_window): session.close() response = find_element(session, "notReal", "css selector", "foo") - assert_error(response, "no such window") @@ -49,6 +48,41 @@ def test_find_element(session, using, value): assert_success(response) +@pytest.mark.parametrize("document,value", [ + ("link text", "link text"), + (" link text ", "link text"), + ("link
text
", "link\ntext"), + ("link&text", "link&text"), + ("LINK TEXT", "LINK TEXT"), + ("link text", "LINK TEXT"), +]) +def test_find_element_link_text(session, document, value): + # Step 8 - 9 + session.url = inline("
{0}
".format(document)) + element = session.find.css("div", all=False) + + response = find_element(session, element.id, "link text", value) + assert_success(response) + + +@pytest.mark.parametrize("document,value", [ + ("partial link text", "link"), + (" partial link text ", "link"), + ("partial link text", "k t"), + ("partial link
text
", "k\nt"), + ("partial link&text", "k&t"), + ("PARTIAL LINK TEXT", "LINK"), + ("partial link text", "LINK"), +]) +def test_find_element_partial_link_text(session, document, value): + # Step 8 - 9 + session.url = inline("
{0}
".format(document)) + element = session.find.css("div", all=False) + + response = find_element(session, element.id, "partial link text", value) + assert_success(response) + + @pytest.mark.parametrize("using,value",[("css selector", "#wontExist")]) def test_no_element(session, using, value): # Step 8 - 9 @@ -65,7 +99,8 @@ def test_no_element(session, using, value): ("tag name", "a"), ("xpath", "//*[name()='a']")]) def test_xhtml_namespace(session, using, value): - session.url = inline("""

full link text

""", doctype="xhtml") + session.url = inline("""

full link text

""", + doctype="xhtml") from_element = session.execute_script("""return document.querySelector("p")""") expected = session.execute_script("return document.links[0]") diff --git a/testing/web-platform/tests/webdriver/tests/element_retrieval/find_elements.py b/testing/web-platform/tests/webdriver/tests/element_retrieval/find_elements.py index a00ae2358c20..781dd3b6408e 100644 --- a/testing/web-platform/tests/webdriver/tests/element_retrieval/find_elements.py +++ b/testing/web-platform/tests/webdriver/tests/element_retrieval/find_elements.py @@ -30,10 +30,7 @@ def test_closed_context(session, create_window): session.window_handle = new_window session.close() - response = session.transport.send("POST", - "session/%s/elements" % session.session_id, - {"using": "css selector", "value": "foo"}) - + response = find_elements(session, "css selector", "foo") assert_error(response, "no such window") @@ -52,6 +49,51 @@ def test_find_elements(session, using, value): assert len(response.body["value"]) == 1 +@pytest.mark.parametrize("document,value", [ + ("link text", "link text"), + (" link text ", "link text"), + ("link
text
", "link\ntext"), + ("link&text", "link&text"), + ("LINK TEXT", "LINK TEXT"), + ("link text", "LINK TEXT"), +]) +def test_find_elements_link_text(session, document, value): + # Step 8 - 9 + session.url = inline("not wanted
{0}".format(document)) + expected = session.execute_script("return document.links[1];") + + response = find_elements(session, "link text", value) + value = assert_success(response) + assert isinstance(value, list) + assert len(value) == 1 + + found_element = value[0] + assert_same_element(session, found_element, expected) + + +@pytest.mark.parametrize("document,value", [ + ("partial link text", "link"), + (" partial link text ", "link"), + ("partial link text", "k t"), + ("partial link
text
", "k\nt"), + ("partial link&text", "k&t"), + ("PARTIAL LINK TEXT", "LINK"), + ("partial link text", "LINK"), +]) +def test_find_elements_partial_link_text(session, document, value): + # Step 8 - 9 + session.url = inline("not wanted
{0}".format(document)) + expected = session.execute_script("return document.links[1];") + + response = find_elements(session, "partial link text", value) + value = assert_success(response) + assert isinstance(value, list) + assert len(value) == 1 + + found_element = value[0] + assert_same_element(session, found_element, expected) + + @pytest.mark.parametrize("using,value", [("css selector", "#wontExist")]) def test_no_element(session, using, value): # Step 8 - 9 @@ -67,8 +109,9 @@ def test_no_element(session, using, value): ("tag name", "a"), ("xpath", "//*[name()='a']")]) def test_xhtml_namespace(session, using, value): - session.url = inline("""

full link text

""", doctype="xhtml") - expected = session.execute_script("return document.links[0]") + session.url = inline("""full link text""", + doctype="xhtml") + expected = session.execute_script("return document.links[0];") response = find_elements(session, using, value) value = assert_success(response) diff --git a/testing/web-platform/tests/webdriver/tests/element_retrieval/find_elements_from_element.py b/testing/web-platform/tests/webdriver/tests/element_retrieval/find_elements_from_element.py index 486d7cb7aee2..8bbd4c54f4d8 100644 --- a/testing/web-platform/tests/webdriver/tests/element_retrieval/find_elements_from_element.py +++ b/testing/web-platform/tests/webdriver/tests/element_retrieval/find_elements_from_element.py @@ -48,6 +48,53 @@ def test_find_elements(session, using, value): assert_success(response) +@pytest.mark.parametrize("document,value", [ + ("link text", "link text"), + (" link text ", "link text"), + ("link
text
", "link\ntext"), + ("link&text", "link&text"), + ("LINK TEXT", "LINK TEXT"), + ("link text", "LINK TEXT"), +]) +def test_find_elements_link_text(session, document, value): + # Step 8 - 9 + session.url = inline("
not wanted
{0}
".format(document)) + element = session.find.css("div", all=False) + expected = session.execute_script("return document.links[1];") + + response = find_elements(session, element.id, "link text", value) + value = assert_success(response) + assert isinstance(value, list) + assert len(value) == 1 + + found_element = value[0] + assert_same_element(session, found_element, expected) + + +@pytest.mark.parametrize("document,value", [ + ("partial link text", "link"), + (" partial link text ", "link"), + ("partial link text", "k t"), + ("partial link
text
", "k\nt"), + ("partial link&text", "k&t"), + ("PARTIAL LINK TEXT", "LINK"), + ("partial link text", "LINK"), +]) +def test_find_elements_partial_link_text(session, document, value): + # Step 8 - 9 + session.url = inline("
not wanted
{0}
".format(document)) + element = session.find.css("div", all=False) + expected = session.execute_script("return document.links[1];") + + response = find_elements(session, element.id, "partial link text", value) + value = assert_success(response) + assert isinstance(value, list) + assert len(value) == 1 + + found_element = value[0] + assert_same_element(session, found_element, expected) + + @pytest.mark.parametrize("using,value", [("css selector", "#wontExist")]) def test_no_element(session, using, value): # Step 8 - 9 @@ -64,7 +111,8 @@ def test_no_element(session, using, value): ("tag name", "a"), ("xpath", "//*[name()='a']")]) def test_xhtml_namespace(session, using, value): - session.url = inline("""

full link text

""", doctype="xhtml") + session.url = inline("""

full link text

""", + doctype="xhtml") from_element = session.execute_script("""return document.querySelector("p")""") expected = session.execute_script("return document.links[0]")