Continue if element not found, if found save it - java

I have a loop, where I open links one by one. Inside this loop I have the if statement, which checks:
If I see name, then I copy it
If I don't see name, then I ignore it and continue looping.
List<WebElement> demovar = driver.findElements(By.xpath("//*[#id=\"big_icon_view\"]/ul/li/p/a"));
System.out.println(demovar.size());
ArrayList<String> hrefs = new ArrayList<String>();
for (WebElement var : demovar) {
System.out.println(var.getText());
System.out.println(var.getAttribute("href"));
hrefs.add(var.getAttribute("href"));
}
int i = 0;
for (String href : hrefs) {
driver.navigate().to(href);
System.out.println((++i) + ": navigated to URL with href: " + href);
if(driver.findElement(By.xpath("//a[#id='name']")).isDisplayed()) {
System.out.println("I can see Name");
} else {
System.out.println("I cant see Name");
}
Thread.sleep(3000); // To check if the navigation is happening properly.
}
Why is this not working properly? As I assume, it should have the following:
If the element is displayed then I can see Name
else the element is NOT displayed, then I cannot see Name.

I'm not sure what error message you are seeing here, but if your code is not working then it's quite likely the element is not displayed on the page, so you will receive an exception when attempting to locate it.
You can catch the NoSuchElementException to handle the case where the element does not appear on the page.
for (String href : hrefs) {
driver.navigate().to(href);
System.out.println((++i) + ": navigated to URL with href: " + href);
// create isDisplayed variable
boolean isDisplayed = true;
try {
isDisplayed = driver.findElement(By.xpath("//a[#id='name']")).isDisplayed();
}
catch(NoSuchElementException) {
isDisplayed = false;
}
// do something else here with isDisplayed
if (isDisplayed) { System.out.println("I can see Name"); }
else { System.out.println("I can not see Name"); }
}
This code does almost the same thing as yours, but we catch the NoSuchElementException that gets thrown if the element does not appear on the page.
If this does not work for you, feel free to post the error message or results you are seeing in your code, it'll help track down the issue.

API of the findElement(By by) in the Interface WebDriver states the following
"Find the first WebElement using the given method. This method is affected by the 'implicit wait' times in force at the time of execution. The findElement(..) invocation will return a matching row, or try again repeatedly until the configured timeout is reached. findElement should not be used to look for non-present elements, use findElements(By) and assert zero length response instead."
Which means that in case if the element is not found it keeps trying until configured timeout and throws the exception NoSuchElementException - If no matching elements are found
Hence it would be better to handle in the following ways
Using FindElements which returns a list of all WebElements, or an empty list if nothing matches as follows:
if(driver.findElements(By.ByXPath).size()<0)
Using a try/catch/finally to catch the NoSuchElementException and a boolean flag to determine if its present or not. The boolean flag can be set to false in case if exception is caught.

After #Christine help, i did a solution for me
for (String href : hrefs) {
driver.navigate().to(href);
boolean isPresent = driver.findElements(By.xpath("element")).size() > 0;
if (isPresent) {
String test = driver.findElement(By.xpath("element")).getText();
System.out.println(test);
} else {
System.out.println("Name not found");
}
Thread.sleep(3000); // To check if the navigation is happening properly.
}
}
}
And this is working fine =)

Related

Trying to resolve StaleElementReferenceException error [duplicate]

I am implementing a lot of Selenium tests using Java - sometimes, my tests fail due to a StaleElementReferenceException.
Could you suggest some approaches to making the tests more stable?
This can happen if a DOM operation happening on the page is temporarily causing the element to be inaccessible. To allow for those cases, you can try to access the element several times in a loop before finally throwing an exception.
Try this excellent solution from darrelgrainger.blogspot.com:
public boolean retryingFindClick(By by) {
boolean result = false;
int attempts = 0;
while(attempts < 2) {
try {
driver.findElement(by).click();
result = true;
break;
} catch(StaleElementException e) {
}
attempts++;
}
return result;
}
I was having this issue intermittently. Unbeknownst to me, BackboneJS was running on the page and replacing the element I was trying to click. My code looked like this.
driver.findElement(By.id("checkoutLink")).click();
Which is of course functionally the same as this.
WebElement checkoutLink = driver.findElement(By.id("checkoutLink"));
checkoutLink.click();
What would occasionally happen was the javascript would replace the checkoutLink element in between finding and clicking it, ie.
WebElement checkoutLink = driver.findElement(By.id("checkoutLink"));
// javascript replaces checkoutLink
checkoutLink.click();
Which rightfully led to a StaleElementReferenceException when trying to click the link. I couldn't find any reliable way to tell WebDriver to wait until the javascript had finished running, so here's how I eventually solved it.
new WebDriverWait(driver, timeout)
.ignoring(StaleElementReferenceException.class)
.until(new Predicate<WebDriver>() {
#Override
public boolean apply(#Nullable WebDriver driver) {
driver.findElement(By.id("checkoutLink")).click();
return true;
}
});
This code will continually try to click the link, ignoring StaleElementReferenceExceptions until either the click succeeds or the timeout is reached. I like this solution because it saves you having to write any retry logic, and uses only the built-in constructs of WebDriver.
Kenny's solution is good, however it can be written in a more elegant way
new WebDriverWait(driver, timeout)
.ignoring(StaleElementReferenceException.class)
.until((WebDriver d) -> {
d.findElement(By.id("checkoutLink")).click();
return true;
});
Or also:
new WebDriverWait(driver, timeout).ignoring(StaleElementReferenceException.class).until(ExpectedConditions.elementToBeClickable(By.id("checkoutLink")));
driver.findElement(By.id("checkoutLink")).click();
But anyway, best solution is to rely on Selenide library, it handles this kind of things and more. (instead of element references it handles proxies so you never have to deal with stale elements, which can be quite difficult). Selenide
Generally this is due to the DOM being updated and you trying to access an updated/new element -- but the DOM's refreshed so it's an invalid reference you have..
Get around this by first using an explicit wait on the element to ensure the update is complete, then grab a fresh reference to the element again.
Here's some psuedo code to illustrate (Adapted from some C# code I use for EXACTLY this issue):
WebDriverWait wait = new WebDriverWait(browser, TimeSpan.FromSeconds(10));
IWebElement aRow = browser.FindElement(By.XPath(SOME XPATH HERE);
IWebElement editLink = aRow.FindElement(By.LinkText("Edit"));
//this Click causes an AJAX call
editLink.Click();
//must first wait for the call to complete
wait.Until(ExpectedConditions.ElementExists(By.XPath(SOME XPATH HERE));
//you've lost the reference to the row; you must grab it again.
aRow = browser.FindElement(By.XPath(SOME XPATH HERE);
//now proceed with asserts or other actions.
Hope this helps!
The reason why the StaleElementReferenceException occurs has been laid out already: updates to the DOM between finding and doing something with the element.
For the click-Problem I've recently used a solution like this:
public void clickOn(By locator, WebDriver driver, int timeout)
{
final WebDriverWait wait = new WebDriverWait(driver, timeout);
wait.until(ExpectedConditions.refreshed(
ExpectedConditions.elementToBeClickable(locator)));
driver.findElement(locator).click();
}
The crucial part is the "chaining" of Selenium's own ExpectedConditions via the ExpectedConditions.refreshed(). This actually waits and checks if the element in question has been refreshed during the specified timeout and additionally waits for the element to become clickable.
Have a look at the documentation for the refreshed method.
In my project I introduced a notion of StableWebElement. It is a wrapper for WebElement which is able to detect if element is Stale and find a new reference to the original element. I have added a helper methods to locating elements which return StableWebElement instead of WebElement and the problem with StaleElementReference disappeared.
public static IStableWebElement FindStableElement(this ISearchContext context, By by)
{
var element = context.FindElement(by);
return new StableWebElement(context, element, by, SearchApproachType.First);
}
The code in C# is available on my project's page but it could be easily ported to java https://github.com/cezarypiatek/Tellurium/blob/master/Src/MvcPages/SeleniumUtils/StableWebElement.cs
A solution in C# would be:
Helper class:
internal class DriverHelper
{
private IWebDriver Driver { get; set; }
private WebDriverWait Wait { get; set; }
public DriverHelper(string driverUrl, int timeoutInSeconds)
{
Driver = new ChromeDriver();
Driver.Url = driverUrl;
Wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(timeoutInSeconds));
}
internal bool ClickElement(string cssSelector)
{
//Find the element
IWebElement element = Wait.Until(d=>ExpectedConditions.ElementIsVisible(By.CssSelector(cssSelector)))(Driver);
return Wait.Until(c => ClickElement(element, cssSelector));
}
private bool ClickElement(IWebElement element, string cssSelector)
{
try
{
//Check if element is still included in the dom
//If the element has changed a the OpenQA.Selenium.StaleElementReferenceException is thrown.
bool isDisplayed = element.Displayed;
element.Click();
return true;
}
catch (StaleElementReferenceException)
{
//wait until the element is visible again
element = Wait.Until(d => ExpectedConditions.ElementIsVisible(By.CssSelector(cssSelector)))(Driver);
return ClickElement(element, cssSelector);
}
catch (Exception)
{
return false;
}
}
}
Invocation:
DriverHelper driverHelper = new DriverHelper("http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp", 10);
driverHelper.ClickElement("input[value='csharp']:first-child");
Similarly can be used for Java.
Kenny's solution is deprecated use this, i'm using actions class to double click but you can do anything.
new FluentWait<>(driver).withTimeout(30, TimeUnit.SECONDS).pollingEvery(5, TimeUnit.SECONDS)
.ignoring(StaleElementReferenceException.class)
.until(new Function() {
#Override
public Object apply(Object arg0) {
WebElement e = driver.findelement(By.xpath(locatorKey));
Actions action = new Actions(driver);
action.moveToElement(e).doubleClick().perform();
return true;
}
});
I've found solution here. In my case element becomes inaccessible in case of leaving current window, tab or page and coming back again.
.ignoring(StaleElement...), .refreshed(...) and elementToBeClicable(...) did not help and I was getting exception on act.doubleClick(element).build().perform(); string.
Using function in my main test class:
openForm(someXpath);
My BaseTest function:
int defaultTime = 15;
boolean openForm(String myXpath) throws Exception {
int count = 0;
boolean clicked = false;
while (count < 4 || !clicked) {
try {
WebElement element = getWebElClickable(myXpath,defaultTime);
act.doubleClick(element).build().perform();
clicked = true;
print("Element have been clicked!");
break;
} catch (StaleElementReferenceException sere) {
sere.toString();
print("Trying to recover from: "+sere.getMessage());
count=count+1;
}
}
My BaseClass function:
protected WebElement getWebElClickable(String xpath, int waitSeconds) {
wait = new WebDriverWait(driver, waitSeconds);
return wait.ignoring(StaleElementReferenceException.class).until(
ExpectedConditions.refreshed(ExpectedConditions.elementToBeClickable(By.xpath(xpath))));
}
Clean findByAndroidId method that gracefully handles StaleElementReference.
This is heavily based off of jspcal's answer but I had to modify that answer to get it working cleanly with our setup and so I wanted to add it here in case it's helpful to others. If this answer helped you, please go upvote jspcal's answer.
// This loops gracefully handles StateElementReference errors and retries up to 10 times. These can occur when an element, like a modal or notification, is no longer available.
export async function findByAndroidId( id, { assert = wd.asserters.isDisplayed, timeout = 10000, interval = 100 } = {} ) {
MAX_ATTEMPTS = 10;
let attempt = 0;
while( attempt < MAX_ATTEMPTS ) {
try {
return await this.waitForElementById( `android:id/${ id }`, assert, timeout, interval );
}
catch ( error ) {
if ( error.message.includes( "StaleElementReference" ) )
attempt++;
else
throw error; // Re-throws the error so the test fails as normal if the assertion fails.
}
}
}
StaleElementReferenceException
StaleElementReferenceException indicates that the reference to an element is now stale i.e. the element no longer appears within the HTML DOM of the page.
Details
Every DOM Tree element is identified by the WebDriver by a unique identifying reference, known as a WebElement. The web element reference is a UUID used to execute commands targeting specific elements, such as getting an element's tag name or retrieving a property off an element.
When an element is no longer attached to the DOM, i.e. it has been removed from the document or the document has changed, it is said to be got stale. Staleness occurs for example when you have a web element reference and the document it was retrieved from navigates and due to navigation, all web element references to the previous document will be discarded along with the document. This will cause any subsequent interaction with the web element to fail with the stale element reference error.
Solution
The best approach to avoid StaleElementReferenceException is to induce WebDriverWait for the elementToBeClickable() before invoking click as follows:
new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.elementToBeClickable(By.cssSelector("elementCssSelector"))).click();
Note: You have to import the following:
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.By;
Create a wrapper function (Java)
As an alternative to the accepted answer, my approach is similar in that it catches the exception and makes a few attempts, but it's more generic, so you can throw any kinds of actions at it as long as they are wrapped in a void function.
Please feel free to copy and use this code:
public void doPreventingStaleElement(Runnable function)
{
int maxRetries = 3; // maximum number of retries
int retries = 0;
boolean stale;
// try/catch block attempts to fix a stale element
do {
try {
function.run();
stale = false;
}
catch (StaleElementReferenceException eStale) {
stale = true;
// Work-around for stale element reference when getting the first page
if (retries < maxRetries) {
retries++;
System.out.println(function.getClass().getSimpleName() + " failed due to stale element reference, retry=" + retries);
try {
// Exponential increase of wait time - 1, 4, 9, 16, 25 seconds
Thread.sleep(1000 * (int) Math.pow(retries,2));
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
}
else {
System.out.println(function.getClass().getSimpleName() + " failed due to stale element reference, too many retries");
eStale.printStackTrace();
throw(eStale);
}
}
} while (stale && retries < maxRetries);
return;
}
Note that it will still throw a StaleElementReferenceException after maxRetries attempts.
Example of usage
As an example I want to do this:
final List<WebElement> buttons = getDriver().findElements(By.xpath("//button[#testid='dismiss-me']"));
for (final WebElement closeButton : buttons) {
closeButton.click();
}
or this:
driver.findElement(By.id("login-form-username")).sendKeys(getUser());
driver.findElement(By.id("login-form-password")).sendKeys(getPassword());
driver.findElement(By.id("login-form-submit")).click();
Then I wrap them in void functions
private void clickButtons() {
final List<WebElement> buttons = getDriver().findElements(By.xpath("//button[#testid='dismiss-me']"));
for (final WebElement closeButton : buttons) {
closeButton.click();
}
}
private void performLogin() {
driver.findElement(By.id("login-form-username")).sendKeys(getUser());
driver.findElement(By.id("login-form-password")).sendKeys(getPassword());
driver.findElement(By.id("login-form-submit")).click();
}
and so I can just
doPreventingStaleElement(whateverObject::clickButtons);
doPreventingStaleElement(whateverObject::performLogin);
Try this
while (true) { // loops forever until break
try { // checks code for exceptions
WebElement ele=
(WebElement)wait.until(ExpectedConditions.elementToBeClickable((By.xpath(Xpath))));
break; // if no exceptions breaks out of loop
}
catch (org.openqa.selenium.StaleElementReferenceException e1) {
Thread.sleep(3000); // you can set your value here maybe 2 secs
continue; // continues to loop if exception is found
}
}
There could be a potential problem that leads to the StaleElementReferenceException that no one mentioned so far (in regard to actions).
I explain it in Javascript, but it's the same in Java.
This won't work:
let actions = driver.actions({ bridge: true })
let a = await driver.findElement(By.css('#a'))
await actions.click(a).perform() // this leads to a DOM change, #b will be removed and added again to the DOM.
let b = await driver.findElement(By.css('#b'))
await actions.click(b).perform()
But instantiating the actions again will solve it:
let actions = driver.actions({ bridge: true })
let a = await driver.findElement(By.css('#a'))
await actions.click(a).perform() // this leads to a DOM change, #b will be removed and added again to the DOM.
actions = driver.actions({ bridge: true }) // new
let b = await driver.findElement(By.css('#b'))
await actions.click(b).perform()
Usually StaleElementReferenceException when element we try to access has appeared but other elements may affect the position of element we are intrested in hence when we try to click or getText or try to do some action on WebElement we get exception which usually says element not attached with DOM.
Solution I tried is as follows:
protected void clickOnElement(By by) {
try {
waitForElementToBeClickableBy(by).click();
} catch (StaleElementReferenceException e) {
for (int attempts = 1; attempts < 100; attempts++) {
try {
waitFor(500);
logger.info("Stale element found retrying:" + attempts);
waitForElementToBeClickableBy(by).click();
break;
} catch (StaleElementReferenceException e1) {
logger.info("Stale element found retrying:" + attempts);
}
}
}
protected WebElement waitForElementToBeClickableBy(By by) {
WebDriverWait wait = new WebDriverWait(getDriver(), 10);
return wait.until(ExpectedConditions.elementToBeClickable(by));
}
In above code I first try to wait and then click on element if exception occurs then I catch it and try to loop it as there is a possibility that still all elements may not be loaded and again exception can occur.
This works for me using C#
public Boolean RetryingFindClick(IWebElement webElement)
{
Boolean result = false;
int attempts = 0;
while (attempts < 2)
{
try
{
webElement.Click();
result = true;
break;
}
catch (StaleElementReferenceException e)
{
Logging.Text(e.Message);
}
attempts++;
}
return result;
}
The problem is by the time you pass the element from Javascript to Java back to Javascript it can have left the DOM.
Try doing the whole thing in Javascript:
driver.executeScript("document.querySelector('#my_id')?.click()")
Maybe it was added more recently, but other answers fail to mention Selenium's implicit wait feature, which does all the above for you, and is built into Selenium.
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
This will retry findElement() calls until the element has been found, or for 10 seconds.
Source - http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp

Selenium, default values assigned to web elements instead of the ones i am search for

I am sending text to an input field then within the array of elements searching for specific by checking if element text equal street address
As you can see i have Thread sleep which is not the right approach, the reason i am using this is because i am not to sure how to proceed with the current state of the default values.
When i click on input field there are some values by default within the web elements i am locating which means if i remove Thread sleep it will fail due to the fact that the default values will be assigned to the web elements so i am wondering what can i do in such case
Since i know the default values i could potential just find one and wait until it disappears but thinking if there is a better approach to deal with it
default values on input click
the text i am then entering
public LocatedCarParksMap searchForCarPark(String carPark,String location) {
clickOnSearchInput();
searchCarPark.sendKeys(carPark);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (WebElement i : locatedCarParkAddresses) {
if(i.getText().equals(location)){
click(i);
}
}
return new LocatedCarParksMap(driver);
}
You can look for some loaders that are appearing in between you enter the search text and the search result appearance. You can wait for that loader to vanish. After that, you can look for your search results.
Even if you have/don't have loader, this similar FluentWait approach should work:
public LocatedCarParksMap searchForCarPark(String carPark,String location) {
clickOnSearchInput();
searchCarPark.sendKeys(carPark);
//If loader available, write code here to wait for your loader to vanish. Just a simple invisibilityOf should work.
boolean clickStatus = waitAndClickSearchElement(location);
if(! clickStatus) {
throw new Exception(carPark + " is not available in Search Results");
}
return new LocatedCarParksMap(driver);
}
public boolean waitAndClickSearchElement() {
try {
//Change this timeout of 10 sec according to your need.
WebDriverWait webDriverWait = new WebDriverWait(driver,10);
//Increased the polling time to 2 secs to avoid checking the results frequently.
webDriverWait.pollingEvery(Duration.ofSeconds(2))
//Ignoring these 2 exceptions as they are more likely to occur.
webDriverWait.ignoring(NoSuchElementException.class, StaleElementReferenceException.class);
//This until method keeps checking the text for 10 secs. Once it finds the element, will click on it.
return webDriverWait.until(driver -> {
for (WebElement weAddress : locatedCarParkAddresses) {
if(weAddress.getText().equals(location)){
weAddress.click();
return true;
}
}
return false;
});
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
There is one edge case here. Lets say your expected search result is already part of default search results, the above code may throw StaleElementReferenceException. But we have handled it so I hope it would work fine. Please let me know if you have any issues.

Doing some standard validation to web element before doing the actual action

As the title suggest, I'm doing some standard checking of an web element before the actual action. Check like if the element is displayed and enabled. I want to separate the the two checking because I want a specific reason why it fail. I feel the code below is too long.
Any suggestion would be appreciated.
Boolean isActionSuccess = false;
if (currentObject.isDisplayed()) {
if (currentObject.isEnabled()) {
// move to the object before clicking
CommonFunctions.silentWait(1);
actionToE.moveToElement(currentObject).perform();
if (!actionPar.isEmpty()) {
// do something else
} else {
currentObject.sendKeys(Keys.ARROW_UP);
isActionSuccess = true;
}
} else {
System.out.println("Web Element is disabled!");
}
} else {
System.out.println("Web Element is not displayed!");
}
Your best course of action here will be to separate them into their own little functions and return boolean.
Like
Boolean isElementDisplayed(WebElement element){
if (element.isDisplayed())
return true;
System.out.println(element + " is not displayed!");
return false;
}
Boolean isElementEnabled(WebElement element){
if (element.isEnabled())
return true;
System.out.println(element + " is not enabled!");
return false;
}
But I will also suggest to call isElementDisplayed after moveToElement is performed because some browsers consider differently what "displayed" means.
You can also use try catch to log the exceptions per function.
Boolean isActionSuccess = false;
CommonFunctions.silentWait(1);
actionToE.moveToElement(currentObject).perform();
if (CommonFunctions.isElementDisplayed(currentObject)) {
if (CommonFunctions.isElementEnabled(currentObject)) {
if (!actionPar.isEmpty()) {
// do something
}
} else {
currentObject.sendKeys(Keys.ARROW_LEFT);
isActionSuccess = true;
}
}
}
While using Selenium to execute the Automated Tests you don't need any sort of additional standard checking of an web element before the actual action. For the record, each extra line of code will induce extra instructions and instruction cycles. Instead you need to optimize your code/program.
If your usecase is to invoke click() or sendKeys() you don't need to invoke isDisplayed() or isEnabled() separately to check. Instead you need to wait for a predefined time period (as per the Test Specification) using WebDriverWait inconjunction with ExpectedConditions.
Example:
presenceOfElementLocated() is an expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
new WebDriverWait(driver, 20).until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("button.nsg-button")));
visibilityOfElementLocated() is an expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0.
new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("button.nsg-button")));
elementToBeClickable() is an expectation for checking an element is visible and enabled such that you can click it.
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//button[#class='nsg-button']"))).click();

Amazon login and logout scenario using selenium webdriver

I am new to selenium.
I am trying to automate amazon login and log out.
I am facing couple of problems.
1.In login page the button "continue" appears after username when I try to login for first time.
But later when I try to login for second time , its does not appear.
How to handle this.
Here is the code I have written so far:
public void logindetails()
{
Datafile d=new Datafile("C:\\Users\\kirruPC\\selenium divers\\Data.xlsx",0);
String uname= d.username(0, 0);
WebElement u=driver.findElement(useid);
u.sendKeys(uname);
u.click();
if(driver.findElement(By.xpath(".//*[#id='continue']")).isDisplayed()==true)
{
driver.findElement(By.id("continue")).click();
String psw=d.pass(0,1);
driver.findElement(password).sendKeys(psw);
}
else
{
String psw=d.pass(0,1);
driver.findElement(password).sendKeys(psw);
}
}
Unable to locate sign Out element.
Below is the code I have written to move to sign out link and click:
public void logout() throws Exception
{
Actions a= new Actions(driver);
WebElement ele=driver.findElement(By.xpath(".//*[#id='nav-link-accountList']"));
a.moveToElement(ele).build().perform();
driver.findElement(By.xpath(".//*[#id='nav-al-your-account']"));
Thread.sleep(3000);
driver.findElement(By.xpath(".//*[#id='nav-al-your-account']/a[22]")).click();
}
Please help me
Thanks in advance
First of all, there is a high change that the element you are searching for might not exist at all in the page, so first let's check if the element exist (if the element does not exist, an exception is thrown, so let's add a handle for that as well). For all that, create a function like so:
public bool ElementExists(By locator)
{
try
{
driver.findElement(locator);
//If no exception is thrown here, element exists, so return true
return true;
}
catch (NoSuchElementException ex)
{
return false;
{
}
Now that we have a function that can safely check if an element exists without getting an exception, you can use it to determine if you will run the code handling the element.
Function isDisplayed() already returns a bool, so checking equality with true is not necessary.
if(ElementExists(By.xpath(...)).isDisplayed())
{
if(driver.findElement(By.xpath(".//*[#id='continue']")).isDisplayed())
{
driver.findElement(By.id("continue")).click();
}
}
//The code below will run either way, so move it out of the if statement
String psw=d.pass(0,1);
driver.findElement(password).sendKeys(psw);
As for the second part of your question, your code can be simplified by just, searching for the element and then clicking it like so:
driver.findElement(By.xpath(".//*[#id='nav-al-your-account']/a[22]")).click();
If you will, double-check the xpath or "catch" the element by an ID.

Can isDisplayed() return false without breaking run in Selenium?

I would like to use conditional function using .isDisplayed() method. Everything is working correct as long as this method returns true.
HTML is not required I think here, because I have only one button to be visible on the page, which is correclty found (I successfully clicked the button with the following xpath.
Now I try with:
if (driver.findElement(By.xpath("//a[#id='button1']")).isDisplayed()) {
//do stuff
}
else {
//do other stuff
}
Or even
WebElement withdrawnBtn = driver.findElement(By.xpath("//a[#id='button1']"));
boolean isVisible = withdrawnBtn.isDisplayed();
if (isVisible) {
//do stuff
}
else {
//do other stuff
}
but both conditionals fails, if in the first run there should be executed code from else, because everytime when the button is not available, there is fail pointing on the line with driver.findElement(By.xpath("//a[#id='button1']")).isDisplayed()); - fails, because the button is not displayed. I need t o do something, when the button is not displayed instead failing code...
Before checking isDisplayed conditions we need to check whether element exist on the page or not Otherwise it will throw Nosuchelementfound exception
driver.findElements("Locator").size()-- will return integer value if the element exist on the page.
Below is the fix code.
int size = driver.findElements("Locator").size();
if(size!=0){
if(driver.findElement("Locator").isDisplayed()){
// do operations
}
}
After reading comments, I got to know isEmpty is better way to use instead of size I made changes to the above code.
WebDriver driver;
List<WebElement> webElements = driver.findElements(By.xpath("test"));
if(!webElements.isEmpty()){
if(driver.findElement(By.xpath("test")).isDisplayed()){
// do operations
}
}
Try it and let me know if it works for you
you can also use following to identify if an element exists or not:
private boolean isPresent(WebElement element) {
try {
element;
} catch (NoSuchElementException e) {
return false;
}
return true;
}
OK, I was thinking about catching NoElementFound exception, but I found this issue:
Selenium Webdriver: best practice to handle a NoSuchElementException
using link above I used:
List<WebElement> withdrawnBtn = driver.findElements(By.xpath("//a[#id='button1']"));
if (withdrawnBtn.size() != 0) {
//do stuff
}
else {
//do other stuff
}
Instead of size() method you could use isEmpty() method.

Categories

Resources