Skip to content

Commit 0ff768a

Browse files
authored
[py] Raise InvalidSelectorException for compound class names (#16291)
1 parent 034f503 commit 0ff768a

File tree

4 files changed

+30
-56
lines changed

4 files changed

+30
-56
lines changed

py/selenium/webdriver/remote/locator_converter.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17+
18+
from selenium.common.exceptions import InvalidSelectorException
1719
from selenium.webdriver.common.by import By
1820

1921

@@ -23,6 +25,8 @@ def convert(self, by, value):
2325
if by == By.ID:
2426
return By.CSS_SELECTOR, f'[id="{value}"]'
2527
elif by == By.CLASS_NAME:
28+
if value and any(char.isspace() for char in value.strip()):
29+
raise InvalidSelectorException("Compound class names are not allowed.")
2630
return By.CSS_SELECTOR, f".{value}"
2731
elif by == By.NAME:
2832
return By.CSS_SELECTOR, f'[name="{value}"]'

py/selenium/webdriver/remote/shadowroot.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from hashlib import md5 as md5_hash
1919

20+
from selenium.common.exceptions import InvalidSelectorException
2021
from selenium.webdriver.common.by import By
2122
from selenium.webdriver.remote.command import Command
2223

@@ -74,6 +75,8 @@ def find_element(self, by: str = By.ID, value: str = None):
7475
by = By.CSS_SELECTOR
7576
value = f'[id="{value}"]'
7677
elif by == By.CLASS_NAME:
78+
if value and any(char.isspace() for char in value.strip()):
79+
raise InvalidSelectorException("Compound class names are not allowed.")
7780
by = By.CSS_SELECTOR
7881
value = f".{value}"
7982
elif by == By.NAME:
@@ -112,6 +115,8 @@ def find_elements(self, by: str = By.ID, value: str = None):
112115
by = By.CSS_SELECTOR
113116
value = f'[id="{value}"]'
114117
elif by == By.CLASS_NAME:
118+
if value and any(char.isspace() for char in value.strip()):
119+
raise InvalidSelectorException("Compound class names are not allowed.")
115120
by = By.CSS_SELECTOR
116121
value = f".{value}"
117122
elif by == By.NAME:

py/selenium/webdriver/remote/webdriver.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17+
1718
"""The WebDriver implementation."""
1819

1920
import base64

py/test/selenium/webdriver/common/driver_element_finding_tests.py

Lines changed: 20 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from selenium.common.exceptions import InvalidSelectorException, NoSuchElementException
2121
from selenium.webdriver.common.by import By
2222

23-
# By.id positive
23+
# By.ID positive
2424

2525

2626
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):
5353
assert len(elements) == 8
5454

5555

56-
# By.id negative
56+
# By.ID negative
5757

5858

5959
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):
9999
driver.find_element(By.ID, "non_Existent_Button")
100100

101101

102-
# By.name positive
102+
# By.NAME positive
103103

104104

105105
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
120120
assert element.get_attribute("name") == "div1"
121121

122122

123-
# By.name negative
123+
# By.NAME negative
124124

125125

126126
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
159159
assert len(elements) == 0
160160

161161

162-
# By.tag_Name positive
162+
# By.TAG_NAME positive
163163

164164

165165
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):
174174
assert len(elements) > 1
175175

176176

177-
# By.tag_Name negative
177+
# By.TAG_NAME negative
178178

179179

180180
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_
189189
assert len(elements) == 0
190190

191191

192-
@pytest.mark.xfail_firefox(reason="https://github.com/mozilla/geckodriver/issues/2007")
193-
@pytest.mark.xfail_remote(reason="https://github.com/mozilla/geckodriver/issues/2007")
192+
@pytest.mark.xfail_firefox(reason="unlike chrome, firefox raises NoSuchElementException")
193+
@pytest.mark.xfail_remote(reason="unlike chrome, firefox raises NoSuchElementException")
194194
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises NoSuchElementException")
195-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
196-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
197195
def test_finding_asingle_element_by_empty_tag_name_should_throw(driver, pages):
198196
pages.load("formPage.html")
199197
with pytest.raises(InvalidSelectorException):
200198
driver.find_element(By.TAG_NAME, "")
201199

