1

I am trying to select choices from a dropdown menu, using Selenium with Python. The menu might be built as a button as I had no luck trying to use Select. It also might be a Bootstrap dropdown. Here is an excerpt of what I see when I use Inspect on Chrome. The “Choice 4” selection near the end of the code is the menu choice I would like to make. This is a webpage that is not publicly accessible.

<div class="SLP-dropdown SLP-dropdown-placement-bottomLeft" data-qa="SLP-dropdown" style="left: 429px; top: 436px; width: 117px;">
    <ul class="SLP-dropdown-menu SLP-dropdown-menu-root SLP-dropdown-menu-vertical" role-“menu" tabindex="0">
        <li class="SLP-dropdown-menu-item" role="menuitem">Choice 1</li>
        <li class="SLP-dropdown-menu-item" role="menuitem">Choice 2</li>
        <li class="SLP-dropdown-menu-item" role="menuitem">Choice 3</li>
        <li class="SLP-dropdown-menu-item" role="menuitem">Choice 4</li>

Here is my current code. I can get the dropdown to display the four selections on the screen using the "SLP-input" ID, but it won't let me select any of the four selections.

import selenium
from selenium import webdriver

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://sample URL")
driver.find_element(By.ID, "SLP-input").click()
driver.find_element(By.XPATH, "//select/option[contains(text(),'Choice 4')]").click()

Here is the error:

---------------------------------------------------------------------------
NoSuchElementException                    Traceback (most recent call last)
Cell In[30], line 28
     24 #driver.find_element(By.XPATH, "//span[contains(text(),'dummy')]").click()
     26 driver.find_element(By.ID, "ag-105-input").click()
---> 28 driver.find_element(By.XPATH, "//select/option[contains(text(),'Choice 4')]").click()
     30 #driver.find_element(By.XPATH, "//li[contains(text(),'Choice 4')]").click()
     31 #driver.find_element(By.XPATH, "//li[text()='Choice4rmats']").click()
     32 
   (...)     80 
     81 #driver.quit()

File ~\AppData\Local\anaconda3\Lib\site-packages\selenium\webdriver\remote\webdriver.py:926, in WebDriver.find_element(self, by, value)
    923         raise NoSuchElementException(f"Cannot locate relative element with: {by.root}")
    924     return elements[0]
--> 926 return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"]

File ~\AppData\Local\anaconda3\Lib\site-packages\selenium\webdriver\remote\webdriver.py:458, in WebDriver.execute(self, driver_command, params)
    455 response = cast(RemoteConnection, self.command_executor).execute(driver_command, params)
    457 if response:
--> 458     self.error_handler.check_response(response)
    459     response["value"] = self._unwrap_value(response.get("value", None))
    460     return response

File ~\AppData\Local\anaconda3\Lib\site-packages\selenium\webdriver\remote\errorhandler.py:232, in ErrorHandler.check_response(self, response)
    230         alert_text = value["alert"].get("text")
    231     raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
--> 232 raise exception_class(message, screen, stacktrace)

NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//select/option[contains(text(),'All formats')]"}
  (Session info: chrome=143.0.7499.41); For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#nosuchelementexception
Stacktrace:
Symbols not available. Dumping unresolved backtrace:
    0x7ff7ccbe8255
    0x7ff7ccbe82b0
    0x7ff7cc9c165d
    0x7ff7cca19a33
    0x7ff7cca19d3c
    0x7ff7cca6df67
    0x7ff7cca6ac97
    0x7ff7cca0ac29
    0x7ff7cca0ba93
    0x7ff7cceffff0
    0x7ff7ccefa930
    0x7ff7ccf19096
    0x7ff7ccc05754
    0x7ff7ccc0e6fc
    0x7ff7ccbf1974
    0x7ff7ccbf1b25
    0x7ff7ccbd7852
    0x7ffccbe5e8d7
    0x7ffccd0ac53c
1
  • There is no HTML element with the id of "SLP-input" in the fragment you've shown Commented 2 days ago

3 Answers 3

0

Your locator:

driver.find_element(By.XPATH, "//select/option[contains(text(),'Choice 4')]").click()

... doesn't match the HTML you posted? I don't see a <select> element with options. Don't you want something like:

driver.find_element(By.XPATH, "//li[contains(text(),'Choice 4')").click()

You could also select all elements with class SLP-dropdown-menu-item, and filter the one with the text you want:

elements  = driver.find_elements(By.CLASS_NAME, "SLP-dropdown-menu-item")
element = [e for e in elements if "Choice 4" in e.text][0]
element.click()
Sign up to request clarification or add additional context in comments.

Comments

0

As you've discovered, not every dropdown on the page is a SELECT element in the HTML. In this case they've used CSS to format UL and LI elements to look like a dropdown. Since it's not an actual SELECT element, we can't use the typical Selenium SELECT helper methods... we need to treat this like any other HTML elements.

From your stack trace I can see two issues:

  1. Your XPath, //select/option[contains(text(),'Choice 4')] is referencing a SELECT element that doesn't exist... at least not in the HTML you provided and seemingly not on the page since you're getting a NoSuchElementException.

  2. Your XPath, //li[contains(text(),'Choice 4')] in the commented code should have worked... but probably didn't because you didn't have a wait. Clicking the dropdown, it likely takes a fraction of a second to open the dropdown but likely long enough that a straight driver.find_element() will probably fail because the element doesn't exist as fast as the code is running.

Solutions:

  1. From the HTML provided, you shouldn't need the XPath contains(). It can be simplified to //li[text()='Choice 4']. If there is whitespace in there, you'll need to add the contains() back.

  2. I would add code for a wait for each of the clicks: 1. open the dropdown, 2. select the desired option.

Updated code:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

url = 'https://sample URL'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(url)

wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div[data-qa='SLP-dropdown']"))).click()
wait.until(EC.element_to_be_clickable((By.XPATH, "//li[text()='Choice 4']"))).click()

Bonus: If you are going to make different selections in different scripts, I would spend a minute and write a method that takes the choice as a parameter so that it's reusable and easier to maintain.

def choice(number):
    wait = WebDriverWait(driver, 10)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div[data-qa='SLP-dropdown']"))).click()
    wait.until(EC.element_to_be_clickable((By.XPATH, f"//li[text()='Choice {number}']"))).click()

Now your code looks like:

url = 'https://sample URL'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(url)

choice(4)
...

3 Comments

Thank you for the input. I found an issue with my original question. I have NOT successfully opened the dropdown. The "SLP-input" checks a checkbox for a previous step, which makes the dropdown available. But it doesn't exposure the choices in the dropdown like I thought. Apologies for the error. I will revise the question or add to it.
I updated the first click's locator based on the HTML you provided. Let me know if it works.
Did you ever try my updated answer?
-1
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# ----------------------------
# 1. Open browser
# ----------------------------
driver = webdriver.Chrome()
driver.maximize_window()

# ----------------------------
# 2. Go to page
# ----------------------------
driver.get("https://sample_URL")   # <<< change to your URL

wait = WebDriverWait(driver, 10)

# ----------------------------
# 3. Click the dropdown input
# ----------------------------
dropdown_input = wait.until(
    EC.element_to_be_clickable((By.ID, "SLP-input"))
)
driver.execute_script("arguments[0].click();", dropdown_input)

# ----------------------------
# 4. Wait for the dropdown items and select Choice 4
# ----------------------------
choice4 = wait.until(
    EC.element_to_be_clickable((
        By.XPATH, "//li[contains(@class,'SLP-dropdown-menu-item')][contains(text(),'Choice 4')]"
    ))
)

# JavaScript click is safest for dynamic dropdowns
driver.execute_script("arguments[0].click();", choice4)

print("Successfully selected Choice 4!")

# ----------------------------
# 5. Close browser (optional)
# ----------------------------
# driver.quit()
New contributor
Ruhaan is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

2 Comments

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
Please justify your comment "JavaScript click is safest for dynamic dropdowns"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.