I am writing a script right now to take information from a website and there is a lot of select/option fields. The problem is, currently I am checking to see if the select box is clickable before trying to click the options but this works about 15% of the time. Here is the line that waits for the element to be clickable:
schoolbox = Select(WebDriverWait(driver, 100).until(EC.element_to_be_clickable((By.ID, "clCampusSelectBox"))))
How do I wait for the options below this select element to be clickable?
Thanks
Edit: here are the dropdowns: https://shop.bookstore.ubc.ca/courselistbuilder.aspx
Clickable element has to be visible and enabled. The <option> elements under the <select> are usually not visible, so "is clickable" check will fail. I suggest you wait for the dropdown to be visible and then use select class to select the option
schoolbox = Select(WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "clCampusSelectBox"))))
schoolbox.select_by_value("someValue")
I am writing this to inform you that waiting for select_list and waiting for options are two different thing! Why are you waiting for select_list to be clickable? You need to wait for option,right? I don't know python, I am using WATIR(language is Ruby) where waiting for select_list and then waiting for option will automatically happen, you don't have write anything
This simple code is enough
b.select_list(:id,'q').select 'hi'
It will automatically wait for select list to be present and then it will wait for option to be present, you don't have to do anything deliberately.
But if I want to write the code to wait for select_list, then I will write
b.select_list(:id,'q').wait_until_present.select 'hi'
If I want to write the code to wait for option in the select_list then I will write
b.select_list(:id,'q').option(:text,'hi').wait_until_present.select
If I want to wait for both, then I will write
b.select_list(:id,'q').wait_until_present.option(:text,'hi').wait_until_present.select
but these are not necessary in WATIR because it automatically waits for everything.
So all you need to know is whether to wait for select_list or to wait for option because in certain condition your select list option will be populated according to some condition.
Related
I'm working on my first-ever Selenium Python project and am baby stepping through it. I have an inconsistent issue and want to see if there's a better way to code it.
I need to select "Active" from a drop-down menu. I'm selecting the drop down input element and clicking on it. This will open a child element of the input with the list items in it. Here's where the problem lies...sometimes the drop down element stays open and I can select "Active" and everything works great. Sometimes, however, the drop down element opens and closes immediately before I can pick "Active". I'm currently trying to sleep for 3 seconds after clicking on the input element, hoping that will solve the issue. It seemed to for a little while, but now then it will revert back to closing immediately.
So is there a better way to open this drop down box and select active?
#select the status drop down box and click to open it, wait 3 seconds to make sure it loads
#and select the 'A'ctive list item and click to select it
WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.ID, "input-w_112"))).click()
time.sleep(3)
WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.ID, "w_113"))).find_element(By.XPATH, '//*[#combovalue="A"]').click()
Sometimes the list items box will stay open, sometimes it closes immediately.
You can do this task with executing a JS script from Selenium WebDriver.
Select the drop-down menu you need.
Select an option by its index.
Code
JS_script = """
var menu = document.getElementById("menu");
menu.selectedIndex = 0;
"""
driver.execute_script(JS_script)
I have this problem where I can't access a button trough it's class name in any way I could think of.
This is the HTML:
<button class="expand-button">
<faceplate-number pretty="" number="18591"><!---->18.591</faceplate-number> weitere Kommentare anzeigen
</button>
I tried to access it using:
driver.find_element(By.CLASS_NAME, "expand-button")
But the error tells me that there was no such element.
I also tried X-Path and Css-Selector which both didn't appear to work.
I would be glad for any help!
Kind Regards and Thanks in advance
Eirik
Possible issue 1
It could be because you check before the element is created in the DOM.
One way to solve this problem is by using the waites option like below
driver.implicitly_wait(10)
driver.get("http://somedomain/url_that_delays_loading")
my_dynamic_element = driver.find_element(By.ID, "myDynamicElement")
You can read more about it here: https://www.selenium.dev/documentation/webdriver/waits/#implicit-wait
Another way is by using the Fluent Wait whhich marks the maximum amount of time for Selenium WebDriver to wait for a certain condition (web element) becomes visible. It also defines how frequently WebDriver will check if the condition appears before throwing the “ElementNotVisibleException”.
#Declare and initialise a fluent wait
FluentWait wait = new FluentWait(driver);
#Specify the timout of the wait
wait.withTimeout(5000, TimeUnit.MILLISECONDS);
#Sepcify polling time
wait.pollingEvery(250, TimeUnit.MILLISECONDS);
#Specify what exceptions to ignore
wait.ignoring(NoSuchElementException.class)
#specify the condition to wait on.
wait.until(ExpectedConditions.element_to_be_selected(your_element_here));
you can also read more about that from the official documentation
https://www.selenium.dev/documentation/webdriver/waits/#fluentwait
Possible issue 2
it is also possible that the element might be partially or completely blocked by an element overlaying it. If that is the case, then you will have to dismiss the overlaying element before you will be able to perform any action on your target
I'm trying to implement an explicit wait before giving a click on a checkbox:
WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.XPATH, "pay_type_list_item_id_salary"]")))
self.driver.find_element_by_xpath('//input[#id="pay_type_list_item_id_salary"]').click()
My problem is that my explicit wait keeps sending the error:
not clickable at point (663, 478). Other element would receive the click.
I'm trying to use different kind of explicit waits like visibility_of_element_located or invisibility_of_element_located (using an element from the previous step on my script), but no luck with those options.
If I add a time.sleep(1) between the 2 lines my scripts works but I know it's not the most efficient thing to use time.sleep.
The previous step before this one opens a calendar and I'm not sure if it tries to give the click when the calendar is closing and that's the reason to receive this error.
The error you are getting is indicating that another element is covering the element you are trying to click. If you look at the error message (you really should post the full error message in your question), it will tell you the HTML of the element that is in the way. That will give you a good idea of what element is blocking the click so you can find it and figure out what part of the page it is. Then you can wait for it to get out of the way. From your description, it sounds like you need to add a wait for the calendar to close.
I have a website having youtube iframe. I want to click the replay button after the video gets over. I switched to youtube iframe and found the play button. But how can I click it after a particular time period(like after the video gets over) using selenium(python). Here the element to be clicked is always available but i need to click it only after a particular time.
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[#id='YTPlayer']"))
driver.implicitly_wait(10000)
driver.find_element_by_css_selector(".ytp-play-button.ytp-button").click()
Tried Explicit wait as well but the conditions dont match.
An implicit wait tells WebDriver to poll the DOM for a certain amount of time when trying to find any element (or elements) not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object.
This is probably not what you want as your element is available all the time.
Instead you can just run time.sleep() within your code.
Like this:
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[#id='YTPlayer']"))
time.sleep(1)
driver.find_element_by_css_selector(".ytp-play-button.ytp-button").click()
However instead you should try to find a condition that needs to be satisfied and then click the button instead.
Example:
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[#id='YTPlayer']"))
while True:
if your-condition:
driver.find_element_by_css_selector(".ytp-play-button.ytp-button").click()
break
time.sleep(1)
You could also use Explicit Waits as described here: http://selenium-python.readthedocs.io/waits.html
I have web page, where the user needs to upload a list of documents and only after which the Submit button is enabled.
I am using python selenium for this automation. My program is able to upload the documents but is unable to click on the Submit button after it is enabled.
I tried this:
element = WebDriverWait(driver, 10000).until(EC.element_to_be_clickable("(//button[#type='submit'][2]"))
element.click()
but it is not working, as the jobs are not submitted in the front end
Change code to be:
element = WebDriverWait(driver, 100).until(
EC.element_to_be_clickable((By.XPATH, "//input[contains(#ng-click,'SubmitJob')]")))
element.click()
So we now are waiting for up to 100 seconds (instead of 3 hours), and we are passing a tuple argument (By.XPATH, "//input[contains(#ng-click,'SubmitJob')]") to EC.element_to_be_clickable, which is what it expects.
Cannot comment on the correctness of the xpath though, but please check it as well.
Edit: changed the xpath based on comment. There are many ways to express that xpath. I would prefer ng-click over class attribute, since classes may change; action, however, will likely stay the same. But if you choose using classes, I still suggest going with something like
//input[contains(#class,'btn') and contains(#class,'form-control')]
because you never know if the order of classes will change.