Как проверить, виден ли элемент с помощью WebDriver - PullRequest
59 голосов
/ 15 апреля 2010

С WebDriver из Selenium 2.0a2 У меня проблемы с проверкой, видим ли элемент.

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

Есть идеи получше?

Ответы [ 11 ]

131 голосов
/ 23 сентября 2011

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

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

Примечание

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

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

19 голосов
/ 15 апреля 2010

element instanceof RenderedWebElement должно работать.

15 голосов
/ 11 октября 2012

У меня есть 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")));
7 голосов
/ 27 ноября 2012

Если вы используете 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
4 голосов
/ 10 сентября 2018

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

Ни один из ответов, использующих isDisplayed или аналогичный, не является правильным. Они только проверяют, является ли свойство display не none, а не то, действительно ли элемент можно увидеть! В Selenium был добавлен набор статических служебных методов в классе 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, поскольку они могут только сказать вам, существует ли элемент , а не если он действительно видим . ОП не определил, что означает visible , но обычно влечет за собой

  • имеет opacity> 0
  • свойство display имеет значение, отличное от none
  • visibility реквизит установлен на visible
  • другие элементы не скрывают его (это самый верхний элемент)

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

По какой-то причине эта вполне нормальная потребность не удовлетворяется чистым Java API, в то время как внешние интерфейсы Selenium, основанные на нем, часто реализуют некоторые вариации isVisible, поэтому я знал, что это должно быть возможно. И после просмотра источника Node framework WebDriver.IO я нашел источник из isVisible, который теперь переименован в более удачное имя isVisibleInViewport в 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 на var в случае не вечнозеленых браузеров)! Чтобы использовать его, прочитайте его из File в String, который Selenium может отправить для запуска на клиенте.

Еще один интересный и связанный скрипт, на который стоит обратить внимание: selectByVisibleText .

Если вы не выполняли JS с использованием Selenium до того, как могли взглянуть на этот или просмотреть JavaScriptExecutor API .

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

/** 
 * 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']"));
    }
}
2 голосов
/ 19 августа 2011

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

1 голос
/ 12 июня 2014

Проверка элемента видима.

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

        if (driver.findElements(by).size() > 0) {
            value = true;
        }
        return value;
    }
0 голосов
/ 18 апреля 2018
    try{
        if( driver.findElement(By.xpath("//div***")).isDisplayed()){
          System.out.println("Element is Visible");
        }
}
catch(NoSuchElementException e){
   else{
     System.out.println("Element is InVisible");
        }
}
0 голосов
/ 14 февраля 2017
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
0 голосов
/ 22 мая 2015

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

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...