Selenium - webdriver Test if-else loop stuck/error - java

I am trying to fill up a dynamic from which is automatically generated with user info. So I want to set if else condition for field of the from. So i use if else loop in step defenition but suppose if condition true its ok the code excute but if "if condition fail the code stuck in else loop why.Please help
The code is below
#And("^Input Height in add report$")
public void Input_Height_in_add_report(DataTable newHeight) throws Throwable {
if(driver.findElement(By.xpath("//label//span[contains(text(),'Height')]")).isDisplayed()){
Thread.sleep(2000);
List<List<String>> data = newHeight.raw();
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[2]/form/div[7]/div[1]/div/div/input")).sendKeys(data.get(1).get(1));
}
else{
}
}

The problem is that if findElement finds the element it goes if statement but if it doenst find the element it gives NosuchElementFound exception. To handle this yo can use try-catch block to run code in the else, check the following:
#And("^Input Height in add report$")
public void Input_Height_in_add_report(DataTable newHeight) throws Throwable {
try {
if(driver.findElement(By.xpath("//label//span[contains(text(),'Height')]")).isDisplayed()){
Thread.sleep(2000);
List<List<String>> data = newHeight.raw();
driver.findElement(By.xpath("/html/body/div[1]/div/div/div[2]/form/div[7]/div[1]/div/div/input")).sendKeys(data.get(1).get(1));
}
}
catch(Exception e) {
// your else code should be here
}
}

Related

Selenium click function is not getting Fail

The below code is written for click function.
public void click(By element) {
try {
driver.findElement(element).click();
}
catch (AssertionError e) {
System.out.println("Element " + element + " not found on page");
return;
}
}
The below code is written for calling the click function in my test case.
#Test(priority = 1)
public void accept_cookies_dialog() throws Exception {
try {
click(By.id(propObjctRepo.getProperty("id_cookieCta")));
} catch (Exception e) {
addErrorlogs(e, "Not found accpet cookie dialog.");
}
}
My concern is, In every case either the element present or not the test case is getting pass. I am doing something wrong, Please suggest me the solution.
Instead of using try/catch block, you can directly use assertions to check if the element is present on the page or not. If the list size of the element is greater than zero then the element is present on the page else it is not. By this, if the element is not present on the page, assertion will fail and so will the test case.
You can do it like:
Assert.assertTrue(driver.findElements(By.id(propObjctRepo.getProperty("id_cookieCta"))).size()>0);
And then below this you can click the element, so if and only if the assertion passes, your code will reach the click method else your test case will fail.

Selenium- exception instead of boolean value

