Comment vérifier si un élément est visible avec WebDriver

Avec WebDriver de Selenium 2. 0a2 j'ai du mal à vérifier si un élément est visible.

WebDriver.findElement renvoie un WebElement, qui n'offre malheureusement pas de méthode isVisible. Je peux contourner cela en utilisant WebElement.clear ou WebElement.click qui jettent tous deux un ElementNotVisibleException, mais cela se sent très sale.

De meilleures idées?

54
demandé sur ponzao 2010-04-15 18:34:58

13 réponses

element instanceof RenderedWebElement ça devrait marcher.

16
répondu hleinone 2010-04-15 15:55:32

Même si je suis un peu en retard pour répondre à la question:

Vous pouvez maintenant utiliser WebElement.isDisplayed() pour vérifier si un élément est visible.

Note:

Il y a plusieurs raisons pour lesquelles un élément pourrait être invisible. Le sélénium essaie de couvrir la plupart d'entre eux, mais il y a des cas de bord où cela ne fonctionne pas comme prévu.

Par exemple, isDisplayed() retourne false si un élément a display: none ou opacity: 0, mais au moins dans mon test, il ne détecte pas de manière fiable si un élément est couvert par un autre en raison du positionnement CSS.

121
répondu sleske 2018-09-12 13:03:10

J'ai les 2 façons suggérées suivantes:

  1. Vous pouvez utiliser isDisplayed() comme ci-dessous:

    driver.findElement(By.id("idOfElement")).isDisplayed();
    
  2. Vous pouvez définir une méthode comme indiqué ci-dessous et l'appeler:

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

Maintenant, vous pouvez faire l'affirmation ci-dessous pour vérifier l'élément est présent ou non:

assertTrue(isElementPresent(By.id("idOfElement")));
13
répondu Ripon Al Wasim 2017-10-13 10:59:17

Si vous utilisez C#, ce serait driver.Afficher. Voici un exemple de mon propre projet:

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
répondu Christopher Bales 2012-11-27 15:21:19

Il est important de voir si l'élément est visible ou non car le Driver.FindElement ne vérifiera que la source HTML. Mais le code contextuel pourrait être dans la page html, et ne pas être visible. Par conséquent, la fonction Driver.FindElement renvoie un faux positif (et votre test échouera)

2
répondu Jason 2011-12-15 14:56:57

La vérification de l'ele est visible.

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

        if (driver.findElements(by).size() > 0) {
            value = true;
        }
        return value;
    }
1
répondu Adnan Ghaffar 2014-06-12 14:06:07

Réponse courte: utiliser #visibilityOfElementLocated

Aucune des réponses utilisant isDisplayed ou similaire n'est correcte. Ils vérifient seulement si la propriété display n'est pas none, pas si l'élément peut réellement être vu! Selenium avait un tas de méthodes utilitaires statiques ajoutées dans le ExpectedConditions classe. Deux d'entre eux peuvent être utilisés dans ce cas:

L'Utilisation de

@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();

Vérification de visibilité personnalisée exécutée sur le client

C'était ma réponse avant de découvrir les méthodes utilitaires sur ExpectedConditions. Cela pourrait toujours être pertinent, car je suppose qu'il fait plus que la méthode mentionnée ci-dessus, qui vérifie seulement que l'élément a une hauteur et une largeur.

En substance: cela ne peut pas être répondu par Java et les méthodes findElementBy* et WebElement#isDisplayed seuls, car ils ne peuvent que vous dire si un élément existe , pas si elle est réellement visible . L'OP n'a pas défini ce quevisible signifie, Mais cela implique normalement

  • Il a un opacity > 0
  • la propriété display est définie sur autre chose que none
  • l'accessoire visibility est défini sur visible
  • Il n'y a pas d'autres éléments qui le cachent (c'est l'élément le plus haut)

La plupart des gens incluraient également l'exigence qu'il se trouve également dans la fenêtre d'affichage (donc une personne pourrait pour le voir).

Pour une raison quelconque, ce besoin tout à fait normal n'est pas satisfait par L'API Java pure, tandis que les frontaux de Selenium qui s'appuie dessus implémentent souvent une variation de isVisible, c'est pourquoi je savais que cela devrait être possible. Et après avoir parcouru la source du framework Node WebDriver.IO j'ai trouvé la source de isVisible, qui est maintenant renommée pour le nom plus justement de isVisibleInViewport dans la version 5.0-beta.

Fondamentalement, ils implémentent la commande personnalisée comme un appel qui délègue à un javascript qui s'exécute sur le client et fait le travail réel! C'est le bit "serveur":

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

Donc, le bit intéressant est le javascript envoyé pour fonctionner sur le client:

/**
 * 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
}

Ce morceau de JS peut effectivement être copié (presque) verbatim dans votre propre base de code (supprimer export default et remplacer const par var dans le cas de navigateurs non-evergreen)! Pour l'utiliser, lisez-le de File dans un {[24] } qui peut être envoyé par Selenium pour s'exécuter sur le client.

Un autre script intéressant et connexe qui pourrait valoir la peine d'être examiné est selectByVisibleText .

Si vous n'avez pas exécuté JS en utilisant Selenium avant que vous puissiez avoir un petit coup d'oeil dans ce ou parcourir l'API JavaScriptExecutor.

Habituellement, essayez de toujours utiliser des scripts asynchrones non bloquants (ce qui signifie #executeAsyncScript), mais comme nous avons déjà un script synchrone bloquant, nous pourrions aussi bien utiliser la synchronisation normale appeler. L'objet retourné peut être plusieurs types D'objet, donc cast approprately. Cela pourrait être une façon de le faire:

/** 
 * 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']"));
    }
}
0
répondu oligofren 2018-09-11 08:21:04

Voici comment je le ferais (veuillez ignorer les appels de classe 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;
}
-1
répondu Charlie Seligman 2015-05-22 11:14:24
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
répondu akhilesh gulati 2017-02-14 16:20:48
    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
répondu Vishnu B S 2018-04-18 05:29:11

Élément.isDisplayed est inutile. Elle renvoie Vrai si l'élément n'est pas visible.

-1
répondu Steve Staple 2018-09-04 12:41:46

Essayez ceci

public boolean isPrebuiltTestButtonVisible() {
    try {

        if (preBuiltTestButton.isEnabled()) {

            return true;

        } else {

            return false;
        }

    } catch (Exception e) {

        e.printStackTrace();
        return false;
    }
}
-2
répondu Tarun Yaduvanshi 2014-10-18 10:26:29

element instanceof RenderedWebElement ça devrait marcher. // Mais c'est pour l'ancienne version de selenium rc.

Veuillez noter:

RenderedWebElement Il était obsolète Il y a quatre ans (en 2013). il était supporté jusqu'à selenium-2.0-rc-2 et retiré de selenium-2.0-rc-3 à partir de

Il n'y a donc pas une telle classe RenderedWebElement dans la dernière version.La version actuelle est 2.46.0.Essayez d'utiliser la dernière version

Veuillez utiliser WebElement à la place pas besoin de lancer et tout avec isDisplayed() isEnabled() and driver.findElements(By.xpath(accessor)).size() > 0

Quelque chose comme ce:

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.
}
-2
répondu Om Sao 2017-08-30 14:06:40