Как проверить, видим ли элемент с WebDriver

С WebDriver от Селена 2.0a2 я испытываю затруднения при проверке, видим ли элемент.

WebDriver.findElement возвраты a WebElement, который, к сожалению, не предлагает isVisible метод. Я могу обойти это при помощи WebElement.clear или WebElement.click оба из которых бросают ElementNotVisibleException, но это чувствует себя очень грязным.

Какие-либо лучшие идеи?

62
задан 27 November 2012 в 23:32

10 ответов

Даже при том, что я несколько поздно отвечаю на вопрос:

можно теперь использовать WebElement.isDisplayed() , чтобы проверить, видим ли элемент.

Примечание :

существует много причин, почему элемент мог быть невидимым. Попытки селена покрывают большинство из них, но существуют пограничные случаи, где это не работает как ожидалось.

, Например, isDisplayed() делает возврат false, если элемент имеет display: none или opacity: 0, но по крайней мере в моем тесте, он надежно не обнаруживает, если элемент покрыт другим из-за расположения CSS.

134
ответ дан 31 October 2019 в 13:18

У меня есть следующие 2 предложенных пути:

  1. можно использовать isDisplayed() как указано ниже:

    driver.findElement(By.id("idOfElement")).isDisplayed();
    
  2. можно определить метод как показано ниже и назвать его:

    public boolean isElementPresent(By by) {
      try {
        driver.findElement(by);
        return true;
      }
    catch (org.openqa.selenium.NoSuchElementException e) {
        return false;
      }
    }
    

Теперь, можно сделать утверждение как ниже, чтобы проверить, что или элемент присутствует или нет:

assertTrue(isElementPresent(By.id("idOfElement")));
15
ответ дан 31 October 2019 в 13:18

При использовании C# это был бы драйвер. Отображенный. Вот пример из моего собственного проекта:

if (!driver.FindElement(By.Name("newtagfield")).Displayed)      //if the tag options is not displayed
    driver.FindElement(By.Id("expand-folder-tags")).Click();    //make sure the folder and tags options are visible
7
ответ дан 31 October 2019 в 13:18

Короткий ответ: используйте #visibilityOfElementLocated

, Ни один из ответов с помощью isDisplayed или подобный не корректен. Они только проверяют, не ли display свойство none, не, если элемент может на самом деле быть замечен! Селен имел набор статических служебных методов, добавленных в ExpectedConditions класс. Два из них могут использоваться в этом случае:

Использование

