Python selenium scrolling doesn't work when used in class instance - python

I'm trying to write a selenium script with python that downloads my bills from a website. There are more bills (rows) that can fit in the view port, and when the script reaches the end of the view port it fails. So I tried:
ActionChains(self.driver).move_to_element(element).perform() ==> NOK
element.location_once_scolled_into_view ==> OK in console
self.driver.execute_script("window.scrollTo({});") ==> OK in console
Number 2. and 3. worked like a charm when I ran it in the pycharm python console line-by-line:
the sidebar scroll moves down to the target element
can .click() the element in question.
When used in a class
the scroll bar does not move at all, and throws this error:
selenium.common.exceptions.ElementClickInterceptedException: Message:
element click intercepted: Element is not clickable at point (1187,
642)
def downloader(self, count, provider):
print("count: ", count) # count is the number of row for a
provider
for number in range(1, (count + 1)) :
#sleep(2)
element = self.wait.until(EC.visibility_of(
self.driver.find_element(By.XPATH,
"//table/tbody/tr[{}]/td[6]".format(number))))
location = element.location_once_scolled_into_view
# ActionChains(self.driver).move_to_element(element)
.perform()
#self.driver.execute_script("arguments[0]
.scrollIntoView(true);",element);
# self.wait.until(EC.element_to_be_clickable(element))
# sleep(1)
self.driver.execute_script("window.scrollTo({});"
.format(location))
element.click()

The issue could be due to the fact that the element is not being scrolled into view completely when being executed as part of a class. When you're executing the script line by line in the console, it has enough time to complete the scroll before the element is clicked.
To resolve the issue, you can try adding an explicit wait after scrolling to give the page enough time to load before attempting to click the element.
Here's an updated version of your code with the added explicit wait:
def downloader(self, count, provider):
print("count: ", count) # count is the number of row for a provider
for number in range(1, (count + 1)):
element = self.wait.until(EC.visibility_of(
self.driver.find_element(By.XPATH, "//table/tbody/tr[{}]/td[6]".format(number))))
location = element.location_once_scolled_into_view
self.driver.execute_script("window.scrollTo({});".format(location))
# Add explicit wait
self.wait.until(EC.element_to_be_clickable(element))
element.click()

Related

Can't find a way to upload an image (interact with the element)

So i have a code which logins to Facebook and fills everything needed to publish an item in marketplace, but I've been struggling in uploading images.
First of all there is no input tag inside the 'parent tag' (div class="aov4n071") (the first div):
However when i try this line of code:
ele = wait.until(EC.presence_of_element_located((By.XPATH,'//*[contains(text(), "AƱadir fotos")]')))
ele.click()
The element does get clicked without any error, and the dialog where you need to browse your folder manually shows up. AS EXPECTED. However when i send_keys() to ele it shows:
selenium.common.exceptions.ElementNotInteractableException: Message: Element <span class="a8c37x1j ni8dbmo4 stjgntxs l9j0dhe7 ltmttdrg g0qnabr5 oi732d6d ik7dh3pa d2edcug0 qv66sw1b c1et5uql muag1w35 ew0dbk1b jq4qci2q a3bd9o3v lrazzd5p oo9gr5id"> is not reachable by keyboard
Which is understandable because it is not an input element. But where the hell is the input tag??
I found out that there are two input classes that are right above the 'parent' class i talked about in the first picture. But these elements are not like the others, when i put my cursor on them, they don't behave like the other elements. It seems like they are invisible. (look how they are not colored like the other ones)
I tried this line of code:
ele = wait.until(EC.presence_of_element_located((By.CLASS_NAME,'mkhogb32')))
ele.send_keys(var)
But it gives me this error:
selenium.common.exceptions.ElementNotInteractableException: Message: Element <div class="eopy0mj9 ina5je9e kr520xx4 j9ispegn poy2od1o b5wmifdl mw227v9j n7fi1qx3 dya21fl7 a47luoao sbevj9st ev399l9o iwynql29 kuz35qqg mkhogb32"> is not reachable by keyboard
But when i try this:
ele.click()
I get the following error:
selenium.common.exceptions.ElementNotInteractableException: Message: Element <div class="eopy0mj9 ina5je9e kr520xx4 j9ispegn poy2od1o b5wmifdl mw227v9j n7fi1qx3 dya21fl7 a47luoao sbevj9st ev399l9o iwynql29 kuz35qqg mkhogb32"> could not be scrolled into view
I don't know much about HTML but i can tell these are the tags that will allow me to upload pictures, but why do the behave different?
What can i do do finally upload pictures?
Are the input tags in another frame?
this code is running good
POST="c:\\maphoto.jpg"
l=navigateur.find_elements_by_tag_name('input')
for g in l:
if g==navigateur.find_element_by_xpath("//input[#type='file'][#class='mkhogb32']"):
g.send_keys(POST)
time.sleep(5)

Appium + Python on Android - scrolling doesn't work

Appium + Python on Android - scrolling
I have an app to automate tests for. Scenario looks like this:
I tap on date picker > calendar appears
I tap on the year > a list of years appears
I want to scroll until '1993' is visible
the year '1993' is not visible on the screen and I want to keep scrolling until it is. I've tried
TouchAction(driver).press(x=746, y=1351).move_to(x=755, y=588).release().perform()
^but I don't want to use coordinates, plus I'd have to repeat that line several times.
def set_year(self):
visibility = self.driver.find_element(By.XPATH, "//android.widget.TextView[#text='1993']").is_displayed()
while not visibility:
TouchAction(self.driver).press(x=746, y=1351).move_to(x=755, y=588).release().perform()
visibility = self.driver.find_element(By.XPATH, "//android.widget.TextView[#text='1993']").is_displayed()
else:
print("not found")
^but it keeps throwing me selenium.common.exceptions.NoSuchElementException: Message: An element could not be located on the page using the given search parameters error, since as I said, it's not visible
What is the best approach for this?
el = self.driver.find_element_by_xpath(<your_xpath>) driver.execute_script("mobile: scrollTo", {"element": el.id})
^this one gives me an error saying that a tuple does not have id
Appium will throw an error each time an element is not find.
So, your script stops before swiping, when you define your variable visibility.
Try this :
def set_year(self):
visibility = False
i = 0
while not visibility or i<100:
i += 1
try:
visibility = self.driver.find_element(By.XPATH,
"//android.widget.TextView[#text='1993']").is_displayed()
except:
TouchAction(self.driver).press(x=746, y=1351).move_to(x=755,
y=588).release().perform()
if not visibility:
print("not found")
Your script will scroll down until the year 1993 is found.

the OK button can't be click - why?

