I have a case when I need to find out what button is displayed now. I try it in this way first
{please don't mind on my helper functions. I thinks you can easy understand that Ui.find_el it is almost the same as driver.find_element_by....}:
if Ui.find_el(link.AuthorPopupNodes.LOGIN_EMAIL).is_displayed():
pass
else:
if Ui.find_el(link.HeaderNodes.LOGOUT_BUTTON).is_displayed():
self.log_out()
Ui.wait_for_element(link.HeaderNodes.LOGIN_BUTTON, "Timeout: Wait for Login button!")
Ui.click_el(link.HeaderNodes.LOGIN_BUTTON)
But then it start to fall errors that driver can't find element, so I cover it by try but it didn't work for me too.
try:
if Ui.find_el(link.AuthorPopupNodes.LOGIN_EMAIL).is_displayed():
pass
else:
if Ui.find_el(link.HeaderNodes.LOGOUT_BUTTON).is_displayed():
self.log_out()
Ui.wait_for_element(link.HeaderNodes.LOGIN_BUTTON, "Timeout: Wait for Login button!")
Ui.click_el(link.HeaderNodes.LOGIN_BUTTON)
except:
pass
For example if first IF fails, than it get out from try and I need to check if there is LOGOUT button. HIs it possible to check for element without try but also without selenium errors?
You can catch specific selenium errors, for example:
from selenium.common.exceptions import NoSuchElementException, ElementNotVisibleException
try:
Ui.find_el(link.AuthorPopupNodes.LOGIN_EMAIL)
except (NoSuchElementException, ElementNotVisibleException):
try:
Ui.find_el(link.HeaderNodes.LOGOUT_BUTTON)
self.log_out()
except (NoSuchElementException, ElementNotVisibleException):
pass
Ui.wait_for_element(link.HeaderNodes.LOGIN_BUTTON, "Timeout: Wait for Login button!")
Ui.click_el(link.HeaderNodes.LOGIN_BUTTON)
Related
I am trying to open a page and click on download button. It works fine for the pages that have download element but for the pages which doesn't have that element it raises error
Code:
for i in data["allurl"]:
driver.get('{0}'.format(i))
if(driver.find_element_by_id('ContentPlaceHolder1_grdFileUpload_lnkDownload_0')):
button_element = driver.find_element_by_id('ContentPlaceHolder1_grdFileUpload_lnkDownload_0')
button_element.click()
else:
pass
It should pass instead of raising the error but when I run this it says:
NoSuchElementException: Message: no such element: Unable to locate
element:
{"method":"id","selector":"ContentPlaceHolder1_grdFileUpload_lnkDownload_0"}
How do I solve this?
driver.find_element_by_id() doesn't return True or False as your if-statement expects. Either change your if-statement, or use a try/except statement.
from selenium.common.exceptions import NoSuchElementException
for i in data["allurl"]:
driver.get('{0}'.format(i))
try:
button_element = driver.find_element_by_id('ContentPlaceHolder1_grdFileUpload_lnkDownload_0')
button_element.click()
except NoSuchElementException:
pass
Check the length count of the web element.If it is more than 0 then element available and click otherwise it will go to else condition.
for i in data["allurl"]:
driver.get('{0}'.format(i))
if len(driver.find_elements_by_id('ContentPlaceHolder1_grdFileUpload_lnkDownload_0'))>0:
button_element = driver.find_element_by_id('ContentPlaceHolder1_grdFileUpload_lnkDownload_0')
button_element.click()
else:
pass
from selenium.common.exceptions import NoSuchElementException
try:
button_element = driver.find_element_by_id('ContentPlaceHolder1_grdFileUpload_lnkDownload_0')
except NoSuchElementException:
pass
else:
button_element.click()
Note that even if it worked as you expected, it's inefficient because you perform search for the element twice.
EDIT: included the import statement for the exception
UPDATE: as a side note, assuming elements in data["allurl"] are url (i.e. strings) there is no need for string formatting. driver.get(i) would do. And i is poor choice for variable name - better use something more meaningful....
I want to check
def first_page_error:
-if the element is not existing "break" and move on with the script
-if element exists then refresh the page
-if element stops existing after the refresh run firstPage()
I will appreciate any help I'm learning python :)
My code right now
def first_page_error():
cap_error = driver.find_element_by_xpath('//*[#id="js-register-with-email"]/div[2]')
while True:
try:
cap_error
except NoSuchElementException:
break
else:
time.sleep(5)
driver.refresh()
def firstPage():
element = driver.find_element_by_xpath('//*[#id="sign-up-link"]')
driver.execute_script("arguments[0].click();", element)
emailInput = driver.find_element_by_xpath('//*[#id="register-email"]')
emailInput.send_keys(emails[0])
condInput = driver.find_element_by_xpath('//*[#id="register-terms"]')
condInput.click()
firstPage()
first_page_error()
A few points of feedback...
If you are automating user scenarios, avoid using JS clicks. A user can't click an element that isn't visible or is covered or is off the screen, etc. Selenium was designed to act like a user and throw errors when a user can't click an element. That's a good thing. It helps you find the problems and solve them as a user would.
Prefer IDs and CSS selectors. They are faster, better supported, and so on. There's a lot of info on the web if you want more explanation. I converted your XPaths that were just locating by ID to *_by_id().
Check for existence by using driver.find_elements_* (Notice the plural, elementS) and check the len of the collection
I would write something like the below.
def first_page_error():
return len(driver.find_elements_by_xpath('//*[#id="js-register-with-email"]/div[2]')) > 0
def firstPage():
driver.find_element_by_id('sign-up-link').click()
driver.find_element_by_id('register-email').send_keys(emails[0])
driver.find_element_by_id('register-terms').click()
firstPage()
if first_page_error():
driver.refresh()
if first_page_error():
firstPage()
# move on with the script
Thank you all for input
I've resolved it with this
def err_redeem_func():
err_redeem = driver.find_element_by_class_name('error')
try:
if err_redeem.is_displayed() and err_redeem.is_enabled():
driver.refresh()
redeem_func()
except NoSuchElementException:
pass
err_redeem_func()
This XPath may available sometime or sometime not.
If reject is true then I am using if statement:
from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.firefox.options import Options
import time
import bs4
import requests
url="abc"
options = Options()
options.set_preference("dom.webnotifications.enabled", False)
driver=webdriver.Firefox(executable_path="C:\driver\geckodriver.exe",options=options)
driver.get(url)
driver.maximize_window()
reject = driver.find_element_by_xpath("/html/body/div/div/div/main/div/section/div[2]/div[2]/div/ul/a[1]/div[3]/label")
if reject:
driver.find_element_by_xpath("/html/body/div[1]/div/div/main/div/section/div[2]/div[2]/div/ul/a[1]/div[1]/span/i").click()
time.sleep(1)
driver.find_element_by_xpath("/html/body/div[1]/div/div/main/div/section/div[2]/div[2]/div/ul/a[1]/div[1]/div/ul/li[2]").click()
time.sleep(2)
driver.find_element_by_xpath("/html/body/div[3]/div/div/div[3]/button[1]").click()
time.sleep(5)
# Above code blocking to run below code (if reject is None).
neighbourhood= Select(driver.find_element_by_name("Locality"))
neighbourhood.select_by_value("5001641")
But the problem is if this reject variable XPath doesn't exist so it's showing error & blocking below code.
how to make this reject variable optional if XPath available then work if not then leave it & run below code.
You could catch the exception. Something like following:
...
try:
reject = driver.find_element_by_xpath("/html/body/div/div/div/main/div/section/div[2]/div[2]/div/ul/a[1]/div[3]/label")
except:
print("No element found")
if reject:
...
If you need this more often you could create a utility method for that.
def elementVisible(xpath):
try:
driver.find_element_by_xpath(xpath);
return true;
except:
return false;
try-except block will do the trick.
try:
reject = driver.find_element_by_xpath("/html/body/div/div/div/main/div/section/div[2]/div[2]/div/ul/a[1]/div[3]/label")
except:
print("An exception occurred")
Whenever the xpath is not found, the print statement is executed, and further code gets executed without an error like before.
The following script follows a page in Instagram:
browser = webdriver.Chrome('./chromedriver')
# GO INSTAGRAM PAGE FOR LOGIN
browser.get('https://www.instagram.com/accounts/login/?hl=it')
sleep(2)
# ID AND PASSWORD
elem = browser.find_element_by_name("username").send_keys('test')
elem = browser.find_element_by_name("password").send_keys('passw')
# CLICK BUTTON AND OPEN INSTAGRAM
sleep(5)
good_elem = browser.find_element_by_xpath('//*[#id="react-root"]/section/main/div/article/div/div[1]/div/form/span/button').click()
sleep(5)
browser.get("https://www.instagram.com")
# GO TO PAGE FOR FOLLOW
browser.get("https://www.instagram.com/iam.ai4/")
sleep(28)
segui = browser.find_element_by_class_name('BY3EC').click()
If an element with class BY3EC isn't found I want the script to keep working.
When an element is not found it throws NoSuchElementException, so you can use try/except to avoid that, for example:
from selenium.common.exceptions import NoSuchElementException
try:
segui = browser.find_element_by_class_name('BY3EC').click()
except NoSuchElementException:
print('Element BY3EC not found') # or do something else here
You can take a look at selenium exceptions to get an idea of what each one of them is for.
surround it with try catches, than you can build a happy path and handle failures as well, so your test case will always work
Best practice is to not use Exceptions to control flow. Exceptions should be exceptional... rare and unexpected. The simple way to do this is to get a collection using the locator and then see if the collection is empty. If it is, you know the element doesn't exist.
In the example below we search the page for the element you wanted and check to see that the collection contains an element, if it does... click it.
segui = browser.find_elements_by_class_name('BY3EC')
if segui:
segui[0].click()
I have a page where the number of elements to loop through is not easily known. As such I’ve made the job loop through Href “a” (364 matches) and when it cannot find the Next button, I am wanting the job to come to an end.
I have tried:
try:
element = driver.find_element_by_xpath('//span[text()="Next Page"]')
except NoSuchElementException:
pass
#except IOError:
#pass
#except OSError:
#pass
As well as other variations and indenting.
My full code is here (it does not allow me to post it here fully due to character limit)
Below code should allow you to close browser and WebDriver session once you reach last page
from selenium.common.exceptions import NoSuchElementException
try:
element = driver.find_element_by_xpath('//span[text()="Next Page"]')
except NoSuchElementException:
driver.quit()