Validating Pin-Pad form using Selenium Python - 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()

Related

Python Selenium: Click Instagram next post button

I'm creating an Instagram bot but cannot figure out how to navigate to the next post.
Here is what I tried
#Attempt 1
next_button = driver.find_element_by_class_name('wpO6b ')
next_button.click()
#Attempt 2
_next = driver.find_element_by_class_name('coreSpriteRightPaginationArrow').click()
Neither of two worked and I get a NoSuchElementException or ElementClickInterceptedException . What corrections do I need to make here?
This is the button I'm trying to click(to get to the next post)
I have checked your class name coreSpriteRightPaginationArrow and i couldn't find any element with that exact class name. But I saw the class name partially. So it might help if you try with XPath contains as shown below.
//div[contains(#class,'coreSpriteRight')]
another xpath using class wpO6b. there are 10 elements with same class name so filtered using #aria-label='Next'
//button[#class='wpO6b ']//*[#aria-label='Next']
Try these and let me know if it works.
I have tried below code and it's clicking next button for 10 times
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == '__main__':
driver = webdriver.Chrome('/Users/yosuvaarulanthu/node_modules/chromedriver/lib/chromedriver/chromedriver') # Optional argument, if not specified will search path.
driver.maximize_window()
driver.implicitly_wait(15)
driver.get("https://www.instagram.com/instagram/");
time.sleep(2)
driver.find_element(By.XPATH,"//button[text()='Accept All']").click();
time.sleep(2)
#driver.find_element(By.XPATH,"//button[text()='Log in']").click();
driver.find_element(By.NAME,"username").send_keys('username')
driver.find_element(By.NAME,"password").send_keys('password')
driver.find_element(By.XPATH,"//div[text()='Log In']").click();
driver.find_element(By.XPATH,"//button[text()='Not now']").click();
driver.find_element(By.XPATH,"//button[text()='Not Now']").click();
#it open Instagram page and clicks 1st post and then it will click next post button for the specified range
driver.get("https://www.instagram.com/instagram/");
driver.find_element(By.XPATH,"//div[#class='v1Nh3 kIKUG _bz0w']").click();
for page in range(1,10):
driver.find_element(By.XPATH,"//button[#class='wpO6b ']//*[#aria-label='Next']" ).click();
time.sleep(2)
driver.quit()
As you can see, the next post right arrow button element locator is changing between the first post to other posts next page button.
In case of the first post you should use this locator:
//div[contains(#class,'coreSpriteRight')]
While for all the other posts you should use this locator
//a[contains(#class,'coreSpriteRight')]
The second element //a[contains(#class,'coreSpriteRight')] will also present on the first post page as well, however this element is not clickable there, it is enabled and can be clicked on non-first pages only.
As you can see on the picture below, the wp06b button is inside a lot of divs, in that case you might need to give Selenium that same path of divs to be able to access the button or give it a XPath.
It's not the most optimized but should work fine.
driver.find_element(By.XPATH("(.//*[normalize-space(text()) and normalize-space(.)='© 2022 Instagram from Meta'])[1]/following::*[name()='svg'][2]")).click()
Note that the XPath leads to a svg, so basically we are clicking on the svg element itself, not in the button.

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"].

Unable to send text to Email field on Microsoft login page using Selenium

