it-swarm.com.de

So prüfen Sie, ob ein Element mit WebDriver sichtbar ist

Mit WebDriver aus Selen 2.0a2 kann ich nicht überprüfen, ob ein Element sichtbar ist.

WebDriver.findElement gibt eine WebElement zurück, die leider keine isVisible -Methode bietet. Ich kann das umgehen, indem ich WebElement.clear oder WebElement.click Beide werfen ein ElementNotVisibleException, aber das fühlt sich sehr schmutzig an.

Irgendwelche besseren Ideen?

62
ponzao

element instanceof RenderedWebElement sollte arbeiten.

20
hleinone

Auch wenn ich die Frage etwas spät beantworte:

Sie können jetzt mit WebElement.isDisplayed() prüfen, ob ein Element sichtbar ist.

Hinweis :

Es gibt viele Gründe, warum ein Element unsichtbar sein kann. Selen-Versuche decken die meisten davon ab, aber es gibt Edge-Fälle, in denen es nicht wie erwartet funktioniert.

Beispielsweise gibt isDisplayed()false zurück, wenn ein Element display: none oder opacity: 0, aber zumindest in meinem Test erkennt es aufgrund der CSS-Positionierung nicht zuverlässig, ob ein Element von einem anderen verdeckt wird.

131
sleske

Ich habe die folgenden 2 vorgeschlagenen Möglichkeiten:

  1. Sie können isDisplayed() wie folgt verwenden:

    driver.findElement(By.id("idOfElement")).isDisplayed();
    
  2. Sie können eine Methode wie folgt definieren und sie aufrufen:

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

Nun können Sie wie folgt die Assertion durchführen, um zu überprüfen, ob das Element vorhanden ist oder nicht:

assertTrue(isElementPresent(By.id("idOfElement")));
15
Ripon Al Wasim

Wenn Sie C # verwenden, wird dies als driver.Display angezeigt. Hier ist ein Beispiel aus meinem eigenen Projekt:

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

Kurze Antwort: benutze #visibilityOfElementLocated

Keine der Antworten mit isDisplayed oder ähnlichem ist richtig. Sie prüfen nur, ob die Eigenschaft display nicht none ist, nicht, ob das Element tatsächlich sichtbar ist! Selenium hatte eine Reihe von statischen Hilfsmethoden in der Klasse ExpectedConditions hinzugefügt. In diesem Fall können zwei davon verwendet werden:

Verwendung

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

Auf dem Client ausgeführte benutzerdefinierte Sichtbarkeitsprüfung

Dies war meine Antwort, bevor ich etwas über die Utility-Methoden von ExpectedConditions erfuhr. Es könnte immer noch relevant sein, da ich davon ausgehe, dass es mehr tut als die oben erwähnte Methode, die nur prüft, ob das Element eine Höhe und eine Breite hat.

Im Wesentlichen: Dies kann nicht durch Java und die findElementBy* - Methoden und WebElement#isDisplayed Allein beantwortet werden, da sie Ihnen nur sagen können, ob ein Element existiert , nicht wenn es tatsächlich sichtbar ist. Das OP hat nicht definiert, was sichtbar bedeutet, aber es beinhaltet normalerweise

  • es hat eine opacity> 0
  • die Eigenschaft display ist auf etwas anderes als none festgelegt.
  • die Requisite visibility ist auf visible gesetzt.
  • es gibt keine anderen Elemente, die es verbergen (es ist das oberste Element)

Die meisten Leute würden auch die Anforderung aufnehmen, dass es sich tatsächlich auch im Ansichtsfenster befindet (damit eine Person es sehen kann).

Aus irgendeinem Grund wird diese ganz normale Anforderung von der reinen Java API nicht erfüllt, während Front-Ends für Selenium, das darauf aufbaut, häufig eine Variation von isVisible implementieren warum ich wusste, dass dies möglich sein sollte. Und nachdem ich die Quelle des Node framework WebDriver.IO durchsucht hatte, fand ich die Quelle von isVisible, das jetzt in der 5.0-Beta in den passenderen Namen isVisibleInViewport umbenannt wird.

Grundsätzlich implementieren sie den benutzerdefinierten Befehl als einen Aufruf, der an ein auf dem Client ausgeführtes Javascript delegiert und die eigentliche Arbeit erledigt! Dies ist das "Server" -Bit:

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

Das Interessante ist also, dass Javascript auf dem Client ausgeführt wird:

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

Dieser Teil von JS kann tatsächlich (fast) wörtlich in Ihre eigene Codebasis kopiert werden (entfernen Sie export default Und ersetzen Sie const bei nicht immergrünen Browsern durch var)! Um es zu verwenden, lesen Sie es von File in ein String, das von Selenium zur Ausführung auf dem Client gesendet werden kann.

Ein weiteres interessantes und verwandtes Skript, das es wert sein könnte, untersucht zu werden, ist selectByVisibleText .

Wenn Sie JS noch nicht mit Selenium ausgeführt haben, können Sie ein kleiner Einblick oder die JavaScriptExecutor API durchsuchen.

Versuchen Sie normalerweise, immer nicht blockierende asynchrone Skripte zu verwenden (dh # executeAsyncScript ). Da wir jedoch bereits über ein synchrones blockierendes Skript verfügen, können Sie auch den normalen Synchronisierungsaufruf verwenden. Das zurückgegebene Objekt kann aus vielen Objekttypen bestehen, die entsprechend umgewandelt werden. Dies könnte eine Möglichkeit sein, dies zu tun:

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

Es ist wichtig zu sehen, ob das Element sichtbar ist oder nicht, da Driver.FindElement Nur die HTML-Quelle überprüft. Popup-Code könnte sich jedoch in der HTML-Seite befinden und nicht sichtbar sein. Daher gibt die Funktion Driver.FindElement Ein falsches positives Ergebnis zurück (und Ihr Test schlägt fehl).

2
Jason

Überprüfung, ob ele sichtbar ist.

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

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