Webdriver to open a mail in Gmail - selenium

I have started using Webdriver to automate our testing which is 100% manual.
In one of the use cases I need to click on a link sent to the user's inbox. I am facing problems with Gmail in this case. After logging in I am not able to figure out how to open a particular email.
I know the email subject etc but I am unable use it to access the element. Gmail receives all its data as JSON and then build the entire page through js functions. So the webdriver is not able to access any of the elements built using the JSOn data received.
Any help is greatly appreciated.
Thanks,
Chris.

I would suggest NOT to use UI to verify Gmail. Gmail's UI is extremely complicated and it's a trap. To me, automating with selenium is not a solution at all.
Consider using JavaMail API and HTTPURLConnection. This is what I do in a similar testing scenario.
While running the webdriver test, after doing certain action if you expect an email then using JavaMail API poll (for a certain timeout if its not immediate) for the email in the background with certain 'subject' or 'sender' etc. Once the email is found then grab the link from the email content and then simulate a click using HTTPURLConnection

If you can search the specific email you can use the following code to locate the email you are looking for:
//div [#class='y6']/span[contains(.,'<your original search text>')]
mind that google will cut off the subject which results in something like 'subject...' if the subject is too long. We use a unique number to identify messages in our automated test environment.

I don't think I got your question correctly but I suppose you are having trouble finding the locator to open the mail after you've entered text in search box of gmail.
//div[5]/div/div/table/tbody/tr[n]" //n is the row no. of mailbox, for first result use 1 and like
use this as identifier for element before cliking on it.
Hope this helps.

In my case, I found the solution by using Action class of Web driver
Pre-requisite: Your driver needs to move to specific frame to locate element
wd.switchTo().frame("canvas_frame");
Step 1) Search for specific email that is created/generated using below code
String searchvalue="html/body/div[1]/div[2]/div/div[1]/div[3]/div/div[1]/div[2]/div[2]/div/form/fieldset[2]/div/div/div[2]/input";
wd.findElement(By.xpath(searchvalue)).sendKeys(sendkeys);
String clickSearch=".//*[#id='gbqfb']";
wd.findElement(By.xpath(clickSearch)).click();
Step 2) Now use Actions class to navigate through.
Actions action= new Actions(wd);
action.click(firstrecord).build().perform();
Hope this helps out!

The above answer is correct to identify a mail in Gmail if we replace the subject.
I have tried with Selenium IDE to find the object with the
target as
xpath=//div [#class='y6']/span[contains(.,'<your original search text>')]
The object was found but click is not opening the mail.
So after some investigation I found that mouseDown method is working with the above xpath to open a mail.
So command will be
selenium.mouseDown("xpath=//div [#class='y6']/span[contains(.,'<your original search text>')]");
or
<td>mouseDown</td>
<td>xpath=//div[#class='y6']/span[contains(.,'£10 OFF when you spend £30 or more online')]</td>
<td></td>
in the IDE.
Hope this helps.

The current locator for gmail body is:
driver.findElement(By.className("LW-avf")).click();
driver.findElement(By.className("LW-avf")).clear();
driver.findElement(By.className("LW-avf")).sendKeys("your body message");

The below selenese command would do:
clickAt | //table/tbody/tr/td[5]/div[#class='yW'] |
Click at the FROM field of first/recent/top most mail to go to mail detail page. // note: tr for first mail, tr[2] for second and so on.

Try this out , working perfectly for me. This will select random emails, you can also modify as your requirement
for i in xrange(int(num)):
time.sleep(3)
m=random.randint(1,10)
print("Mail Number "+str(m)+" is selected")
browser.find_element_by_xpath("//div[#role='tabpanel'][1]//table//tr"+str([m])).click()
time.sleep(3)
browser.find_element_by_xpath('//*[#id=":5"]/div[2]/div[1]/div/div[1]/div/div/div').click()

You can use this also if you want to open a particular mail in gmail:
driver.findElement(By.xpath("//tr[i[td[4[div[contains(#class,'yW')]]]")).click();
Here i is the mail number which you want