I'm trying to figure out a way to automatically log in / enter text into a given text field on a particular web page. I've already don't this before, but this particular page isn't responding to anything I've thrown at it yet.
The default page load already has the auto-focus on the necessary text box. I'm currently using Python to write the Selenium code. My current script includes prior processes that lead to the page in question, where my current problem lies. Additionally, I've been running this code in a Google-Chrome browser, but with the user-agent selected to Edge - Mobile (but that probably won't matter here).
The website in question is the Microsoft login at this link.
The CSS/HTML of the text box in question:
<input type="email" name="loginfmt" id="i0116" maxlength="113" lang="en" class="form-control ltr_override" aria-describedby="usernameError loginHeader loginDescription" aria-required="true" data-bind="textInput: usernameTextbox.value,
hasFocusEx: usernameTextbox.focused,
placeholder: $placeholderText,
ariaLabel: tenantBranding.UserIdLabel || str['CT_PWD_STR_Username_AriaLabel'],
css: { 'has-error': usernameTextbox.error },
attr: inputAttributes" placeholder="Email, phone, or Skype" aria-label="Enter your email, phone, or Skype.">
The code I'm currently testing (which is basically three varied iterations of the same idea), after the given page loads:
element = driver.find_element_by_id("i0116")
element.click()
element.clear()
element.send_keys("wbhyatt3#gmail.com")
element.send_keys(Keys.RETURN)
time.sleep(1)
element = driver.find_element_by_name("loginfmt")
element.click()
element.clear()
element.send_keys("wbhyatt3#gmail.com")
element.send_keys(Keys.RETURN)
time.sleep(1)
element = driver.find_element_by_css_selector("input.email")
element.click()
element.clear()
element.send_keys("wbhyatt3#gmail.com")
element.send_keys(Keys.RETURN)
Unfortunately, trying to select the textbox via the input id, class, or name don't seem to be working. It should be worth noting that the page CSS I'm referencing for the text box includes an element "input" prior - I'm not sure if this will affect my current code. I'm fairly certain that either the send_keys aren't working, or perhaps the selection of the element, itself.
What makes the situation even more frustrating is that the page's default focus is on the textbox - so I don't even truly need to select the element, I just need to be able to enter text and submit/enter.
I've also tried targeting it as an iframe, but that hasn't seemed to help either.
Any ideas? Any and all help would be deeply appreciated. I am simply trying to find a way to enter text into the login box.
To enter an EmailID into the field with placeholder text as Email, phone, or Skype you can use the following code block :
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get('https://login.live.com/login.srf')
print("Page Title is : %s" %driver.title)
element = driver.find_element_by_xpath("//input[#class='form-control ltr_override' and #name='loginfmt']")
element.click()
element.clear()
element.send_keys("wbhyatt3#gmail.com")
Console Output :
Page Title is : Sign in to your Microsoft account
Snapshot :

Selenium input text that has dropdown & hidden values

I am writing a python script to input text, that then has a dropdown appear to select from a list of items. These items are all hidden values and are not inputted to the webpage until selected by clicking on said item.
Specifically I am attempting to input data on Fitbits website to track food (a thing for work, but it is tedious to input food consumption each day). I would like to automate this :)
My script currently looks like this...
#! python3
# fitbitSubmitFood.py this script submits the food log on fitbit.com
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.Chrome()
# open webpage to log food
browser.get('https://www.fitbit.com/foods/log')
# login to the website
# email username input
emailSelect = browser.find_element_by_xpath('//*[#id="loginForm"]/fieldset/dl/dd[1]/input')
emailSelect.send_keys('EMAIL')
# email password input
inputPassword = browser.find_element_by_xpath('//*[#id="loginForm"]/fieldset/dl/dd[2]/input')
inputPassword.send_keys('PASSWORD')
# click log in
clickLogin = browser.find_element_by_xpath('//*[#id="loginForm"]/div[1]/button')
clickLogin.click() # clicky click!
# input What did you eat?
foodSelect = browser.find_element_by_xpath('//*[#id="foodselectinput"]')
foodSelect.send_keys('Pizza, Bread') # select by visible text
# input How Much?
howMuch = browser.find_element_by_xpath('//*[#id="quantityselectinput"]')
howMuch.send_keys('3')
# click Log Food
logfood = browser.find_element_by_xpath('//*[#id="foodAutoCompButton"]')
# logfood.click() # clicky click!
# Close web browser
The current script above throws the following error.
selenium.common.exceptions.InvalidElementStateException: Message: invalid element state
So I have also tried suggestions from this stackoverflow question.
Entering a value into a type="hidden" field using Selenium + Python
WebDriverWait(foodSelect, 10).until(EC.visibility_of_element_located((By.XPATH,'//*[#id="foodId"]'))) # wait for hidden text to populate
This threw the following error...
selenium.common.exceptions.TimeoutException: Message:
Here is a snippet from the website
input type="text" name="foodselectinput" id="foodselectinput" class="text columnFull yui-ac-input" maxlength="80" tabindex="1" autocomplete="off"
I can see the following on the website for the hidden value. This value is not passed to the webpage until after the food is selected from the drop down menu.
input name="foodId" id="foodId" type="hidden" value="13272"
Note: I have already tried using the click method for the Pizza, Bread
clickFood = browser.find_element_by_xpath('//*[#id="foodselectcontainer"]/div/div[2]/ul/li[1]/div/div[1]')
clickFood.click() # click it!
This did not work.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id="foodselectcontainer"]/div/div[2]/ul/li[1]/div/div[1]"}
The script cannot continue until the food item is selected on the webpage. Hence, the question.
How would one pass the hidden value or select from a dropdown?
From your snippet
input type="text" name="foodselectinput" id="foodselectinput" class="text columnFull yui-ac-input" maxlength="80" tabindex="1" autocomplete="off"
yui-ac-input refers AutoComplete from YUI 2 Library (That's what I thought)
As the site mentioned by you asked credentials. I created a sample code for YUI Example
Sorry I dont know python.Below is a Java code. The syntax looks more or less same. So get the idea from below code and implement it
public void start() {
driver.get("http://yui.github.io/yui2/docs/yui_2.9.0_full/examples/autocomplete/ac_basic_array.html");
yuiAutoSuggestSelect("Cali");
}
public void yuiAutoSuggestSelect(String value) {
WebElement inputElement = driver.findElement(By.className("yui-ac-input"));
inputElement.sendKeys(value);
By autoSuggSel = By.xpath("//div[#class='yui-ac-container']//div[#class='yui-ac-bd']//li");
WebElement autoSuggestEl = driver.findElement(autoSuggSel);
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOf(autoSuggestEl)).click();
}

