"Element is not clickable" error in selenium python - python

I have been using the same scripts for over a year, but since yesterday i am getting this error when click on links having images. I am getting the element by xpath and then clicking it.
test_101_HomePage_links (__main__.SprintTests) ... ERROR
======================================================================
ERROR: test_101_HomePage_links (__main__.SprintTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\Zaakpay\website\sanity results\debug\tests.py", line 17, in test_101_HomePage_links
a.click()
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 73, in click
self._execute(Command.CLICK_ELEMENT)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 456, in _execute
return self._parent.execute(command, params)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 236, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 194, in check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: Element is not clickable at point (281.25, 61). Other element would receive the click: <span></span>
----------------------------------------------------------------------
Ran 1 test in 23.062s
FAILED (errors=1)
Other info:
using windows,
using python,
using firefox,
same script was working fine till yesterday
My code:
import unittest
from selenium import webdriver
import datetime
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
import time
class SprintTests(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.driver.maximize_window()
self.driver.get("https://www.zaakpay.com")
def test_101_HomePage_links(self):
a= self.driver.find_element_by_xpath("/html/body/div[5]/div[1]/div[3]/ul/li[1]/a/i")
a.click()
time.sleep(5)
a = self.driver.find_element_by_xpath('//*[#id="view1"]/p')
b=a.text
self.assertEqual('-Payment Gateway Services.\n-More than you want payment options with.\n-major credit cards, debit cards and 52 netbanking banks.\n-Fastest Merchant Approval.\n-Smooth integration across 22 platforms.\n-Start in minutes.\n-Multi-Currency Processing Service with 13 currencies.\n\nSIGN UP',b )
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main(verbosity=2)
link i am trying to click is circular image above text- WEBSITE PAYMENT GATEWAY

Using XPATHs like this /html/body/div[5]/div[1]/div[3]/ul/li[1]/a/i are problematic for a number of reasons.
First and foremost, they are extremely brittle. All it takes is a minor update to the site, one that might night even be visually perceptible, and the hard coded div indexes break. The site devs might have added a div to slightly alter a font style and then your XPATH is completely broken.
Second, it makes it next to impossible to debug once it does break. I have absolutely no idea what you were intending to click on, and if this were production code that someone else was attempting to fix, they would also have no idea what you were intending to click on.
My best guess is that zaakpay made some small, imperceptible change that slightly changed the location of your target element in the DOM. If you update the XPATH to something like //div[#class=\"prdtBlck\"]/ul/li/a, as I've done below, your script works:
import unittest
from selenium import webdriver
import datetime
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
import time
class SprintTests(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.driver.maximize_window()
self.driver.get("https://www.zaakpay.com")
def test_101_HomePage_links(self):
a=self.driver.find_element_by_xpath("//div[#class=\"prdtBlck\"]/ul/li/a")
a.click()
time.sleep(5)
a = self.driver.find_element_by_xpath('//*[#id="view1"]/p')
b=a.text
self.assertEqual('-Payment Gateway Services.\n-More than you want payment options with.\n-major credit cards, debit cards and 52 netbanking banks.\n-Fastest Merchant Approval.\n-Smooth integration across 22 platforms.\n-Start in minutes.\n-Multi-Currency Processing Service with 13 currencies.\n\nSIGN UP',b )
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main(verbosity=2)

Related

Selenium - how to continue with url list after hitting a offline website?

may I ask please with some assistance on the following task I'm trying to complete. Im trying to use Selenium to automatically check a list of urls and do a set of click actions on each of them, if the website is offline I would like to go to the next urls on the list and do the same click actions.
Bellow is the code that I have achieved so far, however it doesn't work:
from selenium import webdriver ## importing webdriver
import time ## importing waiting time fuctions
from selenium.common.exceptions import TimeoutException ## importing the timeout fuctions
driver = webdriver.Chrome()
## Setting the Timeout timer in seconds
MAX_TIMEOUT_SECONDS = 60
## Getting url from list "url"
urlsList = ['urlone','urltwo', 'urlthree', 'urlfour']
## Getting list of urls
for s in urlsList:
urls = str(s)
## loop with timeout exception
try:
## Activinting the Timeout fuctions
driver.set_page_load_timeout(MAX_TIMEOUT_SECONDS)
driver.get(urls)
## Clicking on tab
systemTab = driver.find_element_by_xpath('/html/body/ul[1]/li[3]/a')
systemTab.click()
## Clicking on Bottom
buttonRaul = driver.find_element_by_xpath('/html/body/ul[2]/li[4]/a')
buttonRaul.click()
## Clicking on confirmation
buttomGoo = driver.find_element_by_xpath('/html/body/div[2]/div[2]/button')
buttomGoo.click()
time.sleep(5) ## Wait 5 seconds
except TimeoutException:
continue
driver.quit()
I tried using timeout as form to determinate if a website is offline/not responding after 60 seconds, however when the I run the code, the code online work until it hits a off-line website and stops there.
I am trying to reply this question in java as I am not much familiar with Python.
When you run the test offline mode, we can use the loadingFailed() to get the logs from browser i.e – net::ERR_INTERNET_DISCONNECTED and then you can proceed to next URL.
import org.openqa.selenium.devtools*;
driver = new ChromeDriver();
devTools = ((ChromeDriver)driver).getDevTools();
driver.get("https://www.homepage.com");
devTools.createSession();
devTools.addListener(loadingFailed(), loadingFailed ->
{
System.out.println(loadingFailed.getErrorText());
Assert.assertEquals(loadingFailed.getErrorText(), "net::ERR_INTERNET_DISCONNECTED");
});
Im pretty new to Selenium and python, The first url runs as it should be, however my second url is currently offline, The second url open the window and after 10-20seconds the following message shows and the code stop running:
Traceback (most recent call last):
File "/Users/sweatynerd/Desktop/smtautomation.py", line 19, in <module>
driver.get(urls)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py", line 333, in get
self.execute(Command.GET, {'url': url})
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: net::ERR_ADDRESS_UNREACHABLE
(Session info: chrome=92.0.4515.107)
Thank for your help

Fill out form and download zipfile using Selenium in Python

EDITED: I incorporated the final lines suggested by Sushil. At the end, I am copying the output in my terminal. I still do not get the zipfile.
SOLVED: My error was due to an incompatibility between the driver and chrome versions. I fixed by following the instructions here: unknown error: call function result missing 'value' for Selenium Send Keys even after chromedriver upgrade
I am trying to use Selenium to fill out a form and download a zipfile.
After extensively googling, I have written a Python code, but I am currently unable to download the file. A browser opens, but nothing is filled out.
I am very new at Python, so I am guessing I am missing something very trivial since the website I am trying to get info from is super simple.
This is what I have tried:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome(executable_path='/home/miranda/webscrap_Python/chromedriver')
#driver.wait = WebDriverWait(driver,5)
driver.get("http://www.cis.es/cis/opencms/EN/formulario.jsp?dwld=/Microdatos/MD3288.zip")
Name = '//*[#id="Nombre"]'
LastName = '//*[#id="Apellidos"]'
University = '//*[#id="profesion"]'
email = '//*[#id="Email"]'
ob_req = '//*[#id="objeto1"]'
terms = '//*[#id="Terminos"]'
download = '//*[#id="mediomicrodatos"]/form/div[3]/input'
driver.find_element_by_xpath(Name).send_keys("Miranda")
driver.find_element_by_xpath(LastName).send_keys("MyLastName")
driver.find_element_by_xpath(University).send_keys("MySchool")
driver.find_element_by_xpath(email).send_keys("my_email#gmail.com")
#lines added by Sushil:
ob_req_element = driver.find_element_by_xpath(ob_req) #Finds the ob_req element
driver.execute_script("arguments[0].click();", ob_req_element) #Scrolls down to the element and clicks on it
terms_element = driver.find_element_by_xpath(terms) #The same is repeated here
driver.execute_script("arguments[0].click();", terms_element)
driver.find_element_by_xpath(download).click() #Scrolling down is not needed for the download button as it would already be in view. Only when an element is not in view should we scroll down to it in order to click on it.
Output in my terminal:
Traceback (most recent call last):
File "myCode.py", line 18, in <module>
driver.find_element_by_xpath(Name).send_keys("Miranda")
File "/home/miranda/anaconda3/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 479, in send_keys
'value': keys_to_typing(value)})
File "/home/miranda/anaconda3/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "/home/miranda/anaconda3/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/home/miranda/anaconda3/lib/python3.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: call function result missing 'value'
(Session info: chrome=86.0.4240.75)
(Driver info: chromedriver=2.29.461571 (8a88bbe0775e2a23afda0ceaf2ef7ee74e822cc5),platform=Linux 5.4.0-45-generic x86_64)
For each and every element below the email element, you have to scroll down to click them. Here is the full code to do it:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
#driver.wait = WebDriverWait(driver,5)
driver.get("http://www.cis.es/cis/opencms/EN/formulario.jsp?dwld=/Microdatos/MD3288.zip")
Name = '//*[#id="Nombre"]'
LastName = '//*[#id="Apellidos"]'
University = '//*[#id="profesion"]'
email = '//*[#id="Email"]'
ob_req = '//*[#id="objeto1"]'
terms = '//*[#id="Terminos"]'
download = '//*[#id="mediomicrodatos"]/form/div[3]/input'
driver.find_element_by_xpath(Name).send_keys("Miranda")
driver.find_element_by_xpath(LastName).send_keys("MyLastName")
driver.find_element_by_xpath(University).send_keys("MySchool")
driver.find_element_by_xpath(email).send_keys("my_email#gmail.com")
#All the lines below were added by me
ob_req_element = driver.find_element_by_xpath(ob_req) #Finds the ob_req element
driver.execute_script("arguments[0].click();", ob_req_element) #Scrolls down to the element and clicks on it
terms_element = driver.find_element_by_xpath(terms) #The same is repeated here
driver.execute_script("arguments[0].click();", terms_element)
driver.find_element_by_xpath(download).click() #Scrolling down is not needed for the download button as it would already be in view. Only when an element is not in view should we scroll down to it in order to click on it.

Timeout Exception while web scraping an element in Selenium Python

I am facing a timeout exception while trying to click on a drop down link - have tried all the solutions I could find on various forums (eg: Increasing the wait time to upto 60 sec, using time.sleep, changing locators)
but the error doesn't seem to go away.
FWIW: The page and the link I am trying to click otherwise loads in just 1 second so not sure what's going on.
Could anyone please assist on what am I missing?
The code snippet is as follows:
def __init__(self, driver): # initialize each WebElement here
self.driver = driver
wait = WebDriverWait(self.driver.instance, 10)
self.data_dropdown = wait.until(
EC.visibility_of_element_located((
By.XPATH, '//*[#id="ProjectDataTab"]'))) # Data dropdown
self.view_all_link = wait.until(
EC.visibility_of_element_located((
By.LINK_TEXT, 'View All'))) # View All link
Error stack trace:
ERROR: test_form_case_exports (__main__.TestCCHQ)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:/Users/DSI/PycharmProjects/CCHQ_Smoke/testcases/CCHQ_1.py", line 27, in test_form_case_exports
form_case_exports = FormCaseExports(self.driver)
File "C:\Users\DSI\PycharmProjects\CCHQ_Smoke\pageobjects\form_case_exports.py", line 21, in __init__
By.LINK_TEXT, 'View All'))) # View All link
File "C:\Users\DSI\AppData\Local\Programs\Python\Python37-32\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:

