Send text and click ENTER on expath - python

I clicked the text box but I am unable to send a text.
divselected = driver.find_elements_by_xpath("//*[contains(text(), 'Add a public comment...')]")[0].click()
divselected.send_keys("Talk-Talk")
Unable to add comments and press enter.

I did some search and I think this should work, just clear and send return key.
divselected = driver.find_elements_by_xpath("//*[contains(text(), 'Add a public comment...')]")[0].click()
divselected.clear()
divselected.send_keys("Talk-Talk")
divselected.send_keys("Keys.RETURN")

You wrong variable initialize for divselected, remove .click().
So, it's should like this:
divselected = driver.find_elements_by_xpath("//*[contains(text(), 'Add a public comment...')]")[0]
divselected.click()
divselected.send_keys('Talk-Talk')
divselected.submit()
Or if .submit() doesn't work, use .send_keys(Keys.ENTER):
#following import
from selenium.webdriver.common.keys import Keys
divselected.send_keys(Keys.ENTER)
But in this case if you want get the first element (refers to your index [0]), actually you don't need .find_elements_*. You can use .find_element_(without s):
divselected = driver.find_element_by_xpath("//*[contains(text(), 'Add a public comment...')]")

Related

Python Selenium hover action concatenates in memory

I am testing a website which has a menu with submenus appearing on hover.
I have created a function to interact with this menu:
def go_to(navbar_item, menu_item):
# find the navbar item
assets_main_menu = driver.find_element(By.ID, navbar_item)
#hover over the navbar item, so the submenu appears
hover.move_to_element(assets_main_menu).perform()
# find the submenu item
xpath = "//*[contains(text(), \'" + menu_item + "\')]"
destination = driver.find_element_by_xpath(xpath)
# hover over the submenu item and clicks
hover.move_to_element(destination).click().perform()
The problem is that i use this function more than once such as:
# action 1
go_to('navbar item1 id', 'submenu item1')
do_something()
# action 2
go_to('navbar item1 id', 'submenu item2')
do something()
# action 3
go_to('navbar item1 id', 'submenu item3')
do_something()
selenium actually repeats the previous steps going through the past menu items like:
ACTUAL OUPTUP
action 1, do something -> action 1, action 2, do something -> action 1, action 2, action 3, do something
Instead my DESIRED OUTPUT would be:
action 1, do something -> action 2, do something -> action 3, do something
I tried unsetting the variables:
navbar_item, menu_item, hover, xpath, destination.
at the end of the function with no luck.
I have also tried to instantiate hover within my function
hover = ActionChains(driver);
but in this last attempt my code stopped working.
When you call an action chain, perform() does not clear out the previous steps. You've only really shared your function so the real culprit is the structure of your code and how python consumes variables.
I note in your function, you pass in two strings but your function knows what driver and hover are. Which sounds like you're using global variables.
To demo your problem I created this simple page for you with a click counter:
<html>
<body>
<button id="button" onclick="document.getElementById('input').value = parseInt(document.getElementById('input').value) + 1">Click me</button>
<input id="input" value="0"></input>
</body>
</html>
It's a flat page that just knocks up a number each time you press the button:
Then, to show you what's happening, i created a similar version of your code:
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get(r"c:\git\test.html")
actions = ActionChains(driver)
def ClickByActions(element):
actions.move_to_element(element).click().perform()
#find the button and click it a few times...
button = driver.find_element_by_id('button')
ClickByActions(button)
ClickByActions(button)
ClickByActions(button)
With this, you expect the end click-count-value to be 3. However, it is 6.
Same as your problem. First call does +1, second call does +1 +1, third call does +1 +1 +1.
Finally! the solution - create action chain in the function with your driver:
def ClickByActions(element):
localActions = ActionChains(driver)
localActions.move_to_element(element).click().perform()
I note in the comments you say you tried this. Can you please try:
not using hover but another name -
pass in driver instead of relying on it being a global variable. For this you would use go_to(navbar_item, menu_item, driver)
Apparently hover.reset_actions() should also work - but this didn't work for me.
If these don't work, please share your site URL so I can try on your actual site or say what the error is and describe what happens.

Check if text is visible with Selenium, Python

