From 10f7615de27413ecd679c86ef3ab2ced94424721 Mon Sep 17 00:00:00 2001 From: Jani Mikkonen Date: Tue, 30 Mar 2021 16:57:25 +0300 Subject: [PATCH] Support 'data-' attributes as locators Adds new locator by data-* id's with syntax: data:id_name:actual_id Fixes #1474 --- .../acceptance/locators/locator_parsing.robot | 5 ++++ atest/resources/html/links.html | 3 ++- src/SeleniumLibrary/__init__.py | 4 +++ src/SeleniumLibrary/locators/elementfinder.py | 14 ++++++++++ ...cumentation.test_many_plugins.approved.txt | 4 +++ utest/test/locators/test_elementfinder.py | 27 +++++++++++++++++++ 6 files changed, 56 insertions(+), 1 deletion(-) diff --git a/atest/acceptance/locators/locator_parsing.robot b/atest/acceptance/locators/locator_parsing.robot index 3f13561cb..eca57d054 100644 --- a/atest/acceptance/locators/locator_parsing.robot +++ b/atest/acceptance/locators/locator_parsing.robot @@ -14,6 +14,11 @@ xpath with // and without prefix should work xpath with (// and without prefix should work Page Should Contain Element (//div[@id="div_id"]/a)[1] +Locator with with data prefix + Page Should Contain Element data:id:my_id + Page Should Contain Element data:automation:my_automation_id + Page Should Not Contain Element data:non_existent:some_random_id + Locator without prefix Page Should Contain Element div_id diff --git a/atest/resources/html/links.html b/atest/resources/html/links.html index bf38d6a4c..bfde01584 100644 --- a/atest/resources/html/links.html +++ b/atest/resources/html/links.html @@ -36,9 +36,10 @@ Image Link -
+
Target opens in new window
+ diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 6bb072885..c47ee4100 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -136,6 +136,7 @@ class SeleniumLibrary(DynamicCore): | link | Exact text a link has. | ``link:The example`` | | partial link | Partial link text. | ``partial link:he ex`` | | sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` | + | data | Element ``data-*`` attribute | ``data:id:my_id`` | | jquery | jQuery expression. | ``jquery:div.example`` | | default | Keyword specific default behavior. | ``default:example`` | @@ -171,6 +172,9 @@ class SeleniumLibrary(DynamicCore): the system under test contains the jQuery library. - Prior to SeleniumLibrary 3.0, table related keywords only supported ``xpath``, ``css`` and ``sizzle/jquery`` strategies. + - ``data`` strategy is conveniance locator that will construct xpath from the parameters. + If you have element like `
`, you locate the element via + ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0 === Implicit XPath strategy === diff --git a/src/SeleniumLibrary/locators/elementfinder.py b/src/SeleniumLibrary/locators/elementfinder.py index 6b904ac2d..d74486a3e 100644 --- a/src/SeleniumLibrary/locators/elementfinder.py +++ b/src/SeleniumLibrary/locators/elementfinder.py @@ -46,6 +46,7 @@ def __init__(self, ctx): "sizzle": self._find_by_jquery_selector, "tag": self._find_by_tag_name, "scLocator": self._find_by_sc_locator, + "data": self._find_by_data_locator, "default": self._find_by_default, } self._strategies = NormalizedDict( @@ -220,6 +221,19 @@ def _find_by_tag_name(self, criteria, tag, constraints, parent): parent.find_elements(By.TAG_NAME, criteria), tag, constraints ) + def _find_by_data_locator(self, criteria, tag, constraints, parent): + try: + name, value = criteria.split(":", 2) + if "" in [name, value]: + raise ValueError + except ValueError: + raise ValueError( + f"Provided selector ({criteria}) is malformed. Correct format: name:value." + ) + + local_criteria = f'//*[@data-{name}="{value}"]' + return self._find_by_xpath(local_criteria, tag, constraints, parent) + def _find_by_sc_locator(self, criteria, tag, constraints, parent): self._disallow_webelement_parent(parent) criteria = criteria.replace("'", "\\'") diff --git a/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt b/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt index 0603c647b..d9699f302 100644 --- a/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt +++ b/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt @@ -79,6 +79,7 @@ below. In addition to them, it is possible to register `custom locators`. | link | Exact text a link has. | ``link:The example`` | | partial link | Partial link text. | ``partial link:he ex`` | | sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` | +| data | Element ``data-*`` attribute | ``data:id:my_id`` | | jquery | jQuery expression. | ``jquery:div.example`` | | default | Keyword specific default behavior. | ``default:example`` | @@ -114,6 +115,9 @@ Examples: the system under test contains the jQuery library. - Prior to SeleniumLibrary 3.0, table related keywords only supported ``xpath``, ``css`` and ``sizzle/jquery`` strategies. +- ``data`` strategy is conveniance locator that will construct xpath from the parameters. + If you have element like `
`, you locate the element via + ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0 === Implicit XPath strategy === diff --git a/utest/test/locators/test_elementfinder.py b/utest/test/locators/test_elementfinder.py index 1c5958484..98f5ddc87 100644 --- a/utest/test/locators/test_elementfinder.py +++ b/utest/test/locators/test_elementfinder.py @@ -68,6 +68,13 @@ def test_strategy_case_is_not_changed(): _verify_parse_locator("XPATH=//foo/bar ", "XPATH", "//foo/bar ") +def test_data_locator_parsing(): + _verify_parse_locator("data:id:my_id", "data", "id:my_id") + _verify_parse_locator( + "data:automation:my_automation_id", "data", "automation:my_automation_id" + ) + + def test_remove_whitespace_around_prefix_and_separator(): _verify_parse_locator("class = foo", "class", "foo") _verify_parse_locator("class : foo", "class", "foo") @@ -271,6 +278,26 @@ def test_find_with_tag(finder): verify(driver).find_elements(By.XPATH, "//div[(@id='test1' or @name='test1')]") +def test_find_with_data(finder): + driver = _get_driver(finder) + finder.find("data:id:my_id", tag="div", required=False) + verify(driver).find_elements(By.XPATH, '//*[@data-id="my_id"]') + + +def test_find_with_invalid_data(finder): + with pytest.raises( + ValueError, + match=r"^Provided selector \(id:\) is malformed\. Correct format: name:value\.", + ): + finder.find("data:id:", tag="div", required=False) + + with pytest.raises( + ValueError, + match=r"^Provided selector \(\) is malformed\. Correct format: name:value\.", + ): + finder.find("data:", tag="div", required=False) + + def test_find_with_locator_with_apos(finder): driver = _get_driver(finder) finder.find("test '1'", required=False) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy