Selenium: element not interactable - python

I have developed an application using Angular, Node.js/Express.js and MySQL. The application has a login page that is displayed when any user visits the link. After logging in, the user is taken to the home page with a lot of other pages that are displayed in the navbar. I am trying to perform an automation test on the application and I am getting this error when I try to make my automated test click on one of the links in the navbar.
TypeError: 'WebElement' object is not subscriptable
After trying different things the error still does not get resolved. I ended up getting an error of Message: element not interactable
I have found the element using the console in Chrome and it is also clickable when I perform the click action in the console $x("//a")[1].click() or $$("[class = 'navbar-nav ml-auto'] li a")[1].click() but when I run the script in selenium then it throws the error. Can anybody tell me how can I make the navbar item clickable in selenium?
Here's my code:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('http://name-of-the-local-server:3000')
browser.implicitly_wait(3);
email_element = browser.find_element_by_css_selector("input[name = 'usermail']")
password_element = browser.find_element_by_css_selector("input[name = 'passcode']")
submit_btn_element = browser.find_element_by_css_selector("button[name = 'loginButton']")
email_element.send_keys("someone#example.com")
password_element.send_keys("pass123")
submit_btn_element.click()
#executes perfectly until here
navbar_element = browser.find_elements_by_css_selector("[class = 'navbar-nav ml-auto'] li a")
navbar_element[1].click()
EDIT: I have added a bit of HTML that I want to click as by default it loads the home page
<a _ngcontent-imt-c24="" routerlinkactive="active" routerlink="/admin"
class="nav-link" href="/admin"><i _ngcontent-imt-c24="" class="bi bi-people"
style="font-size: 1.3rem;"></i> Admin</a>
<i _ngcontent-sun-c24="" class="bi bi-people" style="font-size: 1.3rem;"></i>
Any help would be appreciated. Thanks!

Instead of this :
navbar_element = browser.find_element_by_xpath("//a")
use this
navbar_element = browser.find_elements_by_xpath("//a")
find_element will return a single web element where as find_elements will return list of web elements
You are using navbar_element[0].click() if stored in list, it will click on first web element.
or iterate over a list like this :
for link in navbar_element:
ActionChains(driver).move_to_element(link).click().perform()

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

Unable to click on drop-down element (uib-dropdown-toggle) using selenium python

