python - having a hard time on selenium to click on button - python

I am working with selenium (python) and I would like for it to click on a button. The code goes something like this:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('my_url')
try:
driver.find_element_by_partial_link_text('Mais').click()
except:
pass
Nothing at all happens. After inspecting the source, and I am pretty sure this is the element I want to find:
<input class="ksb _kvc" value="Mais resultados" id="smb" data-lt="Carregando..." jsaction="str.smr" data-ved="0ahUKEwjPtK6Fwv3PAhVGI5AKHTkSDVsQxdoBCE8" type="button" />

Have you tried
driver.find_element_by_id('smb').click()
Rather than
driver.find_element_by_partial_link_text('Mais').click()
I suspect nothing happens because an exception is thrown in your original code if the find fails.
When attempting to locate elements I would usually use id/name as these are normally unique. For a full list see selenium-python.readthedocs.io/locating-elements.html

You are having issue clicking the button because you are using driver.find_element_by_partial_link_text() which is only good for finding link (anchor elements) by its partial text, and performing actions on it.
You should rely on the other find_element_by_xxxx() methods which allow us to find by element ID, Name, XPath, CSS selector, or Class name.
Refer the documentation on locating elements at : http://selenium-python.readthedocs.io/locating-elements.html

Related

Selenium: How to click a label

I'm trying to click this object with selenium (pyhton) using the code:
driver.find_element_by_('publicForm_customFields').click()
But I'm receiving this error:
id="publicForm_customFields" tabindex="0" type="radio" value="value"> is not clickable at point (480, 98). Other element would receive the click: value
"Other element would receive the click" means that you have another element over your element. There are a couple of options to get around this:
Try to find another element above in the DOM tree and click on it.
Use js click, you need to write a function like this:
def js_click(self, element):
element = driver.find_element_by_id("myid")
driver.execute_script("arguments[0].click();", element)
js script will click on the element even if it is intersected by another
There might be two possibilities:
1- Your locator to find element might be wrong or not unique.
2- You need to apply explicit wait till element is ready [load successfully] to be clickable.
Hope above possibilities might help you out, Or you share the link of the sight so I might debug correctly.
You are not passing any find method to the driver. Try refactoring the code to:
driver.find_element_by_id('publicForm_customFields').click()
Also, try using some sort of wait so the driver does not click before the page/element is loaded.
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.ID, 'publicForm_customFields'))).click()

Cannot click button - element not found

I have tried to make my script click the log in button on the Spotify login page. I have been searching all day for a solution, but no matter what class, css or whatever I put in, it is just saying it could not find the object.
My code:
import selenium
from selenium import webdriver
browser = webdriver.Firefox()
browser.get("https://accounts.spotify.com/en/login?
continue=https:%2F%2Fwww.spotify.com%2Fdk%2Faccount%2Foverview%2F")
username = browser.find_element_by_id("login-username")
password = browser.find_element_by_id("login-password")
username.send_keys("myUser")
password.send_keys("myPass")
login = browser.find_element_by_class_name('ng-pristine ng-valid-sp-
disallow-chars ng-invalid ng-invalid-required').click()
It is the last line I have a problem with. Note: This is just one of the options I tried.
You can try this code that have xpath:
login = browser.find_element_by_xpath("//button[contains(.,'Log In')]");
login.click();
You're using multiple classes in your class selector. Try using only one class. Something like this:
browser.find_element_by_class_name('btn-green').click()
If it still doesn't work, perhaps the element has not yet been rendered when you try to click it, so you may want to try with an explicit wait
Also, I checked out your selector and it looks like you weren't even pointing to the button, but to the form.
And finally, a class selector may not be the optimal way to locate your element here. I'd probably go with a XPath selector to find the button that contains the text Log In, using the following XPath
//button[text()='Log In']
Use this, i Updated the answer:
login = browser.find_element_by_xapth("//button[#class='btn btn-sm btn-block btn-green ng-binding']")
login .click()
browser.find_element_by_xpath(".//button[contains(text(), 'Log In'])").click()
This should work so give it a try. :)
As #Verv stated, you could be having timing issues. So just for the test try with time.sleep() to see if this is it.

Using Python and Selenium I am unable to get to elements in overlaying model

In my test I have to click a button to add an item to the cart. At that point a model dialog comes up and allows some options and links, one of which I am trying to click; View Cart and Checkout.
Every attempt I make to find my element with find_element_by fails with a NoSuchElementException. Doesn't matter how I try to find it; ID, Class, Link Text, etc.
I have tried setting up WebDriverWait in a try/catch statement to see if pausing for the model to be added to the page would help, and it doesn't. I have also checked to see if there is another window or frame to switch to, but there is only the one window.
Are there any other ways to get what I need done, or troubleshooting steps that I can do to figure this out?
Below is what Firefox shows the HTML to be.
<div class="summary">
<dl></dl>
<a class="bb-button" href="/shopping/cart">View Cart and Checkout</a>
<div class="continue"></div>
The python I have written is:
product_details.addDocumentToCart('Printed Edition')
try:
WebDriverWait(self.driver, 10).until(EC.presence_of_element_located(By.CLASS_NAME, 'bb-button'))
print 'bb-button found'
except:
print 'bb-button not found'
windows = self.driver.window_handles
print 'Windows after: ' + str(len(windows))
element = self.driver.find_element_by_class_name('bb-button')
element.click()
The messages I printed out return:
added_to_cart-container not found
and
Windows after: 1
The error I get when running this is:
NoSuchElementException: Message: Unable to locate element: {"method":"class name","selector":"bb-button"}
Thanks Mikko, with your advice about the pbd.set_trace() I was able to discover that my problem was really with the button that I thought was being clicked but wasn't. Further troubleshooting showed that my addDocumentToCart() method was clicking the wrong element, and so my model didn't come up, but no error was generated which lead me to believe that things were working when the really were not.

Selenium Python document.getElementsByClassName()

I'm using Selenium with Python3 to automate entering data into a website.
I have tried looking everywhere for how to deal with selecting an element by class if there is more than one but I can't figure out how to select the accordion-toggle[1]. Nothing happens on selenium but it works fine on any browser. Also, is there any way to just use the regular javascript or jquery commands?:
accordion=find_element_by_class("accordion-toggle"[1])
accordion.click()
#otheraccordion=find_element_by_css_selector("#AdvancedAddress > div.accordion-heading.in > div.accordion-toggle > span.accordionExpandCollapse")
#otheraccordion.click()
StreetNameField=driver.find_element_by_id("Advanced_FindMyParcel_PropertyStreetName")
StreetNameField.send_keys("Sherman")
ZipField=driver.find_element_by_id("Advanced_FindMyParcel_PropertyZip")
ZipField.send_keys("90201")
ZipButton=driver.find_element_by_id("btnSearchFindMyParcels")
ZipButton.click()
You actually can use document.getElementsByClassName() through execute_script() call:
driver.execute_script("document.getElementsByClassName('accordion-toggle')[0].click();")
But I would not go down to executing javascript for such a simple task. Easier to locate the element using find_element_by_class_name():
accordion = driver.find_element_by_class_name('accordion-toggle')
accordion.click()
You are looking for find_element(s)_by_css_selector - reference here - use the css prefix '.classname` to indicate the class.
e.g. to find
<div class='theClass'>
driver.find_elements_by_css_selector('.theClass')
You can also use the By syntax:
driver.find_elements(By.CSS_SELECTOR, '.theClass')
Edit
It seems the problem may be more to Clicking the element, rather than finding it.
Ensure the element is visible
For Chrome, you may need to mimic hovering the mouse over the element before clicking this - see Actions / ActionChains MoveToElement to hover over the element.
For IE, you may need to ensure the browser / frame gets the focus, prior to the element Click - you may need to apply a hack like one of these.
In addition to #alecxe response, I would also suggest using the function find_elements_by_class_name instead of find_element_by_class_name in case there are multiple elements with the same class name.
accordion = driver.find_elements_by_class_name('accordion-toggle')[1] # Selects second element
accordion.click()
Using find_element_by_class_name will return only the first element with that class name.

Selenium - Click at certain position

Using the Python version of Selenium, is it possible to click some element in the DOM and to specify the coordinates where you want to click it?
The Java version has the method clickAt, which actually does exactly what I am looking for, but can't find the equivalent in Python.
This should do it! Namely you need to use action chains from webdriver. Once you have an instance of that, you simply register a bunch of actions and then call perform() to perform them.
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.google.com")
el=driver.find_elements_by_xpath("//button[contains(string(), 'Lucky')]")[0]
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(el, 5, 5)
action.click()
action.perform()
This will move the mouse 5 pixels down and 5 pixels right from the upper-left corner of the button I feel lucky. Then it will click().
Notice that you must use perform(). Else nothing will happen.
The reason you are getting confused is clickAt is an old v1 (Selenium RC) method.
WebDriver has a slightly different concept, of 'Actions'.
Specifically, the 'Actions' builder for the Python bindings live here.
The idea of the clickAt command is to click at a certain position relative to a particular element.
The same is achievable within the WebDriver, using the 'Actions' builder.
Hopefully this updated documentation can help.
You can perform the task with the Action chains in the python specially with Edge browser:
from selenium.webdriver import ActionChains
actionChains = ActionChains(driver)
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
actionChains.move_to_element(button).click().perform()
But sometimes Action chain does not finds the DOM element. Hence better option to use execute scipt in following way:
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
driver.execute_script("arguments[0].click();", button)
I've not personally used this method, but looking through the source code of selenium.py I've found the following methods that look like they'd do what you want - They look to wrap clickAt:
def click_at(self,locator,coordString):
"""
Clicks on a link, button, checkbox or radio button. If the click action
causes a new page to load (like a link usually does), call
waitForPageToLoad.
'locator' is an element locator
'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator.
"""
self.do_command("clickAt", [locator,coordString,])
def double_click_at(self,locator,coordString):
"""
Doubleclicks on a link, button, checkbox or radio button. If the action
causes a new page to load (like a link usually does), call
waitForPageToLoad.
'locator' is an element locator
'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator.
"""
self.do_command("doubleClickAt", [locator,coordString,])
They appear in the selenium object and here is their online API documentation.

Categories

Resources