To send threekeys using send_keys() in selenium python webdriver - python

I am trying to type a float number into a textbox with default value 0.00.But it tries to get appended instead of overwriting it.I tried with .clear() and then send_keys('123.00') but still it gets appended.
Then i tried with send_keys(Keys.CONTROL+'a','123.00').It updates 0.00 only.
Any help is really appreciated.
For more info ..
URL : http://new.ossmoketest.appspot.com
userid: senthil.arumugam#mycompanyname.com -- mycompanyname = orangescape (sorry to avoid spam mails)
password not needed now.
click purchaseorder... in the form please new product and new price... sample application for automation.. thanks

I've had good results with:
from selenium.webdriver.common.keys import Keys
element.send_keys(Keys.CONTROL, 'a')
element.send_keys('123.00')
If that doesn't work it may have something to do with the code in the web page.

Unless you have custom editbox, click() should work for you:
from selenium.webdriver import Firefox
b = Firefox()
b.get('http://google.com')
e = b.find_element_by_id('lst-ib')
e.click() # is optional, but makes sure the focus is on editbox.
e.send_keys('12.34')
e.get_attribute('value')
# outputs: u'12.34'
e.click()
e.clear()
e.get_attribute('value')
# outputs: u''
e.send_keys('56.78')
e.get_attribute('value')
# outputs: u'56.78'

I just found the clear() command - see here:
If this element is a text entry element, this will clear the value. Has no effect on other elements. Text entry elements are INPUT and TEXTAREA elements.
EDIT:
So your approach would be:
element.clear();
element.sendKeys('123.00');

I've experienced issues with all the examples given in other answers.
el.send_keys(Keys.CONTROL + 'a' + Keys.NULL, 'your string')
Has worked in all the projects I've worked in, so much I've wrapped it into my own implementation of the Webdriver class with more robust operations.

Related

Issue extracting specific data with Selenium

I am back with essentially a somewhat similar problem. I have now learnt that you cannot find elements that are in an iframe if you haven't switched to it, which helped a lot, but I seem to still have issues locating elements even though they are not in an iframe.
I also ask for any advice regarding my script in general, or how one would go about improving it. Yes, I will change the implicitwait to WebDriverWait, but besides that. Is it okay if a script is structured in this way, with task -> task -> task and so forth, or is it simply bad practice?
I don't really see how I would go about throwing in some objective-oriented programming, or what I would gain from it besides if I wanted to customise the script in a major way, besides of course the learning aspect.
In any case, here is the code:
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import accandpass as login
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import datetime
x = datetime.datetime.now()
x = x.strftime("%d")
driver = browser=webdriver.Firefox()
driver.get("https://connect.garmin.com/modern/activities")
driver.implicitly_wait(2)
iframe = driver.find_element(By.ID, "gauth-widget-frame-gauth-widget")
driver.switch_to.frame(iframe)
element = driver.find_element("name", "username")
element.send_keys(login.username)
element = driver.find_element("name", "password")
element.send_keys(login.password)
element.send_keys(Keys.RETURN)
driver.switch_to.default_content()
driver.implicitly_wait(10)
element = driver.find_element("name", "search")
element.send_keys("Reading")
element.send_keys(Keys.RETURN)
element = driver.find_element(By.CLASS_NAME, "unit")
print(element)
So everything actually works fine so far, to my great surprise. The element gives off this: <selenium.webdriver.remote.webelement.WebElement (session="0ef84b2e-e0af-4b0c-b04c-94d5371356c5", element="a70f4ee1-e840-457c-a255-4b2df603efec")> which wasn't really what I was looking for.
I am more looking for some check, to see that the element with name unit has the same date as x, which is today. So basically:
Minutes read
minutes = 0
for i in element:
if element == x:
minutes += (element with time)
For loop to run through all the elements and check them all for the same date, and if the date matches then add the minutes read that day to the integer minutes for a sum of total minutes read today, for example.
Then do the same for the activities I will do, running, hiking and meditating.
Questions:
How do I get the integer from the element, so I can check it with x?
Is the for loop -> if statement -> add time from element a good solution to the case at hand?
Is it bad practice to structure a script this way, and how would you improve it?
Thanks in advance
Part of your question sounds like you want a code review. If you do, you'll want to post your code over on https://codereview.stackexchange.com but review their question requirements carefully before posting.
I think the main issue you are asking about is wanting to compare the date on the page to the current system date and you're getting some session and element GUIDs instead. You are printing the element object and not the contained text. You want
print(element.text)
or add an assert to compare it to the current system date in a specific format, something like...
assert element.text == datetime.today().strftime('%m %d')
Some quick additional feedback since you asked for some...
It sounds like you've already been informed that .implicitly_wait() is a bad practice and should be replaced with WebDriverWait for each instance where you need to wait.
If you aren't going to reuse a variable, don't declare one. In most cases you don't need to use one.
element = driver.find_element("name", "username")
element.send_keys(login.username)
can be written
driver.find_element("name", "username").send_keys(login.username)
If you are going to use variables, don't reuse the same name over and over, e.g. element. Give each variable a meaningful name so that the next person (or maybe yourself in a few weeks/months) will be able to more easily read and understand your code.
element = driver.find_element("name", "search")
element.send_keys("Reading")
element.send_keys(Keys.RETURN)
should instead be
search = driver.find_element("name", "search")
search.send_keys("Reading")
search.send_keys(Keys.RETURN)
If you are going to continue writing scripts, do some reading on the page object model. Done right, it will clean up your code significantly, make maintenance much faster and easier, and make writing new scripts much faster. Basically you create a class for each page of the site and then add methods to the class for actions you need to take on the page.
I don't have a garmin account so I can't log in but from the screenshot you posted you might have some methods like .search_activities(string), .get_search_results(), .filter_activities(string), etc. Once you've created those methods, they can be called repeatedly from the same script or many scripts.

Python Selenium- Cant find correct element. Login Button

#Thanks in advance for help. New to python, tried for hour trying to correct mistake.#
Trying to locate login button element. Attached is the image of the website with the element of the login button. please see here
Below is code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
url = "https://www.xxxxxx.com/index.php/admin/index"
username = 'xxxx'
password = 'xxxxx'
driver = webdriver.Firefox(executable_path="C:\\Users\\kk\\AppData\\Local\\Programs\\Python\\Python38-32\\geckodriver.exe")
driver.get(url)
driver.find_element_by_name(name='aname').send_keys(username)
driver.find_element_by_name(name='apass').send_keys(password)
driver.find_elements_by_xpath('//style[#type="submit"]')
Rather than finding it with a CSS selector. Why not use find_element_by_xpath()
To get the XPath of that element just right-click the HTML of the input in Inspect Element, hover over Copy and you'll see "Full XPath"
Issue is your xpath.
driver.find_elements_by_xpath('//style[#type="submit"]')
Use below:
driver.find_elements_by_xpath('//input[#type="submit"]')
or
driver.find_elements_by_xpath('//input[#value="login"]')
#This is more accurate as many input tags could have type as submit
Also, please use some sort of wait as i am not sure if page will be loading fast enough every time you launch URL.
You can identify the submit button by using any of these 2:
//input[#type="submit"] or //input[#value="login"]
They should work without any problem if you don't have any similar elements on your page (which I doubt)
But if you want to be more precise, you can mix these 2 into:
//input[#value="login" and #type="submit"]

How to enter numeric value in input field using Python Selenium?

