Selenium - Python: scroll to the element found by find_element* methods - python

I developed a selenium script, which makes automatic comments in facebook groups.
It works relatively good, but it does not execute the click() method if the targeted element is not visible on the browser.
As a working around I'm using the execute_script("window.scrollTo(x,y";), method, but it's not ideal script. The piece of code that must be improved is the following:
text_box = driver.find_element_by_class_name("UFIAddCommentInput")
try:
driver.execute_script("window.scrollTo(100, 0);")
text_box.click()
except:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
text_box.click()
element = driver.switch_to.active_element
element.send_keys(frase)
element.send_keys(Keys.RETURN)
It first tries for the element on the top of the page, and, if does not get to execute click(), it tries at the bottom.
However, there is a more effective way to scroll at the element found by the find_element_by_class_namemethod?

You can try
text_box.location_once_scrolled_into_view
text_box.click()
to scroll page down right to required element and click it

Related

What is wrong with my xpath? Why is a different element receiving the click?

Steps to recreate:
Go to http://practice.automationtesting.in/
Click on add to basket
Then view basket
Change the quantity to 2
Click on Update Basket
Click on remove item'X'
Or use coupon code "krishnasakinala"
Click on Apply Coupon button
The error I am getting is:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element ... is not clickable at point (216, 220). Other element would receive the click:
I have tried different locators but getting the same error.
Read more: https://softwaretestingboard.com/q2a/4041/exceptions-elementclickinterceptedexception-intercepted#ixzz6iUxRC97y
My code:
url = "http://practice.automationtesting.in"
driver.get(url)
wait_timeout = 5
wait_variable = W(driver, wait_timeout)
driver.find_element_by_xpath("//a[#data-product_id='160']").click()
wait_variable.until(E.presence_of_element_located((By.XPATH, "//a[#class ='added_to_cart wc-forward']"))).click()
wait_variable.until(E.presence_of_element_located((By.XPATH, "//input[#type='number']"))).clear()
wait_variable.until(E.presence_of_element_located((By.XPATH, "//input[#type='number']"))).send_keys(2)
wait_variable.until(E.element_to_be_clickable((By.NAME, "update_cart"))).click()
wait_variable.until(E.presence_of_element_located((By.XPATH, "//a[#title='Remove this item']"))).click()
There are multiple ways to solve this problem like making the driver wait, using a different element identifier (CSS/class/etc.) but the most effective one is to use the method execute_script()
element = driver.find_element_by_xpath('the xpath of the element')
driver.execute_script("arguments[0].click();", element)
wait_variable.until(E.element_to_be_clickable(
(By.NAME, "update_cart"))).click()
wait_variable.until(E.presence_of_element_located(
(By.CSS_SELECTOR,'[class="blockUI blockOverlay"]')))
wait_variable.until(E.staleness_of(
driver.find_element_by_css_selector('[class="blockUI blockOverlay"]')))
wait_variable.until(E.presence_of_element_located(
(By.XPATH, "//a[#title='Remove this item']"))).click()
The error is due to the overlay loader use this code , using javascript to click an element is not a right way it will bypass the UI rendering and direcly trigger click event on the element.
This should be avoided if you are using selenium for testing
How to find locator for overlay loader:
what is overlay loader :
This spinner is a UI element used to block user interaction with UI while ajax components are being loaded in the background.
What are the challenges:?
The spinner load so fast that it is hard to locate the element from dev tool
How to find the locator?
open element tab , right click the html and seelct break on sub tree modification
now click play button:
click update cart and click the blue play button till the loader is present in the UI.
This will freeze UI with the spiner in screen , now you can easily find the locator

Why a click function of a web page element doesn't work (using Selenium module of Python)?

