python's selenium "send_keys" with chrome driver drops characters - python

I am using selenium package with Python (https://pypi.python.org/pypi/selenium) with Windows 7.
When I try to login to my facebook account I use the send_keys command, e.g.
elem = browser.find_element_by_name("email")
elem.send_keys(email);
elem = browser.find_element_by_name("pass")
elem.send_keys(password);
Login fails apparently because the second send_keys drops the first character of the password (I found this by directly sending the password characters to the email field.
What's going on? Why can't selenium do something so simple as sending keys to an input field?
Is this some kind of a protection measure coded by Facebook to reject automatic scripting?
Tried to send the whole alphabet and got this:
abcdefghijklmnopqrstuvwxyzBCDFGIKLNOQSTWX
Notice how many characters are missing...
Update
Apparently the problem has nothing to do with facebook but to the chrome driver.
If I send the following simple code
browser = webdriver.Chrome()
browser.get("https://www.google.com") # Load page
elem = browser.find_element_by_name("q") # Find the query box
query= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
elem.send_keys(query)
With chrome driver I get
BCDFGIKLNOQSTWX
Notice how A, E, H ... Y, Z are missing
With firefox driver (replacing browser = webdriver.Chrome() with browser = webdriver.Firefox() I get:
ABCDEFGHIJKLMNOPQRSTUVWXYZ

I ran into a similar problem as OP and was satisfied with none of the answers written here nor anywhere else on this site that I could find.
Since I read during my research that the issue was at some point in time fixed, I have to assume that it re-appeared nowadays.
As P.T. mentioned, if you run into similar problems, chances are the chromedrivers/firefoxdrivers are buggy again.
Since none of the solutions I found helped alleviate the issue, I instead opted for just circumventing selenium and its drivers altogether. So I used javascript to first find the element (through its absolute Xpath), then write to it / set it.
from selenium import webdriver
def write_to_element(driver, element_xpath, input_string),
js_command = f'document.evaluate(\'{xpath}\', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.value = \'{input_string}\';'
driver.execute_script(js_command)
driver = webdriver.Chrome()
driver.get('WebPage/With/Element/You/Want/To/Write/To')
xpath = 'Xpath/Of/Element/You/Want/To/Write/To'
write_to_element(driver, xpath, 'SomeRandomInput')
document.evaluate(\'{xpath}\', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null) evaluates the xpath to an element, so essentially finds your element on the webpage.
.singleNodeValue.value = \'{input_string}\';' sets the value of that element to input_string

Looks like there are (were) some bugs in the Chrome webdriver: https://code.google.com/p/chromedriver/issues/detail?id=435
The core of the problem looks to be when either the keyboard is configured for a non-English language, or if the webdriver process and the chrome display are running in different language/environments (e.g., when going through a remote display from one host to another, etc.)

I've solved using a custom method for send_keys, which works a little bit lower but fast enough.
from selenium.webdriver.remote.webelement import WebElement
def send_keys(el: WebElement, keys: str):
for i in range(len(keys)):
el.send_keys(keys[i])
send_keys(el, keys)

Use selenium Ide and export test case in python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
class Test1(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.facebook.com/"
self.verificationErrors = []
self.accept_next_alert = True
def test_1(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("email").clear()
driver.find_element_by_id("email").send_keys("username")
driver.find_element_by_id("pass").clear()
driver.find_element_by_id("pass").send_keys("password")
driver.find_element_by_id("u_0_b").click()
driver.find_element_by_xpath("//div[#id='u_ps_0_1_5']/div/div").click()
driver.find_element_by_link_text("1 Requests").click()
driver.find_element_by_id("globalContainer").click()
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException, e: return False
return True
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException, e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()

Related

Selenium IDE to Python WebDriver - Trying to return a message

I've never really done any serious coding before so please bear with me if I say something incorrect, and just correct me so I know better.
I've create a very simple Selenium IDE test case where it searches a term through google and then waits for a certain link to come up:
Base Url: https://www.google.com/
open | /
sendKeys | id=lst-ib | This is Sparta${KEY_ENTER}
waitForElementPresent | xpath=(//a[contains(text(),'300 (film) - Wikipedia')])[2]
clickAndWait | xpath=(//a[contains(text(),'300 (film) - Wikipedia')])[2]
And when I export that as a Python2/unittest/WebDriver it gives me this .py file:
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
class ThisIsSpartaTestCase(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.google.com/"
self.verificationErrors = []
self.accept_next_alert = True
def test_this_is_sparta_test_case(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("lst-ib").send_keys("This is Sparta", Keys.ENTER)
for i in range(60):
try:
if self.is_element_present(By.XPATH, "(//a[contains(text(),'300 (film) - Wikipedia')])[2]"): break
except: pass
time.sleep(1)
else: self.fail("time out")
driver.find_element_by_xpath("(//a[contains(text(),'300 (film) - Wikipedia')])[2]").click()
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
Which works, and it's all great and dandy.
My issue is that I would like to output a message onto the Python IDLE Shell that says something like "The link element is present" when the python code is able to find the wiki link on the Google page. I tried to do a "print "Wiki Link is Found on Google Page" after the return True in def is_element_present, and even though it runs, it doesn't output that message onto the Shell.
Do any of y'all know how to make it output a message onto the Shell?
Please let me know, thank you!

Wait for element to load when testing an iOS app using Appium and Python?

I am testing a native iOS app and need to wait for some elements to load in some of my testing. Appium is going too fast on some screens right now.
Can someone please point me to an example of using a WebDriverWait style of waiting for Appium iOS testing? There was a question that was answered for Ruby here: Wait for element to load when testing an iOS app using Appium and Ruby?. Looking for something similar in Python.
The Python client documentation doesn't seem to document the wait functions.
Thanks.
At the top of the test import these.
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
TL/DR is this should work, you may have to change self.driver to just driver in the wait = section depending on how you're doing things. Also, obviously change the By.XPath to whatever locator you're using:
wait = WebDriverWait(self.driver, 20)
currently_waiting_for = wait.until(EC.element_to_be_clickable((By.XPATH,'//UIAApplication[1]/UIAWindow[1]/UIAButton[#text="example text"]')))
Or you could just tell the driver to use implicit waits.
self.driver.implicitly_wait(10)
myElement = driver.find_element_by_id("fakeid")
myElement.click()
Most of this is explained here.
Here's an example of using wait to log into an Android App (Haven't used it on ios but it should be the similar) using the default account selector then asserting the right text appeared. During the setup, I'm loading my desired capabilities from another file.
class TrainUpSmokeTests(unittest.TestCase):
def setUp(self):
desired_caps = desired_capabilities.get_desired_capabilities('app-debug.apk')
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
def tearDown(self):
self.driver.quit()
def example_test(self):
wd = self.driver
## Depending on how you're running the test the first variable may just be driver. Or in my case self.driver which I shortened above. The number is how many seconds it should wait before timing out.
wait = WebDriverWait(wd, 20)
## Waiting for account selector to be clickable.
currently_waiting_for = wait.until(EC.element_to_be_clickable((By.XPATH,'//android.widget.CheckedTextView[#text="FakeEmail#example.com"]')))
## Locating test account and selecting it.
account = wd.find_element_by_android_uiautomator('text("FakeEmail#example.com")')
account.click()
ok_button = wd.find_element_by_android_uiautomator('text("OK")')
ok_button.click()
## Waiting for an Element on the home screen to be locatable.
currently_waiting_for = wait.until(EC.presence_of_element_located((By.XPATH,'//android.widget.RelativeLayout[#resource-id="com.name.app:id/overview"]')))
hero_headline = wd.find_element_by_android_uiautomator('new UiSelector().description("Example Header")')
self.assertIsNotNone(hero_headline)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TrainUpSmokeTests)
unittest.TextTestRunner(verbosity=2).run(suite)
It's a your testings a website using appium (instead of an app). Change the setup so self.driver opens a browser.
self.driver = webdriver.Firefox()
And then use By selectors like class, name, id, e.g. the example below.
currently_waiting_for = wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'search-results')))
This article also helped. Also if you don't know how to find xpaths, look into setting up uiautomatorviewer that comes with appium.
The python usage is:
driver.implicitly_wait(timeToWaitSec)
Selenium sourcecode(Py)
You can use WaitForElement class:
class WaitForElement:
#staticmethod
def wait(driver, id, time_out=100):
try:
WebDriverWait(driver, time_out).until(
lambda driver: driver.find_element(*id))
except TimeoutException:
print('Not able to find ID:' + id)
You can find all you need in selenium.webdriver.support.expected_conditions
Then from it you can do something like:
def wait_for_element_visible(self, by=By.XPATH, value=None, text=None, wait_time=20):
if text is not None:
value = value % text
wait = WebDriverWait(self.driver, wait_time)
return wait.until(EC.visibility_of_element_located((by, value)))
You can use implicitWait. Something like remoteWebDriver.implicitlyWait(time, timeUnit) This of course is for java. Something similar should be available for python.

Python / Selenium : Switch to an alert and verify the text within

My issue: Being able to detect an alert box has been opened, verify the text inside the alert, confirm the text and then close the alert. Then, go back and correct the invalid email.
My test is one for registering a user. I need to validate when someone might input incorrect data or mismatched data. In this case, I am entering an email and verifying the email first entered. Should they have a mismatch, a popup will appear alerting the user to check the email addresses they have entered and that they match. So far all I can get is an error.
Error:
E UnexpectedAlertPresentException: Message: u'Modal dialog
present' ; Stacktrace: Method nsCommandProcessor.prototype.execute
threw an error in file:///var/folders/1j/x3cxkrqn3sscdyq0t36169hr0000gn/T/tmpTCqMgm/extensions/fxdriver#googlecode.com/components/command_processor.js
I thought my code would handle this, but nope. If someone could point out my, obvious to you, mistake I would be grateful.
My entire test code:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
class ChallengeTests(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(5)
self.base_url = "https://www.testpage.com"
self.verificationErrors = []
self.accept_next_alert = True
# SIGN UP NEW USER
def test_00_sign_up(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("remail").send_keys("foobar#me.com")
driver.find_element_by_id("remail_confirm").send_keys("bar#me.com")
driver.find_element_by_id("next").click()
alert = self.driver.switch_to_alert()
alert = self.assertTrue(self.is_text_present("The email addresses you entered"))
driver.find_element_by_id("remail_confirm").send_keys("foobar#me.com")
driver.find_element_by_id("registration_button").click()
# NON TESTS
def is_element_present(self, how, what):
try:
self.driver.find_element(by=how, value=what) # to find page elements
except NoSuchElementException, e: return False
return True
def is_text_present(self, text):
try:
body = self.driver.find_element_by_tag_name("body") # find body tag element
except NoSuchElementException, e: return False
return text in body.text # check if the text is in body's text
def is_alert_present(self):
try:
self.driver.switch_to_alert()
except NoAlertPresentException, e:
return False
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
return True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
On newer version of Python(3.4)
def is_alert_present(self):
try:
self.driver.switch_to_alert()
except NoAlertPresentException:
return False
Try waiting for the alert to appear, before directly switching to it.
If that does not work, I have a feeling that the popup actually is a weblement and not a JS alert. if that is the case try looking for a selector using the browser developer tools and directly interact with it.

I need Selenium to open it's web browser in a larger resolution ( preferably maximized)

I am using Selenium WebDriver and coding in Python
I have looked all over the place and the best I could find were things written in different languages. I also tried to use the export tool on Selenium IDE but when I look at the data says that the function is not supported for export.
EDIT: The reason I need the browser to open up with a larger resolution is because the web application that I am testing is supporting tablet resolution as so elements are different depending on the resolution of the browser window.
This is the script I exported from the IDE with a couple of modifications.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
from Funk_Lib import RS
class CreatingEditingDeletingVault(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://cimdev-qa40/"
self.verificationErrors = []
def test_creating_editing_deleting_vault(self):
driver = self.driver
driver.get(self.base_url + "/Login?contoller=Home")
driver.find_element_by_id("UserName").click()
driver.find_element_by_id("UserName").clear()
driver.find_element_by_id("UserName").send_keys("user#gocodigo.com")
driver.find_element_by_name("Password").click()
driver.find_element_by_name("Password").clear()
driver.find_element_by_name("Password").send_keys("Codigo#123")
driver.find_element_by_id("fat-btn").click()
driver.get(self.base_url + "/Content/Vaults/")
driver.find_element_by_link_text("Content").click()
driver.find_element_by_link_text("Vaults").click()
driver.find_element_by_css_selector("button.btn.dropdown-toggle").click()
driver.find_element_by_link_text("New vault").click()
driver.find_element_by_name("Name").clear()
driver.find_element_by_name("Name").send_keys("Test Vault")
driver.find_element_by_xpath("//button[#onclick=\"vault_action('createvault', null, $('#CreateVault [name=\\'Name\\']').val())\"]").click()
driver.find_element_by_css_selector("button.btn.dropdown-toggle").click()
driver.find_element_by_link_text("Rename vault").click()
driver.find_element_by_name("Id").click()
Select(driver.find_element_by_name("Id")).select_by_visible_text("Test Vault")
driver.find_element_by_css_selector("option[value=\"2\"]").click()
driver.find_element_by_name("Name").clear()
driver.find_element_by_name("Name").send_keys("Test Change")
driver.find_element_by_xpath("//button[#onclick=\"vault_action('renamevault', $('#RenameVault [name=\\'Id\\']').val(), $('#RenameVault [name=\\'Name\\']').val())\"]").click()
driver.find_element_by_css_selector("button.btn.dropdown-toggle").click()
driver.find_element_by_link_text("Delete vault").click()
driver.find_element_by_name("Id").click()
Select(driver.find_element_by_name("Id")).select_by_visible_text("Test Change")
driver.find_element_by_css_selector("option[value=\"2\"]").click()
driver.find_element_by_xpath("//button[#onclick=\"vault_action('deletevault', $('#DeleteVault [name=\\'Id\\']').val(), '')\"]").click()
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException, e: return False
return True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
Selenium 2.31.0
driver = webdriver.Firefox()
# Resize the window to the screen width/height
driver.set_window_size(300, 500)
# Move the window to position x/y
driver.set_window_position(200, 200)
browser = webdriver.Firefox()
url = 'http://www.google.com/'
browser.get(url)
browser.maximize_window()
You can either use selenium.windowMaxmize(); or if you want to run your test in some specific resolution,You can go with
selenium.getEval("window.resizeTo(X, Y); window.moveTo(0,0);")
Are you asking to increase the screen magnification?
This will magnify a Firefox browser, Python 2.7
from selenium.webdriver.common.keys import Keys
br = webdriver.Firefox()
zoomAction = ActionChains(br)
body = br.find_element_by_tag_name('body')
for i in range(2):
zoomAction.send_keys_to_element(body,Keys.CONTROL,"+").perform()

Auto Filling Forms That Use ASP

I am trying to write some code, to automatically fill this webform:
http://scoweb.sco.ca.gov/UCP/
Then read the returned results. I'll look for my name and notify myself when I have UCP.
I have tried writing programs in C#(System.Net), curl(in conjunction with formfind), Ruby(Mechanize), and Python(Scrapy, urllib2).
All of my scripts work on regular HTML forms that communicate with databases, but this one returns nothing.
My theory is because the site uses ASP and I am failing to do something to account for that?
Any working code, though python preferred, filling the form and returning the results would be greatly appreciated.
I think the problem is because the form uses javascript. You can use selenium for such a thing http://seleniumhq.org/
#!/usr/bin/env python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re
class Shiply(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://scoweb.sco.ca.gov/" #California UCP
self.verificationErrors = []
def test_shiply(self):
driver = self.driver
driver.get(self.base_url + "/UCP/")
driver.find_element_by_id("ctl00_ContentPlaceHolder1_txtLastName").clear()
driver.find_element_by_id("ctl00_ContentPlaceHolder1_txtLastName").send_keys("YOUR_NAME")
driver.find_element_by_id("ctl00_ContentPlaceHolder1_btnSearch").click()
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException, e: return False
return True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()

Categories