I've got a script writing values into a web page, and all values write except for one field that keeps throwing up the following error:
(Screenshot provided b/c in other similar questions many comments said this is impossible to happen on a web page.)
"Please enter a numeric value."
Here's my code:
workcenter_to_add = {}
workcenter_to_add['BatchCycle'] = str(2.78)
# driver = my_chrome_webpage
WebDriverWait(driver, wait_time).until(EC.presence_of_element_located((By.XPATH, "//input[#id='BatchSize']"))).send_keys(workcenter_to_add['BatchCycle'])
As everyone knows, if I do not input the 2.78 value in as a string WebDriver throws an error. But my page demands a numeric value. I'm stuck.
I've Googled around and not found a usable answer to this. It seems if you're using Java there's a setAttribute method you can use, but if you're using Pythonyou've got to figure something out.
For example, the question here looked promising but I could not find the String or how to import it to get it to work. There's a couple of other much older questions that talk about executing java but I have had no luck getting them to work.
I've got the page-source HTML here:
https://drive.google.com/open?id=1xRNPfc5E65dbif_44BQ_z_4fMYVJNPcs
I am sure though you are passing the value .send_keys('2.78'), still the value will be numeric. So, ideally you should not get this issue.
Here is the sample html and script to confirm the same.
<html><head>
<script>
function validateOnClick(evt) {
var theEvent = evt || window.event;
// Handle paste
if (theEvent.type === 'click') {
key = document.querySelector('input').value.toString();
} else {
// Handle key press
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
}
var regex = /[0-9]|\./;
console.log(key);
if( !regex.test(key) ) {
alert("Please enter numeric value");
theEvent.returnValue = false;
if(theEvent.preventDefault) theEvent.preventDefault();
}
}
</script>
</head>
<body>
<input placeholder='check'></input>
<button type='submit' onClick='validateOnClick(event)'>Submit</button>
</body></html>
Script to check:
driver.get(url)
# check with string (not integer)
driver.find_element_by_tag_name('input').send_keys('Hello')
driver.find_element_by_tag_name('button').click()
print(driver.switch_to.alert.text)
driver.switch_to.alert.dismiss()
# now check with integer
driver.find_element_by_tag_name('input').clear()
driver.find_element_by_tag_name('input').send_keys(workcenter_to_add['BatchCycle'])
driver.find_element_by_tag_name('button').click()
Screenshot:
So, We have to check what's the js/method implemented to validate the value entered in the field. As you can see passing integer with in quotes from python script does not make any difference to the field and it's data type.
I'm sure this is going to be an unpopular answer, but this is how I got it work.
The field in this question and another field on another page in the same ERP system were throwing the same error. send_keys() would not work no matter what I tried.
That's when I put on my thinking cap and starting trying other ways.
I tried entering the information into another field on the page that would accept numbers via send_keys() and then cutting and pasting the values into the field that would not accept the value had I used send_keys(). It worked!
Here's a code snippet I used on the different page with the same issue:
elem1 = driver.find_element_by_id('txtNote')
elem1.send_keys(rm['txtGross_Weight'])
elem1.send_keys(Keys.CONTROL, 'a') #highlight all in box
elem1.send_keys(Keys.CONTROL, 'x') #cut
elem2 = driver.find_element_by_id('txtGross_Weight')
elem2.send_keys(Keys.CONTROL, 'v') #paste
I was looking for a high tech answer when a low tech work around sufficed.
Is it code or methodology I'd write on a job resume? Probably not. Did it work and can I live with it? Yes. Thank you for the people who tried to answer.
It looks a lot like a comma vs dot problem?
But I could be wrong.
It depends on the browser locale of the machine that your selenium is running on.
So a simple test could be to enter the text '2,78' or '2.78' into the field.
Python converts the number to a string, and that is not a localized number.
When it is sent as keys, it is sent as four characters '2' '.' '7' '8'.
It then ends in the Javascript scope of your browser, that depending on the OS and Language settings will be either using comma or dot as a decimal separator.
The dialog box with the notification
possibly is the outcome of Constraint API's element.setCustomValidity() method.
I had been through the page-source HTML which you have shared. But as per your code trials:
By.XPATH, "//input[#id='BatchSize']"
I didn't find any <input> tag within the pagesource. The text based relevant HTML would have helped us to construct an answer in a better way. However, you need to consider a few things as follows:
As you are dealing with an <input> tag, instead of presence_of_element_located() you should be using element_to_be_clickable().
You haven't told us about the error WebDriver throws if you do not input the 2.78 value as a string. Still, as str(2.78) works so you can stick to it.
Effectively your line of code will be:
workcenter_to_add = {}
workcenter_to_add['BatchCycle'] = str(2.78)
WebDriverWait(driver, wait_time).until(EC.element_to_be_clickable((By.XPATH, "//input[#id='BatchSize']"))).send_keys(workcenter_to_add['BatchCycle'])
References
You can find a couple of relevant discussions on Constraint_validation in:
How to handle html5 constraint validation pop-up using Selenium?
How can I extract the text of HTML5 Constraint validation in https://www.phptravels.net/ website using Selenium and Java?

