Wie kann man Selenium WebDriver zwingen, auf ein Element zu klicken, das derzeit nicht sichtbar ist?


99

Ich verwende die Selenium 2 Java API mit FirefoxDriver. Wenn ich ein Formular ausfülle, werden der Seite abhängig von den Formulareingaben Kontrollkästchen hinzugefügt.

Ich möchte mit Selen einen Klick auf diese Kontrollkästchen simulieren. Das Element ist in einem normalen Browser sichtbar und verwendbar, aber Selen behauptet, dass die Elemente nicht sichtbar sind.

"Element is not currently visible and so may not be interacted with"

Kann ich Selen zwingen, den nicht sichtbaren Zustand der Elemente zu ignorieren? Wie kann ich Selen zwingen, mit dem nicht sichtbaren Element zu interagieren?


Welchen Browser verwenden Sie? Sie können nicht mit Elementen interagieren, die deaktiviert oder nicht sichtbar sind, da ein Endbenutzer nicht mit ihnen interagieren kann. Sie müssen Ihren Testcode und Ihre Seitenquelle angeben, wenn ich versuchen soll, das Problem zu diagnostizieren.
Ardesco

Antworten:


102

Selen bestimmt anhand der folgenden Kriterien, ob ein Element sichtbar ist oder nicht (verwenden Sie einen DOM-Inspektor, um zu bestimmen, welche CSS für Ihr Element gilt, und achten Sie auf den berechneten Stil):

  • Sichtbarkeit! = versteckt
  • display! = none (wird auch für jedes übergeordnete Element geprüft)
  • Deckkraft! = 0 (dies wird nicht zum Klicken auf ein Element aktiviert)
  • Höhe und Breite sind beide> 0
  • für eine Eingabe ist der Attributtyp! = versteckt

Ihr Element entspricht einem dieser Kriterien. Wenn Sie nicht in der Lage sind, das Design des Elements zu ändern, können Sie dies folgendermaßen mit Javascript tun (vorausgesetzt, Sie haben WebDriver angenommen, da Sie Selenium2 API gesagt haben):

((JavascriptExecutor)driver).executeScript("arguments[0].checked = true;", inputElement);

Dies löst jedoch kein Javascript-Ereignis aus. Wenn Sie für diese Eingabe vom Änderungsereignis abhängig sind, müssen Sie es ebenfalls auslösen (viele Möglichkeiten, dies zu tun, am einfachsten, die auf dieser Seite geladene Javascript-Bibliothek zu verwenden).

Die Quelle für die Sichtbarkeitsprüfung -

https://github.com/SeleniumHQ/selenium/blob/master/javascript/atoms/dom.js#L577

Die WebDriver-Spezifikation, die dies definiert -

https://dvcs.w3.org/hg/webdriver/raw-file/tip/webdriver-spec.html#widl-WebElement-isDisplayed-boolean


1
Haben Sie eine Quelle (oder einen kanonischen Link) für die Liste der Bedingungen?
mjs

2
Solange Sie Javascript lesen können, bestimmt die Methode bot.dom.isShown die Sichtbarkeit: code.google.com/p/selenium/source/browse/trunk/javascript/atoms/…
lukeis

Was ist InputElement hier? Ich führe den folgenden Code aus: WebElement inputElement = driver.findElement (By.xpath (PASSWORD_PATH)); ((JavascriptExecutor) Treiber) .executeScript ("Argumente [0] .checked = true;", inputElement); Aber keine Hilfe inputElement.sendKeys (Passwort);
Deepak Goel

2
@NIleshSharma Python hat die Methode execute_script direkt auf dem Treiberobjekt selbst: driver.execute_script (...)
lukeis

1
Der von @TunaBum gepostete Quelllink wurde in code.google.com/p/selenium/source/browse/javascript/atoms/…
Shepmaster

27

Manchmal bedeutet dies, dass eine Seite mehrere Elemente enthält, die dieselbe Eigenschaft haben, nach der Sie suchen möchten, und dass Sie "mit der falschen sprechen".

Wenn Ihr Element nicht eindeutig durch: id oder: name (oder: class) identifiziert werden kann, kann es schwierig sein.

Manchmal hilft die Suche nach dem Element über: xpath, und in einigen Fällen ist sogar das nicht praktikabel.

In diesen Fällen müssen Sie möglicherweise alle Elemente abrufen, die Ihren Kriterien entsprechen, und anhand des Index auf das richtige verweisen. Es ist schmutzig, aber es funktioniert.

Ich verwende Selenium / Watir von der Ruby on Rails-App. In meinem Fall wäre das Beispiel:

browser = Watir::Browser.new(:firefox, :profile => "default")       
browser.goto("http://www.google.com/analytics")
# login
browser.divs(:text, "+ New Property").last.click

Hoffe das hilft.


Das Hinzufügen einer ID zum dom-Element hat dies für mich
behoben

Ich hatte das gleiche Problem und habe den XPath so angepasst, dass er ein eindeutiges Element unterscheiden kann.
JohnL

Ich hatte das gleiche Problem. Der Aufruf von findElements () wurde geändert, um Übereinstimmungen zu zählen, und es gab ein weiteres übereinstimmendes Element. Vielen Dank!
Widder

Soviel zu mir. Stellen Sie IMMER sicher, dass Ihre Auswahlkriterien spezifisch genug für das Element sind, mit dem Sie zu interagieren glauben. Oft hatte ich zwei Elemente im Spiel und eines ist versteckt und gibt mir diesen Fehler.
Chris

14

Ich hatte ein ähnliches Problem, aber es hing damit zusammen, dass das Element im Ansichtsfenster nicht sichtbar war. Ich machte einen Screenshot und stellte fest, dass das Browserfenster zu eng war und das Element nicht gesehen werden konnte. Ich habe eines davon gemacht und es hat funktioniert:

driver.maximize_window()

Siehe: WebDriver.maximize_window ()


7

Oder Sie können die Selenium-Aktionsklasse verwenden, um die Benutzerinteraktion zu simulieren - zum Beispiel

    WebDriver = new FirefoxDriver();

    WebElement menu = driver.findElement(By.xpath("")); // the triger event element

    Actions build = new Actions(driver); // heare you state ActionBuider
    build.moveToElement(menu).build().perform(); // Here you perform hover mouse over the needed elemnt to triger the visibility of the hidden
    WebElement m2m= driver.findElement(By.xpath(""));//the previous non visible element
    m2m.click();

7

Es gibt auch einen anderen Fall, in dem sichtbares Element als nicht sichtbar erkannt wird:

  • Wenn das Element CSS-transformiert ist
  • Wenn das übergeordnete Element des Elements CSS-transformiert wird

Um zu überprüfen, ob das Element, mit dem Sie nicht interagieren möchten, CSS-transformiert ist, gehen Sie auf CHROME folgendermaßen vor:

  1. Inspektor öffnen
  2. Finden Sie ein interessantes Element (oder eher das übergeordnete Element, angeblich das div-Element).
  3. Wählen Sie die Registerkarte "Berechnet"
  4. Wenn es einen Parameter gibt: webkit-transform: matrix (...) bedeutet dies, dass das Element CSS-transformiert ist und von Selen 2 möglicherweise nicht als sichtbares Element erkannt wird


2

Ich hatte das gleiche Problem mit Selen 2 in Internet Explorer 9, aber mein Fix ist wirklich seltsam. Ich konnte nicht in Eingaben in meinem Formular klicken -> Selen-Wiederholungen, sie sind nicht sichtbar.

Es trat auf, als meine Form gekrümmte Schatten hatte -> http://www.paulund.co.uk/creating-different-css3-box-shadows-effects : im konkreten "Effekt Nr. 2"

Ich habe keine Ahnung, warum und wie diese Pseudoelementlösung die Selentests gestoppt hat, aber es funktioniert für mich.


2

Sie können den Zugriff auf / das Ändern von Elementen, auf die der Benutzer normalerweise keinen Zugriff hat, nicht erzwingen, da Selenium die Benutzerinteraktion imitieren soll.

Wenn dieser Fehler auftritt, überprüfen Sie, ob:

  • Wenn das Element in Ihrem Ansichtsfenster sichtbar ist, versuchen Sie, das aktuelle Fenster zu maximieren, das der Webdriver verwendet (z. B. maximize()in node.js , maximize_window()in Python).
  • Ihr Element wird nicht zweimal angezeigt (unter demselben Selektor), und Sie wählen das falsche aus.
  • Wenn Ihr Element ausgeblendet ist, sollten Sie es sichtbar machen.
  • Wenn Sie trotz der Einschränkung auf den Wert eines versteckten Elements zugreifen oder diesen ändern möchten, verwenden Sie dafür Javascript (z. B. executeScript()in node.js , execute_script()in Python).

1
Ich hatte keine Ahnung, dass Selen so streng ist. Es scheint also nicht wirklich ein Automatisierungstool im allgemeinen Sinne zu sein, sondern eher ein automatisiertes Benutzerinteraktionstool. Macht ein bisschen Sinn, denke ich. Danke fürs klarstellen!
Daniel Lidström

1

Ich löse diesen Fehler nur, während ich Capybara in einem Projekt verwende, indem ich Folgendes hinzufüge:

