簡體   English   中英

Selenium WebDriver:當使用WebDriver.findElement定位時,等待元素存在是不可能的

[英]Selenium WebDriver: wait for element to be present when locating with WebDriver.findElement is impossible

等待WebElementWebDriverWaitExpectedConditions一起出現是很方便的。

問題是, 如果WebElement.findElment是唯一可能找到元素的方法,那該怎么辦?因為它沒有id,沒有名字,沒有唯一的類?

WebDriverWait的構造函數只接受WebDriver作為參數,而不接受WebElement

我已經設置了implicitlyWait等待時間,所以使用try{} catch(NoSuchElementException e){}似乎不是一個好主意,因為我不想等待這個元素的那么長時間。

這是場景:

有一個網頁,其中包含一個包含許多input標簽的表單。 每個input標簽都有格式要求。

當不滿足格式要求時,在此input標記之后將存在動態div標記。

由於有很多input標簽,我創建了一個通用的方法,如:

public WebElement txtBox(String name) {
    return driver.findElement(By.name(name));
}

而不是為每個input標簽創建數據成員。

然后我創建一個方法isValid來檢查某些input中的用戶輸入是否有效。 我在isValid應該做的就是檢查inputboxToCheck之后是否存在div標簽,代碼如下:

public boolean isValid(WebElement inputboxToCheck) {
    WebElementWait wait = new WebElementWait(inputboxToCheck, 1);
    try {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("./following-sibling::div")));
        return false;
    } catch (TimeOutException e) {
        return true;
    }    
}

WebElementWait是一個虛構的(不存在的)類,其工作方式與WebDriverWait相同。

上面提到的WebElementWait類:

package org.openqa.selenium.support.ui;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.NotFoundException;
import org.openqa.selenium.WebElement;

public class WebElementWait  extends FluentWait<WebElement>  {
    public final static long DEFAULT_SLEEP_TIMEOUT = 500;

      public WebElementWait(WebElement element, long timeOutInSeconds) {
            this(element, new SystemClock(), Sleeper.SYSTEM_SLEEPER, timeOutInSeconds, DEFAULT_SLEEP_TIMEOUT);
      }

      public WebElementWait(WebElement element, long timeOutInSeconds, long sleepInMillis) {
            this(element, new SystemClock(), Sleeper.SYSTEM_SLEEPER, timeOutInSeconds, sleepInMillis);
      }

      protected WebElementWait(WebElement element, Clock clock, Sleeper sleeper, long timeOutInSeconds,
              long sleepTimeOut) {
            super(element, clock, sleeper);
            withTimeout(timeOutInSeconds, TimeUnit.SECONDS);
            pollingEvery(sleepTimeOut, TimeUnit.MILLISECONDS);
            ignoring(NotFoundException.class);
      }

}

它與WebDriverWait相同,只是WebDriver參數被WebElement替換。

然后,isValid方法:

//import com.google.common.base.Function;
    //import org.openqa.selenium.TimeoutException;

public boolean isValid(WebElement e) {
    try {
        WebElementWait wait = new WebElementWait(e, 1);
        //@SuppressWarnings("unused")
        //WebElement icon = 
        wait.until(new Function<WebElement, WebElement>() {
                    public WebElement apply(WebElement d) {
                        return d.findElement(By
                                .xpath("./following-sibling::div[class='invalid-icon']"));
                    }
                });
        return false;
    } catch (TimeoutException exception) {
        return true;
    }
}

我不知道這是否對你有所幫助,但它允許等待元素你想要多少時間。

public WebElement findDynamicElement(By by, int timeOut) {
    WebDriverWait wait = new WebDriverWait(driver, timeOut);
    WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
    return element;
}

findDynamicElement(By.xpath("//body") , 30);

user2432405解決方案的一個更通用的變體是使用SearchContext類型而不是WebElement:

public class SearchContextWait  extends FluentWait<SearchContext>  {
    ...

這允許在WebDriver和WebElement上進行等待,就像SearchContext接口是WebDriver和WebElement的祖先一樣。 isValid方法也需要調整:

...
        WebElement icon = wait
                .until(new Function<SearchContext, WebElement>() {
                    public WebElement apply(SearchContext d) {
...

不幸的是,當你在內部使用WebDriver接口時,你失去了ExpectedConditions.xxxx()方法的所有便利。

我發現這個博客:檢查一個元素 - 存在?,可見?,存在? - https://jkotests.wordpress.com/2012/11/02/checking-for-an-element-exists-visible-present/

它帶來了存在,可見和現在之間的差異。

  • 存在? - 返回此元素是否確實存在。
  • 當下? - 如果元素存在且在頁面上可見,則返回true
  • 可見? - 如果任何父元素不可見,那么我們就不能寫入元素。 確定這一點的唯一可靠方法是迭代DOM元素樹,檢查每個元素以確保它
    可見。

存在將告訴您,您正在搜索的內容是否在DOM中的任何位置; 但是, WebDriver似乎沒有內置的方法來檢查元素是否存在,類似於普通的driver.findElement(By.name(name))

而且,正如博客中所解釋的, ExistsPresent不同 所以我不能使用ExpectedConditions.presenceOfAllElementLocatedBy(By.cssSelector(cssSelector)

我的解決方案:(在這里尋找反饋:)

public WebElement waitForElementExists(String selector, String timeout) {
    Wait<WebDriver> wait = new WebDriverWait(driver, timeout);

    WebElement element = wait.until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver driver) {
            return driver.findElement(By.cssSelector(selector));
        }
    });

    return element;
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM