如何使用 Selenium 和 Java 通过 PageFactory 等待元素不可见

Posted

技术标签:

【中文标题】如何使用 Selenium 和 Java 通过 PageFactory 等待元素不可见【英文标题】:How to wait for invisibility of an element through PageFactory using Selenium and Java 【发布时间】:2019-07-07 05:47:15 【问题描述】:

有没有办法使用 PageFactory 注释等待 Selenium 中不存在的元素?

使用时:

@FindBy(css= '#loading-content')
WebElement pleaseWait;

定位元素,然后:

wait.until(ExpectedConditions.invisibilityOfElementLocated(pleaseWait));

我会得到:

org.opeqa.selenium.WebElement cannot be converted to org.openqa.selenium.By

我可以通过以下方式做我需要的事情:

wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector('loading-content')));

但是,我希望能够使用 PageFactory 注释以保持框架的一致性。有没有办法做到这一点?

【问题讨论】:

【参考方案1】:

PageObjectModel 中使用 PageFactory 时,如果您希望元素不可见,您可以使用 Explicit Wait 支持普通定位器工厂并使用以下任一解决方案:


invisibilityOfElementLocated()

invisibilityOfElementLocated() 是一种期望的实现,用于检查元素是否不可见或不存在于 DOM 上。定义如下:

public static ExpectedCondition<java.lang.Boolean> invisibilityOfElementLocated(By locator)
An expectation for checking that an element is either invisible or not present on the DOM.

Parameters:
    locator - used to find the element

Returns:
    true if the element is not displayed or the element doesn't exist or stale element

代码块:

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.WebDriverWait;

public class fooPage 

    WebDriver driver;
    public fooPage(WebDriver driver)
    
        PageFactory.initElements(driver, this);
    

    //you don't need this
    //@FindBy(css= '#loading-content')
    //WebElement pleaseWait;

    public void foo()
    
        Boolean bool = new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector('#loading-content')));
        //other lines of code
    


您也可以使用invisibilityOf() 方法,如下所示:

invisibilityOf()

invisibilityOf() 是对检查元素是否不可见的期望的实现。定义如下:

public static ExpectedCondition<java.lang.Boolean> invisibilityOf(WebElement element)
An expectation for checking the element to be invisible

Parameters:
    element - used to check its invisibility

Returns:
    Boolean true when elements is not visible anymore

代码块:

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.WebDriverWait;

public class fooPage 

    WebDriver driver;
    public fooPage(WebDriver driver)
    
        PageFactory.initElements(driver, this);
    


    @FindBy(css= '#loading-content')
    WebElement pleaseWait;

    public void foo()
    
        Boolean bool = new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOf(fooPage.getWebElement()));
        //other lines of code
    

    public WebElement getWebElement()
    
        return pleaseWait;
    

您可以在How to use explicit waits with PageFactory fields and the PageObject pattern找到详细讨论

【讨论】:

【参考方案2】:

invisibilityOfElementLocated 期待定位器,但您正在发送一个网络元素,这就是它抛出错误的原因。您可以通过使用以下命令检查 webelement 列表来执行操作:

wait.until(ExpectedConditions.invisibilityOfAllElements(Arrays.asList(pleaseWait)));

更新答案: 如果要检查页面上是否不存在该元素,则可以检查其列表大小是否等于 0,因为当其未显示在 UI 上时,其列表大小将为 0。

您可以通过以下方式获取元素列表:

@FindBy(css='#loading-content')
List<WebElement> pleaseWait;

您可以使用以下命令检查列表大小是否等于 0:

if(pleaseWait.size()==0)
     System.out.println("Element is not visible on the page");
     // Add the further code here

这也不会给 NoSuchElement 异常。

【讨论】:

不,不起作用。我收到Expected condition failed: waiting for invisibility of all elements [Proxy element for: DefaultElementLocator 'By.cssSelector: #loading-content'] (tried for 5 second(s) with 500 miliseconds interval)。不过,似乎正在执行下一步。 是的,所以我猜它给出了错误,因为它期望元素不可见但它是可见的。 因为方法有效并且下一行代码也被执行了。 这是上述消息的延续:Caused by: org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: "method":"css selector","selector":"#loading-content"。我不认为它按预期工作。为什么会抛出异常呢? 如果您收到NoSuchElementException,这意味着该元素在页面上不可见,或者您的 css 不正确,您可以通过它找到该元素。请告诉我您想在此处验证的场景是什么,我将能够更好地为您提供帮助。【参考方案3】:

您也可以使用正确的预期条件:

wait.until(ExpectedConditions.invisibilityOf(pleaseWait));

Reference.

希望对你有帮助!

【讨论】:

我正在等待元素 not 可见。 @MateMrše,是的,我明白了。我已经更新了我的答案。请再检查一次。谢谢。 我收到Expected condition failed: waiting for invisibility of Proxy element for: DefaultElementLocator 'By.cssSelector: #loading-content' (tried for 5 second(s) with 500 miliseconds interval) 错误消息。似乎元素消失得太快了。【参考方案4】:

默认情况下,如果页面上不存在该元素,invisibilityOf 不会返回 true。 (NoSuchElementException)

public static ExpectedCondition<Boolean> invisibilityOf(final WebElement element) 
return new ExpectedCondition<Boolean>() 
    public Boolean apply(WebDriver webDriver) 
        return ExpectedConditions.isInvisible(element);
    

    public String toString() 
        return "invisibility of " + element;
    
;

你可以在你的 WebDriverUtils 类中创建一个你可以使用的方法:

public static ExpectedCondition<Boolean> invisibilityOf(final WebElement element) 
return new ExpectedCondition<>() 
    public Boolean apply(WebDriver webDriver) 
        try 
            return !element.isDisplayed();
         catch (NoSuchElementException | StaleElementReferenceException e) 
            return true;
        
    

    public String toString() 
        return "invisibility of " + element;
    
;

类似于invisibilityOfElementLocated(final By locator)

【讨论】:

以上是关于如何使用 Selenium 和 Java 通过 PageFactory 等待元素不可见的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Java 使用 XPath 和 Selenium WebDriver 单击 SVG 元素

如何通过 selenium、appium、java 和 android 以更快的方式多次点击一个元素

使用.p12证书验证Selenium WebDriver(Java)

如何使用Selenium和Python从Java脚本获取变量值

如果我通过 Selenium Webdriver 和 Java 知道相应的文本,如何提取 DOM 元素的 ID 属性

如何使用 Selenium WebDriver、Java 通过文本选择 Web 元素