creating for loop using selenium python to click dropdown items - python

I am trying to create a for loop which:-
1) clicks the dropdown item
2) add a comment
3) submit a comment
This whole loop will happen in the same page itself. The XPath is correct and I can execute these lines individually once but it fails in a loop. What am I doing wrong here?
No particular error message given
add_comments = driver.find_elements_by_class_name('add')
comments = driver.find_elements_by_xpath("//form[#class='addComment expand']//textarea[contains(#placeholder,'Add a comment')]")
submit_comments = driver.find_elements_by_xpath("//button[text()='Comment']")
i = 0
for add_comment in add_comments:
for comment in comments:
for submit_comment in submit_comments:
WebDriverWait(driver, 5)
add_comment.click()
comment.click()
comment.send_keys("Awesome Art")
WebDriverWait(driver, 2)
submit_comment.click()
i += 1
if i > 4:
driver.close()
Link is https://society6.com/society?show=2 but might not work since its within my account. Here is the screenshot
The '+add comment is the part where i want to put comment
Html is here-
<form class="addComment expand" data-id="9647336">
<img src="https://ctl.s6img.com/society6/img/g2taHIrokQ01R_67jS8ulaWI2wk/h_150,w_150/users/avatar/~artwork/s6-original-art-uploads/society6/uploads/u/sul97/avatar_asset/d837ee10016843a3bba9ae3310cc338d" width="25" height="25">
<textarea placeholder="Add a comment..." data-button="9647336"></textarea>
<button id="b9647336">Comment</button>
</form>

Related

Validating Pin-Pad form using Selenium Python

I am trying to input code on a pin pad form available on a website and get it validated. However, I am getting a validation error. I fear the clicked pin buttons are not being read by the website's script. Can anyone help me with this? I am attaching the code as well as the page source code.
The UI of website looks like this
The div class on website which contains the keypad is as follows:-
<div class="pin_pad">
<span id='keypad1' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">1</span>
<span id='keypad2' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">2</span>
<span id='keypad3' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">3</span>
<span id='keypad4' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">4</span>
<span class="submit_btn" onmouseout="this.className='submit_btn'" onmouseover="this.className='submit_btnpin_hover'" onclick="return validate();">Submit</span>
</div>
My pin is "4444". I am trying to use the .click() method to get "4" clicked. Although I can see that "4" has been clicked 4 times, upon submit, the page shows a validation error. Can anyone help me in solving this problem? Here's my code in python:-
pinpad = driver.find_elements_by_class_name('pin_pad')
element = driver.find_element_by_xpath("//span[text()=4]").click()
for k in range(4):
actionChains = ActionChains(driver)
actionChains.context_click(element).perform()
time.sleep(1)
driver.find_element_by_xpath("//span[text()='Submit']").submit()
Instead of
context_click(element).perform()
do this :
move_to_element(key4).click().perform()
context_click is for right click and move_to_element() is for moving your mouse cursor to the specify element.
Brief explanation :
You can introduce WebDriverWait for more stability, and I don't think you need to do context_click() instead it is move_to_element() plus ActionChains object creation optimization and instead of submit you may wanna use click(). Check out the code below :
pinpad = driver.find_elements_by_class_name('pin_pad')
key4 = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span#keypad4"))).click()
actionChains = ActionChains(driver)
for k in range(4):
actionChains.move_to_element(key4).click().perform()
sleep(1)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Submit']"))).click()

NoSuchElementException when using Selenium Python [duplicate]