I write a code where I have found the result element visible or not, but I have received an exception.
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']"}
Here is my code
wd.navigate().refresh();
Thread.sleep(7000);
boolean airbnb = wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed();
assertFalse(airbnb, "Airbnb Add will not show After clicking Add one times");
Is there any suggestion why element not found showing? if element not found then it should be false I am not sure where I mistake?
To avoid an exception, and expensive use of try - catch, you can locate the element using findElements. If the result list is not empty you can check if the existed element is displayed or not
List<WebElement> elements = wd.findElements(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']"));
assertFalse(elements.size() > 0 && elements.get(0).isDisplayed(), "Airbnb Add will not show After clicking Add one times");
Either use try- catch block or use throws Exception to catch the NoSuchElementException
public void methodName() throws Exception
{
if(wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed())
{
System.out.println("Element displayed");
}
}
or
try
{
if(wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed())
{
System.out.println("Element displayed");
}
}
catch(NoSuchElementException e)
{
System.out.println("Element is not displayed");
}
Since you do not expect the element to be there the following code would throw an exception :
boolean airbnb = wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed();
and your assert statement would not even be reached.
You can actually place an expected exception in your code instead of asserting as(in Junit):
#Test(expected = NoSuchElementException.class)
public void youtTest() {
// do whatever you're doing
Thread.sleep(7000);
wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']"));
}
in TestNG the syntax is somehwat like :
#Test(expectedExceptions = { NoSuchElementException.class })
This is the issue with Selenium, you need to use try catch block something like below
try
{
if(wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed())
{
//Your code
}
}
catch (Exception e)
{
//Your code
}
Let me put it this way: IsDisplayed will work on Object of Type WebElement.
here is the clarification
findElement should not be used to look for non-present elements, use findElements(By) and assert zero length response instead.
found on findElement

Checking for `driver.findElement(...)` in an IF statement throws `NoSuchElementException`

I'm getting NoSuchElementException when running the following code.
if (driver.findElement(By.xpath("//*[#id='gr2']")).isDisplayed()) {
Thread.sleep(5000);
driver.findElement(By.xpath("//*[#id='balInqTableStep2']/td/table/tbody/tr/td/table/tbody/tr[3]/td[4]/input[2]")).click();
}
else {
test.log(LogStatus.FAIL,"Please configure Gift Slabs for this site. Contact business.");
test.log(LogStatus.FAIL,"Second time wallet credit is not done");
}
NoSuchElementException exception means there is not element present on the page.
isDisplayed method assumes that element is already present on the page and so throws you exception when element is not present.
you can either make sure that element is present before calling webdriver method and you can write your own method to handle this for you.
following code snippet might help you
public boolean isDisplayed(By identifier){
boolean isElementDisplayed = false;
try{
WebElement element = driver.findElement(identifier);
isElementDisplayed = element.isDisplayed()
}catch (NoSuchElementException){
return false;
}
return isElementDisplayed;
}
and you can call it like this
isDisplayed(By.xpath("//*[#id='gr2']")
Always when you call driver.findElement(By.xpath("//*[#id='gr2']")) and the element is not present in the DOM, it's gonna throw a NoSuchElementException.
There is an alternative to avoid the code throwing the exception, calling the method findElements, instead of findElement.
E.g.:
List<WebElement> elements = driver.findElements(By.xpath("//*[#id='gr2']"));
if(!elements.isEmpty() && elements.get(0).isDisplayed()) {
Thread.sleep(5000);
driver.findElement(By.xpath("//*[#id='balInqTableStep2']/td/table/tbody/tr/td/table/tbody/tr[3]/td[4]/input[2]")).click();
}
else {
test.log(LogStatus.FAIL,"Please configure Gift Slabs for this site. Contact business.");
test.log(LogStatus.FAIL,"Second time wallet credit is not done");
}
Hope it works for you.

if/else statement fail

I'm using if/else statements as below, but the script fails in Selenium WebDriver. Here, for one test case the if statement works but, for another test case, the else one doesn't.
if (driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--top")).isDisplayed()){
driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--top")).click();
}
else
{
driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--bottom")).click();
}
Im not good at Java, so im putting the steps. Give try.
1. First Find elements seperately.
2. Now check if 'top' is not null and then check for is displayed and can continue further .Pseudo code below
IWebElement top= driver.findelement( put you locator top here )
IWebElement bottom = driver.findelement( put you bottom here)
if(top!=null)
{
if(top.IsDisplayed)
{
top.click()
}
}
else
{
if(bottom!=null)
{
bottom.click()
}
}
we need to click on element "div.Tooltip__body.Tooltip__body--top" if it is displayed. if not then need to click on "div.Tooltip__body.Tooltip__body--bottom"
If we use .isDisplayed to check element displayed or not, in any case element is not there, it will throw exception. that's why we need to handle this exception by using try/catch.
try{
//if element is displayed, then click it
if (driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--top")).isDisplayed()==true){
driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--top")).click();
}
}catch(Exception e){
//exception occurred as element (top) is not available.
//so i need to click on bottom
driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--bottom")).click();
//if required we can collect exception : e.getMessage()
}
Thanks
try
{
if (driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--top")).isDisplayed()==true)
driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--top")).click();
}
catch(Exception ex)
{
driver.findElement(By.cssSelector("div.Tooltip__body.Tooltip__body--bottom")).click();
}

Selenium exception handling, problems

I have problems with Java Selenium. I use it to automate testing web page, which structure is very complicated - a lot of elements are loaded dynamically, there is a lot of unnecessary elements in html pages. It's very difficult to make my tests reliable. Sometimes page can't load or I try to click on the button which doesn't exist yet (in similiar method of course).
So, I wrote Util class with methods like this one:
public static void findAndSendKeys(String vToSet, By vLocator) {
log.info("findAndSendKeys " + vLocator.toString());
int attempts = 0;
while (attempts < ATTEMPTS) {
WebElement element = null;
try {
element = webDriverWait.until(ExpectedConditions.presenceOfElementLocated(vLocator));
element.sendKeys(vToSet);
break;
} catch (TimeoutException e) {
log.error("timeOut exception " + e.getMessage());
} catch (StaleElementReferenceException e) {
log.error("StaleElementReference exception " + e.getMessage());
} catch (UnhandledAlertException e) {
log.error("UnhandledAlert exception " + e.getMessage());
Alert alert = driver.switchTo().alert();
alert.accept();
}
attempts++;
}
}
I know it looks terrible, I didn't refactor it yet, but method usually works fine for most cases - on the second or third loop input field is filled.
Firstly I was using only sendKeys with exception handling, but I noticed that although input field exists, StaleElementReferenceException is thrown, so I put while() in this static method and try to sendKeys again.
Sometimes my webPage shows Alert that is just validation and after catching exception and ignoring alert I can continue work.
I wonder.. It could be easier if there would exist method similiar to "Pause 1000" method in Selenium IDE. Sometimes my web page works fast and good, sometimes page loading process is very long and I have to wait.
There is also problems with while() loop. I don't know what to do if while loop ends and nothing is send - for example loaded page/container is blank, dynamic loading fails, so there is no chance to find our input field
Automate testing process for this web page causes me a headache. Please, be placable, I don't have technical support and I am on my own.
In my opinion, you are trying to overengineer the whole thing. I think you are trying to write a single function that will handle all cases and I don't think that is a good approach. Each case is potentially different and you will need to understand each case and handle it appropriately.
A few tips.
Don't loop a wait.until(). Instead of
for (int i = 0; i < 5; i++)
{
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(...);
}
do
WebDriverWait wait = new WebDriverWait(driver, 50);
wait.until(...);
The end result is the same (max 50s wait) but the 2nd code is less confusing. Read up on waits to better understand them. The default behavior for a wait is to wait up to the max time and poll the condition every 500ms.
If you are getting StaleElementReferenceException, you are missing something. I don't mean that to sound critical... it happens. You need to understand how the HTML of the page is changing because you are looking for an element that is disappearing and then you try to scrape it. You will need to change either the element you are looking for or when you are looking for it.
Don't use Thread.sleep(). In general it's a bad practice because it's hard coded. Depending on the environment, it may be too long or not long enough of a wait. Instead prefer the wait.until() mechanism you are already using. The hard part, at times, is finding what to wait for.
If you are trying to scrape the page after the items are sorted, then you need to determine what changes after sorting occurs. Maybe there's an arrow on the column header that appears to indicate a sort direction (ascending vs descending)? One thing you could do is to grab one of the TD elements, wait for it to go stale (while the elements are being sorted), and then regrab all elements?
Maybe something like this
WebDriverWait wait = new WebDriverWait(driver, 10);
// grab the first TD as a stale reference
WebElement td = driver.findElement(By.tagName("td"));
// wait for it to go stale
wait.until(ExpectedConditions.stalenessOf(td));
// now grab them all and do something with them
List<WebElement> tds = driver.findElements(By.tagName("td"));
Without a link to the page or a lot more explanation of what is happening on the page and some relevant HTML, I'm not sure what else we can provide.
This code works for me:
jsPageLoadWait ="
try {
if (document.readyState !== 'complete') {
return false; // Page not loaded yet
}
if (window.jQuery) {
if (window.jQuery.active) {
return false;
} else if (window.jQuery.ajax && window.jQuery.ajax.active) {
return false;
} else if ($(':animated').length != 0) {
return false;
}
}
if (window.angular) {
if (!window.qa) {
// Used to track the render cycle finish after loading is complete
window.qa = {
doneRendering: false
};
}
// Get the angular injector for this app (change element if necessary)
var injector = window.angular.element('body').injector();
// Store providers to use for these checks
var $rootScope = injector.get('$rootScope');
var $http = injector.get('$http');
var $timeout = injector.get('$timeout');
// Check if digest
if ($rootScope.$$phase === '$apply' || $rootScope.$$phase === '$digest' || $http.pendingRequests.length !== 0) {
window.qa.doneRendering = false;
return false; // Angular digesting or loading data
}
if (!window.qa.doneRendering) {
// Set timeout to mark angular rendering as finished
$timeout(function() {
window.qa.doneRendering = true;
}, 0);
return false;
}
}
return true;
} catch (ex) {
return false;
}"
public static Boolean WaitLoad(this ISearchContext context, UInt32 timeoutInMilliseconds = 10000, UInt32 millisecondPolling = 1000)
{
Boolean waitReadyStateComplete;
var wait = new DefaultWait<ISearchContext>(context);
wait.Timeout = TimeSpan.FromMilliseconds(timeoutInMilliseconds);
wait.PollingInterval = TimeSpan.FromMilliseconds(millisecondPolling);
wait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(StaleElementReferenceException));
waitReadyStateComplete = wait.Until<Boolean>(ctx =>
{
if ((Boolean)((IJavaScriptExecutor)context).ExecuteScript(jsPageLoadWait))
return true;
else
return false;
});
return waitReadyStateComplete;
}

Categories