Element not found, continue test - java

I have a page that randomly displays windows before homepage, to enter the site, I sometimes need to complete the form, so I use :
#FindBy(xpath = "")
public WebElement element;
Then i try to implement solution, but it fail.
if(element.isDisplayed()){
element.click();
}else if {
do something else // if not Displayed do something else and get test true?
}
Get error:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element
In my project i use java, cucumber nad testNG. I have no idea how to do that, when it does not find a form on the page, it continues the test. Maybe I should do more methods or scenarios?

The error message means it cannot find the element.
Few things,
Do you have the right selector for that element?
Does the webpage use JQuery or AngularJS? If so, you need to wait for them to load
Are you using any type of wait? Before checking if the element exist on the page? (ex. ImplicitWait, FluentWait, Thread.sleep [bad practice])
Try this -> driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
This waits for an element to load up to 10 seconds before not finding it.

1) You need to use something like this:
public WebElement [] elements = driver.findElementsBy(xpath = "The Xpath you are looking for");
if (elements)
In case the randomly displayed window appear your list will not be empty, will contain an element you are looking for. Otherwise the list will be empty.
Your code fails since your are looking for an element that not always existing in the page.
2) You can also use Try - Catch

This is solution:
#FindAll(#FindBy(xpath = ""))
List<WebElement> buttonelements
if(!buttonelements.isEmpty()){
'code here'
}
Cause of a problem:
Using FindBy and method isDisplayed() throws NoSuchElementException if no matching elements are found.
Using FindAll and method isEmpty() don't throw any suchexception, it will return empty list.

Related

How to fix TimeOutException error when using explicit wait in selenium using java

try {
WebDriverWait wait = new WebDriverWait(driver,30);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("myDynamicElement")));
} catch (TimeOutException toe) {
TimeOutException exception is thrown when Selenium fails locating on the page element matching the passed locator. myDynamicElement id in your case.
This may be caused by one of the following:
1)
You are using a wrong locator.
2)
The element is inside an iframe.
3)
You have opened a new tab / window on your browser but did not switch the driver to the new opened tab.
Etc.
Java Exceptions
When executing Java programs different errors can occur, e.g. coding errors made by the programmer, errors due to wrong input or any other unforeseeable things. When any of these error occurs, Java will throw an exception.
Java Try-Catch{}
The try and catch keywords come in pairs.
try: The try statement allows you to define a block of code to be tested for errors while it is being executed.
catch: The catch statement allows you to define a block of code to be executed, if an error occurs in the try block.
visibilityOfElementLocated()
visibilityOfElementLocated() is the 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 which returns the WebElement once it is located and visible else raises TimeOutException.
This usecase
I don't see any such syntactical error in your code block:
try {
WebDriverWait wait = new WebDriverWait(driver,30);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("myDynamicElement")));
} catch (TimeOutException toe) {
System.out.println("WebElement wasn't found");
}
However there can be numerous reasons for the WebElement not being found and some of them are as follows:
The Locator Strategy you have adopted doesn't identifies any element in the HTML DOM.
The Locator Strategy you have adopted is unable to identify the element as it is not within the browser's Viewport.
The Locator Strategy you have adopted identifies the element but is invisible due to presence of the attribute style="display: none;".
The Locator Strategy you have adopted doesn't uniquely identifies the desired element in the HTML DOM and currently finds some other hidden / invisible element.
The WebElement you are trying to locate is within an <iframe> tag.
The WebDriver instance is looking out for the WebElement even before the element is present/visibile within the HTML DOM.
Solution
Each of the above mentioned cases can be addressed using different approaches. You can find a couple of detailed discussion in:
NoSuchElementException, Selenium unable to locate element
Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate element: //*[#id='login-email']

Selenium error: no such element: Unable to locate element on .isDisplayed() method

I have an if statement below which is getting me an issue. If certain selections are made in a different dropdown, the page displays a second dropdown and a check box. The below code works as expected when a selection is made that causes those two elements to display but it doesn't if a selection is made that doesn't make them display. I get the no such element: Unable to locate element error. At first I thought it was returning true either way but the issue is it's crashing because. I even added a check at trying to assign the value to a booolean but still get the same error.
boolean dropdown = driver.findElement(By.id("DROPDOWN")).isDisplayed(); gets the same error.
if(driver.findElement(By.id("DROPDOWN")).isDisplayed()){
driver.findElement(By.id("DROPDOWN")).click();
driver.findElement(By.xpath("Choice in Drop DOWN)).click();
driver.findElement(By.id("CheckBox")).click();
}
findElement method will throw this hard exception - No such element if the element is not found. Just include Exception Handling for No Such Element and your logic should work just fine.
try{
if(driver.findElement(By.id("DROPDOWN")).isDisplayed()){
driver.findElement(By.id("DROPDOWN")).click();
driver.findElement(By.xpath("Choice in Drop DOWN)).click();
driver.findElement(By.id("CheckBox")).click();
}
catch (NoSuchElementException e)
{
// I believe you dont have to do anything here. May be a console log will do.
}
The following answers explain how to handle checking an element exists and handle the exception by wrapping in a custom method.
How to check if Element exists in c# Selenium drivers
I would also recommend re-writing your code as the following to avoid duplication and avoid xpath selectors. Using findElement twice for in the same context is not necessary just create a variable.
var dropdown = driver.findElement(By.id("DROPDOWN"));
if (dropdown.Displayed())
{
var selectElement = new SelectElement(dropdown);
selectElement.SelectByValue("valuehere");
}
If you are using the text rather than the value in the select box you can use SelectByText("texthere"); instead of SelectByValue.
isDisplayed() will work if the element is present in the DOM, followed by the style attribute :- display should not be false or none.
If prior action is a selection which led both the element to be displayed, it means the element is in the DOM but that wont be visible. So checking the visibility condition would return u false.
Try waiting for the element to get visible and perform the check operation on it which would reduce the sync latency.
WebDriverWait wait = new WebDriverWait(WebDriverRunner.getWebDriver(),5);
wait.until(ExpectedConditions.visibilityOfElementLocated("By Locator"));
if (dropdown.isDisplayed())
`````````// If the dropdown is tagged with <Select> tag
``````````` Select dropDown = new Select(dropdown);
```````````dropDown .selectByValue("value);
```````` // Else fetch the dropdown list item and store it in a list and iterate through and perform the desired action
```````````List<WebElement> dropDownList = new ArrayList<Webelements>;
```````````dropDownList.forEach(element -> {
```````````if(element.getText().equals("value")){
``````` ````element.click();
``````````` }
``````````` });
```````````driver.findElement(By.id("CheckBox")).click();
}

ExpectedConditions.or function not working as expected

I have to test an e-shop. The users can add items to their cart.
When the cart is empty, a special section with id "empty-basket" is created. If the cart is not empty, this section's id becomes "basket".
I use Java and Selenium 3.9
These are my two selectors
#FindBy(how = How.CSS, using = "#empty-basket > section")
private WebElement conteneur_panier_vide;
#FindBy(how = How.CSS, using = "#basket > section:nth-child(1)")
private WebElement conteneur_panier_non_vide;
To check if the bloc containing the elements is well formed, I check if there is one of the sections described above. I use this piece of code to do so:
this.wait.until(
ExpectedConditions.or(
ExpectedConditions.visibilityOf(conteneur_panier_vide),
ExpectedConditions.visibilityOf(conteneur_panier_non_vide)
)
);
However, this gives me an error
org.openqa.selenium.TimeoutException: Expected condition failed: waiting for at least one condition to be
valid
Surprised, I tried this:
this.wait.until(ExpectedConditions.visibilityOf(conteneur_panier_vide))
on a page with an empty basket. It works, the WebElement is found.
I then tried this:
this.wait.until(
ExpectedConditions.or(
ExpectedConditions.visibilityOf(conteneur_panier_vide),
)
);
And it works as well. It means that adding a non-existing element to the 'or' breaks it, which is exactly the opposite of what it should be.
Does anyone have an idea of why my code is not working?
Edit: SOLVED!
The problem was that the element I was looking for was not on the page when the or function is called, resulting in the malfunctioning mentioned above.
I simply put
this.wait.until(ExpectedConditions.urlContains(MY_CART_URL));
which ensures the presence of one of the two sections.
There are two things you can do to clean this up:
Create a CSS selector that matches both elements
Use ExpectedConditions.visibilityOfElementLocated(By.css(...)) instead of the more complicated or
// CSS selectors can be separated by a comma (,)
String cssSelector = "#empty-basket > section, #basket > section:nth-child(1)";
this.wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(cssSelector));
Your original problem was that using the conteneur_panier_vide and conteneur_panier_non_vide attributes was causing Selenium to attempt to fetch them. You just need to wait for the appearance of either element.
Have you instantiated your wait object? You didn't specify your environment but here's what I do in
C#
var wait = new WebDriverWait( Driver, TimeSpan.FromSeconds( 10 ) );
Java
WebDriverWait wait = new WebDriverWait(driver, 20);
I did solve the problem, and edited the question to let people know.
TL;DR:
I needed some delay before calling the or function, and did so by waiting for the URL to be the right one.

Getting error Element not found in the cache - perhaps the page has changed since it was looked up, when i am trying to select an option from dropdown

I am getting error "Element not found in the cache - perhaps the page has changed since it was looked up" , when i am trying to select an option from dropdown. Please find my code below
WebElement searchID=driver.findElement(By.xpath("ctl00$ContentPlaceHolderView$ctlRegistration$DropDownList1"));
List <WebElement> searchOptions=searchID.findElements(By.tagName("option"));
for(int i=0;i<searchOptions.size();i++)
{
if(i==1)
{
String searchIdDropdown=searchOptions.get(i).getText().toString().trim();
System.out.println(searchIdDropdown);
driver.findElement(By.name("ctl00$ContentPlaceHolderView$ctlRegistration$DropDownList1")).click();
driver.findElement(By.name("ctl00$ContentPlaceHolderView$ctlRegistration$DropDownList1")).sendKeys(searchIdDropdown);
driver.findElement(By.name("ctl00$ContentPlaceHolderView$ctlRegistration$DropDownList1")).submit();
driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS);
driver.findElement(By.name("ctl00$ContentPlaceHolderView$ctlRegistration$TextBox1']")).sendKeys(Keys.TAB);
driver.findElement(By.name("ctl00$ContentPlaceHolderView$ctlRegistration$TextBox1")).sendKeys(this.getProperties(Country+"_"+UserType+"_Registration_User1"));
driver.findElement(By.name("ctl00$ContentPlaceHolderView$ctlRegistration$TextBox1")).click();
driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS);
Please let me know how this error can be resolved.
Thanks in Advance,
Manasa.
So a few things to note:
If you can get them I would use IDs or Names for the elements you are
trying to find. Hopefully those will be much cleaner than the xpath.
You are rerunning your find element multiple times when you could
just use a WebElement and make your code far more readable.
I would try to use Explicit waits vs the implicit ones.
So this is my best suggestion of a starting point based on the code you provided.:
WebDriverWait wait = new WebDriverWait(driver, 30);
WebElement searchID = driver.findElement(By.xpath("ctl00$ContentPlaceHolderView$ctlRegistration$DropDownList1"));
List<WebElement> searchOptions=searchID.findElements(By.tagName("option"));
for(WebElement option : searchOptions)
{
if(option.getText().equals("drop down name"))// or since you were looking for the index of 1 regardless you can just do just to a .get(1) from the collection directly.
{
wait.until(ExpectedConditions.visibilityOf(option));
option.click();
WebElement textbox = driver.findElement(By.name("ctl00$ContentPlaceHolderView$ctlRegistration$TextBox1"));
wait.until(ExpectedConditions.visibilityOf(textbox));
textbox.sendKeys(this.getProperties(Country+"_"+UserType+"_Registration_User1"));
textbox.click(); //is this supposed to be a submit of some sort?

How can I use Selenium 2 to look for two potential elements?

Super newbie here.
I am testing a page that either returns a list of tweets, or if none are available, a no results page. So I have two possible acceptable outcomes. I am trying to write an assert in Selenium 2 that tests for either element, but if neither appears, return an error.
I am using the page object model and I wrote the following:
Assert.assertTrue((iu.twitterUsername().isDisplayed()) || (iu.noData().isDisplayed()), "Page is not loading")
However, I am getting an element not found on the first part of my OR statement when the no data page is displayed. I thought the point of 'isDisplayed' was to check if the element is there. Why am I getting an element not found error? Obviously its not there, and I want to move onto the second part of my OR statement.
Is there a better way to write this when there are two possible acceptable results?
The WebElement.isDisplayed() method doesn't tell you whether or not an element is there; it tells you whether it is displayed on the page (as opposed to being hidden).
You can use the WebDriver.findElement() method to test whether or not an element has loaded; it will throw a NoSuchElementException if it hasn't. Your method might look like this:
public static boolean isElementLoaded(WebDriver driver, By findBy) {
try {
driver.findElement(findBy));
} catch (NoSuchElementException e) {
return false;
}
return true;
}
You can alter how long WebDriver waits for the element to load with something like the following, which changes it to five seconds:
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
Alternatively, you can create a method that will poll for the element until a timeout is reached.
It should be as simple as
WebDriver driver = new FirefoxDriver();
WebElement element = driver.findElement(By.id(id));
Assuming you're doing something before looking for the element I'd suggest using WebDriverWait then throw and catch exception if you don't find the element in the alloted time.
WebDriverWait wait = new WebDriverWait(driver, 10);
try {
wait.until(ExpectedConditions.elementToBeSelected(By.id(id)));
} catch (ElementNotFound e) {};
element = driver.findElement(By.id(id));

Categories