This question already has an answer here:
Selenium "selenium.common.exceptions.NoSuchElementException" when using Chrome
(1 answer)
Closed 2 years ago.
I'm trying to scrape the promotion information of each product from a website by clicking on the product and go to its detailed page. When the spider clicks on the product, the web will ask it to log in, and I tried the following code:
def __init__(self):
self.driver = webdriver.Chrome(executable_path = '/usr/bin/chromedriver')
...
def start_scraping(self, response):
self.driver.get(response.url)
self.driver.find_element_by_id('fm-login-id').send_keys('iamgooglepenn')
self.driver.find_element_by_id('fm-login-password').send_keys('HelloWorld1_')
self.driver.find_element_by_class_name('fm-button fm-submit password-login').click()
...
However, there is NoSuchElementException when I run it.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="fm-login-id"]"}
'spider_exceptions/NoSuchElementException': 14,
The HTML of the login page is as follows:
<div class='input-plain-wrap input-wrap-loginid'>
<input id='fm-login-id' class='fm-text' name='fm-login-id'...>
event
</div>
So, I'm pretty sure the id should be 'fm-login-id'. The reason I could think of that might cause this issue is that this login page is a popup.
Basically, it pops up in the middle of the main page. Looking at the HTML of the site, I can see that the login type seems to be a new HTML window
<!DOCTYPE html>
<html>event
....
<\html>
I'm not sure if this is the issue, and if so, how to fix it? Also, is there other reasons that might've caused the issue?
The popup will have an ID. You might have to add f'#{popup_id}' to the end of response.url. Like this URL: https://stackoverflow.com/questions/62906380/nosuchelementexception-when-using-selenium-python/62906409#62906409. It contains #62906409 because 62906409 is the ID of an element in the page.
The login page inside a frame, you need switch it first:
#switch it first
self.driver.switch_to.frame(driver.find_element_by_id('J_loginIframe'))
self.driver.find_element_by_id('fm-login-id').send_keys('iamgooglepenn')
self.driver.find_element_by_id('fm-login-password').send_keys('HelloWorld1_')
And for login button you can't use .find_element_by_class_name, this method just for single class name. This element having multiple class name, so use .find_element_by_css_selector like bellow:
#submit button
self.driver.find_element_by_css_selector('.fm-button.fm-submit.password-login').click()
The login content seems to be nested in an iFrame element (if you trace it all the way to the top, you should find an iFrame with id="sufei-dialog-content"), which means you need to switch to that iFrame for that nested html before selecting your desired element, otherwise it will not work.
First you will need to use driver.switch_to.frame("sufei-dialog-content"), and then select your element with driver.find_element_by_name() or whatever you had.
A similar issue can be found here: Selenium and iframe in html
Just a simple mistake:
<div class='input-plain-wrap input-wrap-loginid'>
<input id='fm-login-id class='fm-text' name='fm-login-id'...>
event
</div>
is actually supposed to be:
<div class='input-plain-wrap input-wrap-loginid'>
<input id='fm-login-id' class='fm-text' name='fm-login-id'...>
event
</div>
You forgot a single-quote.
Have you tried driver.find_element_by_name('fm-login-id')?
You should try finding the elements by their XPaths. You just have to inspect the element, right-click on it and copy its XPath. The XPath of the first <input ... is //*[#id="fm-login-id"].

Python Selenium, find a button

I have searched stackoverflow and tried everything, but nothing seems to work.
I am using Python3.8 with Selenium 3.141.0.
This is the button:
<button id="task-open-filters-button" class="btn btn-icon icon-filter list-filter-button sn-tooltip-basic" data-original-title="Edit Filter">
<span class="sr-only">Show / hide filter</span>
</button>
What I tried so far:
# Because the page is so slow, I work with try/except to get the element.
# This works fine for a simple link, but not for this button
while True:
try:
# elem = browser.find_element_by_xpath('//button[#id="task-open-filters-button"]')
# elem = browser.find_element_by_xpath('//button[#class="btn btn-icon icon-filter list-filter-button sn-tooltip-basic"]')
# elem = browser.find_element_by_link_text("Show / hide filter")
# elem = browser.find_element_by_xpath("//*[#id='task-open-filters-button']")[0]
# elem = browser.find_element_by_css_selector('.btn.btn-icon.icon-filter.list-filter-button.sn-tooltip-basic')
elem = browser.find_element_by_id("task-open-filters-button")
break
except NoSuchElementException:
print("Waiting for page to load!")
sleep(1)
elem.click()
I do not get another error message, the while loop just does not break.
Do you guys have any idea what else to try?
Thank you for your help!
When I look at your code, I see several potential issues.
There is a missing quote:
browser = webdriver.Chrome(chromedriver.exe")
Also - are you sure chromedriver.exe is the correct path? Maybe better provide the absolute path.
The button is commented out (although # is no html comment).
# <button id="task-open-filters-button"
# class="btn btn-icon icon-filter list-filter-button sn-tooltip-basic"
# data-original-title="Edit Filter">
# <span class="sr-only">Show / hide filter</span></button>
This definitely is correct syntax:
elem = browser.find_element_by_id("task-open-filters-button")
So I suggest make sure your setup is correct. Do something simple. Load an URL and return the text from the page.
P.S.: Have a look at this tutorial
http://jonathansoma.com/lede/foundations-2018/classes/selenium/selenium-windows-install/
It looks like the configuration is more like this
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.nytimes.com")

Unable to enter value to input box with 'OnKeyPress' attribute - Selenium Python

I want my code to enter value in the box below and move to the next page. I'm using selenium in Python to do this.
This is the HTML for the element.
<input name="ctl00$SPWebPartManager1$g_d6877ff2_42a8_4804_8802_6d49230dae8a$ctl00$txtPageNumber" type="text" value="260" maxlength="5"
onchange="return ValidateNumber(this);setTimeout('__doPostBack(\'ctl00$SPWebPartManager1$g_d6877ff2_42a8_4804_8802_6d49230dae8a$ctl00$txtPageNumber\',\'\')', 0)"
onkeypress="if (WebForm_TextBoxKeyHandler(event) == false)
return false;javascript:return isNumber(event);" id="ctl00_SPWebPartManager1_g_d6877ff2_42a8_4804_8802_6d49230dae8a_ctl00_txtPageNumber"
onpaste="return false;" style="width:60px;">
This is my code. How should get this to perform 'onkeypress' function?:
for i in range (2,10307): #looping over the page numbers
wait.until(EC.presence_of_element_located((By.ID, "ctl00_SPWebPartManager1_g_d6877ff2_42a8_4804_8802_6d49230dae8a_ctl00_txtPageNumber"))).send_keys(i)
after waiting for the element, since you need only the function onkeypress, try execute script.
driver.execute_script("if (WebForm_TextBoxKeyHandler(event) == false) return false;javascript:return isNumber(event);")

Python Selenium IE - Clicking on an anchor does not change the URL

As Short As Possible
I am trying to do test automation using Python with py.test and Selenium.
I have tried two approaches to change the URL by clicking an anchor <a> element, neither of the approaches seems to work - the URL does not change.
There are no errors reported, other than the incorrect assertion result.
The element I want to click on is:
<li class="ng-scope" ng-repeat="crumb in bcCtrl.data">
<!-- ngIf: !$last -->
<a class="ng-binding ng-scope" ng-if="!$last" ng-href="#/accounts/8" href="#/accounts/8">RC München</a>
<!-- end ngIf: !$last -->
<!-- ngIf: $last -->
</li>
<!-- end ngRepeat: crumb in bcCtrl.data -->
What I have checked so far
I can find the anchor,
The anchor found is the correct one (has the correct text, and href)
(using JScript) That doing .click() on the anchor indeed causes the page to load the new URL just like the user action would
First approach
The first approach was to use:
pre_last_breadcrumb_element = self.find_elements_by_locator(locators['breadcrumb_elements'])[-1]
pre_last_breadcrumb_element.click()
but this seems not to have done anything.
Second approach
The second approach was to use:
actions = ActionChains(self.driver)
el = self.find_elements_by_locator(locators['breadcrumb_elements'])[-1]
actions.move_to_element(el).click(el).perform()
But still no desired result.
What am I doing wrong? Please help...
More details
The code that I've used is:
pre_last_breadcrumb_element = self.find_elements_by_locator(locators['breadcrumb_elements'])[-1]
# this will click the pre-last element in the breadcrumb
print("PreLast = {0}".format(pre_last_breadcrumb_element.text))
print("BEFORE CLICK get_current_url='{0}'".format(self.driver.get_current_url))
# APPROACH 1
actions = ActionChains(self.driver)
el = self.find_elements_by_locator(locators['breadcrumb_elements'])[-1]
actions.move_to_element(el).click(el).perform()
# FIXME: The click on the anchor does not work...
# APPROACH 2
# pre_last_breadcrumb_element.click()
# FIXME: The click on the anchor does not work...
print("AFTER CLICK get_current_url='{0}'".format(self.driver.get_current_url))
# checking if the pre-last element changed due to the click
print("PreLast = {0}".format(pre_last_breadcrumb_element.text))
print("Changing between URLs\nFROM:'{0}'\n TO:'{1}'".format(self.get_url, pre_last_breadcrumb_element.get_attribute("href")))
# this will reload the page class at the newer URL
self.open_at_current_location()
print("Current URL:'{0}'".format(self.get_url))
assert last_breadcrumb_element.text is pre_last_breadcrumb_element.text
This is the result:
PreLast = RC München
BEFORE CLICK get_current_url='http://fct:8080/fct/#/accounts/9'
AFTER CLICK get_current_url='http://fct:8080/fct/#/accounts/9'
PreLast = RC München
Changing between URLs
FROM:'http://fct:8080/fct/#/accounts/9'
TO:'http://fct:8080/fct/#/accounts/8'
get_current_url='http://fct:8080/fct/#/accounts/9'
Current URL:'http://fct:8080/fct/#/accounts/9'
If you've tried all but nothing get success, you can try using WebDriver#execute_script() as an alternate solution where you can execute some piece of JavaScript code on the desired element to perform click as below :-
element = self.driver.find_element_by_link_text("RC München")
#now click on this element using JavaScript
self.driver.execute_script("arguments[0].click()", element)
Warning :- The JavaScript injection HTMLElement.click() shouldn't be used in a testing context. It defeats the purpose of the test. First because it doesn't generate all the events like a real click (focus, blur, mousedown, mouseup...) and second because it doesn't guarantee that a real user can interact with the element.
But some time due to designing or other issues this is to be only solution, so you can consider it as an alternate solution.

Categories