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



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



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



идеи получше?

1163   13  

13 ответов:

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

хотя я несколько запоздал с ответом на вопрос:

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

Примечание:

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

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

у меня есть следующие 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")));

Если вы используете 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

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

проверка ele видна.

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

        if (driver.findElements(by).size() > 0) {
            value = true;
        }
        return value;
    }

короткий ответ: используйте #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* методы и , так как они могут только сказать вам, если элемент , нет, если это на самом деле видимого. ОП не определил, что видимого означает, но это обычно влечет за собой

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

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

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

еще один интересный и связанный с ним скрипт, который, возможно, стоит изучить, это selectByVisibleText.

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

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

/** 
 * 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']"));
    }
}

вот как я бы это сделал (Пожалуйста, игнорируйте вызовы класса worry 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;
}
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
    try{
        if( driver.findElement(By.xpath("//div***")).isDisplayed()){
          System.out.println("Element is Visible");
        }
}
catch(NoSuchElementException e){
   else{
     System.out.println("Element is InVisible");
        }
}

элемент.отображается бесполезно. Он возвращает True, даже если элемент не виден.

попробуй такое

public boolean isPrebuiltTestButtonVisible() {
    try {

        if (preBuiltTestButton.isEnabled()) {

            return true;

        } else {

            return false;
        }

    } catch (Exception e) {

        e.printStackTrace();
        return false;
    }
}

element instanceof RenderedWebElement должны работать. // Но это для более старой версии selenium rc.

обратите внимание:

RenderedWebElement был устаревший четыре года назад (в 2013 г.).он поддерживался до селен-2.0-rc-2 и удалены из selenium-2.0-rc-3 и далее

так что нет такого класса RenderedWebElement в последней версии.Текущая версия 2.46.0.Попробуйте использовать последнюю версию

Пожалуйста, Используйте WebElement вместо этого нет необходимости бросить и все с isDisplayed() isEnabled() and driver.findElements(By.xpath(accessor)).size() > 0

что-то вроде этого:

public static boolean isElementFoundDisplayedEnabled(WebDriver driver, String accessor){

        return driver.findElements(By.xpath(accessor)).size() > 0 && driver.findElement(By.xpath(accessor)).isDisplayed() && driver.findElement(By.xpath(accessor)).isEnabled();
        //isDisplayed(): method avoids the problem of having to parse an element's "style" attribute to check hidden/visible. False when element is not present
        //isEnabled(): generally return true for everything but disabled input elements.
}

Comments

    Ничего не найдено.