I am trying to automate a task which can save me thousands of clicks.
I searched a bit for available modules in Python and I have selected to work with Selenium.
I installed Firefox drivers and did some progress but I am stuck for a long time. I finally gave up, opened a Stack Overflow account and wanted to bring this problem into this helpful medium.
My code can successfully do some clicks, but I could not make the code click a button like element. I have to click such items so that page opens some new elements. (Hopefully I am going to click on these new elements to save some excels files automatically).
Here is the part which works as expected:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
browser = webdriver.Firefox()
url = "https://www.tbb.org.tr/tr/bankacilik/banka-ve-sektor-bilgileri/istatistiki-raporlar/59"
browser.get(url)
time.sleep(2)
bank_reports_element_xpath = "//*[#title= 'Tüm Raporlar']"
bank_reports_element = browser.find_element_by_xpath(bank_reports_element_xpath)
bank_reports_element.click()
time.sleep(2)
second_item = "//div[#data-catid = '52']"
finance_tables_element = browser.find_element_by_xpath(second_item)
finance_tables_element.click()
years_item = "//div[#class = 'years']"
years_element = finance_tables_element.find_element_by_xpath(years_item)
year_elements = years_element.find_elements_by_xpath("a")
There I would like to click on the years.
a screenshot of the years that I can't click using Selenium
As an example, I get the element related to year 2004.
year2004 = year_elements[2]
Issuing a year2004.click() command gives an ElementNotInteractableException exception.
year2004.click() # ElementNotInteractableException: Element could not be scrolled into view
Based on searching similar posts, I tried the following (executing the click via javascript). I got no error but it does not do anything. When I click the year2004 button with mouse, a list pops-up in the page. But when I run the below code, no list pops up in the page.
browser.implicitly_wait(4)
browser.execute_script("arguments[0].scrollIntoView();", year2004)
browser.execute_script("arguments[0].click()", year2004)
I tried also the following code. I get "TypeError: rect is undefined"
browser.implicitly_wait(4)
action = ActionChains(browser)
action.move_to_element(year2004) # gives: TypeError: rect is undefined
action.click(on_element = year2004) # gives: TypeError: rect is undefined
action.perform()
I tried using Chrome Driver and got similar results. The errors definitions were not exactly the same. Instead of the above "rect is undefined" error, Chrome error is like: "Javascript error: Failed to execute 'elementsFromPoints' on 'Document': Provided double value is non-finite"
I don't know if it is relevant but year2004.location dictionary has a 0 value for "x".
I would appreciate any answer,
Keep safe
Use this xpath will give you all the elements of year in 52 category
//div[#data-catid='52']/descendant-or-self::*/div[#class='years']/child::a
for scrolling try
browser.send_keys(Keys.PAGE_DOWN)
I checked manually and page down button is working for me press it twice for desire element

StaleElementReferenceException while trying to move_to_element (Python)

I'm trying to .click() a few elements in a pop up-list on a webpage, but keep getting the StaleElementReferenceException when i try to move_to_elements.
The code is based around a number of clickable elements in a feed. When clicked, these elements result in a pop-up box with more clickable elements that I want to access.
I access the pop up-box with the following code, where popupbox_links are a list with coordinates and links for the pop up boxes:
for coordinate in popupbox_links:
actions = ActionChains(driver)
actions.move_to_element(coordinate["Popupbox location"]).perform()
time.sleep(3)
popupboxpath = coordinate["Popupbox link"]
popupboxpath.click()
time.sleep(3)
This works fine. But when the pop up box is opened, I want to perform the following:
seemore = driver.find_element_by_link_text("See More")
time.sleep(2)
actions.move_to_element(seemore).perform()
time.sleep(2)
seemore.click()
time.sleep(3)
findbuttons = driver.find_elements_by_link_text("Button")
time.sleep(2)
print(findbutton)
for button in findbuttons:
time.sleep(2)
actions.move_to_element(button).perform()
time.sleep(2)
button.click()
time.sleep(randint(1, 5))
The trouble starts at actions.move_to_element on both "See more" and "Button". Even though the print(findbutton) actually returns a list with contents, containing the elements that I want to click, Selenium seems to be unable to move_to_element on these. Instead, it throws StaleElementReferenceException.
To make it more confusing, the script seems to work at times. Although usually it just crashes.
Any clues on how to solve this? Big thanks in advance.
I'm running the latest Selenium on Python 3.6 with the Chrome WebDriver.
StaleElementReferenceException Says that element is stage because something has changed in page after you created the webElement object. In you case that could be happening due to button.click().
The simplest solution is to create new element every time, rather than iterate element from the loop.
following changes might work.
findbuttons = driver.find_elements_by_link_text("Button")
time.sleep(2)
print(findbuttons)
for i in range(len(findbuttons)):
time.sleep(2)
elem = driver.find_elements_by_link_text("Button")[i]
actions.move_to_element(elem).perform()
time.sleep(2)
elem.click()
time.sleep(randint(1, 5))

Scroll to the very bottom of the page Python

Having issue with scrolling method. Here is my code, by looks like it works fine, but completely ignoring self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") line.
Is there any other method by chance?
Keep in mind, I cannot use any particular element like 'self.driver.find_element_by_id' at the end, because they keep changing all the time.
def ViewEventHistory(self):
self.login()
self.controlMenu('2')
time.sleep(2)
view_event = self.driver.find_element_by_id('com.eightdevelopment.eas.android:id/btn_event_history')
view_event.click()
time.sleep(10)
self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
As I understand, the problem here is that your are trying to scroll the window, but actually you need to scroll the pop-up that is opened by view_event.click().
You can use a snippet I wrote for one of my projects. It accepts an optional Selenium element and scrolls it. If it's not provided, the function scrolls the main window.
def _scroll(self, scroll_obj=None):
if scroll_obj:
self.driver.execute_script(
'arguments[0].scrollTop = arguments[0].scrollHeight;', scroll_obj)
else:
self.driver.execute_script(
'document.body.scrollTop = document.body.scrollHeight;')

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