StaleElementReferenceException when trying to click on the links in a loop

Please click on the link below to see the link "BEAUTY" on which I am clicking
1. I am using this code to click on the "Beauty" link
driver = webdriver.Chrome("C:\\Users\\gaurav\\Desktop\\chromedriver_win32\\chromedriver.exe")
driver.maximize_window()
driver.get("http://shop.davidjones.com.au")
object = driver.find_elements_by_name('topCategory')
for ea in object:
print ea.text
if ea.text == 'Beauty':
ea.click()
I am getting the following exceptions after clickin on the link succesfully , can anybody tell me why I am getting it ?
Traceback (most recent call last):
File "C:/Users/gaurav/PycharmProjects/RIP_CURL/login_raw.py", line 10, in <module>
print ea.text
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 73, in text
return self._execute(Command.GET_ELEMENT_TEXT)['value']
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 493, in _execute
return self._parent.execute(command, params)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 252, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 194, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
(Session info: chrome=63.0.3239.132)
(Driver info: chromedriver=2.34.522940 (1a76f96f66e3ca7b8e57d503b4dd3bccfba87af1),platform=Windows NT 6.2.9200 x86_64)
Try this:
from selenium import webdriver
print("bot started")
#chromeOptions = webdriver.ChromeOptions()
#driver = webdriver.Chrome(chrome_options=chromeOptions)
def specific_text(text, ea):
return str(text) == ea.text
driver = webdriver.Chrome("C:\\Users\\gaurav\\Desktop\\chromedriver_win32\\chromedriver.exe")
driver.maximize_window()
driver.get("http://shop.davidjones.com.au")
object_ = driver.find_elements_by_name('topCategory')
text_headers = [str(specific_text('Beauty', ea)) for ea in object_]
#print(text_headers)
index_text = text_headers.index("True")
#print(index_text)
object_[index_text].click()
You need to take care of certain factors as follows :
You have tried to create a List by the name object. object is a reserved built-in symbol in most of the Programming Languages. So as per Best Programming Practices we shouldn't use the name object.
The line print ea.text is badly indented. You need to add indentation.
Once you invoke click() on the WebElement with text as Beauty you need to break out of the loop.
Here is your own working code with some minor tweaks :
from selenium import webdriver
driver = webdriver.Chrome(executable_path=r'C:\path\to\chromedriver.exe')
driver.maximize_window()
driver.get("http://shop.davidjones.com.au")
object1 = driver.find_elements_by_name('topCategory')
for ea in object1:
print (ea.text)
if ea.text == 'Beauty':
ea.click()
break
Console Output :
Sale
Brands
Women
Men
Shoes
Bags & Accessories
Beauty
There's an easier way to do this. You can use an XPath that will specify the category name you want to click. That way you don't have to loop, it will find the desired element in one search.
//span[#name='topCategory'][.='Beauty']
I'm assuming you will be reusing this code. In cases like this, I would create a function that takes a string parameter which would be the category name that you want to click. You feed that parameter into the XPath above and you can then click any category on the page.
I tested this and it's working.