Selenium Hover/Click event on ajax filled menu options

Having serious issues here. Someone please help.
I am trying to login to a website. - This Works!
Redirect to the page I want after Login - This Works!
Now once in, I have to hover over the settings icon so the dropdown shows, and then click on the "Settings" options that has NO ID or CLASS or HREF.
Now there is a couple of reasons I cant do this. Number 1 is if I try to click on the link after the hover, it tells me that it's hidden and I cant interact with it. Also the menu options in the form are populated and appended once you hover, through ajax I think. They are not on the initial page load.
wait = WebDriverWait(driver, 10)
box = wait.until(EC.visibility_of_element_located((By.ID, "yucs-help_button")))
menuButton = driver.find_element_by_id("yucs-help_button")
ActionChains(driver).move_to_element(menuButton).perform()
After the above code is deployed I print the driver.page_source and can see (below) that the new menu options are there, if you don't hover, the below code will not be on the page.
Now the <a> i'm trying to click is the <span>Settings</span> option, and for the life of me, it will not work. Either can't find it, not clickable, can't interact with it, etc, etc, etc. xpath, css_selector, partial_name, nothing finds this thing. Also whats weird is once you click on it, from a browser, it appends an ID to <span> So weird. Any ideas?
<a data-ylk="rspns:nav;t3:tl-lst;t5:custitm;slk:custitm;elm:itm;elmt:custitm;itc:0;cpos:2" class="C(#000)! Td(u):h " data-mad="options" data-customevt="true" href="#" data-rapid_p="18"><span>Settings</span></a>
To perform mouse over event on element you should try to use .execute_script() using following java script :-
wait = WebDriverWait(driver, 10)
box = wait.until(EC.visibility_of_element_located((By.ID, "yucs-help_button")))
menuButton = driver.find_element_by_id("yucs-help_button")
driver.execute_script("var clickEvent = document.createEvent('MouseEvents');clickEvent.initEvent('mouseover', true, true); arguments[0].dispatchEvent(clickEvent);", menuButton)
Now after successfully mouse over you should try to click on Settings link as below :-
driver.find_element_by_xpath("//span[contains(text(), 'Settings')]/parent::a[#data-mad = 'options']").click()
Hope it will help you..:)

Categories