Capybara.ignore_elements = true

zu features/support/env.rb.


1

Ich löse diesen Fehler nur, indem ich auf die Anzeigeeigenschaft des Elements warte

waitFor() { element.displayed }

Von allen Antworten auf dieser Seite hat dies mein Problem mit einem Bootstrap Modal-Dialogfeld behoben. Danke @Suat Keskin!
Alastairs

1

Ich gerate in die ElementNotVisibleException-Ausnahme und verwende Selen für Funktionstests auf einer Django-Site mit Bootstrap-Glyphicons als Links in Vorlagen wie folgt:

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger"></span></a>

Während meiner Funktionstests wird der Bootstrap-Stil nicht geladen. Wenn Sie dann versuchen, auf solche Links zu klicken, wird ElementNotVisibleException ausgelöst. Ich schaffe es, sie anklickbar zu machen, indem ich einfach ein Leerzeichen in das Tag einfüge :

<a href="{% url 'item-add' %}"><span class="glyphicon glyphicon-plus text-danger">&nbsp;</span></a>

1

Auf dieser Seite gibt es viele gute Antworten.

  1. Normalerweise beginne ich mit maxim.window (). Eigentlich mache ich das in der Treiberfactory oder wo immer Sie Ihren Treiber initialisieren. Dies geschieht standardmäßig - immer.
  2. Es ist normalerweise ein Warten auf Element wegen einer Verzögerung von Javascript.

Beide werden oben in verschiedenen Details diskutiert. Die Antwort, die ich nicht gesehen habe, war ScrollToElement. Es hört sich so an, als würden Sie eine Liste von Elementen verarbeiten, während Sie mehr Elemente und Kontrollkästchen erstellen. Dies kann dazu führen, dass Elemente in Ihrer Liste von der sichtbaren Seite verschoben werden. Manchmal kann man das Element mit bloßem Auge sehen, aber man kann einfach nicht darauf klicken. Bei der Verarbeitung von Listen muss manchmal das Scrollen unterbrochen werden.

  • Stellen Sie einen Haltepunkt ein und prüfen Sie, ob sich das verwendete Element am Fensterrand oben / unten rechts / links befindet. Manchmal, wenn dies der Fall ist, können Sie nicht über Selen darauf zugreifen, aber Sie können manuell mit der Maus klicken.

Da ich darauf stoße, habe ich eine PageScroll.java erstellt und dort meine Bildlaufskripte abgelegt. Hier sind einige Methoden aus dieser Klasse:

public static void scrollToTop(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0,0)");
    }

    public static void scrollToBottom(WebDriver driver) {
      ((JavascriptExecutor) driver)
        .executeScript("window.scrollTo(0, document.body.scrollHeight)");
    }

    public static void scrollToElementTop(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(true);", element);
    }

    public static void scrollToElementBottom(WebDriver driver, WebElement element) {
      ((JavascriptExecutor) driver).executeScript(
        "arguments[0].scrollIntoView(false);", element);
    }

Weitere Beispiele finden Sie unter Scrollen von Elementen in die Ansicht mit Selen


0

Die akzeptierte Antwort hat bei mir funktioniert. Unten finden Sie einen Code, um das übergeordnete Element zu finden, das Selenium für nicht sichtbar hält.

function getStyles(element){
	
	computedStyle = window.getComputedStyle(element);

	if(computedStyle.opacity === 0
	|| computedStyle.display === "none"
	|| computedStyle.visibility === "hidden"
	|| (computedStyle.height < 0 && computedStyle.height < 0)
	|| element.type === "hidden") {
		console.log("Found an element that Selenium will consider to not be visible")
		console.log(element);
		console.log("opacity: " + computedStyle.opacity);
		console.log("display: " + computedStyle.display);
		console.log("visibility: " + computedStyle.visibility);
		console.log("height: " + computedStyle.height);
		console.log("width: " + computedStyle.width);
	}

	if(element.parentElement){
		getStyles(element.parentElement);
	}
}

getStyles(document.getElementById('REPLACE WITH THE ID OF THE ELEMENT YOU THINK IS VISIBLE BUT SELENIUM CAN NOT FIND'));


0

Um mein Sandkorn hier hinzuzufügen: Wenn sich ein Element hinter einem festen Teil befindet, wird es als nicht sichtbar betrachtet und Sie können nicht darauf klicken. Das ist mir kürzlich passiert und ich habe es gelöst, indem ich ein Skript ausgeführt habe, wie oben empfohlen.

document.evaluate("<xpath locator for element to be clicked>", document, null, XPathResult.ANY_TYPE, null).iterateNext().click()", locator);

Was ist Locator hier?
Anjana
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.