Issue with Selenium,Python

I have written the following.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
bot = webdriver.Firefox()
bot.find_element_by_name("username").send_keys(config['username'])
When I am using send_keys and happen to be typing at the same instant, then what I typed is also added in the username.
How to avoid this?
Example:
I want to fill the username with "sandeep"
If at the same instant I press 'a', then the username becomes "sandeepa" or something equivalent.
You can use executeScript method:
webdriver.execute_script("document.getElementById('username').setAttribute('value', 'Sandeep')")
JavaScript will do text insertion as single operation.
I see 2 options:
Create hidden input send keys to it than perform copy/paste from hidden to visible input, after remove hidden input.
Hide input, than send_keys to it and after show it back.
Usefull links:
Performing a copy and paste with Selenium 2
WebDriver: add new element

selenium python send_key error: list object has no attribute

Helo,
my xpath does validate in firePath but when I try to send _key I get an error.
userID = driver.find_elements_by_xpath(".//*[#id='UserName']")
userID.send_keys('username')
AttributeError: 'list' object has no attribute 'send_keys'
Can someone toss me a bone please?
You are getting a List of webElements with driver.find_elements_by_xpath(".//*[#id='UserName']") which of course not a single element and does not have send_keys() method. use find_element_by_xpath instead. Refer to this api doc.
userID = driver.find_element_by_xpath(".//*[#id='UserName']")
userID.send_keys('username')
instead of this:
userID = driver.find_elements_by_xpath(".//*[#id='UserName']")
userID.send_keys('username')
try:
userID = driver.find_element_by_xpath(".//*[#id='UserName']")
userID.send_keys('username')
I had the same issues and that worked for me.
driver.find_element_by_xpath(".//*[#id='UserName']").send_keys('username')
find_element without s.
I was facing the same problem while using to input for Instagram, tried the time module to sleep for 2 seconds then it started working for me. Problem was that before loading the website bot starts to find that path and report errors.
import time
time.sleep(2)
This error occurs when one tries to perform action on list instead of element. I was getting similar error when I was trying to click on button to submit credentials. I found the work around by emulating pressing enter key on keyboard. e.g. find any element on page using xpath/css, etc. and send enter key.
driver.find_element_by_id('test_id').send_keys(Keys.ENTER)
I had the same problem - so I just did:
userID[0].send_keys('username')
Worked for me
Please replace your code with the following code because you like addressing the first component of your list, not whole list.
userID = driver.find_elements_by_ID('username')[0]
userID.send_keys('username')
or delete "s" from find_elements_by_ID such as follow:
userID = driver.find_element_by_ID('username')
userID.send_keys('username')
from selenium import webdriver
from selenium.webdriver.common.by import By
userID = driver.find_elements( By.XPATH, "//div[#title='Username']")
userID[0].send_keys('username')
when we select multiple element we type elements (s), its return a list. that have no "send_keys" single element have no s. that have "send_keys"

Categories