diff --git a/py/selenium/webdriver/remote/locator_converter.py b/py/selenium/webdriver/remote/locator_converter.py index e924d7fd6904f..ceb05c4f25a80 100644 --- a/py/selenium/webdriver/remote/locator_converter.py +++ b/py/selenium/webdriver/remote/locator_converter.py @@ -14,6 +14,8 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. + +from selenium.common.exceptions import InvalidSelectorException from selenium.webdriver.common.by import By @@ -23,6 +25,8 @@ def convert(self, by, value): if by == By.ID: return By.CSS_SELECTOR, f'[id="{value}"]' elif by == By.CLASS_NAME: + if value and any(char.isspace() for char in value.strip()): + raise InvalidSelectorException("Compound class names are not allowed.") return By.CSS_SELECTOR, f".{value}" elif by == By.NAME: return By.CSS_SELECTOR, f'[name="{value}"]' diff --git a/py/selenium/webdriver/remote/shadowroot.py b/py/selenium/webdriver/remote/shadowroot.py index 960377081f7dd..f23f5c42e38c8 100644 --- a/py/selenium/webdriver/remote/shadowroot.py +++ b/py/selenium/webdriver/remote/shadowroot.py @@ -17,6 +17,7 @@ from hashlib import md5 as md5_hash +from selenium.common.exceptions import InvalidSelectorException from selenium.webdriver.common.by import By from selenium.webdriver.remote.command import Command @@ -74,6 +75,8 @@ def find_element(self, by: str = By.ID, value: str = None): by = By.CSS_SELECTOR value = f'[id="{value}"]' elif by == By.CLASS_NAME: + if value and any(char.isspace() for char in value.strip()): + raise InvalidSelectorException("Compound class names are not allowed.") by = By.CSS_SELECTOR value = f".{value}" elif by == By.NAME: @@ -112,6 +115,8 @@ def find_elements(self, by: str = By.ID, value: str = None): by = By.CSS_SELECTOR value = f'[id="{value}"]' elif by == By.CLASS_NAME: + if value and any(char.isspace() for char in value.strip()): + raise InvalidSelectorException("Compound class names are not allowed.") by = By.CSS_SELECTOR value = f".{value}" elif by == By.NAME: diff --git a/py/selenium/webdriver/remote/webdriver.py b/py/selenium/webdriver/remote/webdriver.py index 84cc7c5b5b751..cb8d08b089085 100644 --- a/py/selenium/webdriver/remote/webdriver.py +++ b/py/selenium/webdriver/remote/webdriver.py @@ -14,6 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. + """The WebDriver implementation.""" import base64 diff --git a/py/test/selenium/webdriver/common/driver_element_finding_tests.py b/py/test/selenium/webdriver/common/driver_element_finding_tests.py index cfdca06e23ca5..42df9ff2f9965 100644 --- a/py/test/selenium/webdriver/common/driver_element_finding_tests.py +++ b/py/test/selenium/webdriver/common/driver_element_finding_tests.py @@ -20,7 +20,7 @@ from selenium.common.exceptions import InvalidSelectorException, NoSuchElementException from selenium.webdriver.common.by import By -# By.id positive +# By.ID positive def test_should_be_able_to_find_asingle_element_by_id(driver, pages): @@ -53,7 +53,7 @@ def test_should_be_able_to_find_multiple_elements_by_numeric_id(driver, pages): assert len(elements) == 8 -# By.id negative +# By.ID negative def test_should_not_be_able_to_locate_by_id_asingle_element_that_does_not_exist(driver, pages): @@ -99,7 +99,7 @@ def test_no_such_element_error(driver, pages): driver.find_element(By.ID, "non_Existent_Button") -# By.name positive +# By.NAME positive def test_should_be_able_to_find_asingle_element_by_name(driver, pages): @@ -120,7 +120,7 @@ def test_should_be_able_to_find_an_element_that_does_not_support_the_name_proper assert element.get_attribute("name") == "div1" -# By.name negative +# By.NAME negative def test_should_not_be_able_to_locate_by_name_asingle_element_that_does_not_exist(driver, pages): @@ -159,7 +159,7 @@ def test_finding_multiple_elements_by_name_with_space_should_return_empty_list(d assert len(elements) == 0 -# By.tag_Name positive +# By.TAG_NAME positive def test_should_be_able_to_find_asingle_element_by_tag_name(driver, pages): @@ -174,7 +174,7 @@ def test_should_be_able_to_find_multiple_elements_by_tag_name(driver, pages): assert len(elements) > 1 -# By.tag_Name negative +# By.TAG_NAME negative def test_should_not_be_able_to_locate_by_tag_name_asingle_element_that_does_not_exist(driver, pages): @@ -189,22 +189,18 @@ def test_should_not_be_able_to_locate_by_tag_name_multiple_elements_that_do_not_ assert len(elements) == 0 -@pytest.mark.xfail_firefox(reason="https://github.com/mozilla/geckodriver/issues/2007") -@pytest.mark.xfail_remote(reason="https://github.com/mozilla/geckodriver/issues/2007") +@pytest.mark.xfail_firefox(reason="unlike chrome, firefox raises NoSuchElementException") +@pytest.mark.xfail_remote(reason="unlike chrome, firefox raises NoSuchElementException") @pytest.mark.xfail_safari(reason="unlike chrome, safari raises NoSuchElementException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_asingle_element_by_empty_tag_name_should_throw(driver, pages): pages.load("formPage.html") with pytest.raises(InvalidSelectorException): driver.find_element(By.TAG_NAME, "") -@pytest.mark.xfail_firefox(reason="https://github.com/mozilla/geckodriver/issues/2007") -@pytest.mark.xfail_remote(reason="https://github.com/mozilla/geckodriver/issues/2007") +@pytest.mark.xfail_firefox(reason="unlike chrome, firefox returns an empty list") +@pytest.mark.xfail_remote(reason="unlike chrome, firefox returns an empty list") @pytest.mark.xfail_safari(reason="unlike chrome, safari returns an empty list") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_multiple_elements_by_empty_tag_name_should_throw(driver, pages): pages.load("formPage.html") with pytest.raises(InvalidSelectorException): @@ -223,7 +219,7 @@ def test_finding_multiple_elements_by_tag_name_with_space_should_return_empty_li assert len(elements) == 0 -# By.class_Name positive +# By.CLASS_NAME positive def test_should_be_able_to_find_asingle_element_by_class(driver, pages): @@ -269,7 +265,7 @@ def test_should_find_elements_by_class_when_its_name_is_surrounded_by_whitespace assert elements[0].text == "Spaced out" -# By.class_Name negative +# By.CLASS_NAME negative def test_should_not_find_element_by_class_when_the_name_queried_is_shorter_than_candidate_name(driver, pages): @@ -279,8 +275,6 @@ def test_should_not_find_element_by_class_when_the_name_queried_is_shorter_than_ @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_asingle_element_by_empty_class_name_should_throw(driver, pages): pages.load("xhtmlTest.html") msg = r"\/errors#invalidselectorexception" @@ -289,8 +283,6 @@ def test_finding_asingle_element_by_empty_class_name_should_throw(driver, pages) @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_multiple_elements_by_empty_class_name_should_throw(driver, pages): pages.load("xhtmlTest.html") with pytest.raises(InvalidSelectorException): @@ -299,13 +291,11 @@ def test_finding_multiple_elements_by_empty_class_name_should_throw(driver, page def test_finding_asingle_element_by_compound_class_name_should_throw(driver, pages): pages.load("xhtmlTest.html") - with pytest.raises(NoSuchElementException): + with pytest.raises(InvalidSelectorException): driver.find_element(By.CLASS_NAME, "a b") @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_asingle_element_by_invalid_class_name_should_throw(driver, pages): pages.load("xhtmlTest.html") with pytest.raises(InvalidSelectorException): @@ -313,15 +303,13 @@ def test_finding_asingle_element_by_invalid_class_name_should_throw(driver, page @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_multiple_elements_by_invalid_class_name_should_throw(driver, pages): pages.load("xhtmlTest.html") with pytest.raises(InvalidSelectorException): driver.find_elements(By.CLASS_NAME, "!@#$%^&*") -# By.xpath positive +# By.XPATH positive def test_should_be_able_to_find_asingle_element_by_xpath(driver, pages): @@ -388,7 +376,7 @@ def test_should_be_able_to_find_element_by_xpath_in_xml_document(driver, pages): assert "baz" in element.text -# By.xpath negative +# By.XPATH negative def test_should_throw_an_exception_when_there_is_no_link_to_click(driver, pages): @@ -398,8 +386,6 @@ def test_should_throw_an_exception_when_there_is_no_link_to_click(driver, pages) @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_invalid_in_driver_find_element( driver, pages ): @@ -409,8 +395,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_inv @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_invalid_in_driver_find_elements( driver, pages ): @@ -420,8 +404,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_inv @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_invalid_in_element_find_element( driver, pages ): @@ -432,8 +414,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_inv @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_invalid_in_element_find_elements( driver, pages ): @@ -444,8 +424,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_inv @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_in_driver_find_element(driver, pages): pages.load("formPage.html") with pytest.raises(InvalidSelectorException): @@ -453,8 +431,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_i @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_in_driver_find_elements(driver, pages): pages.load("formPage.html") with pytest.raises(InvalidSelectorException): @@ -462,8 +438,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_i @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_in_element_find_element(driver, pages): pages.load("formPage.html") body = driver.find_element(By.TAG_NAME, "body") @@ -472,8 +446,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_i @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_in_element_find_elements(driver, pages): pages.load("formPage.html") body = driver.find_element(By.TAG_NAME, "body") @@ -481,7 +453,7 @@ def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_i body.find_elements(By.XPATH, "count(//input)") -# By.css_Selector positive +# By.CSS_SELECTOR positive def test_should_be_able_to_find_asingle_element_by_css_selector(driver, pages): @@ -530,7 +502,7 @@ def test_should_be_able_to_find_an_element_by_boolean_attribute_using_short_css_ assert element.get_attribute("value") == "two" -# By.css_Selector negative +# By.CSS_SELECTOR negative def test_should_not_find_element_by_css_selector_when_there_is_no_such_element(driver, pages): @@ -546,8 +518,6 @@ def test_should_not_find_elements_by_css_selector_when_there_is_no_such_element( @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_asingle_element_by_empty_css_selector_should_throw(driver, pages): pages.load("xhtmlTest.html") with pytest.raises(InvalidSelectorException): @@ -555,8 +525,6 @@ def test_finding_asingle_element_by_empty_css_selector_should_throw(driver, page @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_multiple_elements_by_empty_css_selector_should_throw(driver, pages): pages.load("xhtmlTest.html") with pytest.raises(InvalidSelectorException): @@ -564,8 +532,6 @@ def test_finding_multiple_elements_by_empty_css_selector_should_throw(driver, pa @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_asingle_element_by_invalid_css_selector_should_throw(driver, pages): pages.load("xhtmlTest.html") with pytest.raises(InvalidSelectorException): @@ -573,15 +539,13 @@ def test_finding_asingle_element_by_invalid_css_selector_should_throw(driver, pa @pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException") -@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") -@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743") def test_finding_multiple_elements_by_invalid_css_selector_should_throw(driver, pages): pages.load("xhtmlTest.html") with pytest.raises(InvalidSelectorException): driver.find_elements(By.CSS_SELECTOR, "//a/b/c[@id='1']") -# By.link_Text positive +# By.LINK_TEXT positive def test_should_be_able_to_find_alink_by_text(driver, pages): @@ -632,7 +596,7 @@ def test_driver_can_get_link_by_link_test_ignoring_trailing_whitespace(driver, p assert link.text == "link with trailing space" -# By.link_Text negative +# By.LINK_TEXT negative def test_should_not_be_able_to_locate_by_link_text_asingle_element_that_does_not_exist(driver, pages): @@ -647,7 +611,7 @@ def test_should_not_be_able_to_locate_by_link_text_multiple_elements_that_do_not assert len(elements) == 0 -# By.partial_Link_Text positive +# By.PARTIAL_LINK_TEXT positive def test_should_be_able_to_find_multiple_elements_by_partial_link_text(driver, pages):