I am making a script that will fill the forms to create a Gmail account with Python. When a username is already used a message becomes visible. In dutch: "Dez gebruikersnaam worst al gebruikt. Probeer been andere gebruikersnaam." To be able to deal with this I need to detect when this message is visible, but I have no idea how to do that. If anyone can help, that would be amazing
Try this code:
from selenium import webdriver
import time
path = '/home/avionerman/Documents/stack'
driver = webdriver.Firefox(path)
driver.get('https://www.google.com/intl/nl/gmail/about/#')
try:
print('locating create account button')
create_account_button = driver.find_element_by_class_name('h-c-button')
except:
print("error, couldn't find create account button")
try:
create_account_button.click()
print('navigating to creation page')
except:
print('error navigating to creation page')
time.sleep(8)
handles = driver.window_handles
size = len(handles)
driver.switch_to.window(handles[1])
print(driver.title)
first_name_input = driver.find_element_by_id('firstName')
first_name_input.click()
first_name_input.send_keys("WhateverYouWant")
last_name_input = driver.find_element_by_id('lastName')
last_name_input.click()
last_name_input.send_keys("WhateverYouWant2")
username_input = driver.find_element_by_id('username')
username_input.click()
username_input.send_keys('papadopoulos')
pswd_input = driver.find_element_by_name('Passwd')
pswd_input.click()
pswd_input.send_keys('whateveryouwant')
pswd_conf_input = driver.find_element_by_name('ConfirmPasswd')
pswd_conf_input.click()
pswd_conf_input.send_keys('whateveryouwant')
next_button = driver.find_element_by_id("accountDetailsNext")
next_button.click()
# In the variable x I save the text that is included inside the specific xpath
x = driver.find_element_by_xpath("//*[#id='view_container']/form/div[2]/div/div[1]/div[2]/div[1]/div/div[2]/div[2]/div").text
print(x)
# I assert in order to check if the variable x has the proper text value (the expected one)
assert x == 'Dez gebruikersnaam worst al gebruikt. Probeer been andere gebruikersnaam.'
time.sleep(10)
In this way, if the assert passes mean that you see the warning message and in any other case the username for the mail is unique. So, the part of the code that I wrote to you, you can insert it inside if statements and you can handle it as you wish. If you need any further info feel free to ping me.

Selenium webdriver isn't able to clear a field, but is able to send_keys to it

I'm trying to create a program that signs up for instagram with a new account, I've got the emails and the rest generated, when I go ahead and send_keys to the appropriate fields, it does it just fine. I wanted to implement a retry function, which would clear the email field and try with a different mail. However this does not work, even though send_keys to it worked previously? Snippet of my code below.
driver.get('https://www.instagram.com')
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail)
driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]").send_keys(name + lastname)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(namae+lastonamae+pamae2)
driver.find_element_by_xpath("//*[contains(#aria-label,'Password')]").send_keys(password)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
This attempts to create a new account with the appropriate credentials, however when it fails, I want it to try to look for an element that is only present when it fails, and if it finds that, it should clear the email field and retry with a different one. Code below.
driver.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[2]/div[1]/div/form/div[3]/div/div[2]/span') #this looks for the element only present on the fail page
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").clear()
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)
It doesn't clear the field, but doesn't raise an error either. It then proceeds to type the 2nd email with no problems. I appreciate any help on the matter.
EDIT: Posting a bigger chunk of the code.
def signup():
driver.get('https://www.instagram.com')
time.sleep(7)
if trycounter < 3: #this is almost always true, just a failsafe
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]").send_keys(name + ' ' + lastname)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(name+lastname+extension)
driver.find_element_by_xpath("//*[contains(#aria-label,'Password')]").send_keys(password)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
time.sleep(7)
try: #this only executes if a popup that wants you to confirm your age pops up
driver.find_element_by_xpath('//*[#id="igCoreRadioButtonageRadioabove_18"]').click()
driver.find_element_by_xpath('/html/body/div[3]/div/div[3]/div/button').click()
time.sleep(5)
except:
pass
try:
randomgen() #generates the mail,password and name
driver.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[2]/div[1]/div/form/div[3]/div/div[2]/span')
time.sleep(1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").clear()
time.sleep(1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(username)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
time.sleep(7)
You can use following code as alternative for clear method:
from selenium.webdriver.common.keys import Keys
email_element = driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]")
email_element.send_keys(Keys.CONTROL, 'a')
email_element.send_keys(mail1)
fullname_element = driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]")
fullname_element.send_keys(Keys.CONTROL, 'a')
fullname_element.send_keys(name + ' ' + lastname)
# do it for other field as well
So this will definitely work as a workaround. I just tried it on instagram. Although there was no field with an aria label called Email for me. It was aria-label "Mobile Number or Email" for me.
driver.execute_script("$(\"input[aria-label='Email']"\").value = '';");
I will keep looking at it to see why the clear command didn't work though.
You can try something like this to delete mail1.
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(Keys.chord(Keys.CONTROL,"a"))
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(Keys.DELETE)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)

