Home » Java » java – Passing WebElement as parameter to implicit wait method-Exceptionshub

java – Passing WebElement as parameter to implicit wait method-Exceptionshub

Posted by: admin February 25, 2020 Leave a comment

Questions:

I wrote the below method in my Page.class for reusing implicit wait.

public WebDriver waitForElementToLoad(WebElement element)
{
        WebDriverWait wait = new WebDriverWait(driver, 60);
        wait.until(ExpectedConditions.presenceOfElementLocated((By) element));
        return (driver);
}

In my test.class I am using page factory elements, for example:

//Save button
@FindBy(xpath = "//*[@*='Save']")
private WebElement saveButton;

Now I am trying to call:
waitForElementToLoad(saveButton);
from test.Class but I am getting below error.

“java.lang.ClassCastException: class com.sun.proxy.$Proxy12 cannot be
cast to class org.openqa.selenium.By (com.sun.proxy.$Proxy12 and
org.openqa.selenium.By are in unnamed module of loader ‘app’)”

I also tried

WebElement saveButton = driver.findElement(By.xpath("//*[@*='Save']"));
waitForElementToLoad(saveButton);

but no luck.

How can I make this work?

How to&Answers:

WebDriverWait is explicit wait, not implicit. And you can’t cast WebElement to By.

If saveButton is not null than it was already found by the page factory, waiting for it presence is meaningless, that’s why you don’t have an overload with WebElement. Wait for visibility instead

wait.until(ExpectedConditions.visibilityOf(element));

Answer:

If you need to use ExpectedConditions with some your “Page” class that contains asynchronously loaded elements I would recommend to use the following approach:

  1. Extend AjaxElementLocator where override protected boolean isElementUsable(WebElement element) so that it uses ExpectedConditions to decide if the element is ready for use
  2. Extend AjaxElementLocatorFactory where override public ElementLocator createLocator(Field field) method so that it now returns the instance of your extended class
  3. Where you initialize elements use PageFactory.initElements(new MyAjaxElementLocatorFactory(driver, 10), this); where MyAjaxElementLocatorFactory is the class that you created on step 2

Answer:

This error message…

java.lang.ClassCastException: class com.sun.proxy.$Proxy12 cannot be cast to class org.openqa.selenium.By (com.sun.proxy.$Proxy12 and org.openqa.selenium.By are in unnamed module of loader 'app')

…implies that the ClassCastException occured while trying to cast a proxy object.

You need to consider a few things as follows:

  • The wait you introduced within waitForElementToLoad() isn’t implicit wait as such but an ExplicitWait. See: What is the internal working difference between Implicit Wait and Explicit Wait
  • presenceOfElementLocated() doesn’t garuntees the visibility or interactablity of any element. So for visibility or interactablity you need to use the matching ExpectedConditions either visibilityOf(WebElement element) or elementToBeClickable(By locator). For details, see: Selenium: How selenium identifies elements visible or not? Is is possible that it is loaded in DOM but not rendered on UI?
  • If your usecase involves inducing WebDriverWait you pass the WebElement saveButton in the form of a proxy object within waitForElementToLoad() as follows:

    package com.pol.zoho.PageObjects;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.FindBy;
    import org.openqa.selenium.support.PageFactory;
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.WebDriverWait;
    
    public class ZohoLoginPage {
    
        WebDriver driver;
        public ZohoLoginPage(WebDriver driver)
        {
        PageFactory.initElements(driver, this);
        }
    
        //Save button
        @FindBy(xpath = "//*[@*='Save']")
        private WebElement saveButton;
    
        public void waitForElementToLoad()
        {
        WebElement element = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(ZohoLoginPage.getWebElement()));
        saveButton.click();
        }
    
        public WebElement getWebElement()
        {
        return saveButton;
        }
    
    }
    

Reference

You can find a couple of relevant discussions in: