Accessing web pages automatically using selenium - java

I'm trying to access a webpage using Selenium.
I use the WebDriver and HtmlUnitDriver classes:
WebDriver driver = new HtmlUnitDriver();
WebElement element;
Then to get a webpage I use:
driver.get("url");
url being the specific url of a page.
However, this does not work for all pages? When accessing some pages the program just halts and nothing happens. What I'm doing is logging into a web page, buying some stuff, and all that works, but when I want to go to the check-out and finish the order the check-out page does not load.

you can use some functions like these
public String openBrowser(String object, String data,String configPath) {
APP_LOGS.debug("Opening browser");
if (CONFIG.getProperty(data).equals("Mozilla"))
driver =new FirefoxDriver();
else if (CONFIG.getProperty(data).equals("IE"))
driver =new InternetExplorerDriver();
else if (CONFIG.getProperty(data).equals("Chrome"))
driver =new ChromeDriver();
else if (CONFIG.getProperty(data).equals("Safari"))
driver =new SafariDriver();
driver.manage().window().maximize() ;
}
public String clickButton(String object, String data,String configPath){
OR=new ObjectRepLocator(ObjectRepo);
APP_LOGS.debug("Clicking on Button");
try{
driver.findElement(By.xpath(OR.getLocator(object,configPath))).click();
}catch (Exception e){
return Constants.KEYWORD_FAIL+ " Not able to click on button"+e.getMessage();
}
return Constants.KEYWORD_PASS;
}
Better way is you can get those values for processing this from Excel sheets. I am using the data driven framework that proceeds in this way

Related

Unable to open a link in new tab using Actions Class

I am trying to open a link in a new tab using selenium java automation code.
Initially i tried with actions class but it wasn't working. Later i tried using the Keys to automate the same thru keyboard actions and it worked. But i wanted to know why am i unable achieve the same with Actions class. Just wanted to if i am doing anything wrong here or is Actions class not suitable for this.
Below is the code snippet i have written.
public class InterviewQuestion {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
//System.out.println(System.getProperty("user.dir")+"\\"+"chromedriver.exe");
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\"+"chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.google.co.in/");
driver.manage().window().maximize();
WebElement GoogleSearchTextBox = driver.findElement(By.xpath("//input[#title='Search']"));
GoogleSearchTextBox.sendKeys("test automation");
GoogleSearchTextBox.sendKeys(Keys.ENTER);
**boolean useActionsClass = false,useKeys = true;**
// finding the required element to be clicked
WebElement RequiredSearchResult = driver.findElement(By.xpath("//div[#class='EIaa9b']/div[1]/div[2]/a"));
if(**useActionsClass**)
{
Actions actions = new Actions(driver);
//actions.moveToElement(RequiredSearchResult).build().perform();
Thread.sleep(5000);
actions.moveToElement(RequiredSearchResult).contextClick(RequiredSearchResult).sendKeys(Keys.ARROW_DOWN).sendKeys(Keys.ARROW_DOWN).sendKeys(Keys.ENTER).build().perform();
}
if(useKeys)
{
Thread.sleep(5000);
String s = Keys.chord(Keys.CONTROL,Keys.ENTER);
RequiredSearchResult.sendKeys(s);
Set<String> windows = driver.getWindowHandles();
Iterator itr = windows.iterator();
Object FirstWindowHandle = itr.next();
Object SecondWindowHandle = itr.next();
driver.switchTo().window((String) SecondWindowHandle);
Thread.sleep(5000);
//driver.switchTo().window((String) FirstWindowHandle);
}
//driver.quit();
}
}
First, get the link with the help of href attribute from your RequiredSearchResultLink element. once you have the link, use selenium 4 driver.switchTo().newWindow(WindowType.TAB); method to open a new tab. Once the tab is open, just pass your get method, the url which you got from your link field.
If you are not using selenium 4, I will strongly suggest using it, as it will remove lots of unnecessary code from the action class.
Selenium 4 dependency:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.0.0</version>
</dependency>
Code with Selenium 4:
driver.get("https://www.google.co.in/");
driver.manage().window().maximize();
WebElement GoogleSearchTextBox = driver.findElement(By.xpath("//input[#title='Search']"));
GoogleSearchTextBox.sendKeys("test automation");
GoogleSearchTextBox.sendKeys(Keys.ENTER);
WebElement RequiredSearchResultLink = driver.findElement(By.xpath("//div[#class='EIaa9b']/div[1]/div[2]/a"));
String href = RequiredSearchResultLink.getAttribute("href");
driver.switchTo().newWindow(WindowType.TAB);
driver.get(href);
Thread.sleep(10);
driver.quit();
}
3 things you need to
Copy the link you need to open in new tab
Open new tab
Paste your link
driver.switchTo().newWindow(WindowType.TAB);
driver.get("your new lin");

Login Pop-Up Using Selenium Webdriver

How do I handle the login pop up window using Selenium Webdriver 4.0 beta? Here's my scenario:
Navigate to web app.
Web app detects I am not logged in, and redirects to an SSO site
SSO site then detects I am not logged in, and shows a login popup window.
Redirected back to web app on successful login.
P.S.: I have tried the different solutions offered in previous similar questions but nothing seems to work for me. Code below (I am quite new to Selenium testing so any pointers will be appreciated).
public class LoginTest {
public static void main(String[] args){
//Setting the driver path
System.setProperty("webdriver.chrome.driver", "C:\\path");
//Creating WebDriver instance
WebDriver driver = new ChromeDriver();
//Navigate to web page
driver.get("https://url");
//Maximising window
driver.manage().window().maximize();
//Locating web element
WebElement username = driver.findElement(By.id("email"));
WebElement password = driver.findElement(By.name("password"));
WebElement login = driver.findElement(By.name("submit"));
//Performing actions on web elements
username.sendKeys("email");
password.sendKeys("password");
login.click();
//Closing browser session
driver.quit();
}
}
Then you should give it a try using explicitWait
public static void main(String[] args) throws InterruptedException {
WebDriver driver = new ChromeDriver();
//Navigate to web page
driver.get("https://url");
//Maximising window
driver.manage().window().maximize();
//Locating web element and performing the action
new WebDriverWait(driver,10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("email"))).sendKeys("");
new WebDriverWait(driver,10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("password"))).sendKeys("");
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("submit"))).click();
//Closing browser session
driver.quit();
}
}

About Automated testing, huge number of steps and perfomance issues [duplicate]

I am trying to check if web page is loaded completed or not (i.e. checking that all the control is loaded) in selenium.
I tried below code:
new WebDriverWait(firefoxDriver, pageLoadTimeout).until(
webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
but even if page is loading above code does not wait.
I know that I can check for particular element to check if its visible/clickable etc but I am looking for some generic solution
As you mentioned if there is any generic function to check if the page has completely loaded through Selenium the answer is No.
First let us have a look at your code trial which is as follows :
new WebDriverWait(firefoxDriver, pageLoadTimeout).until(webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
The parameter pageLoadTimeout in the above line of code doesn't really reseambles to actual pageLoadTimeout().
Here you can find a detailed discussion of pageLoadTimeout in Selenium not working
Now as your usecase relates to page being completely loaded you can use the pageLoadStrategy() set to normal [ the supported values being none, eager or normal ] using either through an instance of DesiredCapabilities Class or ChromeOptions Class as follows :
Using DesiredCapabilities Class :
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
public class myDemo
{
public static void main(String[] args) throws Exception
{
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
DesiredCapabilities dcap = new DesiredCapabilities();
dcap.setCapability("pageLoadStrategy", "normal");
FirefoxOptions opt = new FirefoxOptions();
opt.merge(dcap);
WebDriver driver = new FirefoxDriver(opt);
driver.get("https://www.google.com/");
System.out.println(driver.getTitle());
driver.quit();
}
}
Using ChromeOptions Class :
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.PageLoadStrategy;
public class myDemo
{
public static void main(String[] args) throws Exception
{
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
FirefoxOptions opt = new FirefoxOptions();
opt.setPageLoadStrategy(PageLoadStrategy.NORMAL);
WebDriver driver = new FirefoxDriver(opt);
driver.get("https://www.google.com/");
System.out.println(driver.getTitle());
driver.quit();
}
}
You can find a detailed discussion in Page load strategy for Chrome driver (Updated till Selenium v3.12.0)
Now setting PageLoadStrategy to NORMAL and your code trial both ensures that the Browser Client have (i.e. the Web Browser) have attained 'document.readyState' equal to "complete". Once this condition is fulfilled Selenium performs the next line of code.
You can find a detailed discussion in Selenium IE WebDriver only works while debugging
But the Browser Client attaining 'document.readyState' equal to "complete" still doesn't guarantees that all the JavaScript and Ajax Calls have completed.
To wait for the all the JavaScript and Ajax Calls to complete you can write a function as follows :
public void WaitForAjax2Complete() throws InterruptedException
{
while (true)
{
if ((Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")){
break;
}
Thread.sleep(100);
}
}
You can find a detailed discussion in Wait for ajax request to complete - selenium webdriver
Now, the above two approaches through PageLoadStrategy and "return jQuery.active == 0" looks to be waiting for indefinite events. So for a definite wait you can induce WebDriverWait inconjunction with ExpectedConditions set to titleContains() method which will ensure that the Page Title (i.e. the Web Page) is visible and assume the all the elements are also visible as follows :
driver.get("https://www.google.com/");
new WebDriverWait(driver, 10).until(ExpectedConditions.titleContains("partial_title_of_application_under_test"));
System.out.println(driver.getTitle());
driver.quit();
Now, at times it is possible though the Page Title will match your Application Title still the desired element you want to interact haven't completed loading. So a more granular approach would be to induce WebDriverWait inconjunction with ExpectedConditions set to visibilityOfElementLocated() method which will make your program wait for the desired element to be visible as follows :
driver.get("https://www.google.com/");
WebElement ele = new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("xpath_of_the_desired_element")));
System.out.println(ele.getText());
driver.quit();
References
You can find a couple of relevant detailed discussions in:
Selenium IE WebDriver only works while debugging
Selenium how to manage wait for page load?
I use selenium too and I had the same problem, to fix that I just wait also for the jQuery to load.
So if you have the same issue try this also
((Long) ((JavascriptExecutor) browser).executeScript("return jQuery.active") == 0);
You can wrap both function in a method and check until both page and jQuery is loaded
Implement this, Its working for many of us including me. It includes Web Page wait on JavaScript, Angular, JQuery if its there.
If your Application is containing Javascript & JQuery you can write code for only those,
By define it in single method and you can Call it anywhere:
// Wait for jQuery to load
{
ExpectedCondition<Boolean> jQueryLoad = driver -> ((Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active") == 0);
boolean jqueryReady = (Boolean) js.executeScript("return jQuery.active==0");
if (!jqueryReady) {
// System.out.println("JQuery is NOT Ready!");
wait.until(jQueryLoad);
}
wait.until(jQueryLoad);
}
// Wait for ANGULAR to load
{
String angularReadyScript = "return angular.element(document).injector().get('$http').pendingRequests.length === 0";
ExpectedCondition<Boolean> angularLoad = driver -> Boolean.valueOf(((JavascriptExecutor) driver).executeScript(angularReadyScript).toString());
boolean angularReady = Boolean.valueOf(js.executeScript(angularReadyScript).toString());
if (!angularReady) {
// System.out.println("ANGULAR is NOT Ready!");
wait.until(angularLoad);
}
}
// Wait for Javascript to load
{
ExpectedCondition<Boolean> jsLoad = driver -> ((JavascriptExecutor) driver).executeScript("return document.readyState").toString()
.equals("complete");
boolean jsReady = (Boolean) js.executeScript("return document.readyState").toString().equals("complete");
// Wait Javascript until it is Ready!
if (!jsReady) {
// System.out.println("JS in NOT Ready!");
wait.until(jsLoad);
}
}
Click here for Reference Link
Let me know if you stuck anywhere by implementing.
It overcomes the use of Thread or Explicit Wait.
public static void waitForPageToLoad(long timeOutInSeconds) {
ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
};
try {
System.out.println("Waiting for page to load...");
WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeOutInSeconds);
wait.until(expectation);
} catch (Throwable error) {
System.out.println(
"Timeout waiting for Page Load Request to complete after " + timeOutInSeconds + " seconds");
}
}
Try this method
This works for me well with dynamically rendered websites:
Wait for complete page to load
WebDriverWait wait = new WebDriverWait(driver, 50);
wait.until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
Make another implicit wait with a dummy condition which would always fail
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + "This text will always fail :)" + "')]"))); // condition you are certain won't be true
}
catch (TimeoutException te) {
}
Finally, instead of getting the html source - which would in most of one page applications would give you a different result , pull the outerhtml of the first html tag
String script = "return document.getElementsByTagName(\"html\")[0].outerHTML;";
content = ((JavascriptExecutor) driver).executeScript(script).toString();
There is a easy way to do it. When you first request the state via javascript, it tells you that the page is complete, but after that it enters the state loading. The first complete state was the initial page!
So my proposal is to check for a complete state after a loading state. Check this code in PHP, easily translatable to another language.
$prevStatus = '';
$checkStatus = function ($driver) use (&$prevStatus){
$status = $driver->executeScript("return document.readyState");
if ($prevStatus=='' && $status=='loading'){
//save the previous status and continue waiting
$prevStatus = $status;
return false;
}
if ($prevStatus=='loading' && $status=='complete'){
//loading -> complete, stop waiting, it is finish!
return true;
}
//continue waiting
return false;
};
$this->driver->wait(20, 150)->until($checkStatus);
Checking for a element to be present also works well, but you need to make sure that this element is only present in the destination page.
Something like this should work (please excuse the python in a java answer):
idle = driver.execute_async_script("""
window.requestIdleCallback(() => {
arguments[0](true)
})
""")
This should block until the event loop is idle which means all assets should be loaded.

Having trouble with SkipException, testNG, what am I doing wrong?

I am very new to selenium UI automation and I am trying my hands on with a simple application. I am using java with testNG. I need to integrate this test with CI and the test environment url will be different with every deployment. I am passing this as a parameter, difference between test and prod environment is that in the test, there won't be any login screen hence there is no need for authentication but my test verifies login and a login method. I need to be able to skip this test based on the URL supplied. Here is my code and the problem is testNG always suggests that the test was skipped but I can see it executing the login method. Please help me correct or understand what mistake I am committing.
public class Login {
WebDriver driver;
//Parameter - test environment URL
String url = System.getProperty("environment");
#Test (priority = 1)
public void verifyLogin() {
//Skip verifyLogin test in non prod environments
System.setProperty("webdriver.chrome.driver", "C://chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get(url);
if (url=="www.google.com")
//If url matches production url then execute the test, if url doesn't match production URL then skip login test as there won't be any authentication/login in non prod
{
LoginPage login = new LoginPage(driver);
login.signIn();
Assert.assertEquals(driver.getTitle(), "Application Name", "Login failed,");
String title = driver.getTitle();
System.out.println("Page title is " + title);
driver.close();
}
else if (url!="www.google.com"){
throw new SkipException("Skipping this test");
}
}
#Test(priority = 2)
public void userKey() {
System.setProperty("webdriver.chrome.driver", "C://chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get(url);
//If URL equals prod then call the login method to be able to login to the app else just execute the userKey method without having the need to login
if (url=="www.google.com");
{
LoginPage login = new LoginPage(driver);
login.signIn();
}
AccountManagementPage userKey = new AccountManagementPage(driver);
userKey.key();
driver.close();
}
}
The very exact use case is well explained here without throwing SkipException.
The idea is to create a custom annotation for the methods to be skipped & read the methods using IMethodInterceptor - decide to execute or not behind the scenes.
Updated for the question in the comment section:
You do not have to worry about 'TestEnvironment' or 'TestParameters' class.Just directly use the production check logic here.
Predicate<IMethodInstance> isTestExecutingOnProduction = (tip) -> {
return system.getProperty("env").
.equals("<production check here>");
};

Web driver is not performing actions on web page

I'm automating a php web page using webdriver and java language. My code was executing and I was able to perform actions on web page, but today only the login method is executing and my second method gets failed everytime I run. I'm so worried why it is happening. Please help, I'm new in automation testing.
public class TestNGClass {
private String baseUrl = "http://test.com/test2/1.4.6.3/public/admin/";
private WebDriver driver = new FirefoxDriver();
#Test
public void login() {
driver.manage().window().maximize();
driver.get(baseUrl);
driver.findElement(By.name("username")).sendKeys("abc");
driver.findElement(By.name("password")).sendKeys("123");
driver.findElement(By.name("login")).submit();
System.out.print("\nCongrats..You have successfully logged in.");
}
#Test
public void createUser() {
String expectedTitle = "User";
String actualTitle = driver.getTitle();
Assert.assertEquals(actualTitle, expectedTitle,"Title Not Found!");
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.findElement(By.xpath("//body/div[3]/div[2]/ul/li[2]/a/img")).click();
Error :
java.lang.AssertionError: Title Not Found! expected [User] but found []
This is because you are using Assert.
Assert.assertEquals(actualTitle, expectedTitle,"Title Not Found!");
Make use of Try catch in-order to proceed next step.
try{
Assert.assertEquals(actualTitle, expectedTitle,"Title Not Found!");
}catch (Exception e)
{
}

Categories