Selenium with Python: Stale Element Reference Exception

Working from Test Driven Development with Python, and I'm currently encountering a 'StaleElementReferenceException' when running the functional test immediately after migration. Here's the full text of the error:
ERROR: test_start_and_retrieve_list (__main__.NewVisitorTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "functional_tests.py", line 53, in test_start_and_retrieve_list
rows = table.find_elements_by_tag_name('tr')
File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webelement.py", line 237, in find_elements_by_tag_name
return self.find_elements(by=By.TAG_NAME, value=name)
File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webelement.py", line 527, in find_elements
{"using": by, "value": value})['value']
File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webelement.py", line 493, in _execute
return self._parent.execute(command, params)
File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webdriver.py", line 256, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <table id="id_list_table"> stale: either the element is no longer attached to the DOM or the page has been refreshed
----------------------------------------------------------------------
Ran 1 test in 8.735s
FAILED (errors=1)
Here's the test:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import unittest
class NewVisitorTest(unittest.TestCase):
def setUp(self):
self.browser = webdriver.Firefox()
self.browser.implicitly_wait(3)
def tearDown(self):
self.browser.close()
def check_for_row(self, row_text):
table = self.browser.find_element_by_id('id_list_table')
rows = table.find_elements_by_tag_name('tr')
self.assertIn(row_text, [row.text for row in rows])
def test_start_and_retrieve_list(self):
self.browser.get('http://localhost:8000')
self.assertIn('To-Do', self.browser.title)
header_text = self.browser.find_element_by_tag_name('h1').text
self.assertIn('To-Do', header_text)
inputbox = self.browser.find_element_by_id('id_new_item')
self.assertEqual(
inputbox.get_attribute('placeholder'),
'Enter a to-do item'
)
inputbox.send_keys('Buy peacock feathers')
inputbox.send_keys(Keys.ENTER)
self.check_for_row('1: Buy peacock feathers')
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Use peacock feathers to make a fly')
inputbox.send_keys(Keys.ENTER)
table = self.browser.find_element_by_id('id_list_table')
rows = table.find_elements_by_tag_name('tr')
self.check_for_row('1: Buy peacock feathers')
self.check_for_row('2: Use peacock feathers to make a fly')
self.fail('Finish the test!')
if __name__ == '__main__':
unittest.main(warnings='ignore')
How do I configure the test to prevent this? Selenium's own page says this issue can occur when the page refreshes, but this is a necessary part of the application logic as it's configured so far.
Add these imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
Change these lines
inputbox.send_keys(Keys.ENTER)
self.check_for_row('1: Buy peacock feathers')
to:
inputbox.send_keys(Keys.ENTER)
WebDriverWait(self.browser, 10).until(
expected_conditions.text_to_be_present_in_element(
(By.ID, 'id_list_table'), 'Buy peacock feathers'))
self.check_for_row('1: Buy peacock feathers')
This replaces the time.sleep(1) with something more "reasonable"
I have been using selenium for a while now so I understand the struggles of the Stale Element Exception. While not perfect, selenium provides a series of "wait" commands to allow for the website to load complete. Unfortunately, its not perfect as loading can take different time on each run, but these are the tools provided by selenium.
I haven't worked in python but have worked on java/selenium. But,I can give you the idea to overcome staleness.
Generally we will be getting the Stale Exception if the element attributes or something is changed after initiating the webelement. For example, in some cases if user tries to click on the same element on the same page but after page refresh, gets staleelement exception.
To overcome this, we can create the fresh webelement in case if the page is changed or refreshed. Below code can give you some idea.(It's in java but the concept will be same)
Example:
webElement element = driver.findElement(by.xpath("//*[#id='StackOverflow']"));
element.click();
//page is refreshed
element.click();//This will obviously throw stale exception
To overcome this, we can store the xpath in some string and use it create a fresh webelement as we go.
String xpath = "//*[#id='StackOverflow']";
driver.findElement(by.xpath(xpath)).click();
//page has been refreshed. Now create a new element and work on it
driver.fineElement(by.xpath(xpath)).click(); //This works
Another example:
for(int i = 0; i<5; i++)
{
String value = driver.findElement(by.xpath("//.....["+i+"]")).getText);
System.out.println(value);
}
Hope this helps you. Thanks
To prevent an element to become stale, place a new element on the current page, hit the link and wait until the element is not available anymore. Then wait for an element on the new page to appear
script_to_execute = """
var new_element = document.createElement('span');
new_element.setAttribute('id', 'wait4me');
document.body.appendChild(new_element);"""
self.driver.execute_script(script_to_execute)
self.driver.find_element_by_xpath("{}".format(locator)).click()
WebDriverWait(self.driver, self.time_out).until (
lambda x: not x.find_elements_by_id("wait4me"))
This issue happens when the loop starts before an updated page has fully loaded. Especially when you update a page in an application or a form.
One workaround is to place an element on the current page, then update and use the WebDriverWait statement until the element is not found anymore.
Then start your loop. (Otherwise the reload happens during the loop...)
I read the same book as you do and encountered the same problem (solutions from this page didn't work for me).
Here's how I resolved it.
Problem
Exception is thrown whenever you try to access a stale object. So we have to wait for situation when this exception is NOT thrown anymore.
My solution
I created method that waits for my actions until they pass
from selenium.common.exceptions import StaleElementReferenceException
[...]
def stale_aware_for_action(self, action):
while(True):
try:
action()
break
except StaleElementReferenceException:
continue
And in test method I defined actions that I want to wait to finish:
def test_can_start_a_list_and_retrieve_it_later(self):
[...]
def insert_second_item_to_inputbox():
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Use peacock feathers to make a fly')
inputbox.send_keys(Keys.ENTER)
self.stale_aware_for_action(insert_second_item_to_inputbox)
def check_for_first_item():
self.check_for_row_in_list_table('1: Buy peacock feathers')
def check_for_second_item():
self.check_for_row_in_list_table('2: Use peacock feathers to make a fly')
self.stale_aware_for_action(check_for_first_item)
self.stale_aware_for_action(check_for_second_item)

Categories