I'm trying to click on Templates from Mail drop-down in below code, I tried all the methods (by_text , by_link, x_path etc..) but the console ends up saying the element/link was not found.
The mail drop-down doesn't have an id or anything related to known methods.
Here's the code i've written
from selenium import webdriver
from selenium.webdriver.support.ui import Select
driver = webdriver.Chrome(r"C:\Users\vishal
testing\Downloads\chromedriver_win32\chromedriver.exe")
driver.get("http://10.20.242.31")
driver.find_element_by_id("login-
username").send_keys("*******************************")
login = driver.find_element_by_id("login-password")
login.send_keys("**********")
driver.find_element_by_class_name("btn.btn-default.btn-lg").click()
#select = Select(driver.find_element_by_name('MAIL'))
#select.select_by_visible_text('Template')
link = driver.find_element_by_xpath('a//[#href="/mail-template"]')
link.click()
the code im trying to acess
<a href style=color .... ; uib-dropdown-toggle class ="dropdown-
toggle " aria-haspopup='true' aria-expanded='true'>
<img src = ....><br>"Mail"</a>
<u1 class="dropdown-menu" uib-dropdown-menu="menu" aria-
labelledby ="...">
<li role = "menuitems">
Templates
</li>
</u1>
the console says it was not able to find element named Template or link named /mail-template everytime.
You can click on the menu items by using the below locator.
driver.find_element_by_css_selector(".dropdown-menu [role='menuitems'] a").click()
However, make sure you click on the dropdown first to display the menu items, as sometimes the menu items might loaded dynamically.

Selenium not identifying any element in particular HTML, why?

I have a list of URLs that I need to iterate over. The process I am working on is that selenium opens each of the URLs in the list, clicks a button to open the form, and pass some strings into the form.
I have gotten to the point of clicking the button to open the form. I can not pass in any strings into the form however using any of the elements. I get error 'Unable to locate element'
This is my code so far, easily_apply is list of the URLs:
for i in easily_apply:
driver.get(i)
test = driver.find_element_by_class_name('button')
test.click()
test.find_element_by_name("applicant.name")
test.send_keys("John Smith")
This is the HTML in question:
<input type="text" aria-describedby="label-input-applicant.name-error" aria-labelledby="label-input-applicant.name" id="input-applicant.name" name="applicant.name" class="icl-TextInput-control icl-TextInput-control--sm">
Thank you in advance.
edit:
Code with xpath, not working, getting error 'Unable to locate elements':
for i in easily_apply:
driver.get(i)
test = driver.find_element_by_class_name('indeed-apply-button')
test.click()
test.find_element_by_xpath('//input[#type="text"]')
test.send_keys("John Smith")
edit2:
code with wait in it, still getting same error 'Unable to locate elements':
for i in easily_apply:
driver.get(i)
test = driver.find_element_by_class_name('indeed-apply-button')
test.click()
wait = ui.WebDriverWait(driver,60)
test.find_element_by_name('applicant.name')
test.send_keys("John Smith")
I looked at the html, assuming you are using the code from your previous post, obtaining all the easily apply list.
The element you are looking for is inside nested iframe. you need to switch to that iframe and then look for the element
Replace the time.sleep with Webdriverwait
driver.find_element_by_css_selector('a[class="indeed-apply-button"]').click()
driver.switch_to.frame(driver.find_element_by_css_selector('iframe[name*=indeed-ia]'))
import time
time.sleep(5)
driver.switch_to.frame(driver.find_element_by_tag_name('iframe'))
driver.find_element_by_id('input-applicant.name').send_keys('Applicant Name')
Try using xpath.
In Selenium automation, if the elements are not found by the general locators like id, class, name, etc. then XPath is used to find an element on the web page .
Syntax is:
Xpath=//tagname[#attribute='value']
Hope this helps.
driver.find_element_by_css_selector("#jl_1c27f21fec51d296 > a").click()
time.sleep(10)
driver.find_element_by_css_selector('a[class="indeed-apply-button"]').click()

How to find and click on HTML image element

I'm new with Selenium and struggle with this one for few hours.
I have an HTML page that contains icon and stream view (both images), the browser view is on 100% and I would like to modify it and make it smaller,
it can be done by changing browser zoom, modifying CSS property or clicking on the image.
My code starts with open browser and waits till all elements load:
driver = webdriver.Firefox()
driver.get('http://' + user +':'+password+'#'+camera_address)
driver.maximize_window()
driver.implicitly_wait(15) # seconds
I tried to do so via zoom:
driver.execute_script("document.body.style.zoom='0.4'")
Didn't worked.
Tried to do it via Selenium -- find element and change CSS:
myDynamicElement = driver.find_elements_by_id("stream")
or find the image and click it with:
driver.find_element_by_xpath('//img[#src="../pics/button_downsize_27x27px.gif"]').click()
or
driver.find_elements_by_xpath('//*[#img]').click()
or
driver.find_elements_by_tag_name('img').click()
The HTML page looks like this:
<img src="/pics/button_downsize_27x27px.gif" width="27" height="27" border="0" title="Scale down to 800 px width" alt="Scale down to 800 px width">
<td colspan="3" align="center"><img id="stream" src="/mjpg/video.mjpg" width="2560" height="1920" border="0" alt="If no image is displayed, there might be too many viewers, or the browser configuration may have to be changed. See help for detailed instructions on how to do this."><br></td>
Tried with #title and #alt and even contain but nothing works.
What am I doing wrong?!?! How to find and click on this image (/pics/button_downsize_27x27px.gif)?
To click on your desired image -- please use the reference code mentioned here.
new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfAllElementsLocatedBy((By.cssSelector("a"))));
List<WebElement> elem = driver.findElements(By.tagName("a"));
for(WebElement el : elem){
String element = el.getAttribute("src");
if(element.contains("/pics/button_downsize_27x27px.gif")){
el.click();
break;
}
}
It is in Java, you can implement it in Python.
Thank you all, finally, I did a little workaround since I saw that in chrome there is a little bug and via Firefox, I cannot find the element.
So I retrieve again the URL after all elements loaded and modify it so the JavaScript function will be triggered:
myElem = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, 'indexMain')))
driver.get(driver.current_url+'&size=8')
Thank you all for trying, this one was a challenge since the element have no id/name/class/css and the browser could not find the XPath.

Categories