Reputation: 1021
I have the following MRE code that is mean to select EU Odds
from a dropdown:
from pathlib import Path
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.ui import WebDriverWait
chrome_driver = str(Path("chromedriver/chromedriver/"))
driver = webdriver.Chrome(chrome_driver)
driver.get("https://www.oddsportal.com/matches/tennis/")
driver.find_element(By.ID, "user-header-oddsformat-expander").click()
sleep(1)
wait = WebDriverWait(driver, 10)
target = "EU Odds"
wait.until(ec.element_to_be_clickable((By.XPATH, "//li[.='" + target + "']"))).click()
Everything works up until the final line which doesn't make the selection. If I try to do this manually on the page that chromedriver opens then I'm also unable to make the selection. However, if I open up a normal browsing window then I am able to make the selection.
Where am I going wrong?
Upvotes: 1
Views: 128
Reputation: 193308
From a broader perspective there is nothing wrong in your code.
However to optimize your code you may like to:
Induce WebDriverWait for the element_to_be_clickable()
for the expander to be clickable.
The texts EU Odds, UK Odds, US Odds, etc are not exactly within the <li>
but within it's grand parent //li/a/span
So to select EU Odds, UK Odds, US Odds one by one your optimized Locator Strategies can be:
driver.get('https://www.oddsportal.com/matches/tennis/')
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "user-header-oddsformat-expander"))).click()
target = "EU Odds"
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//li/a/span[text()='" + target + "']"))).click()
time.sleep(3) # for visual demonstration
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "user-header-oddsformat-expander"))).click()
target = "UK Odds"
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//li/a/span[text()='" + target + "']"))).click()
time.sleep(3) # for visual demonstration
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "user-header-oddsformat-expander"))).click()
target = "US Odds"
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//li/a/span[text()='" + target + "']"))).click()
However even sucessfully clicking on the options with text as EU Odds, UK Odds, US Odds doesn't changes the DOM Tree. Now if you look into the HTML DOM the expander class itself is having the value as user-header-fakeselect-options
. Additionally, the onclick
attribute of the //li/a/span
items are having return false;
.
As per the discussion What's the effect of adding 'return false' to a click event listener? return false;
does three separate things when called:
event.preventDefault();
event.stopPropagation();
Hence selecting either of the dropdown options doesn't fires the onclick
event and the HTML DOM remains unchanged.
Possibly the DOM would change as per the onclick
events when a authenticated user performs the selection after loggind in within the website.
Upvotes: 1
Reputation: 8564
The actual issue is with the website itself. Trying to select any other option other than EU Odds
doesn’t work even manually. Seems like you need to be logged in to do that.
Upvotes: 2
Reputation: 50939
There are two issues with the xpatי:
Too many apostrophes around the text
Trying to locate the wrong tag, the clickable element is the <a>
tag, not the <li>
tag.
Use "//a[.=' + target + ']"
Upvotes: 0
Reputation: 1
Try this. Selenium has a special way to handle dropdown selection
First import select :
from selenium.webdriver.support.ui import Select
Then assign the dropdown to a variable:
dropdown_element = browser.find_element_by_xpath('//*[@id="exam_id"]')
Then create an object:
dropdown_object = Select(dropdown_element)
Finally select the option:(there will be a value for every options)
dropdown_object.select_by_value('17')
Upvotes: 0