Unable to click on Setting Icon in Gmail with selenium web-driver - selenium

This is what i am trying do on Gmail.
www.gmail.com
Login using a valid user (if does not exist create a dummy user)
Click on Inbox
Click on first email
Click on Compose Email.
Send the mail to the same email account.
Click on options icon on the top right corner
Got to vacation responder on the General settings tab
Select vacation responder to on.
I am able to click on 1st email and pick the email Address and then click on compose email button, also able to send the email.
The problem i am facing is unable to click on settings icon. The element is hidden, i am not able to click it. I tried it with customized-Xpath and also tried to click it with coordinates.
But it not working for me. Please can anyone help me on this.
import org.openqa.selenium.By;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Gmail1 {
public static void main(String[] args) throws InterruptedException {
// Login to browser
WebDriver driver= new FirefoxDriver();
driver.get("https://www.gmail.com");
driver.manage().window().maximize();
System.out.println("Browser opned");
driver.findElement(By.xpath("//*[#id='Email']")).sendKeys("Use your UserId");
System.out.println("Entered Email id");
driver.findElement(By.xpath("//*[#id='next']")).click();
System.out.println("Clicked on Next");
Thread.sleep(3000);
driver.findElement(By.xpath("//*[#id='Passwd']")).sendKeys("Use your password");
System.out.println("Entered the Password");
driver.findElement(By.xpath("//*[#id='signIn']")).click();
System.out.println("Welcome to gmail");
Thread.sleep(5000);
driver.findElement(By.xpath("//*[#id=':3d']")).click();
System.out.println("Clicked on email");
Thread.sleep(3000);
String emailid = driver.findElement(By.xpath("//span[#class='go']")).getText();
emailid=emailid.substring(emailid.indexOf("<")+1, emailid.indexOf(">"));
System.out.println(emailid);
driver.findElement(By.xpath("//*[#id=':it']/div/div")).click();
System.out.println("Clicked on Compose mail");
driver.findElement(By.xpath("//*[#name='to']")).sendKeys(emailid);
System.out.println("Entered the TO Email Address");
driver.findElement(By.xpath("//*[#name='subjectbox']")).sendKeys("My Mail");
System.out.println("Entered Subject of the email");
driver.findElement(By.xpath("//*[#role='button' and .='Send']")).click();
System.out.println("Clicked on send button");
clickSetting(driver);
}
public static void clickSetting(WebDriver driver){
//Tried with Coordinates (doesn't work)
Point point = driver.findElement(By.xpath("//div[#class='G-Ni J-J5-Ji'] [#gh ='s']/*[1]")).getLocation();
System.out.println(point.x + "-" + point.y);
Actions builder = new Actions(driver);
builder.moveByOffset(point.x, point.y).click().build().perform(); //Getting Error.
//Tried with Action Class (doesn't work)
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement SettingWheel=driver.findElement(By.xpath("//*[#data-tooltip='Settings' and #role='button']"));
WebElement SettingsLink=driver.findElement(By.xpath("//*[#role='menuitem']/div[.='Settings']"));
wait.until(ExpectedConditions.elementToBeClickable(SettingWheel));
Actions actions = new Actions(driver);
actions.moveToElement(SettingWheel).moveToElement(SettingsLink).click().build().perform();//Getting Error.
Thread.sleep(2000);
System.out.println("Clicked On Setting");
}
Error message:- "Element is not currently visible and so may not be interacted with (WARNING: The server did not provide any stacktrace information)"
Thanks in Advance.

Try this:-
public static void clickSetting(WebDriver driver){
List<WebElement> elements=driver.findElements(By.xpath("//div[#gh='s']/*[#role='button']"));
for(WebElement element:elements){
if(element.isDisplayed()){
element.click();
Thread.sleep(2000);
driver.findElement(By.xpath("//*[#id='ms']")).click();
Thread.sleep(5000);
}
}

The problem is with your xpath. I tried with id ad it worked. Thread.sleep is bad idea. Don't go with that and instead use WebDriverWait
Anyhow the following snippet will click on settings gear then settings and wait till the Settings panel is loaded completely
Also go through this Gmail Selenium and see how I've handled Gmail login without Thread.sleep
public static void clickSetting(WebDriver driver) {
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id=':3d']"))).click();
System.out.println("Clicked On Settings Gear");
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#role='menuitem']/div[.='Settings']"))).click();
System.out.println("Clicked On Setting");
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#class='dt']")));
System.out.println("Settings Visible");
}

Try this:
package yourPackageName;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class TestClass2 {
static WebDriver driver;
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "c:/chromedriver.exe");
driver = new ChromeDriver();
Step_1_LaunchApp();
Step_2_LoginUsingCredentials();
Step_3_ClickOnInbox();
Step_4_ClickOnFirstEmail();
Step_5_ClickOnComposeEmail();
Step_6_ClickOnSettingsIcon();
}
private static void Step_6_ClickOnSettingsIcon() {
try{
driver.findElement(By.xpath("//*[#class='aos T-I-J3 J-J5-Ji']")).click();
}catch(Exception e){
e.printStackTrace();
}
}
private static void Step_5_ClickOnComposeEmail() {
try{
driver.findElement(By.xpath("//div[contains(text(),'COMPOSE')]")).click();
}catch(Exception e){
e.printStackTrace();
}
}
private static void Step_4_ClickOnFirstEmail() {
try{
driver.findElement(By.xpath("//div[#role='tabpanel'][1]//table//tr[1]")).click();
}catch(Exception e){
e.printStackTrace();
}
waitTimeInSecond(2);
}
private static void Step_3_ClickOnInbox() {
driver.findElement(By.xpath("//span/a[contains(text(),'Inbox')]")).click();
waitTimeInSecond(2);
}
private static void Step_2_LoginUsingCredentials() {
driver.findElement(By.id("Email")).sendKeys("email#gmail.com");
driver.findElement(By.id("next")).click();
waitTimeInSecond(2);
driver.findElement(By.id("Passwd")).sendKeys("Password");
driver.findElement(By.id("signIn")).click();
waitTimeInSecond(5);
}
private static void Step_1_LaunchApp() {
driver.get("http://gmail.com");
}
public static void waitTimeInSecond(int waitTime){
try{Thread.sleep(waitTime*1000);}catch(Exception e){}
}
}
.
Put your credentials first and run the script, it will click on settings gear.

Related

Chromedriver does not work unless I manually click borowser elements

I am new in selenium and trying to run a basic test both firefox and chrome in parallel. Everthing works for firefox but chrome is not working. Actually chrome browser opens up but does nothing unless I click email input and then click anywhere expect email input. When I do that my test starts on chrome and everything works fine. I am really sure that I should'nt click manually to start the test :)
Here is my page object;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import page.objects.AbstractPageObject;
public class LoginPage extends AbstractPageObject {
#FindBy(xpath = "//input[#type='email']")
private WebElement email;
#FindBy(xpath = "//input[#type='password']")
private WebElement password;
#FindBy(xpath = "//button[#type='submit']")
private WebElement continueButton;
public void verifyAllElementsAreDisplaying() {
email.isDisplayed();
password.isDisplayed();
continueButton.isDisplayed();
}
public void fillEmail (String userEmail) {
email.clear();
email.sendKeys(userEmail);
}
public void fillPassword (String userPassword) {
password.clear();
password.sendKeys(userPassword);
}
public void login () {
this.continueButton.click();
}
}
And here is my test;
import org.testng.annotations.Test;
import page.objects.Login.LoginPage;
public class VerifyLogin extends BaseTest {
#Test(description = "Verfifies Login Page Functionality")
public void verifyLogin() throws InterruptedException {
LoginPage loginPage = new LoginPage();
loginPage.verifyAllElementsAreDisplaying();
loginPage.fillEmail("email");
loginPage.fillPassword("***");
Thread.sleep(2000);
}
}
In BaseTest class I have #BeforeSuit and #AfterSuite annotations to manage driver.

Login fail using Selenium Java