send_keys(Keys.RETURN) submitting 1 extra character (python selenium)

I am attempting to automate a login process.
To do so, I am using send_keys('email') and send_keys('password') in their respective fields like so:
email = driver.find_element_by_xpath('//*[#id="email"]')
email.send_keys('e#mail.com')
pwd = driver.find_element_by_xpath('//*[#id="password"]')
pwd.send_keys('pwd12345')
These two steps are successful. Now, I would like to use the "return" key to submit the login credentials and be logged in. To do so, I have tried:
pwd.send_keys(Keys.RETURN)
The password I am attempting to enter is 8 characters long. After the 8 characters have been entered, pwd.send_keys(Keys.RETURN) enters a 9th character into the password field JUST before the credentials are submitted, resulting in "incorrect email address or password".
I have also tried:
email.send_keys(Keys.RETURN) - which also returns "incorrect email address or password"
pwd.submit() - which clears the email and password fields completely and does not log in (?)
Thoughts?
Can you try code below?
pwd = driver.find_element_by_xpath('//*[#id="password"]')
ActionChains(driver).send_keys_to_element(pwd,'pwd12345').send_keys_to_element(pwd, Keys.RETURN).perform()
Here is the Answer to your Question:
Considering you are trying to login in to your PayPal Account with a valid set of credentials the following code block works through all the 3 options as in:
Using click()
Using Keys.ENTER
Using Keys.RETURN
Having said that I will suggest you to consider using the click() and clear() methods before entering any text into any input tag. Here is the working code block:
driver.get('https://www.paypal.com/in/home');
driver.implicitly_wait(20);
driver.find_element_by_id('ul-btn').click();
email = driver.find_element_by_id('email')
email.click();
email.clear();
email.send_keys('debanjan.selenium#gmail.com');
password = driver.find_element_by_id('password');
password.click();
password.clear();
password.send_keys('dev_anjan');
#Using Keys.ENTER
#password.send_keys(Keys.ENTER);
#Using Keys.RETURN
password.send_keys(Keys.RETURN);
#Using LogIn Button Click
#login_button = driver.find_element_by_id('btnLogin')
#login_button.click();
Let me know if this Answers your Question.
Please try this way, it's working for me:
email = driver.find_element_by_xpath('//*[#id="email"]')
email.send_keys('e#mail.com')
pwd = driver.find_element_by_xpath('//*[#id="password"]')
pwd.send_keys('pwd12345')
login_button = driver.find_element_by_xpath('//*[#id="btnLogin"]')
login_button.click()
Insted of pressing Enter on the password field you should do what a normal guy does and press the Log In button.

Can't locate element - Selenium

I'm trying to find a textarea in my facebook group. The login is ok, driver.get(group) is ok too but then, when I try to locate the textarea, it returns that it can't locate it. The weird thing is that I can clearly see it there.
def send_post(self,text,group):
assert self.logged == True
self.driver.get(group)
text_field = self.driver.find_element_by_css_selector('div.innerWrap').find_element_by_tag_name('xhpc_message_text')
text_field.send_keys(text)
self.driver.find_element_by_xpath("//button[#value='1']").click()
Do you know what am I doing wrong? Do you have a better way to post to fb group?
xhpc_message_text isn't a tag name; textarea is.
If you're talking about the post-writing <textarea>, then it has a name attribute (different!) of xhpc_message_text. You can combine your find_element_by_* calls into one:
text_field = self.driver.find_element_by_css_selector('div.innerWrap [name="xhpc_message_text"]')

Categories

Resources