Related

RobotFramework Opening Email Links using robotframework-imaplibrary2

Currently using a robotframework-imaplibrary2 [a extension of robot framework]
To open emails sent, I just want to open the link from the sent email in a using the the normal robot framework selenium functions
Is this possible?
Email Verification
Open Mailbox host=imap.hiddeb.com user=fsf#fsefesf.com password=sfefsff
${LATEST} = Wait For Email sender=sfefsefs#sfefsf.com timeout=300
${HTML} = Open Link From Email ${LATEST}
The library contains this
${HTML} = Open Link From Email ${LATEST}
Looking at the implementation of the keywords, I'd say this has nothing to with selenium.
What seems to happen is, you need an email that is in HTML format (not plain text). Then you need the index of that email, which is in your case stored in variable ${LATEST}
Calling Open link from Email ${LATEST} uses the first link (that is the default behaviour) that is found in that email and opens the url and gets the HTML content of that website. There does not seem to be any browser or webdriver involved.
However, if you like to open a link in a browser, I would try the keyword Get Links from Email:
${ALL_LINKS} Get Links from Email ${LATEST}
SeleniumLibrary.Go To ${ALL_LINKS}[0]
Disclaimer: Since I do not have any test-email server available, my suggestion might require adjustments.

Auto login to website using script or bookmark

I've been trying to figure this out using various different methods. I'm trying to create a script/bookmark or some type of quick action to open a browser tab or window with a specific URL, and automatically log me in using my credentials. I'm not all that concerned about security for this at the moment.
At first I figured I'd try to use a javascript bookmark to do this, but nothing I found in my research worked. Next I tried to create a bash script, but I couldn't figure out how to send the credentials in via the terminal. Most recently, I literally copied the source code of a site, created a local file and tried to hack together something where I could prefill the form data with credentials and use JS to submit the form, and I've gotten close with this, but for some reason when I use the JS submit function, it errors out and says that the username and password are invalid. But when i turn off the submit function and manually click "log in" on my local html page, it works as expected. I want this to be a one click process, so the idea of using onload/submit or something to that affect is really important to me.
The site I'm testing with has a Rails backend and my next attempt might be trying to use POST to do what I'm thinking, but that's currently outside of my level of knowledge on the subject.
Anyone answering: i do not want to use a password manager to accomplish this.
My requirement is that i will either be able to a) run a script or b) use a 1-click option to do this per website. Ideally i'd be able to set this up in a sort of programmatic way to do this with multiple sites, but I'd be happy with 1 at the moment.
i know similar questions have been answered before, but I haven't been able to use information from those posts (the ones I've seen anyway) to figure out a good way to do this.
Create a bookmark for the current page you have opened.
Edit the bookmark
Change the value for the URL to something like this.
(javascript:(function(){CODE_GOES_HERE_FROM_BELLOW})();
find the field for username and password on the page.
Given example for hotmail
var inputs = document.getElementsByTagName('input'); for(var i=0;i<inputs.length;i++){if(inputs[i].name === 'passwd'){inputs[i].value = 'YOUR_PASSWORD'}else if(inputs[i].name === 'loginfmt'){inputs[i].value = 'YOUR_USERNAME'}}; document.getElementById(document.getElementsByTagName('form')[0].id).submit();
OR
try out casperjs.
The proposed solution didn't work for me and rather than spending tons of time installing a testing framework that I'll never use other than for this purpose, I decided to try to do this another way.
First, I found out that the reason my JS wasn't working before is because the site did not allow a JS submit to be done, or atleast that's what it seemed to be when I got this error: "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience"
The javascript I was using was in fact working, just not submitting. I used the following code to fill the fields (using "Class Name" elements on the page since there was no name or ID):
document.getElementsByClassName('username')[0].setAttribute('value', 'user');
document.getElementsByClassName('password')[0].setAttribute('value', 'password');
As I mentioned, the problem was when I tried to use JQuery to submit the form: document.getElementsByClassName('loginForm')[0].submit();
Which is when the above error cropped up. I can't really say for sure whether this is the root of the cause, but the page does submit, but I get an invalid username/password error when I do
I haven't figured out a great way to get around this just yet, but my short-term, "hacky" solution was to use Applescript to send a return keystroke to the browser to submit the form. I'd ideally like to figure out how to get the submission to work using JQuery, but I'm not sure how to get around it.

Using Capybara finder on HTML block

I had my Selenium tests navigating to a public dummy inbox to verify receipt of email deliveries and would perform some confirmation workflows there (password change, etc). It was becoming far too slow and unreliable.
I'm now using the API of a mail service to retrieve an email message. I'm able to search for the message I need and I'm able to retrieve the block of HTML that I'm usually inspecting.
Is there a way to use a Capybara finder on a block of HTML text?
You can turn a string of html into something Capybara can work with by doing
node = Capybara.string(the_html.to_s)
then you can call finders on node
node.find(...)

How to map xpath of web element in its actual class?

I am creating a framework in selenium from scratch where i am scripting below scenarios:
1.Login in to https://www.yahoomail.com
2.entering username
3.entering password
4.click on Sign-In
5.click on Compose button
6.Enter Email ID, Subject and Message body.
Below is the code script i have written for above scenario:
WebDriver oYahoo = new FirefoxDriver();
oYahoo.get("http://www.yahoomail.com/");
oYahoo.manage().window().maximize();
oYahoo.findElement(By.xpath(".//*[#id='login-username']")).sendKeys("abcdefasdf#yahoo.com");
oYahoo.findElement(By.xpath(".//*[#id='login-passwd']")).sendKeys("sfgas234#123");
oYahoo.findElement(By.xpath(".//*[#id='login-signin']")).click();
oYahoo.findElement(By.xpath(".//*[#id='Compose']/button")).click();
oYahoo.findElement(By.xpath(".//*[#id='yui_3_16_0_1_1448364357109_2222']")).sendKeys("abcdefgh#gmail.com");
oYahoo.findElement(By.xpath(".//*[#id='subject-field']")).sendKeys("Hi This is my first automated mail");
oYahoo.findElement(By.xpath(".//*[#id='yui_3_16_0_1_1448364357109_1966']")).sendKeys("Hi This is my first automated mail");
oYahoo.findElement(By.xpath(".//*[#id='yui_3_16_0_1_1448364357109_2465']")).click();
oYahoo.quit();
Scripts fine till it clicks on "Compose" button, Once i get Mail editor, Script does not enters email-ID,Subject, and Message body.
What other action i should perform to achieve the same so that script will enter these parameters and can send a mail to particular user.
Do we need to create some class which will maps the locators to "compose-Email" screen?
If yes, how we can map/assign x-path to particular web element of Compose-Email page.
Thanks in Advance.
Well you should try by using the xpath and enter the required text. Something like this (it works for me)-
oYahoo.findElement(By.xpath(".//*[#id='to-field']")).sendKeys("xxxx#xxx.com");
oYahoo.findElement(By.xpath(".//*[#id='subject-field']")).sendKeys("My first automated email");
oYahoo.findElement(By.id("rtetext")).sendKeys("Hello....Hi....This is my first automated email");

How do I check for error message popup in browser using webdriver?

I have login form on website,
i want to make automatic testcase for this scenario:
i give phone number but no password:
How do I test selenium to give me expected red error message popup?
What function is in selenium api to check for it? I did not find it!
EDIT: or maybe my expected thing to happen should be "stay on same page"?
There is no specific function like that. Find out what is the xpath for that red colored text. Then you can create a web element using that xpath and check whether it is visible and what is the text value of that element, and assert on that.
As an example:
You first define the error message WebElement as messageElement
You may locate the element like this:
driver.findElement(By.id("error-message"))
Then you may get the error message text using this:
messageElement.getText());
Once you get the text you can then validate it with the expected text.
Assert.assertEquals(actualMessage, expectedMessage);
PS:
From snap, it doesn't seem to be another pop-up so no need to use switch to alert etc.