@Test
// visibilityOfElementLocated has been statically imported
public demo(){
    By searchButtonSelector = By.className("search_button");
    WebDriverWait wait = new WebDriverWait(driver, 10);
    driver.get(homeUrl);

    WebElement searchButton = wait.until(                
            visibilityOfElementLocated
            (searchButtonSelector)); 

    //clicks the search button 
    searchButton.click();

Пользовательская проверка видимости, работающая на клиенте

, Это было моим ответом перед обнаружением о служебных методах для ExpectedConditions. Это могло бы все еще быть релевантно, поскольку я предполагаю, что это делает больше, чем упомянутый выше метод, который только проверяет, что элемент имеет высоту и ширину.

В сущности: этому не может ответить Java и эти findElementBy* методы и WebElement#isDisplayed одному, как они могут только сказать Вам, если элемент существует , не, если это на самом деле видимо . OP не определил то, что видимый средства, но он обычно влечет за собой

  • , он имеет opacity> 0
  • , он имеет display набор свойств к чему-то еще, чем [1 114]
  • эти visibility, опора установлена на [1 116]
  • нет никаких других элементов, скрывающих его (это - самый верхний элемент)

, Большинство людей также включало бы требование, чтобы это было на самом деле в области просмотра также (таким образом, человек смог бы видеть его).

По некоторым причинам, эти довольно нормальные потребности не удовлетворены чистым Java API, в то время как фронтенды к Селену, который полагается на него часто, реализуют некоторое изменение [1 117], который является, почему я знал, что это должно быть возможно. И после просмотра источника платформы Узла WebDriver. IO, который я нашел источник из [1 118], который теперь переименован к более точно название [1 119] в с 5.0 бетами.

В основном, они реализуют пользовательскую команду как вызов, что делегаты в JavaScript, который работает на клиенте и делает фактическую работу! Это - бит "сервера":

export default function isDisplayedInViewport () {
    return getBrowserObject(this).execute(isDisplayedInViewportScript, {
        [ELEMENT_KEY]: this.elementId, // w3c compatible
        ELEMENT: this.elementId // jsonwp compatible
    })
}

, Таким образом, интересным битом является JavaScript, отправленный для работы клиента:

/**
 * check if element is visible and within the viewport
 * @param  {HTMLElement} elem  element to check
 * @return {Boolean}           true if element is within viewport
 */
export default function isDisplayedInViewport (elem) {
    const dde = document.documentElement

    let isWithinViewport = true
    while (elem.parentNode && elem.parentNode.getBoundingClientRect) {
        const elemDimension = elem.getBoundingClientRect()
        const elemComputedStyle = window.getComputedStyle(elem)
        const viewportDimension = {
            width: dde.clientWidth,
            height: dde.clientHeight
        }

        isWithinViewport = isWithinViewport &&
                           (elemComputedStyle.display !== 'none' &&
                            elemComputedStyle.visibility === 'visible' &&
                            parseFloat(elemComputedStyle.opacity, 10) > 0 &&
                            elemDimension.bottom > 0 &&
                            elemDimension.right > 0 &&
                            elemDimension.top < viewportDimension.height &&
                            elemDimension.left < viewportDimension.width)

        elem = elem.parentNode
    }

    return isWithinViewport
}

Эта часть JS может на самом деле быть скопирована (почти) дословно в Вашу собственную кодовую базу (удалите export default и замените const [1 122] в случае невечнозеленых браузеров)! Для использования его считайте его от [1 123] в String, который может быть отправлен Селеном за работой клиента.

Другой интересный и связанный сценарий, который могло бы стоить изучить, selectByVisibleText.

, Если Вы не выполнили JS использование Селена, прежде чем Вы могли иметь маленький быстрый взгляд в это или просмотреть JavaScriptExecutor API.

Обычно, попытайтесь всегда использовать неблокирующиеся асинхронные сценарии (значение #executeAsyncScript), но так как у нас уже есть синхронный, блокирующийся сценарий, мы могли бы также использовать нормальный синхронизирующий вызов. Возвращенный объект может быть многими типами Объекта, таким образом, бросает approprately. Это могло быть одним способом сделать его:

/** 
 * Demo of a java version of webdriverio's isDisplayedInViewport
 * https://github.com/webdriverio/webdriverio/blob/v5.0.0-beta.2/packages/webdriverio/src/commands/element/isDisplayedInViewport.js
 * The super class GuiTest just deals with setup of the driver and such
 */
class VisibleDemoTest extends GuiTest {
    public static String readScript(String name) {
        try {
            File f = new File("selenium-scripts/" + name + ".js");
            BufferedReader reader = new BufferedReader( new FileReader( file ) );
            return reader.lines().collect(Collectors.joining(System.lineSeparator()));
        } catch(IOError e){
            throw new RuntimeError("No such Selenium script: " + f.getAbsolutePath()); 
        }
    }

    public static Boolean isVisibleInViewport(RemoteElement e){
        // according to the Webdriver spec a string that identifies an element
        // should be deserialized into the corresponding web element,
        // meaning the 'isDisplayedInViewport' function should receive the element, 
        // not just the string we passed to it originally - how this is done is not our concern
        //
        // This is probably when ELEMENT and ELEMENT_KEY refers to in the wd.io implementation
        //
        // Ref https://w3c.github.io/webdriver/#dfn-json-deserialize
        return js.executeScript(readScript("isDisplayedInViewport"), e.getId());
    }

    public static Boolean isVisibleInViewport(String xPath){
        driver().findElementByXPath("//button[@id='should_be_visible']");
    }

    @Test
    public demo_isVisibleInViewport(){
        // you can build all kinds of abstractions on top of the base method
        // to make it more Selenium-ish using retries with timeouts, etc
        assertTrue(isVisibleInViewport("//button[@id='should_be_visible']"));
        assertFalse(isVisibleInViewport("//button[@id='should_be_hidden']"));
    }
}
6
ответ дан 31 October 2019 в 13:18

Важно видеть, видим ли элемент или не, поскольку эти Driver.FindElement только проверит источник HTML. Но всплывающий код мог быть в HTML страницы и не быть видим. Поэтому Driver.FindElement функция возвращает положительный false (и Ваш тест перестанет работать)

2
ответ дан 31 October 2019 в 13:18

Проверка ele видима.

public static boolean isElementVisible(final By by)
    throws InterruptedException {
        boolean value = false;

        if (driver.findElements(by).size() > 0) {
            value = true;
        }
        return value;
    }
1
ответ дан 31 October 2019 в 13:18

Вот то, как я сделал бы это (проигнорируйте вызовы класса Регистратора беспокойства):

public boolean isElementExist(By by) {
    int count = driver.findElements(by).size();
    if (count>=1) {
        Logger.LogMessage("isElementExist: " + by + " | Count: " + count, Priority.Medium);
        return true;
    }
    else {
        Logger.LogMessage("isElementExist: " + by + " | Could not find element", Priority.High);
        return false;
    }   
}

public boolean isElementNotExist(By by) {
    int count = driver.findElements(by).size();
    if (count==0) {
        Logger.LogMessage("ElementDoesNotExist: " + by, Priority.Medium);
        return true;
    }
    else {
        Logger.LogMessage("ElementDoesExist: " + by, Priority.High);
        return false;
    }   
}

public boolean isElementVisible(By by) {
    try {
        if (driver.findElement(by).isDisplayed()) {
            Logger.LogMessage("Element is Displayed: " + by, Priority.Medium);
            return true;
        }
    }
    catch(Exception e) {       
        Logger.LogMessage("Element is Not Displayed: " + by, Priority.High);
        return false;
    }       

    return false;
}
-1
ответ дан 31 October 2019 в 13:18
public boolean isElementFound( String text) {
        try{
            WebElement webElement = appiumDriver.findElement(By.xpath(text));
            System.out.println("isElementFound : true :"+text + "true");
        }catch(NoSuchElementException e){
            System.out.println("isElementFound : false :"+text);
            return false;
        }
        return true;
    }

    text is the xpath which you would be passing when calling the function.
the return value will be true if the element is present else false if element is not pressent
-1
ответ дан 31 October 2019 в 13:18
    try{
        if( driver.findElement(By.xpath("//div***")).isDisplayed()){
          System.out.println("Element is Visible");
        }
}
catch(NoSuchElementException e){
   else{
     System.out.println("Element is InVisible");
        }
}
-1
ответ дан 31 October 2019 в 13:18

попробуйте это

public boolean isPrebuiltTestButtonVisible() {
    try {

        if (preBuiltTestButton.isEnabled()) {

            return true;

        } else {

            return false;
        }

    } catch (Exception e) {

        e.printStackTrace();
        return false;
    }
}
-2
ответ дан 31 October 2019 в 13:18

Другие вопросы по тегам:

Похожие вопросы: