I'm attempting to use expected_conditions.element_to_be_clickable but it doesn't appear to be working. I'm still seeing "Element...is not clickable at point" errors in about 30% of the runs.
Here's the full error message:
selenium.common.exceptions.WebDriverException: Message: unknown
error: Element ... is not clickable at point (621, 337). Other
element would receive the click: ...
(Session info: chrome=60.0.3112.90)
(Driver info: chromedriver=2.26.436421 (6c1a3ab469ad86fd49c8d97ede4a6b96a49ca5f6),platform=Mac OS X 10.12.6
x86_64)
Here's the code I'm working with:
def wait_for_element_to_be_clickable(selector, timeout=10):
global driver
wd_wait = WebDriverWait(driver, timeout)
wd_wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, selector)),
'waiting for element to be clickable ' + selector)
print ('WAITING')
return driver.find_element_by_css_selector(selector)
Update:
So now this is really odd. Even if I add a couple of fixed wait periods, it still throws the error message occasionally. Here's the code where the call is being made:
sleep(5)
elem = utils.wait_for_element_to_be_clickable('button.ant-btn-primary')
sleep(5)
elem.click()
Ended up creating my own custom function to handle the exception and perform retries:
""" custom clickable wait function that relies on exceptions. """
def custom_wait_clickable_and_click(selector, attempts=5):
count = 0
while count < attempts:
try:
wait(1)
# This will throw an exception if it times out, which is what we want.
# We only want to start trying to click it once we've confirmed that
# selenium thinks it's visible and clickable.
elem = wait_for_element_to_be_clickable(selector)
elem.click()
return elem
except WebDriverException as e:
if ('is not clickable at point' in str(e)):
print('Retrying clicking on button.')
count = count + 1
else:
raise e
raise TimeoutException('custom_wait_clickable timed out')
The problem is stated in the error message.
Element ... is not clickable at point (621, 337). Other element would receive the click: ...
The problem is that some element, the details of which you removed from the error message, is in the way... on top of the element you are trying to click. In many cases, this is some dialog or some other UI element that is in the way. How to deal with this depends on the situation. If it's a dialog that is open, close it. If it's a dialog that you closed but the code is running fast, wait for some UI element of the dialog to be invisible (dialog is closed and no longer visible) then attempt the click. Generally it's just about reading the HTML of the element that is blocking, find it in the DOM, and figure out how to wait for it to disappear, etc.
Related
I am scrolling an element into view via JavaScript, but when trying to click on that element an exception is being raised which says the element cannot be scrolled into view, but when I look at the browser, it has been scrolled into view. I've even tried waiting for the item to be clickable but the same error is still thrown.
I'd appreciate it if anyone could provide any solutions in python, but java is okay. Thanks you. :)
Here is my code:
for i in range(len(units)):
matchCnt += '0'
for name in className:
if name.lower() in str(units[i].text).lower():
matchCnt[i] = str(int(matchCnt[i]) + 1)
if int(matchCnt[i]) == len(className):
browser.execute_script('return arguments[0].scrollIntoView(true);', units[i])
WebDriverWait(browser, 200).until(EC.element_to_be_clickable((By.CLASS_NAME, classId)))
#element[i].click()
#WebDriverWait(browser, 200).until(webdriver.support.expected_conditions.element_to_be_clickable(units[i]))
#time.sleep(5)
units[i].click()
doesMatch = True
if doesMatch:
break
You can use Javascript to click on the unit, by this way the element will be clicked though not scrolled element into view.
driver.execute_script("arguments[0].click();",unit[i])
My code works, but not in all cases
Basically the functionality is to click a load_more button until it no longer appears.
As of right now, I simply have a loop which finds the loadmore button and clicks it twice, but there are cases that it will click on something else when the load more button disappears.
I was planning on making a while loop, which would constantly find the click the load_more option until the loadmore disappeared then break the loop.
Here is the code: (This simply finds and clicks it twice)
load_more = browser.find_element_by_css_selector("#mainContent > div.left-panel > div > div.result-list > div > div.content")
WebDriverWait(browser, timeout).until(EC.visibility_of(load_more))
#Need bugfix,
for i in range(2):
browser.execute_script("return arguments[0].scrollIntoView(true);", load_more)
ActionChains(browser).move_to_element(load_more).click().perform()
I noticed when playing around with the load more button that.
<div class="progressbtnwrap" data-search-type="search" style="display: block;">
When the load more button is present on the site, the element is set to "display: block;"
But once the load more button disappears,
<div class="progressbtnwrap" data-search-type="search" style="display: none;">
the element changes to none, notice "display: none;"
Any suggestions how I can search for this?
When looking through the selenium documentations I couldn't find any way of searching for this element and specifically checking if the style is triggered to none,
https://selenium-python.readthedocs.io/locating-elements.html
My goal here is to create something like this
while(True):
if browser.find_element_by_notsurewhat == "block":
ActionChains(browser).move_to_element(load_more).click().perform()
if browser.find_element_by_notsurewhat == "none":
break
browser.execute_script("return arguments[0].scrollIntoView(true);", load_more)
I'm sure the logic must be much more complicated than that, or even if what I want to achieve is even possible, Any suggestions would be amazing!
Thank you all!
UPDATE:
def load_more(browser):
print("I'm in the function LOAD MORE")
try:
if browser.find_element_by_xpath('//*[#id="mainContent"]/div[1]/div/div[5]/div'):
print("I HAVE ENTERED THE TRY BLOCK WITHIN THE LOAD MORE FUNCTION")
return True
except Exception as e:
print(e)
return False
return False
while load_more(browser):
print("I'm in the while loop!")
ActionChains(browser).move_to_element(load_more).click().perform()
browser.execute_script("return arguments[0].scrollIntoView(true);", load_more)
When placing my locating and clicking commands, I began to receive the following error:
Traceback (most recent call last):
File "C:\Users\David\eclipse-workspace\Web_Scrap\setup.py", line 81, in <module>
ActionChains(browser).move_to_element(load_more).click().perform()
File "C:\Users\David\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\common\action_chains.py", line 83, in perform
action()
File "C:\Users\David\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\common\action_chains.py", line 293, in <lambda>
Command.MOVE_TO, {'element': to_element.id}))
AttributeError: 'function' object has no attribute 'id'
I noticed from trying to figure out exactly where the program crashes that, once the code below is run, the program crashes, but this works prior to placing this inside the while loop, or the function. (I tried to place the scrollIntoView, line inside the function right before the try, and I receive a similar error).
ActionChains(browser).move_to_element(load_more).click().perform()
browser.execute_script("return arguments[0].scrollIntoView(true);", load_more)
The idiomatic way to do this is to use "explicit waits" (AKA WebDriverWait with ExpectedConditions).
The following will wait until the element is no longer visible. If it doesn't disappear in 10 secs, a TimeOutError is raised:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
element = wait.until(EC.invisibility_of_element_located(By.CLASS_NAME, 'progressbtnwrap'))
If the style attribute for an html element is set to display: none, selenium won't be able to find the element using the built-in DOM selector functions like find_element_by_id/find_elements_by_class etc.
You could simply wrap the find operation in a try except block and add a delay to allow the browser some time for the Ajax call.
def load_more(browser):
time.sleep(1)
try:
display = browser.execute_script("return document.getElementsByClassName('progressbtnwrap')[0].style.display")
if display == 'none':
return False
elem = browser.find_element_by_xpath('//div[contains(#class, "progressbtnwrap")]/div[contains(#class, "content")]')
browser.execute_script("arguments[0].click();", elem)
return True
except Exception as e:
print("Error")
print(e)
return False
while load_more(browser):
print("scrolling further")
Assuming you are currently just trying to find a way on how you can check the current style of your element you can use this code.
driver.execute_script("return arguments[0].style.display;", load_more)
And you can use to check that when the return value is 'none' for a few seconds which means no more data will be loaded, you can exit your loop.
I have this page. I have to click on Facebook icon. Upon doing it I m getting:
selenium.common.exceptions.ElementNotVisibleException: Message: Element is not currently visible and so may not be interacted with
Code is given below:
if 'log' in html.lower():
print("not logged in")
sleep(3)
#Click on Fb button
fb_element = driver.find_element_by_xpath('//a[#tooltip="Facebook"]')
fb_element.vis
fb_element.send_keys(Keys.TAB)
There is an another element with tooltip="Facebook" on the page and this element is actually invisible. Well, there are actually 10 of them:
> $x('//a[#tooltip="Facebook"]').length
10
You can find find all elements matching your locator and filter the visible one via next() and is_displayed():
facebook_links = driver.find_elements_by_xpath('//a[#tooltip="Facebook"]')
visible_link = next(link for link in facebook_links if link.is_displayed())
visible_link.click()
I'm trying to take look at several pages on one web with Selenium - PhantomJS().
The problem is that it started freezing and I can't figure out why. It is probably something with Timeout.
Here is the__init__ method of a class.
self.driver = webdriver.PhantomJS(service_args=["--load-images=false"])
self.wait = WebDriverWait(self.driver, 2)
And here is the method:
def click_next_page(self):
log('click_next_page : '+self.driver.current_url) # THIS LINE RUNS
rep = 0
while 1:
try:
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'li.arr-rgt.active a'))) # IT MAY FREEZE HERE
self.driver.find_element_by_css_selector('li.arr-rgt.active a').click()# IT MAY FREEZE HERE
print 'NEXT' # DOESNT PRINT ANY TEXT SO THIS LINE NOT EXECUTED
log('NEXT PAGE')
return True
except Exception as e:
log('click next page EXCEPTION') # DONT HAVE THIS TEXT IN MY LOG SO IT DOES NOT RAISES ANY EXCEPTION
self.driver.save_screenshot('click_next_page_exception.png')
self.driver.back()
self.driver.forward()
rep += 1
log('REPEAT '+str(rep))
if rep>4:
break
sleep(4)
return False
The problem is that it does not raises any exception or any message.
The line log('click_next_page : '+self.driver.current_url) is working and then it freezes, I know it because I have click_next_page : http://.... in my log as a last line.
The problem is definitely somewhere here:
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'li.arr-rgt.active a')))
self.driver.find_element_by_css_selector('li.arr-rgt.active a').click()
But I can't realize where because it does not raise any Exception.
Could you give me an advice?
I don't have any idea about how Selenium works in PhantomJS. But, I am not seeing any issues within your code. To help you in knowing the exact problem, I would suggest you to debug it in smaller chunks and using one line at a time in console (not by running the python file).
So check with this :-
>>> from selenium import webdriver
>>> driver = webdriver.PhantomJS(service_args=["--load-images=false"])
>>> wait = WebDriverWait(driver, 2)
>>> code for clicking next page
>>> time.sleep(5)
>>> driver.find_element_by_css_selector('li.arr-rgt.active a')
So, this should return you the selenium webdriver instance for the object you are searching using the css selector. If, the element itself is not found then it will throw error.
If the above code runs then re-run the above code with following modifications :-
>>> from selenium import webdriver
>>> driver = webdriver.PhantomJS(service_args=["--load-images=false"])
>>> wait = WebDriverWait(driver, 2)
>>> code for clicking next page
>>> wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'li.arr-rgt.active a')))
>>> driver.find_element_by_css_selector('li.arr-rgt.active a').click()
Here you will be able to check whether there is actually problem with wait_until(). If there is any error, you can point it out by running it one by one. Hope this helps...
As a part of our web based application, Customer has to sign contract in docusign and then the initial contract gets generated.
In the document, In some places customer initial is required and some places customer signature is required(These are not in order). I was able to do the following. But I am getting "Element is not visible" message. I guess the click is moving to "Sign here" when there is "Initial here". For each contract selected this keeps changing. How do I write my code to accommodate this? Please let me know.
try:
self.driver.find_element_by_id("chkUserEsign").click()
time.sleep(5)
self.driver.find_element_by_id("ds_hldrBdy_dlgStart_startReview_btnInline").click()
except NoSuchElementException as e:
print('retry in 10s.')
time.sleep(1)
try:
self.driver.find_element_by_id("ds_hldrBdy_navnexttext_btnInline").click()
except NoSuchElementException as e:
print('retry in 9s.')
time.sleep(1)
try:
listofinitial = self.driver.find_elements_by_xpath("//input[#type='image' and #title='Initial Here']")
for i in listofinitial:
i.click()
self.driver.find_element_by_id("ds_hldrBdy_dlgAdoptSig_btnAdoptSignature_btnInline").click()
listofsign = self.driver.find_elements_by_xpath("//input[#type='image' and #title='Sign Here']")
for j in listofsign:
j.click()
except NoSuchElementException as e:
print('retry in 5s.')
time.sleep(1)
Click function will always click on an element if it able to locate it in the HTML DOM using the unique locator specified. It does not matter what is the position the element in the UI unless your are using absolute Xpath or CSS Selector.
In your case I am assuming that either 'Initial Here' or 'Sign Here' element is visible in the UI and you are trying to locate both because of which the test script is failing due to 'Element Not Visible'
There is a function 'isDisplayed' in WebDriver which checks for visibility of the element and returns a boolean, why don't you check the visibility of both you locators before performing the click action.