【问题标题】:Passing WebElement as parameter to implicit wait method将 WebElement 作为参数传递给隐式等待方法
【发布时间】:2020-02-18 09:36:04
【问题描述】:

我在我的 Page.class 中编写了以下方法来重用隐式等待。

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

在我的 test.class 中,我使用了页面工厂元素,例如:

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

现在我正在尝试调用: waitForElementToLoad(saveButton); 来自 test.Class 但我遇到了错误。

"java.lang.ClassCastException: com.sun.proxy.$Proxy12 类不能 转换为 org.openqa.selenium.By 类(com.sun.proxy.$Proxy12 和 org.openqa.selenium.By 在 loader 'app' 的未命名模块中)"

我也试过了

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

但没有运气。

我怎样才能做到这一点?

【问题讨论】:

    标签: java selenium selenium-webdriver pageobjects page-factory


    【解决方案1】:

    WebDriverWait 是显式等待,而不是隐式等待。而且您不能将WebElement 转换为By

    如果saveButton 不是null 而不是页面工厂已经找到它,等待它的存在是没有意义的,这就是为什么你没有WebElement 的重载。而是等待可见性

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

    【讨论】:

    • 这行得通,谢谢。现在,如果我有一个动态 xpath,例如: driver.findElement(By.xpath("(//a[@class='profile-link-label' and text()='"+userName+"'])[1]" ));我想将它作为参数传递给同一个方法。我该怎么做?
    • @user194258 你需要发送返回的WebElement,或者构建一个接收By而不是web元素的新方法并使用ExpectedConditions.visibilityOfElementLocated(By.xpath("(//a[@class='profile-link-label' and text()='"+userName+"'])[1]"))
    • 接收By的新方法,如果不是WebElement,数据类型是什么?另外,当我发送参数时,我应该发送 driver.findElement(By.xpath("(//a[@class='profile-link-label' and text()='"+userName+"'])[ 1]"));或者只是 (//a[@class='profile-link-label' and text()='"+userName+"'])[1]") ?
    • @user194258 你发By, By.xpath("...")
    【解决方案2】:

    如果您需要将ExpectedConditions 与一些包含异步加载元素的“页面”类一起使用,我建议您使用以下方法:

    1. 扩展 AjaxElementLocator where override protected boolean isElementUsable(WebElement element) 以便它使用 ExpectedConditions 来决定元素是否可以使用
    2. 扩展 AjaxElementLocatorFactory where override public ElementLocator createLocator(Field field) 方法,以便它现在返回扩展类的实例
    3. 初始化元素的位置使用PageFactory.initElements(new MyAjaxElementLocatorFactory(driver, 10), this);,其中MyAjaxElementLocatorFactory 是您在第2 步中创建的类

    【讨论】:

      【解决方案3】:

      此错误消息...

      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')
      

      ...暗示 ClassCastException 在尝试强制转换 proxy 对象时发生。

      您需要考虑以下几点:

      • 您在waitForElementToLoad() 中引入的等待不是implicit wait,而是ExplicitWait。见:What is the internal working difference between Implicit Wait and Explicit Wait
      • presenceOfElementLocated() 不保证任何元素的可见性可交互性。因此,对于 visibilityinteractablity,您需要使用匹配的 ExpectedConditions 或 visibilityOf(WebElement element)elementToBeClickable(By locator)。详情见:Selenium: How selenium identifies elements visible or not? Is is possible that it is loaded in DOM but not rendered on UI?
      • 如果您的用例涉及诱导 WebDriverWait,您可以通过 代理 对象的形式传递 WebElement saveButton waitForElementToLoad()如下:

        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;
            }
        
        }
        

      参考

      您可以在以下位置找到一些相关讨论:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-16
        • 1970-01-01
        • 1970-01-01
        • 2015-12-26
        相关资源
        最近更新 更多