My webdriver is the last version, my code have Thread.sleep also, but I can't login to the page.
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
WebDriver driver;
#BeforeTest
public void navegador() throws InterruptedException {
System.setProperty("webdriver.chrome.driver",
"C:\\Users\\chromedriver.exe");
Thread.sleep(1000);
driver = new ChromeDriver();
Thread.sleep(2000);
driver.manage().window().maximize();
Thread.sleep(3000);
}
#Test
public void f() throws InterruptedException {
driver.get("somewebpage");
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
Thread.sleep(3000);
driver.findElement(By.partialLinkText("LOGIN")).click();
Thread.sleep(2000);
driver.findElement(By.xpath("/html/body/div[1]/div[2]/form/div[1]/input")).sendKeys("myemail");
Thread.sleep(2000);
driver.findElement(By.xpath("/html/body/div[1]/div[2]/form/div[2]/input")).sendKeys("mypassword");
Thread.sleep(2000);
driver.findElement(By.xpath("/html/body/div[1]/div[2]/form/div[3]/div[2]/button")).sendKeys(Keys.ENTER);
Thread.sleep(5000);
}
#AfterTest
public void cierre() {
driver.quit();
}
}
The webpage send me this message "These credentials do not match our records."
But when I do it manually, the page give me access to home.
I can't pass from the login page, Suggestions?
may be you can give try this check whether test works in debug mode.
If test is still not working in debug mode. then try to fetch values of both username and password field after sent by script and check whether its going correctly as manually.
Still its failing please share html code.

Using DataProviders to login 3 times but only succeeding one time

I am learning TestNG for selenium. I want to pass three different usernames and passwords to the #Test, which is the login scenario. The scenario is:
go to the login page
click on the username input field and enter the username
click on the password input field and enter the password
click on the login button
click on the logout button
click on "ok" on the alert.
The first test is getting passed. The other two are getting failed with UnhandledAlertException.
package testNG;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class testData {
WebDriver driver;
#Test(dataProvider="data")
public void login(String userName, String password) {
driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://demo.guru99.com/V1/index.php");
WebElement userID = driver.findElement(By.xpath("//input[#name='uid']"));
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(userID));
userID.sendKeys(userName);
driver.findElement(By.xpath("//input[#name='password']")).sendKeys(password);
driver.findElement(By.xpath("//input[#name='btnLogin']")).click();
driver.findElement(By.xpath("//a[#href='Logout.php']")).click();
driver.switchTo().alert().accept();
driver.quit();
}
#DataProvider(name="data")
public Object[][] getUserData(){
return new Object[][] {
{"mngr137366", "jUgyjAn"},
{"mngr137370", "uvetahA"},
{"mngr137371", "utYmEqY"},
};
}
}
Update:
With the handling of the alert and the removing of the hardcoded username, the code is working fine now.
But the browser is being opened for three times for three logins.
I want it to open one time and perform three logins.
For that I have added the below code:
#BeforeClass
public void setUp() {
driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://demo.guru99.com/V1/index.php");
}
and the same is removed from the login() function. Now the first login is only successful. The other two logins are left.
The total code:
public class testData {
//public static void main(String[] args) {
// TODO Auto-generated method stub
WebDriver driver;
#BeforeClass
public void setUp() {
driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://demo.guru99.com/V1/index.php");
}
#Test(dataProvider="data")
public void login(String userName, String password) {
WebElement userID = driver.findElement(By.xpath("//input[#name='uid']"));
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(userID));
userID.sendKeys(userName);
driver.findElement(By.xpath("//input[#name='password']")).sendKeys(password);
driver.findElement(By.xpath("//input[#name='btnLogin']")).click();
driver.findElement(By.xpath("//a[#href='Logout.php']")).click();
WebDriverWait waitAlert = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.alertIsPresent());
driver.switchTo().alert().accept();
WebDriverWait wait1 = new WebDriverWait(driver, 20);
wait1.until(ExpectedConditions.elementToBeClickable(userID));
}
#DataProvider(name="data")
public Object[][] getUserData(){
return new Object[][] {
{"mngr137366", "jUgyjAn"},
{"mngr137370", "uvetahA"},
{"mngr137371", "utYmEqY"},
};
}
}
Try this,
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.alertIsPresent());
driver.switchTo().alert().accept();
It will wait until it will not find alert.
It looks, you have hard coded the username in your login test method.hence test is getting failed for rest of the two input (Valid Login Authentication error is throwing for the invalid user id to password mapping)
All the test is getting passed after assigning the username to the Userid element field.
Modified Login Code:
#Test(dataProvider="data")
public void login(String userName, String password) {
driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://demo.guru99.com/V1/index.php");
WebElement userID = driver.findElement(By.xpath("//input[#name='uid']"));
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(userID));
userID.sendKeys(userName);
driver.findElement(By.xpath("//input[#name='password']")).sendKeys(password);
driver.findElement(By.xpath("//input[#name='btnLogin']")).click();
driver.findElement(By.xpath("//a[#href='Logout.php']")).click();
driver.switchTo().alert().accept();
driver.quit();
}

