clicking slippery "ElementNotVisibleException" button selenium webdriver python - python

https://gist.github.com/codyc4321/724f05aca8f6775e2fc1
Hi, bitbucket changed their login page, and is giving me a hassle. Based on the following gist, using driver.click_button causes:
ElementNotVisibleException at /bitbucket/create-repo
Message: Element is not currently visible and so may not be interacted with
Stacktrace:
at fxdriver.preconditions.visible (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:9981)
at DelayedCommand.prototype.checkPreconditions_ (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:12517)
at DelayedCommand.prototype.executeInternal_/h (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:12534)
at DelayedCommand.prototype.executeInternal_ (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:12539)
at DelayedCommand.prototype.execute/< (file:///tmp/tmpSNzLIl/extensions/fxdriver#googlecode.com/components/command-processor.js:12481)
using driver.submit_form causes error in the browser itself:
using driver.activate_hidden_element causes:
ElementNotVisibleException at /bitbucket/create-repo
Message: Element is not currently visible and so may not be interacted with
activate_hidden_element failing really took the wind outta my sails for the last 5 minutes. How can I click this stonewalling button? Thank you

Okay, so the problem is actually in your locate_element method.
When you check for the xpath: "//button[normalize-space(text())='{text}']" it finds a button successfully but it is not the login button you are looking for. If you switch that with the input xpath: "//input[#value='{text}']" it finds the right input and successfully logs you in.
You should also remove the last two lines in the BitbucketDriver.login() method because the line self.click_button(search_text="Log in") throws an AttributeError.
Your locate_element method should look like this:
def locate_element(self, search_text, xpaths=None):
if not xpaths:
xpaths = [ "//input[#value='{text}']", "//button[normalize-space(text())='{text}']",
"//a[child::span[normalize-space(text())='{text}']]", "//a[normalize-space(text())='{text}']"]
try:
return self.driver.find_element_by_id(search_text)
except:
try:
return self.driver.find_element_by_name(search_text)
except:
try:
return self.driver.find_element_by_class_name(search_text)
except:
for path in xpaths:
try:
return self.driver.find_element_by_xpath(path.format(text=search_text))
except:
pass
return None

Related

Python Selenium send_keys to email input field

I am trying to make an auto-checkout script on https://www.footish.se/sneakers/fila-wmns-disruptor-run-1010866-60m
I have made it to the checkout page, but unable to enter my email in the "email" input-field.
The code looks like this
email = driver.find_element_by_xpath("/html/body/div/span/div/div/div/div[1]/div/div/div[1]/div/form/div[2]/div[1]/div/label/div/div/input")
email.send_keys("test#email.com")
Have implemented some sort of function to wait for the desired elements untill they are loaded in. One example->
while not find:
try:
find = driver.find_element_by_xpath("/html/body/form/div[5]/div/div[4]/div[1]/div[1]/div[2]/div[1]/div[10]/div[1]/h2")
print("Loaded info")
except:
continue
The error i am getting is this.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div/span/div/div/div/div[1]/div/div/div[1]/div/form/div[2]/div[1]/div/label/div/div/input"}
How would i resolve this? Thanks in advance....
It seems like the email field is a dynamicallly generated element and so when a check is initially made it is not yet present. You may try and use the until method to wait for a specific time and see if it indeed does get applied to the DOM.
Sample code
driver = webdriver.Chrome()
driver.get("url")
try:
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, "myDynamicElement")) # set your id here
)
finally:
driver.quit()
Do update if it doesn't work. It's then likely to do with frame or wrong path issues.

Continue when element is not found in selenium python

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()

Python Selenium element is not reachable by keyboard

acc = self.wait.until(EC.visibility_of_element_located((By.XPATH,"//tr[#valign='top']/td[2]/input[#id='account']")))
acc.send_keys(user['userid'])
time.sleep(1)
pwd = self.wait.until(EC.visibility_of_element_located((By.XPATH, "//tr[#valign='bottom']/td/input[#id='passwordInput1']")))
pwd.send_keys(user['pwd'])
I tried to login to a website and i can successfully input the account name--that is "acc" in the codes, but when it came the pwd, it will display an error message. And i tested that the pwd element can be fine, only the send_keys line went wrong.
selenium.common.exceptions.ElementNotInteractableException: Message: Element <input id="passwordInput1" class="inputField1" name="passwordInput1" type="text"> is not reachable by keyboard
It occurred in geckodriver and chromedrive, but was okay with phantomjs. Anyone knows what's happening?
The keyboard is not available at that time.It mean that using a keyboard is not effective.The situation I've encountered is that the page has changed, and the popup window, for example, alter.You should use :
driver.save_screenshot('screen.png')
try:
pwd = self.wait.until(
EC.visibility_of_element_located((By.XPATH, "//tr[#valign='bottom']/td/input[#id='passwordInput1']")))
pwd.send_keys(user['pwd'])
except Exception as e:
print(e)
driver.save_screenshot('screen.png')
to see the page status at that time.
You could try sending text by action chains:
import selenium.webdriver.common.actions
ActionChains(driver).send_keys_to_element(element, password).perform()
Where:
driver is the driver you are using,
element is your located element,
password is the text you want to send.
This solved my similar issue.
Docs:
https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains

Use python and selenium to delete my comments in reddit

I am trying to write a script to delete all my comments on my profile in Reddit.
So I am currently using Selenium to log-in and try to delete my comments, however I am stuck at the point when after my script press delete on my comment and it changes to "Are you sure Yes/No" then it can't find the "Yes" element by Xpath. The following code throws the error:
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotVisibleException: Message:
Element is not currently visible and so may not be interacted with
Stacktrace:
My code is as follows:
del_button = driver.find_element_by_xpath("//*[contains(#id,'thing_"+delete_type+"')]//div[2]/ul/li[7]/form/span[1]/a")
del_button.click()
time.sleep(3)
yes_button = driver.find_element_by_xpath("//*[contains(#id,'thing_"+delete_type+"')]//div[2]/ul/li[7]/form/span[1]//a[1]")
yes_button.click()
time.sleep(3)
As there could be several hidden elements with same attributes on page, you might need to use index to click on exact element:
driver.find_elements_by_xpath('//a[#class="yes"]')‌​[N].clic‌​k() # N is the index of target link
I f you can't define exact index, you can use below code:
from selenium.common.exceptions import ElementNotVisibleException
for link in driver.find_elements_by_xpath('//a[#class="yes"]')‌:
try:
link.click()
break
except ElementNotVisibleException:
pass

How to use find_element_by_link_text() properly to not raise NoSuchElementException?

I have a HTML code like this:
<div class="links nopreview"><span><a class="csiAction"
href="/WebAccess/home.html#URL=centric://REFLECTION/INSTANCE/_CS_Data/null">Home</a></span> • <span><span><a class="csiAction"
href="/WebAccess/home.html#URL=centric://SITEADMIN/_CS_Site">Setup</a></span> • </span><span><a
title="Sign Out" class="csiAction csiActionLink">Sign Out</a></span></div>
I would like to click on the link that has the text Home. As this Home link appears after login, I have a code like this:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import re
browser = webdriver.Firefox() # Get local session of firefox
browser.get("http://myServer/WebAccess/login.html") # Load App page
elem = browser.find_element_by_name("LoginID") # Find the Login box
elem.send_keys("Administrator")
elem = browser.find_element_by_name("Password") # Find the Password box
elem.send_keys("Administrator" + Keys.RETURN)
#try:
elem = browser.find_element_by_link_text("Home")
elem.click()
The part till login works great. However the last but one line is problematic
elem = browser.find_element_by_link_text("Home")
It raises this NoSuchElementException where the Home link is there as you can see from the HTML code.
raise exception_class(message, screen, stacktrace)
NoSuchElementException: Message: u'Unable to locate element: {"method":"link text","selector":"Home"}'
Any guidance as to what I am doing wrong, please?
Have you tried adding an implicit wait to this so that it waits instead of running to quickly.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import re
browser = webdriver.Firefox() # Get local session of firefox
browser.implicitly_wait(10) #wait 10 seconds when doing a find_element before carrying on
browser.get("http://myServer/WebAccess/login.html") # Load App page
elem = browser.find_element_by_name("LoginID") # Find the Login box
elem.send_keys("Administrator")
elem = browser.find_element_by_name("Password") # Find the Password box
elem.send_keys("Administrator" + Keys.RETURN)
#try:
elem = browser.find_element_by_link_text("Home")
elem.click()
The implicitly_wait call makes the browser poll until the item is on the page and visible to be interacted with.
The most common issues with NoSuchElementException while the element is there are:
the element is in different window/frame, so you've to switch to it first,
your page is not loaded or your method of page load is not reliable.
Solution could include:
check if you're using the right frame/window by: driver.window_handles,
write a wait wrapper to wait for an element to appear,
try XPath instead, like: driver.find_element_by_xpath(u'//a[text()="Foo"]').click(),
use pdb to diagnose your problem more efficiently.
See also: How to find_element_by_link_text while having: NoSuchElement Exception?
Maybe the element you are looking for doesn't exactly match that text string?
I know it can be tricky if it looks like it does on-screen, but sometimes there are oddities embedded like this simple markup "Home" or "Home" which makes the first char italic:
"<i>H</i>ome" is visually identical to "<em>H</em>ome" but does not match text.
Edit: after writing the above answer, I studied the question closer and discovered the HTML sample does show "Home" in plain text, but was not visible due to long lines not wrapping. So I edited the OP to wrap the line for readability.
New observation: I noticed that the Logout element has a "title" attribute, but the Home link element lacks such--try giving it one and using that.
Try adding an implicit wait to this in order to wait, instead of running too quickly.
Or
else you can import time and use time.sleep(25)

Categories

Resources