The below is the id of the "Ok" button inside the popup window , just wanted to say that i was able to sendkeys and ENTER for another field inside the same popup window :
OK button
The exception i'm getting is:
selenium.common.exceptions.ElementNotInteractableException: Message: Cannot click on element
Also adding the actual GUI :
actual window
The code is below:
def create_new_customer_iden():
browser.find_element_by_css_selector("#customer_care_app_tab > tbody > tr > td:nth-child(2)").click()
browser.find_element_by_css_selector("#add_customer > td:nth-child(2)").click()
browser.find_element_by_id("go_srch_button").click()
random_number=random.randrange (10000, 99999)
statement ='INSERT INTO sa_customer(CUSTOMER_NO, CUSTOMER_NAME) VALUES(:1, :2)'
cursor.execute(statement,(random_number,random_number))
connection.commit()
browser.find_element_by_name("popup_search_init_customer_id").send_keys(random_number)
browser.find_element_by_name("popup_search_init_customer_id").send_keys(Keys.ENTER)
# works great until here
browser.find_element_by_id("ok_button").click()
i found another issue :
if i'm adding the below lines of code :
button=browser.find_element_by_id ("ok_button")
print(button)
button.click()
The print gives me this element:
selenium.webdriver.remote.webelement.WebElement (session="75fba3d3-bef4-4800-a03d-bfbfcf831209", element="4d27c723-ed64-40a5-9da0-102a52f4d910")
BUT the last line of code throws me the below exception :
selenium.common.exceptions.ElementNotInteractableException: Message: Cannot click on element
WHICH means that i need to find a subtitute to the click() operation.
Any suggestions ???
Try one of the following once the popup loads - driver.switch_to_frame(webelement) / driver.switch_to_window(window_name)
Once you've finished interacting with the popup, e.g. you've closed it use driver.switch_to_default_content() to return to the main page
window_name can be defined by
var window_name = driver.find_element_by_class_name("popup_table")
If none of the above works, the last thing I can suggest to try is: driver.switch_to_alert()
For more information please see: Python webdriver to handle pop up browser windows which is not an alert
Switch to popup in python using selenium
I'd also suggest reading through the Python documentation: http://selenium-python.readthedocs.io/navigating.html - you'll probably find the answer here if the above doesn't help. I'm not really familiar with Python
Try this and then see what exception is thrown?
wait = WebDriverWait(driver, 10)
element = wait.until(expected_conditions.element_to_be_clickable((By.ID, "ok_button")))
How about using XPath or selector? Chrome DevTools provide them.
Here's the sample code
browser.find_element_by_xpath("insert ok_button xpath").click()
browser.find_element_by_css_selector("insert ok_button selector").click()
"The print gives me this element: selenium.webdriver.remote.webelement.WebElement (session="75fba3d3-bef4-4800-a03d-bfbfcf831209", element="4d27c723-ed64-40a5-9da0-102a52f4d910") BUT the last line of code throws me the below exception : selenium.common.exceptions.ElementNotInteractableException: Message: Cannot click on element WHICH means that i need to find a subtitute to the click() operation. Any suggestions ???"
Yes, try the below:
def create_new_customer_iden():
browser.find_element_by_css_selector("#customer_care_app_tab > tbody > tr > td:nth-child(2)").click()
browser.find_element_by_css_selector("#add_customer > td:nth-child(2)").click()
browser.find_element_by_id("go_srch_button").click()
random_number=random.randrange (10000, 99999)
statement ='INSERT INTO sa_customer(CUSTOMER_NO, CUSTOMER_NAME) VALUES(:1, :2)'
cursor.execute(statement,(random_number,random_number))
connection.commit()
browser.find_element_by_name("popup_search_init_customer_id").send_keys(random_number)
browser.find_element_by_name("popup_search_init_customer_id").send_keys(Keys.ENTER)
element = browser.find_element_by_class_name("popup_table")
browser.switch_to_window(window_name)
okButton = browser.find_element_by_id("ok_button")
actions = ActionChains(browser)
actions.move_to_element(okButton).perform()
actions.click(okButton)
//some action to close the popup
browser.switch_to_default_content()
if not, try this...
def create_new_customer_iden():
browser.find_element_by_css_selector("#customer_care_app_tab > tbody > tr > td:nth-child(2)").click()
browser.find_element_by_css_selector("#add_customer > td:nth-child(2)").click()
browser.find_element_by_id("go_srch_button").click()
random_number=random.randrange (10000, 99999)
statement ='INSERT INTO sa_customer(CUSTOMER_NO, CUSTOMER_NAME) VALUES(:1, :2)'
cursor.execute(statement,(random_number,random_number))
connection.commit()
browser.find_element_by_name("popup_search_init_customer_id").send_keys(random_number)
browser.find_element_by_name("popup_search_init_customer_id").send_keys(Keys.ENTER)
driver.switch_to_alert()
okButton = browser.find_element_by_id("ok_button")
actions = ActionChains(browser)
actions.move_to_element(okButton).perform()
actions.click(okButton)
//some action to close the popup
browser.switch_to_default_content()
Obviously you may need to change this slightly to fit in with your code, e.g. browser instead of driver.
https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.action_chains.html
Ok the issue was solved eventually by me :
it appears that there are 2 buttons with the same ID - so i added index as below :
browser.find_element_by_xpath('(//*[#id="ok_button"])[2]').click()
IT WORKED !!!!