Selenium: Presence of a particular WebElement on all pages in the website

We have a search widget at the top of the page in all the pages. I want to check, if that widget is visible on all the pages of the website. Is there any smarter way, rather than going to all the pages and checking it?
Answering straight, when you want to check if an widget is visible or not we should have used a method isVisible(). But isVisible() was available in Selenium RC which is deprecated in current WebDriver implementations. Instead referring to the documentation we can use either of these methods isDisplayed(), isEnabled() or isSelected().
So when you speak about search widget at the top of the page in all the pages I feel isDisplayed() method fits into your requirement. For example let us take an example of the Search field on stackoverflow.com Homepage which is available on all the pages. Now we want to check, if that widget is visible on all the pages of the website or not. A sample code block can be as follows:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class A_Firefox
{
public static void main(String[] args)
{
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://stackoverflow.com");
System.out.println("Application opened");
System.out.println("Page Title is : "+driver.getTitle());
WebElement my_element = driver.findElement(By.xpath("//input[#name='q']"));
if(my_element.isDisplayed())
{
System.out.println("Element is displayed");
}
else
{
System.out.println("Element is not displayed");
}
driver.quit();
}
}
The output on my console is:
Application opened
Page Title is : Stack Overflow - Where Developers Learn, Share, & Build Careers
Element is displayed
Enhancement:
As an enhancement you can create a function as presenceOfSearchBox(WebElement ele) and pass the WebElement as an argument from every page you visit to validate if the widget is displayed or not as follows:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class A_Firefox
{
public static void main(String[] args)
{
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://stackoverflow.com");
System.out.println("Application opened");
System.out.println("Page Title is : "+driver.getTitle());
WebElement my_element = driver.findElement(By.xpath("//input[#name='q']"));
presenceOfSearchBox(my_element);
driver.quit();
}
public static void presenceOfSearchBox(WebElement ele)
{
if(ele.isDisplayed())
{
System.out.println("Element is displayed");
}
else
{
System.out.println("Element is not displayed");
}
}
}

Locating iFrames and controls within them using Selenium WebDriver

I'm trying to automate www.snapdeal.com using Selenium Webdriver. I'm not able to click a web element inside an iframe as I get Element not visible exception.
Below is the code snippet
package com.snapdeal.framework.rough;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
public class Lab {
public static WebDriver browser;
public static WebElement currentElement;
public static Actions actions;
public static void main(String[] args) {
//System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"//src//main//resources//chromedriver.exe");
browser = new FirefoxDriver();
browser.get("http://www.snapdeal.com");
browser.manage().window().maximize();
browser.findElement(By.xpath("//*[#id='pincodeSalienceComponent']/div[2]/i")).click();
actions = new Actions(browser);
actions.moveToElement(browser.findElement(By.xpath("//*[#id='accountHeader']/div[1]"))).perform();
actions.moveToElement(browser.findElement(By.xpath("//*[#id='accountHeader']/div[2]/div[2]/div[1]/p/span[2]"))).click().build().perform();
//By executing a java script
JavascriptExecutor exe = (JavascriptExecutor) browser;
Integer numberOfFrames = Integer.parseInt(exe.executeScript("return window.length").toString());
System.out.println("Number of iframes on the page are " + numberOfFrames);
//By finding all the web elements using iframe tag
List<WebElement> iframeElements = browser.findElements(By.tagName("iframe"));
System.out.println(iframeElements.get(0));
System.out.println("The total number of iframes are " + iframeElements.size());
try{
browser.switchTo().frame(1);
}catch(Exception e){
System.out.println(e.getMessage());
}
try{
browser.findElement(By.xpath("//*[#id='login-register-modal']/div[2]/div[2]/div[2]/div")).click();
}catch(Exception e){
System.out.println(e.getMessage());
}
browser.close();
}
}
Could you please guide me on how to get this resolved?
You need to switch to iframe:
// click Mobile number and email button first an then
driver.switchTo().frame("loginIframe");
// after registration is done switch back to top frame:
driver.switchTo().defaultContent();