I am practicing with Webdriver in running basic tests, and this specific test is to send an email through Gmail and then assert that it's been received.
I'm using the new version of Gmail where the compose email button pops up a window asynchronously (see picture). To access the body of the email to type a message, I have to select the iframe, but then I am unable to switch out and access the "Send" button element.
There are no other noticeable frames which hold the "Send" button, and using driver.switch_to_default_content() doesn't do anything either. I've included a snippet of the code below.
driver.find_element_by_name("to").clear()
driver.find_element_by_name("to").send_keys("toemailaddy#gmail.com")
localtime = time.asctime( time.localtime(time.time()) )
subj = ("TEST - " + localtime)
print(subj)
driver.find_element_by_name("subjectbox").clear()
driver.find_element_by_name("subjectbox").send_keys(subj)
body = ("TEST")
bodyFrame = driver.find_element_by_xpath("//td[#class='Ap']//iframe")
driver.switch_to_frame(bodyFrame)
driver.find_element_by_xpath("//body[#role='textbox']").clear()
driver.find_element_by_xpath("//body[#role='textbox']").send_keys(body)
driver.find_element_by_xpath("/div[#role='button' and contains(text(), 'Send')]").click()
driver.find_element_by_link_text("Inbox (1)").click()
I can get the message to send by using ActionChains send_keys(Keys.CONTROL, Keys,ENTER).perform(), but would like to figure out how to access the "Send" button to click on it for the sake of my sanity :)
My workaround for elements which have different id every test run is to parse page source with regexp in order to extract the id. Maybe it is not most efficient solution but it works.
import re
pattern = "div id=\"(:\w+)\".*Send</div>"
xpath = ""
matchObj = re.search(pattern,driver.page_source)
if(type(matchObj)!=None):
matchTuple = matchObj.groups()
if(len(matchTuple)>0):
xpath = "//*[#id=\"" + matchTuple[0] + "\"]"
print("SEND button xpath = " + xpath)
Related
Help me figure out why when using the get () method a second time, the page does not go? The method works only if you use a time delay time.sleep ()
Not working:
LOGIN = 'something#mail.com'
PASS = 'somepass'
LINK = 'https://stepik.org/'
browser = webdriver.Chrome()
browser.get(LINK)
browser.implicitly_wait(5)
browser.find_element_by_id('ember232').click()
username = browser.find_element_by_name('login').send_keys(LOGIN)
pas = browser.find_element_by_name('password').send_keys(PASS)
button = browser.find_element_by_xpath('//button[#type = "submit"]').click()
browser.get('https://stepik.org/lesson/237240/step/3?unit=209628')
Working
LOGIN = 'something#mail.com'
PASS = 'somepass'
LINK = 'https://stepik.org/'
browser = webdriver.Chrome()
browser.get(LINK)
browser.implicitly_wait(5)
browser.find_element_by_id('ember232').click()
username = browser.find_element_by_name('login').send_keys(LOGIN)
pas = browser.find_element_by_name('password').send_keys(PASS)
button = browser.find_element_by_xpath('//button[#type = "submit"]').click()
time.sleep(5)
browser.get('https://stepik.org/lesson/237240/step/3?unit=209628')
You are trying to login into the web site and then to navigate to some internal page.
By clicking the submit button
button = browser.find_element_by_xpath('//button[#type = "submit"]').click()
You are trying to log into the site.
This process takes some time.
So if immediately after clicking the submit page, while login is still not proceed, you are trying to navigate to some internal page this will not work since you still not logged in.
However you do not need to use a hardcoded sleep of 5 seconds.
You can use an explicit wait of expected conditions like presence_of_element_located() of some internal element to indicate you are inside the web site. Once this condition is fulfilled you can navigate to the desired internal page.
Try an alternative way:
driver.navigate().to("https://stepik.org/lesson/237240/step/3?unit=209628")
I am a novice coder. Trying my hand at creating an instagram bot and I'm following the instructions found here: (https://realpython.com/instagram-bot-python-instapy/)
I can fill in the elements for user name and password, but I'm having trouble clicking the login link. Using the -
#submit = browser.find_element_by_tag_name('form')
#submit.submit()
portion of my code works to log in, but I would like to be able to use find element by xpath and for this so I can apply it in different situations. If someone could please let me know where I can look in the HTML on the instagram page to find what I'm looking for, or direct me towards any helpful reading, I'd really appreciate it! I've tried a few ways to do this.
Here is my code. I also added photos of my code and error message.
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
#sets browser to firefox - need to make sure that geckodriver and firefox are in the path
browser = webdriver.Firefox()
#opens firefox to instagram#
browser.get('https://www.instagram.com/accounts/login/?source=auth_switcher')
#tells selenium to wait 5 seconds before trying again if it can't find something
browser.implicitly_wait(10)
print ('i waited')
user = 'username'
password = 'password'
##### USERNAME #####
username = browser.find_element_by_xpath("//input[#name='username']")
username.send_keys(user)
#username = browser.find_element_by_name('username')
#username.send_keys(user)
##### PASSWORD #####
password = browser.find_element_by_xpath("//input[#name='password']")
password.send_keys(password)
#password = browser.find_element_by_name('password')
#password.send_keys(password)
browser.implicitly_wait(10)
##### LOG IN #####
#instead of searching for the Button (Log In) you can simply press enter when you already selected the password or the username input element.
#submit = browser.find_element_by_tag_name('form')
#submit.submit()
#login_link = browser.find_element_by_xpath("//article/div/div/p/a[text()='Log in']")
login_link = browser.find_element_by_xpath("//a[text()='Log in']")
login_link.click()
#login_form = browser.find_element_by_xpath("//form[#id='loginForm']")
#form.submit()
print ('login incomplete :)')
sleep(5)
browser.quit() #quits geckodriver and mozilla
print ('closed')
Picture of error
code part 1
code part 2
Your xpath is bit wrong. you are using
//a[text()='Log in']
but Log in is inside div tag, not a tag.
Please use this xpath
//div[text()='Log In']/..
In your code
login_link = browser.find_element_by_xpath("//div[text()='Log In']/..")
login_link.click()
The HTML is
<div class=" qF0y9 Igw0E IwRSH eGOV_ _4EzTm ">Log In</div>
and we are using text() to target text Log in and then we are looking for button using /.. which is a parent node.
Replace this link
login_link = browser.find_element_by_xpath("//a[text()='Log in']")
with
login_link = browser.find_element_by_xpath("//div[contains(text(),'Log In')]")
And you should be good. Since the Login In button is wrapped inside a div element and not a element.
As already explained Log In is in a div tag under a button tag with type submit. You can use this xpath too.
browser.find_element_by_xpath("//button[#type='submit']").click()
I am new to selenium and trying to automate a WordPress social media schedule plugin. The problem is there is a link text box as shown below.
Now if I type URL in this box and click continue it I will get the next page like this :
But when I try to automate this step using this code :
mydriver = webdriver.Chrome(Path)
cookies = get_cookies_values("cookies.csv")
mydriver.get(url)
for i in cookies:
mydriver.add_cookie(i)
mydriver.get(url)
link_element = WebDriverWait(mydriver, 10).until(
EC.presence_of_element_located((By.ID, "b2s-curation-input-url"))
)
link_element.send_keys(link)
mydriver.find_element_by_xpath('//*[#id="b2s-curation-post-
form"]/div[2]/div[1]/div/div/div[2]/button').click()
Now, if I run the above code, which gets the URL, it also loads my cookies, but when it clicks on the continue button after sending keys, I get this type of page with an extra field with the name of the title. I don't want this extra title box as shown in the picture below
I would like to know what is causing this issue. I am using python 3.8 with Chrome web driver version 92.0.4515.131.
Thank you
One possibility is to try entering the URL character-by-character, as opposed to sending the entire string. The former is closer to the process of manually typing in the link, and assuming the site has a Javascript listener to catch the input, a character-by-character input process will be intercepted differently than a copy-paste of the entire URL:
mydriver = webdriver.Chrome(Path)
cookies = get_cookies_values("cookies.csv")
mydriver.get(url)
for i in cookies:
mydriver.add_cookie(i)
mydriver.get(url)
link_element = WebDriverWait(mydriver, 10).until(
EC.presence_of_element_located((By.ID, "b2s-curation-input-url"))
)
for c in link: #send each character to the field
link_element.send_keys(c)
#import time; time.sleep(0.3) => you could also add a short delay between each entry
mydriver.find_element_by_xpath('//*[#id="b2s-curation-post-
form"]/div[2]/div[1]/div/div/div[2]/button').click()
I have just started using selenium with Python for the first time, after following a quick tutorial I am now trying to make a program with it that will login to Gmail and then send an email to a chosen email address.
I've gotten the login part done but had some problems with the composing a new email part (only works some of the time) and I get stuck everytime when it comes to writing the message body.
My code is below, I have tried reading the docs but Im having trouble getting the following to work in Gmail and the when I inspect the elements in gmail it seems a lot more complex than the basic html structures in the examples here:
http://selenium-python.readthedocs.org/locating-elements.html#locating-elements-by-tag-name
"""
Write a program that takes an email address and string of text on the command line and then, using Selenium,
logs into your email account and sends an email of the string to the provided address.
"""
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
browser = webdriver.Chrome()
browser.get('http://www.gmail.com')
emailElem = browser.find_element_by_id('Email')
emailElem.send_keys('My_email#gmail.com')
emailElem.submit()
time.sleep(2)
passwordElem = browser.find_element_by_id('Passwd')
passwordElem.send_keys('My_password_here')
passwordElem.submit()
time.sleep(2)
composeElem = browser.find_element_by_class_name('z0') #this only works half of the time
composeElem.click()
time.sleep(7)
toElem = browser.find_element_by_name("to")
toElem.send_keys('my_other_email#gmail.com')
time.sleep(2)
subjElem = browser.find_element_by_name("subjectbox")
subjElem.send_keys('Test with selenium')
time.sleep(2)
bodyElem = browser.find_element_by_???('???') #this is where I get stuck and not sure what to do here
bodyElem.send_keys('A test email with selenium')
time.sleep(2)
sendElem = browser.find_element_by_link_text('send') #not sure if this is correct too
sendElem.submit()
I think the easiest way to select elements on a loaded page is to find them by css selector. You can find them in the browser inspector, and then copy their unique css selector (in firefox press inspect element -> copy unique selector). In this case this should work:
browser.find_element_by_css_selector('#\:nw')
Please Try :
time.sleep(10)
bodyElem = browser.find_element_by_xpath("//*[#id=":ov"]")
OR
bodyElem = browser.find_element_by_xpath("//*[#id=":ou"]")
I assume that it need little more time to find element so I have increased sleep time and also given xpath should work.
As id is changing each time, we can check for aria-label :
browser.find_element_by_css_selector("div[aria-label='Message Body']")
For send, use this :
sendElem = browser.find_element_by_xpath("//div[text()='Send']")
sendElem.click()
You can also hack it using the following once you've found the message box (I'm a noob and couldn't get Send to work)
sendElem.send_keys(Keys.TAB)
sendElem.send_keys(Keys.CONTROL + Keys.RETURN)
I am using Selenium Webdriver for the first time and am running a very simple script, but it is not working. I would like to open Firefox, go to LinkedIn, and enter my email address in the email login field. Using the code below, I'm able to get the first two operations to work, but the script is not properly identifying the email field, and so my email address is never being typed in anywhere.
browser = webdriver.Firefox() #Get local session of firefox
browser.get("http://www.linkedin.com") #Load page
elem = browser.find_element_by_name("session_key-login") #Find the login box
elem.send_keys("email#gmail.com" + Keys.RETURN) #Enter email into login box
How do I correctly identify the email login box and pass it to "elem"?
Try giving
element.send_keys("email#gmail.com");
instead of
elem.send_keys("email#gmail.com" + Keys.RETURN)
How about you just do
elem.send_keys("email#gmail.com")
UPDATE
The identifier used by you was incorrect, you can use either one of the below.
elem = browser.find_element_by_id("session_key-login")
elem = browser.find_element_by_name("session_key")