Selenium won't open a new url in for loop (Python & Chrome)

I can't seem to get Selenium to run this for loop correctly. It runs the first time without issue but when it starts the second loop to the program just stops running with no error message. I get the same results when I attempt this with a firefox browser. Maybe it has to do with me trying to start a browser instance when one is already running?
def bookroom(self):
sessionrooms=["611", "618"] #the list being used by the for loop
driver = webdriver.Firefox()
#for loop trying each room
for rooms in sessionrooms:
room=roomoptions[rooms][0]
sidenum=roomoptions[rooms][1]
bookingurl="https://coparooms.newschool.edu/copa-scheduler/Web/reservation.php?rid="+room+"&sid="+sidenum+"&rd="+self.startdate
driver.get(bookingurl)
time.sleep(3)
usernamefield = driver.find_element_by_id("email")
usernamefield.send_keys(self.username)
passwordfield = driver.find_element_by_id("password")
passwordfield.send_keys(self.password)
passwordfield.send_keys(Keys.RETURN)
time.sleep(5)
begin=Select(driver.find_element_by_name("beginPeriod"))
print(self.starttime)
begin.select_by_visible_text(convertarmy(self.starttime))
end=Select(driver.find_element_by_name("endPeriod"))
end.select_by_visible_text(convertarmy(self.endtime))
creates=driver.find_element_by_xpath("//button[contains(.,'Create')]")
creates.click() #clicks the confirm button
time.sleep(8)
xpathtest=driver.find_element_by_id("result").text
#if statement checks if creation was a success. If it is, exit the browser.
if "success" in xpathtest or "Success" in xpathtest:
print "Success!"
driver.exit()
else:
print "Failure"
time.sleep(2)
#if creation was not success try the next room in sessionrooms
Update:
I found the problem, it was just a matter of uneven spacing. Only some of the loop was "in the loop".
if "success" in xpathtest or "Success" in xpathtest:
print "Success!"
driver.exit()
You will want to break out of your loop here, as you're closing the driver, but using it in the next iteration of the loop without starting a new driver object

Robotframework: Clicking web-elemnt in loop often fails to find an element

I have created a keyword for RF and Selenium2Library. It is supposed to wait for some element by clicking periodically on some other element which will renew the area where the element is supposed to appear. I use it for example for waiting for mails in postbox.
The problem is that pretty often the "renew element" cannot be found and clicked on some loop iteration however it exists on the screenshot. Any ideas why it can happen?
def check_if_element_appeared(self, element_locator, renew_locator, renew_interval=10, wait_interval=300):
if not self.is_visible(renew_locator):
raise AssertionError("Error Message")
start_time=int(time())
scan_time = start_time
if not self.is_visible(element_locator):
while int(time())<=start_time+wait_interval:
if int(time()) >= scan_time + renew_interval:
scan_time = int(time())
self.click_element(renew_locator)
if self.is_visible(element_locator):
break
if not self.is_visible(element_locator):
raise AssertionError("Error Message")
self._info("Message")
else:
self._info("Current page contains element '%s'." % element_locator)
Shouldn't be using the keywords Wait Until Page Contains Element or Wait Until Element Is Visible of the Selenium2Library for this purpose:
*** Test cases ***
Your Test Case
Prerequisite steps
Wait Until Page Contains Element ${locator}
Succeeding steps
Edit: Below is what your Python code might look like in pure Robot syntax.
${iteration}= Evaluate ${wait_interval} / ${renew_interval}
: FOR ${i} IN RANGE 0 ${iteration}
\ Click Element ${renew_locator}
\ Sleep 1
\ ${is_visible}= Run Keyword And Return Status Element Should Be Visible ${element_locator}
\ Exit For Loop If ${is_visible}
\ Run Keyword If '${is_visible}' == 'False' Sleep ${renew_interval}
Click Element ${element_locator}

Categories