I working in selenium and now for checking visibility of element i use following wait until:
#FindBy (css=".delete-basket-modal-btn") WebElement deleteItemFromBasketCancelButton;
public void clickDeleteItemFromBasketCancelButton() throws InterruptedException {
wait.until(ExpectedConditions.elementToBeClickable(deleteItemFromBasketCancelButton));
deleteItemFromBasketCancelButton.click();
}
that's not good idea, this function is not checking for presence of element, so sometimes i get 'stale element reference element is not attached to the page document'
Now i trying to create universal function which will be inherited by all of mine page object class. In this function i need checking (5 sec) for presence, enability, clickability and visibilty of WebElement passed in argument.
For this moment i have new function below, but i dont know that is good approach for my problem
public void verifyElement(WebElement element) throws InterruptedException {
boolean isPresent = false;
for (int i = 0; i < 5; i++) {
try {
if (element != null) {
isPresent = true; // metoda do czekania na element
break;
}
} catch (Exception e) {
// System.out.println(e.getLocalizedMessage());
Thread.sleep(1000);
}
}
Assert.assertTrue(isPresent, "\"" + element + "\" is not present.");
boolean isEnabled = false;
for (int i = 0; i < 5; i++) {
try {
if (element.isEnabled()==true) {
isEnabled = true;
break;
}
}catch (Exception e) {
Thread.sleep(1000);
}
}
Assert.assertTrue(isEnabled, "\"" + element + "\" is not enabled.");
}
Do you have any suggestion or similar problem for this issue?
StaleElementReferenceException doesn't (necessarily) mean the element is not present, it means the DOM had changed/refreshed since the element was located, so the element reference which the driver holds is no longer valid. This is a disadvantage of using PageFactory model.
The solution is to locate the element just before the click operation, however this will break the consistency of the page object. Instead of using FindBy send By to the method and locate the element there
public void clickDeleteItemFromBasketCancelButton(By by) throws InterruptedException {
WebElement deleteItemFromBasketCancelButton = wait.until(ExpectedConditions.elementToBeClickable(by));
deleteItemFromBasketCancelButton.click();
}
The first written code is enough. To overcome stale element exception write code in try/catch block and use ExpectedConditions.stalenessOf(deleteItemFromBasketCancelButton) for presence, enability, clickability and visibilty (for any type of operation).
Try below one, hope it's help for you.
try{
wait.until(ExpectedConditions.elementToBeClickable(deleteItemFromBasketCancelButton));
deleteItemFromBasketCancelButton.click();
}
catch(Exception e){
wait.until(ExpectedConditions.refreshed(ExpectedConditions.stalenessOf(deleteItemFromBasketCancelButton)))
deleteItemFromBasketCancelButton.click();
}
Related
I saw one os the posts before regarding stale element exception and used the retry code for handling it. But inspite of keeping the count at 20 , stale element exception still persists. I can see that the element2 is loaded in the webpage being tested .But its still id'd as stale element. The code works in case of element1 sometimes. but never for element2
code:
for (i = 1; i < 7; i++)
{
sServiceID = ExcelUtils.getCellData(i,Constant.Col_ServiceID);
System.out.println("sServiceID:"+sServiceID);
ServiceID_Filter().clear();//function returns element
ServiceID_Filter().sendKeys(sServiceID);
BaseClass.driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
Thread.sleep(3000);
ApplyFilters_element().click();
Thread.sleep(3000);
boolean result = false;
int attempts = 0;
while(attempts < 20) {
System.out.println("inside stale check loop");
BaseClass.driver.manage().timeouts().implicitlyWait(20,TimeUnit.SECONDS);
try {
if(element1.isDisplayed()||element2.isDisplayed()) //either one of the elements will be loaded
{
System.out.println("not stale "+Table_widget.ExportButton().isDisplayed());
result = true;
break;
}
} catch(StaleElementReferenceException e) {
System.out.println("stale at attempt "+attempts);
}
attempts++;
}
if(result==true)
{
if(element1.isDisplayed())
{
element3.click();
System.out.println(" button clicked");
Thread.sleep(1000);
}
else
if(element2.isDisplayed())
{ element3.click();
System.out.println("No records found");
Thread.sleep(1000);
}
}
}
In my humble opinion the problem is here:
BaseClass.driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
Thread.sleep(3000);
ApplyFilters_element().click();
Thread.sleep(3000);
First of all you are using implicit wait plus thread sleep which is a recipe for disaster. This is what is causing your stale elements exceptions, try something like this below:
public boolean waitForElement(String elementXpath, int timeOut) {
try{
WebDriverWait wait = new WebDriverWait(driver, timeOut);
boolean elementPresent=wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(elementXpath)).isDisplayed());
System.out.printf("%nElement is present [T/F]..? ")+elementPresent;
}
catch(TimeoutException e1){e1.printStackTrace();elementPresent=false;}
return elementPresent;
}
Best of luck!
I have a If Else block within a while block. If element is present, click it to remove it and put it back to parent list. Else if element is not in the list then select from parent list and put it back.
The first time it works. It sees that the element is present, clicks it to removes it. On the second pass it fails when checking for the element
I tried with FindElement.IsDisplayed and !=null.
I get this exception :
org.openqa.selenium.NoSuchElementException: Unable to find element with css selector == select[id="idSelSelectedLanes"]>option[value="9012"] (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 30.16 seconds
What am I missing?
This is my first post here so apologize for any formatting issues.
thanks
count ++;
if(count % 2 == 0){
if(BROWSER.equals("IE")) {
// check if 9012 is present
if(driver.findElement(By.cssSelector("select[id=\"idSelSelectedLanes\"]>option[value=\"9012\"]"))!=null){
try {
// since its present, click to remove
driver.findElement(By.cssSelector("select[id=\"idSelSelectedLanes\"]>option[value=\"9012\"]")).click();;
Thread.sleep(1000);
} catch(NoSuchElementException e) {
System.out.println("Couldn't remove 9012");
}
} else {
try {
//Not present, so select from Available Lanes
driver.findElement(By.cssSelector("select[id=\"idSelAvailableLanes\"]>option[value=\"9012\"]")).isDisplayed();
} catch (NoSuchElementException e) {
System.out.println("Couldn't add 9012");
}
}
}
}
You need to put driver.findElement(...) in a try-catch block
count ++;
WebElement e;
if(count % 2 == 0) {
if(BROWSER.equals("IE")) {
// check if 9012 is present
try {
e = driver.findElement(By.cssSelector("select[id=\"idSelSelectedLanes\"]>option[value=\"9012\"]"));
Thread.sleep(1000);
e.click()
} catch (NoSuchElementException e) {
System.out.println("Couldn't remove 9012");
// the else part goes here
}
}
}
Another approach is to use findElements instead of findElement to avoid the try-catch, and use .get(0) to get the element you want.
Another solution, you should check elementExist first using findElements, if it exists -> perform other actions
count ++;
WebElement e;
String e9012Css = "select[id=\"idSelSelectedLanes\"]>option[value=\"9012\"]";
if(count % 2 == 0) {
if(BROWSER.equals("IE")) {
// check if 9012 is present
e9012Existed = driver.findElements(By.cssSelector(e9012Css)).size() > 0;
if(e9012Existed) {
driver.findElement(By.cssSelector(e9012Css)).Click();
}
}
else {
System.out.println("Couldn't remove 9012");
}
}
try to use isElementPresent
if(isElementPresent(By.cssSelector("select[id=\"idSelSelectedLanes\"]>option[value=\"9012\"]"))){
// since its present, click to remove
} else {
//Not present, so select from Available Lanes
}
After much searching and reading, I'm still unclear as to the best way to handle a failed assertion using Webdriver. I would have thought this was a common and core piece of functionality. All I want to do is:
look for an element
if present - tell me
if not present - tell me
I want to present the results for a non technical audience, so having it throw 'NoSuchElementExceptions' with a full stack trace is not helpful. I simply want a nice message.
My test:
#Test
public void isMyElementPresent(){
// WebElement myElement driver.findElement(By.cssSelector("#myElement"));
if(driver.findElement(By.cssSelector("#myElement"))!=null){
System.out.println("My element was found on the page");
}else{
System.out.println("My Element was not found on the page");
}
}
I still get a NoSuchElementException thrown when I force a fail. Do I need a try/catch as well? Can I incorporate Junit assertions and/or Hamcrest to generate a more meaningful message without the need for a System.out.println?
I have encountered similar situations. According to the Javadoc for the findElement and findElements APIs, it appears that the findElement behavior is by design. You should use findElements to check for non-present elements.
Since in your case, there's a chance that the WebElement is not present, you should use findElements instead.
I'd use this as follows.
List<WebElement> elems = driver.findElements(By.cssSelector("#myElement"));
if (elems.size == 0) {
System.out.println("My element was not found on the page");
} else
System.out.println("My element was found on the page");
}
you can do something to check if element exists
public boolean isElementExists(By by) {
boolean isExists = true;
try {
driver.findElement(by);
} catch (NoSuchElementException e) {
isExists = false;
}
return isExists;
}
What about using an xPath inside of a try-catch, passing the elementype, attribute and text as follows?
try {
driver.FindElement(
By.XPath(string.Format("//{0}[contains(#{1}, '{2}')]",
strElemType, strAttribute, strText)));
return true;
}
catch (Exception) {
return false;
}
Even running it in a try block, it behaves as if unhandled,
neither of the catch blocks runs when the selenium exception occurs.
try {
wait.Until(webDriver => webDriver.PageSource.Contains(waitforTitle));
wait.Until(webDriver => webDriver.FindElement(By.Id(waitforControlName)).Displayed);
}
catch (OpenQA.Selenium.NoSuchElementException nse) {
nse = nse = null;
success = false;
}
catch (Exception ex) {
ex = ex = null;
success = false;
}
I need to click on particular element of an dynamically loaded page.Web element generated when we scroll the page.It similar like an jabong webpage.
I try to do that on jabong webpage this is my code
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.navigate().to("http://www.jabong.com/men/clothing/"
+ "?source=topnav");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
System.out.println("Close the modal popup");
driver.findElement(By.id("jab-vchr-cls")).click();
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
/**
* while(true) loop is required to search the
* element until element found.We put find
* element within try-catch and if it get
* exception it scroll the page and again
* try to find the element.
*/
while(true) {
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,100)", "");
try {
WebElement element = driver.findElement(By.xpath("//*[#id='http: //static3.jassets.com/p/The-Indian-Garage-Co.-Checks-Red-Casual-Shirt-2889-679124-1-catalog.jpg']/img"));
Wait<WebDriver> wait_element=new WebDriverWait(driver, 10);
wait_element.until(ExpectedConditions.elementToBeClickable(element));
element.click();
System.out.println("!!!!!!!!!!!!!!At Last Get Success!!!!!!!!!!!!!!!!");
break;
}
catch (Exception ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
System.out.println(ex.getMessage());
}
}
}
}
My question is
1.Is there any better way to do this things?
2.How to make this script faster?
you can do this way if you want to avoid while(true) though I donot think there is any problem with this loop.
boolean reachedbottom = Boolean.parseBoolean(js.executeScript("return $(document).height() == ($(window).height() + $(window).scrollTop());").toString());
while (!reachedbottom) {
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,600)", "");
try {
reachedbottom=Boolean.parseBoolean(js.executeScript("return $(document).height() == ($(window).height() + $(window).scrollTop());").toString());
WebElement element = driver.findElement(By.xpath("//*[#id='http://static3.jassets.com/p/The-Indian-Garage-Co.-Checks-Red-Casual-Shirt-2889-679124-1-catalog.jpg']/img"));
Wait<WebDriver> wait_element = new WebDriverWait(driver, 5);
wait_element.until(ExpectedConditions.elementToBeClickable(element));
element.click();
System.out.println("!!!!!!!!!!!!!!At Last Get Success!!!!!!!!!!!!!!!!");
break;
} catch (Exception ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
System.out.println(ex.getMessage());
}
}
In the Getting Started with Selenium framework, the AutomationTest#waitForElement method is a great way to handle things. It's an alternative to the webdriver wait, but works all the same.
/**
* Private method that acts as an arbiter of implicit timeouts of sorts.. sort of like a Wait For Ajax method.
*/
private WebElement waitForElement(By by) {
int attempts = 0;
int size = driver.findElements(by).size();
while (size == 0) {
size = driver.findElements(by).size();
if (attempts == MAX_ATTEMPTS) fail(String.format("Could not find %s after %d seconds",
by.toString(),
MAX_ATTEMPTS));
attempts++;
try {
Thread.sleep(1000); // sleep for 1 second.
} catch (Exception x) {
fail("Failed due to an exception during Thread.sleep!");
x.printStackTrace();
}
}
if (size > 1) System.err.println("WARN: There are more than 1 " + by.toString() + " 's!");
return driver.findElement(by);
}
You can take it out of the infinite loop. If a page doesn't load something within 10 seconds then i'd say it's an app issue that needs to be rectified. Take it out out of the infinite loop, and using something like waitForElement specified above, or just use a WebDriverWait class.
Furthermore, you shouldn't ever have to scroll to an element. I still have yet to find a reason to do something like this. As long as the element is on the DOM, it should be able to be operated on.
I've been testing an application involving multiple ajax calls, so I required wait condition so that elements are present/visible once the ajax call is made. I used both methods implicitwait and explicitwait but none of them seem to be working for me as one or the other exceptions are generated as follows:
1.Unable to locate element
2.Element is disabled and so may not be used for actions
Implicit wait used as follows:
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
WebElement we = driver.findElement(By.name("q"));
PROBLEM:
When I test this code, after browser opens, it throws exception in 2 seconds.
Result:Exception generated
Explicit Wait
WebDriverWait wait = new WebDriverWait(driver, /*seconds=*/3);
WebElement element = wait.until(presenceOfElementLocated(By.name("q"));
PROBLEM:
When I test this code, after browser opens, it throws exception in 2 seconds
Result:Exception generated.
Also used visibilityOfElementLocated but it does not work for me.
Has anybody faced this issue or anybody has a solution for this??
I can't say that I have faced that issue before but I also wrote my own custom DOM polling class. Here's what I do.
private int Timer = 180;
private bool CheckForElement(WebDriver driver,string byType,string selector)
{
bool elementFound = false;
for (int i = Timer - 1; i > 0; i--)
{
if (!itemFound)
{
Thread.Sleep(1000); //sets the loop to check every second this can be done at a much faster or slower rate depending on your preferences
if (byType.ToLower() == "id")
{
try{
WebDriver element = driver.FindElement(By.Id(selector);
if(element.Displayed)
{
elementFound = true;
}
}
catch {
//Do Nothing Here as we don't need to handle the exception
}
}
else if (byType.ToLower() == "tagname")
{
try{
WebDriver element = driver.FindElement(By.TagName(selector);
if(element.Displayed)
{
elementFound = true;
}
}
catch {
//Do Nothing Here as we don't need to handle the exception
}
}
else if (byType.ToLower() == "cssselector")
{
try{
WebDriver element = driver.FindElement(By.cssSelector(selector);
if(element.Displayed)
{
elementFound = true;
}
}
catch {
//Do Nothing Here as we don't need to handle the exception
}
}
else if (byType.ToLower() == "classname")
{
try{
WebDriver element = driver.FindElement(By.ClassName(selector);
if(element.Displayed)
{
elementFound = true;
}
}
catch {
//Do Nothing Here as we don't need to handle the exception
}
}
}
else
{
i = 0; //stops the loop when the element is found
}
}
return elementFound ;
}