Java selenium how to open a link from google search results? - java

I am new to automation testing in Selenium and i am doing some basic automation testing such as searching for something in Google and then clicking on a link which is required from the search results.
The code below, which i have produced works up until i get to the testing method. I am unable to select a link from the Google search page but i am not being shown any errors on my console. So i setup a thread on this particular line and it mentioned it could find the link name however the link name is used in the html code as i have checked on Google inspect.
Am i missing something obvious? I am relatively new to Selenium so any help is appreciated. Also i have tried mirroring some code from this users response "How to click a link by text in Selenium web driver java" but no luck!
Thanks
package com.demo.testcases;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
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;
public class MyFirstTestScript {
private static WebDriver driver;
public static void main (String[] args) {
SetUp();
testing();
}
// TODO Auto-generated method stub
#setup
public static void SetUp () {
driver = new FirefoxDriver();
driver.get("http://www.google.co.uk");
System.setProperty("webdriver.gecko.driver", "usr/local/bin/geckodriver");
driver.findElement(By.name("q")).sendKeys("BBC" + Keys.ENTER);
}
#Test
public static void testing() {
driver.findElement(By.partialLinkText("BBC - Home")).click();
}
}

Once you obtain the search results for the text BBC on Google Home Page next to click() on the link containing the text BBC - Home you can use the following code block :
List <WebElement> my_list = driver.findElements(By.xpath("//div[#id='rso']//div[#class='rc']/h3[#class='r']/a"));
for (WebElement item:my_list)
{
if(item.getAttribute("innerHTML").contains("BBC - Home"))
item.click();
}

You can use this code:
public class MyFirstTestScript {
private static WebDriver driver;
private static WebDriverWait wait;
public static void main (String[] args) {
SetUp();
testing();
}
#setup
public static void SetUp () {
System.setProperty("webdriver.gecko.driver", "usr/local/bin/geckodriver");
driver = new FirefoxDriver();
wait = new WebDriverWait(driver,50);
driver.manage().window().maximize();
driver.get("http://www.google.co.uk");
wait.until(ExpectedConditions.elementToBeClickable(By.name("q")));
driver.findElement(By.name("q")).sendKeys("BBC" + Keys.ENTER);
}
#Test
public static void testing(){
wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.linkText("BBC - Homepage"))));
driver.findElement(By.linkText("BBC - Homepage")).click();
}

Related

How to get rid of an overlaying pop up