202200

203-
@pytest.mark.xfail_firefox(reason="https://github.com/mozilla/geckodriver/issues/2007")
204-
@pytest.mark.xfail_remote(reason="https://github.com/mozilla/geckodriver/issues/2007")
201+
@pytest.mark.xfail_firefox(reason="unlike chrome, firefox returns an empty list")
202+
@pytest.mark.xfail_remote(reason="unlike chrome, firefox returns an empty list")
205203
@pytest.mark.xfail_safari(reason="unlike chrome, safari returns an empty list")
206-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
207-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
208204
def test_finding_multiple_elements_by_empty_tag_name_should_throw(driver, pages):
209205
pages.load("formPage.html")
210206
with pytest.raises(InvalidSelectorException):
@@ -223,7 +219,7 @@ def test_finding_multiple_elements_by_tag_name_with_space_should_return_empty_li
223219
assert len(elements) == 0
224220

225221

226-
# By.class_Name positive
222+
# By.CLASS_NAME positive
227223

228224

229225
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
269265
assert elements[0].text == "Spaced out"
270266

271267

272-
# By.class_Name negative
268+
# By.CLASS_NAME negative
273269

274270

275271
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_
279275

280276

281277
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
282-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
283-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
284278
def test_finding_asingle_element_by_empty_class_name_should_throw(driver, pages):
285279
pages.load("xhtmlTest.html")
286280
msg = r"\/errors#invalidselectorexception"
@@ -289,8 +283,6 @@ def test_finding_asingle_element_by_empty_class_name_should_throw(driver, pages)
289283

290284

291285
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
292-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
293-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
294286
def test_finding_multiple_elements_by_empty_class_name_should_throw(driver, pages):
295287
pages.load("xhtmlTest.html")
296288
with pytest.raises(InvalidSelectorException):
@@ -299,29 +291,25 @@ def test_finding_multiple_elements_by_empty_class_name_should_throw(driver, page
299291

300292
def test_finding_asingle_element_by_compound_class_name_should_throw(driver, pages):
301293
pages.load("xhtmlTest.html")
302-
with pytest.raises(NoSuchElementException):
294+
with pytest.raises(InvalidSelectorException):
303295
driver.find_element(By.CLASS_NAME, "a b")
304296

305297

306298
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
307-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
308-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
309299
def test_finding_asingle_element_by_invalid_class_name_should_throw(driver, pages):
310300
pages.load("xhtmlTest.html")
311301
with pytest.raises(InvalidSelectorException):
312302
driver.find_element(By.CLASS_NAME, "!@#$%^&*")
313303

314304

315305
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
316-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
317-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
318306
def test_finding_multiple_elements_by_invalid_class_name_should_throw(driver, pages):
319307
pages.load("xhtmlTest.html")
320308
with pytest.raises(InvalidSelectorException):
321309
driver.find_elements(By.CLASS_NAME, "!@#$%^&*")
322310

323311

324-
# By.xpath positive
312+
# By.XPATH positive
325313

326314

327315
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):
388376
assert "baz" in element.text
389377

390378

391-
# By.xpath negative
379+
# By.XPATH negative
392380

393381

394382
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)
398386

399387

400388
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
401-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
402-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
403389
def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_invalid_in_driver_find_element(
404390
driver, pages
405391
):
@@ -409,8 +395,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_inv
409395

410396

411397
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
412-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
413-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
414398
def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_invalid_in_driver_find_elements(
415399
driver, pages
416400
):
@@ -420,8 +404,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_inv
420404

421405

422406
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
423-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
424-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
425407
def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_invalid_in_element_find_element(
426408
driver, pages
427409
):
@@ -432,8 +414,6 @@ def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_inv
432414

433415

434416
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
435-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
436-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
437417
def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_invalid_in_element_find_elements(
438418
driver, pages
439419
):
@@ -444,26 +424,20 @@ def test_should_throw_invalid_selector_exception_when_xpath_is_syntactically_inv
444424

445425

446426
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
447-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
448-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
449427
def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_in_driver_find_element(driver, pages):
450428
pages.load("formPage.html")
451429
with pytest.raises(InvalidSelectorException):
452430
driver.find_element(By.XPATH, "count(//input)")
453431

454432

455433
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
456-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
457-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
458434
def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_in_driver_find_elements(driver, pages):
459435
pages.load("formPage.html")
460436
with pytest.raises(InvalidSelectorException):
461437
driver.find_elements(By.XPATH, "count(//input)")
462438

463439

464440
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
465-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
466-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
467441
def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_in_element_find_element(driver, pages):
468442
pages.load("formPage.html")
469443
body = driver.find_element(By.TAG_NAME, "body")
@@ -472,16 +446,14 @@ def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_i
472446

473447

474448
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
475-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
476-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
477449
def test_should_throw_invalid_selector_exception_when_xpath_returns_wrong_type_in_element_find_elements(driver, pages):
478450
pages.load("formPage.html")
479451
body = driver.find_element(By.TAG_NAME, "body")
480452
with pytest.raises(InvalidSelectorException):
481453
body.find_elements(By.XPATH, "count(//input)")
482454

483455

484-
# By.css_Selector positive
456+
# By.CSS_SELECTOR positive
485457

486458

487459
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_
530502
assert element.get_attribute("value") == "two"
531503

532504

533-
# By.css_Selector negative
505+
# By.CSS_SELECTOR negative
534506

535507

536508
def test_should_not_find_element_by_css_selector_when_there_is_no_such_element(driver, pages):
@@ -546,42 +518,34 @@ def test_should_not_find_elements_by_css_selector_when_there_is_no_such_element(
546518

547519

548520
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
549-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
550-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
551521
def test_finding_asingle_element_by_empty_css_selector_should_throw(driver, pages):
552522
pages.load("xhtmlTest.html")
553523
with pytest.raises(InvalidSelectorException):
554524
driver.find_element(By.CSS_SELECTOR, "")
555525

556526

557527
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
558-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
559-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
560528
def test_finding_multiple_elements_by_empty_css_selector_should_throw(driver, pages):
561529
pages.load("xhtmlTest.html")
562530
with pytest.raises(InvalidSelectorException):
563531
driver.find_elements(By.CSS_SELECTOR, "")
564532

565533

566534
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
567-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
568-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
569535
def test_finding_asingle_element_by_invalid_css_selector_should_throw(driver, pages):
570536
pages.load("xhtmlTest.html")
571537
with pytest.raises(InvalidSelectorException):
572538
driver.find_element(By.CSS_SELECTOR, "//a/b/c[@id='1']")
573539

574540

575541
@pytest.mark.xfail_safari(reason="unlike chrome, safari raises TimeoutException")
576-
@pytest.mark.xfail_chrome(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
577-
@pytest.mark.xfail_edge(reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=4743")
578542
def test_finding_multiple_elements_by_invalid_css_selector_should_throw(driver, pages):
579543
pages.load("xhtmlTest.html")
580544
with pytest.raises(InvalidSelectorException):
581545
driver.find_elements(By.CSS_SELECTOR, "//a/b/c[@id='1']")
582546

583547

584-
# By.link_Text positive
548+
# By.LINK_TEXT positive
585549

586550

587551
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
632596
assert link.text == "link with trailing space"
633597

634598

635-
# By.link_Text negative
599+
# By.LINK_TEXT negative
636600

637601

638602
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
647611
assert len(elements) == 0
648612

649613

650-
# By.partial_Link_Text positive
614+
# By.PARTIAL_LINK_TEXT positive
651615

652616

653617
def test_should_be_able_to_find_multiple_elements_by_partial_link_text(driver, pages):

0 commit comments

Comments
 (0)