Currently practicing running TestNG tests on the Lord & Taylor online site and I have an issue where a overlaying pop up from Lord and Taylor pops up on the screen at least once during a session. Most of the time it appears on the Homepage but can also appear once I click on one of the sections. I have tried using the xpath but it seems to change every time I run the browser. I have also tried using link text but that doesnt seem to work either. I can use an Implicit wait and manually click out of it but I feel like there has to be a way to do this with code. I also run into a problem where sometimes the ad wont load at all so it allows me to complete the initial few tests before it pops up out of nowhere. Its become a hurdle for me that I cant seem to get over. Ive attached what my code looks like now and can really use some help figuring this out.
package com.LT.Tests;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.LT.Pages.googlePage;
import com.LT.Pages.homePage;
public class homepageTest {
WebDriver driver;
googlePage gp;
homePage hp;
#BeforeTest
public void beforeTest() throws InterruptedException {
System.setProperty("webdriver.chrome.driver","/Users/nezamseraj/Desktop/WSA/Drivers/chromedriver 5");
driver = new ChromeDriver();
hp = new homePage(driver);
gp = new googlePage(driver);
driver.manage().deleteAllCookies();
Thread.sleep(2000);
driver.get("https://www.google.com/");
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
}
#AfterTest
public void afterTest() {
driver.quit();
}
#Test
public void gpValidation() {
boolean searchbar = gp.searchBar().isEnabled();
boolean searchbutton = gp.searchbutton().isEnabled();
Assert.assertTrue(searchbar);
Assert.assertTrue(searchbutton);
}
#Test(priority = 2)
public void searchLT() {
gp.searchBar().sendKeys("Lord and Taylor");
gp.searchbutton().click();
gp.ltLink().click();
}
#Test(priority = 3)
public void dismissAD() {
WebDriverWait wait = new WebDriverWait(driver,30);
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("DECLINE OFFER")));
hp.declineOffer().click();
}
#Test(priority = 3)
public void hpValidation() {
boolean ws = hp.womenSection().isEnabled();
boolean ds = hp.designerSection().isEnabled();
boolean as = hp.accessoriesSection().isEnabled();
Assert.assertTrue(ws);
Assert.assertTrue(ds);
Assert.assertTrue(as);
}
}
We are using QAF and utilizing qaf webdriver and webelement listeners for to deal with random popups.
You can add retry in element or driver listener's onfailure method. Ideal example is unexpected or random popup that needs to be dismissed. The implementation may look like below:
public void onFailure(QAFExtendedWebElement element, CommandTracker commandTracker) {
//check and close popup if exist
boolean shouldRetry = closePopUpIfExist();
if (commandTracker.hasException()
&& commandTracker.getException() instanceof StaleElementReferenceException) {
element.setId("-1");
shouldRetry = true;
}
commandTracker.setRetry(shouldRetry);
}
closePopUpIfExist implementation may look like below:
private void closePopUpIfExist(){
QAFExtendedWebElement popup_declineEle = new QAFExtendedWebElement("link=DECLINE OFFER");
if(popup_declineEle.isPresent() && popup_declineEle.isDisplayed()){
popup_declineEle.click();
return true;
}
return false;
}
UPDATE:
With qaf take benefit of base test class and base test page
public class homepageTest extends extends WebDriverTestCase {
#Test
public void gpValidation() {
GooglePage gp = new GooglePage();
gp.launchPage(null);
gp.getSearchTextbox().verifyEnabled();
gp.searchbutton().verifyEnabled();
// this test case doesn't makes sense because google is not your AUT and here you are testing google functionality!...
}
#Test(priority = 3)
public void hpValidation() {
GooglePage gp = new GooglePage();
gp.launchPage(null);
gp.getSearchTextbox().sendKeys("Lord and Taylor");
gp.searchbutton().click();
gp.ltLink().click();
HomePage hp = new HomePage();
hp.womenSection().verifyEnabled();
hp.designerSection().verifyEnabled();
hp.accessoriesSection().verifyEnabled();
}
}
Your page class may look like below:
public class GooglePage extends WebDriverBaseTestPage<WebDriverTestPage>{
//declare elements
// you can use #Findby from selenium support or from qaf
#FindBy(locator = "name=q")
private QAFWebElement searchTextbox;
...
protected void openPage(PageLocator loc){
driver.get("https://www.google.com/");
}
public QAFWebElement getSearchTextbox(){
return searchTextbox;
}
...
}
public class HomePage extends WebDriverBaseTestPage<WebDriverTestPage>{
//declare elements
// you can use #Findby from selenium support or from qaf
protected void openPage(PageLocator loc){
driver.get("/");
}
}
You may observe that there is no code to create/teardown driver. That is done through properties.
driver.name=chromeDriver
I would suggest checkout sample project. It has basic google search test case available with example configuration. you can download from github and run as maven test for playing around.

Can I make the WebDrivers as global variables in Java

I want to create a class where I set all the common actions of the WebDrivers such as: waitExplicit, findElement, click. But if I create a method then I have to create the WebDriver and WebDriverWait over and over on each method of the class, I already tried having a class for the Drivers, but when I call the methods, they just create instances over and over, so multiple windows open, I tried this way, but still cannot get to it:
public class AutomationActions{
static LoadProperties prop = new LoadProperties(); //This class has the System.setProperty for the driver
prop.getSysProp(); //***This is the issue, how can I solve this?****
WebDriver driver = new ChromeDriver(); //this will not work without the one above working
WebDriverWait wait = new WebDriverWait(driver, 30);//this will not work without the one above working
public void waitForPageToLoad() throws Exception {
ExpectedCondition<Boolean> pageLoadCondition = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
// WebDriverWait wait = new WebDriverWait(driver, 30); // I want to avoid having to set this in every method
wait.until(pageLoadCondition); //this is supposed to replace the line of code above
}
I don't really work on Java much any more, I've written our framework in C# but I put together some quick classes in Java to show you how I set things up. I use page object model and I recommend you do too so I've written this example using page object model. I've written a simple test that uses Dave Haeffner's (one of the Selenium contributors) demo site, http://the-internet.herokuapp.com.
The basic concepts are:
There is a class BaseTest that holds things that correspond to tests, e.g. setting up the driver at the start of the test, quitting the driver at the end of the test, etc. All of your tests will inherit from BaseTest
There is a class BasePage that holds things that correspond to generic methods for finding elements, clicking on elements, etc. Each of your tests inherit from BasePage. (This is what I think the main part of your question is asking about).
To follow the page object model, each page (or part of a page) is its own class and holds all locators and actions done on that page. For example, a simple login page would have the locators for username, password, and the login button. It would also hold a method Login() that takes a String username and a String password, enters those in the appropriate fields and clicks the Login button.
The final class of this example is a sample test aptly named SampleTest.
You shouldn't have any FindElements() or related calls in your tests, all those should be in the appropriate page object.
This is using TestNG as the unit test library. Use it or JUnit, your preference but if you use JUnit, you will need to change the asserts and the annotations.
Under 'src', I create a folder for page objects, 'PageObjects', and a folder for tests, 'Tests'. Here's what the files look like on disk.
\src
\PageObjects
BasePage.java
DropdownListPage.java
\Tests
BaseTest.java
SampleTest.java
BasePage.java
package PageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class BasePage
{
private WebDriver driver;
private final int shortWait = 10;
public BasePage(WebDriver _driver)
{
driver = _driver;
}
public void ClickElement(By locator)
{
new WebDriverWait(driver, shortWait).until(ExpectedConditions.elementToBeClickable(locator)).click();
}
public WebElement FindElement(By locator)
{
return new WebDriverWait(driver, shortWait).until(ExpectedConditions.presenceOfElementLocated(locator));
}
// add more methods
}
DropdownListPage.java
package PageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.Select;
public class DropdownListPage extends BasePage
{
private final By dropdownListLocator = By.id("dropdown");
public DropdownListPage(WebDriver _driver)
{
super(_driver);
}
public String GetSelectedOption()
{
return new Select(FindElement(dropdownListLocator)).getFirstSelectedOption().getText();
}
public void SelectOptionByIndex(int index)
{
new Select(FindElement(dropdownListLocator)).selectByIndex(index);
}
}
BaseTest.java
package Tests;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
public class BaseTest
{
public WebDriver driver;
public WebDriver GetChromeDriver()
{
System.setProperty("webdriver.chrome.driver", "C:\\Path\\To\\Chrome\\Driver\\chromedriver.exe");
return new ChromeDriver();
}
#BeforeTest
public void Setup()
{
driver = GetChromeDriver();
driver.manage().window().maximize();
driver.get("http://the-internet.herokuapp.com/dropdown");
}
#AfterTest
public void Teardown()
{
driver.close();
}
}
SampleTest.java
package Tests;
import org.testng.Assert;
import org.testng.annotations.Test;
import PageObjects.DropdownListPage;
public class SampleTest extends BaseTest
{
#Test
public void SampleTestCase()
{
DropdownListPage dropdownListPage = new DropdownListPage(driver);
dropdownListPage.SelectOptionByIndex(1);
Assert.assertEquals(dropdownListPage.GetSelectedOption(), "Option 1", "Verify first option was selected");
}
}
You will need to create a project that contains Selenium for Java and TestNG. Download them and put them on your build path. Create the folder structure as described above and create each of these classes and copy/paste the contents into them. Now all you need to do is run SampleTest as a TestNG Test and it should go.
The test creates a new Chromedriver instance, navigates to the sample page, selects the first option in the dropdown, asserts that the dropdown text is correct, and then quits the driver.
That should get you started. There's a lot of info crammed into the above wall of text, let me know if you have some questions.

Selenium cannot find element on website (chrome/Java)

Trying to test/learn selenium to login
the error - Exception in thread "main" org.openqa.selenium.ElementNotVisibleException: element not visible
package com.indeed.tests;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class test1 {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver",
"C:\\Users\\****\\Desktop\\neww\\trainingfiles\\chromedriver.exe.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.neopets.com/login/index.phtml");
driver.findElement(By.name("username")).sendKeys("test1");
}
private static void sleep(int i) {
}
}
I had a look at that web page. The problem is that there are two input fields with the name "username". One of them is not visible. Probably Selenium is getting that one. What you should do is:
List<WebElement> elements = driver.findElements(...);
and then get the second one (or the first, whatever), then try:
elements.get(1).sendKeys(...);

Adding a public class to click using xpath with Java Selenium

I am trying to create a public class to click an item on a webpage with selenium by just passing it the xpath and driver I'm using. I want to be able to just do:
ClickByXpath(driver, "/html/body/div/div[3]/form/div[2]/div[2]/div[1]/div[1]/div[3]/div/div[3]/div/input[1]");
Here's the code I'm using, but it's complaining that the method xpath string is not applicable:
package TestPackage;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class Question {
public static void main(String[] args) throws Exception {
// The Firefox driver supports javascript
WebDriver driver = new FirefoxDriver();
// Go to google
driver.get("http://www.google.com");
//click in the searchbox
ClickByXpath(driver, "/html/body/div/div[3]/form/div[2]/div[2]/div[1]/div[1]/div[3]/div/div[3]/div/input[1]");
}
public static void ClickByXpath(WebDriver [] driverUsed , String[] XPath_to_click) throws Exception {
driverUsed.findElement(By.xpath(XPath_to_click)).click();
}
}
You are passing a String:
ClickByXpath(driver, "/html/body/div/div[3]/form/div[2]/div[2]/div[1]/div[1]/div[3]/div/div[3]/div/input[1]");
But you method signature says that you should pass a String Array:
public static void ClickByXpath(WebDriver [] driverUsed , String[] XPath_to_click)
Same problem with your driver! If you change the signature and remove the Arrays, you should be good:
public static void ClickByXpath(WebDriver driverUsed , String XPath_to_click)
Please note that this has nothing to do with Selenium, this is (very?) basic Java programming. You should consider getting some help with learning at least basics of programming first.

creating user defined function for selenium webdriver

I want to create some user defined functions for my webdriver automation code. I tried it, but resulted in failure.
the following is my code
public class snapdeal {
WebDriver driver= new FirefoxDriver();
#Test
public void test() {
// I want open browser in function 1
driver.get("http://amazon.in");
driver.manage().window().maximize();
// Function 2 for searching
driver.findElement(By.xpath("//li[#id='nav_cat_2'")).click();
driver.findElement(By.id("twotabsearchtextbox")).sendKeys("Shoes");
driver.findElement(By.xpath("//input[#class='nav-submit-input']")).click();
driver.findElement(By.xpath("//h2[#class='a-size-medium s-inline s-access-title a-text-normal' and contains(text(), \"Fbt Men's 8876 Casual Shoes\")]")).click();
}
}
How ca i write two functions inside the class?
You were probably trying to nest methods inside test() . It is not possible.
You can use this code below which calls the respective methods in the test(). It works as expected:
public class snapdeal {
static WebDriver driver= new FirefoxDriver();
#Test
public void test() {
//Method1 for Opening Browser.
openBrowser();
// Method2 for searching
searchElement();
}
public static void openBrowser(){
driver.get("http://amazon.in");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
}
public static void searchElement(){
driver.findElement(By.xpath("//li[#id='nav_cat_2']")).click();
driver.findElement(By.id("twotabsearchtextbox")).sendKeys("Shoes");
driver.findElement(By.xpath("//input[#class='nav-submit-input']")).click();
driver.findElement(By.xpath("//h2[#class='a-size-medium s-inline s-access-title a-text-normal' and contains(text(), \"Fbt Men's 8876 Casual Shoes\")]")).click();
}
}
I think this is like a Hello World for Selenium for you, you could make use defined methods in Java using Junit with the following annotations which can be found here
But as per norms we usually have a #Before method in Junit or #BeforeTest method in testng for setting up the webdriver and the url of AUT, also in your code a couple of xpaths were wrong which were causing the error, Please find below the correct working code with comments:
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.safari.SafariDriver;
public class snapdeal {
public WebDriver driver;
#Before
public void setUP()
{
// I want open browser in function 1
driver= new SafariDriver();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.get("http://amazon.in");
driver.manage().window().maximize();
}
#Test
public void test() {
// Function 2 for searching
//driver.findElement(By.xpath("//li[#id='nav_cat_2")).click(); //element not needed
driver.findElement(By.id("twotabsearchtextbox")).sendKeys("Shoes");
driver.findElement(By.xpath("//input[#class='nav-submit-input']")).click();
driver.findElement(By.xpath("//*[#title=\"Fbt Men's 8876 Casual Shoes\"]//h2")).click();
}
}
The above code works as desired.
Creating user defined function have two different scope
1) Create function with piece of code and call that function whenever u needed it (Which is done above)
2) Second one creating a custom function wrt each controls like edit boxes , radiobutton , check boxes - etc , so by creating this functions u can make better feasible of your automation framework

Categories