Scrollen Sie mit Selen in die Ansicht


207

Gibt es in Selenium 1.x oder 2.x eine Möglichkeit, das Browserfenster so zu scrollen, dass ein bestimmtes Element, das von einem XPath identifiziert wird, für den Browser sichtbar ist? In Selenium gibt es eine Fokusmethode, die die Ansicht in FireFox jedoch nicht physisch zu scrollen scheint. Hat jemand Vorschläge dazu?

Der Grund, warum ich das brauche, ist, dass ich den Klick eines Elements auf der Seite teste. Leider scheint das Ereignis nur zu funktionieren, wenn das Element sichtbar ist. Ich habe keine Kontrolle über den Code, der beim Klicken auf das Element ausgelöst wird. Daher kann ich weder debuggen noch Änderungen daran vornehmen. Die einfachste Lösung besteht darin, das Element in die Ansicht zu scrollen.


Sie können diesen Hacky versuchen, wenn nichts anderes für Sie funktioniert : stackoverflow.com/a/53771434/7093031
YB Ursache

Antworten:


214

Ich habe viele Dinge in Bezug auf das Scrollen versucht, aber der folgende Code hat bessere Ergebnisse geliefert.

Dadurch wird gescrollt, bis das Element angezeigt wird:

WebElement element = driver.findElement(By.id("id_of_element"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500); 

//do anything you want with the element

6
Dies ist eine gute Lösung, wenn Sie möglicherweise ein Element mit position: fixedauf Ihrer Seite haben und das Element, auf das Selenium klicken möchte, verdeckt. Sehr oft befinden sich diese festen Elemente unten, sodass sie durch die Einstellung ganz scrollIntoView(true)oben im Ansichtsfenster angezeigt werden.
Mandible79

3
Basierend auf der neuesten Version von Selen (2.53) ist dies jetzt eine großartige Hilfslösung. Selen scrollt das Element nicht immer in die Ansicht, daher ist dies definitiv nützlich.
Zoidberg

20
Übergeben Sie an true, scrollIntoViewwenn sich das Objekt, zu dem Sie scrollen, unter dem befindet, zu dem Sie gerade falsescrollen , und wenn sich das Objekt, zu dem Sie scrollen, über dem befindet, wo Sie sich gerade befinden. Es fiel mir schwer, das herauszufinden.
Big Money

2
Warum brauchst du Thread-Schlaf? executeScript sollte synchron sein
riccardo.tasso

1
@ riccardo.tasso Möglicherweise wurde ein Schlaf implementiert, um das Unbekannte der Ziel-App zu behandeln. Wenn es über dynamisches Scrollen verfügt oder eine App mit nur einer Seite, die unter anderem das nächste Bit der Seite nach dem Scrollen lädt. Aus Erfahrung hat Selenium häufig die Website meines Unternehmens beschädigt, weil die automatisierte Aktion schneller erfolgte, als das Javascript abgeschlossen werden konnte, und daher ein unvollständiges Datenmodell bestanden hat. Einige Orte mögen es als Fehler betrachten, aber mir wurde gesagt: "Kein Mensch könnte jemals ein solches Szenario aufrufen, es ist also kein wirklicher Fehler." So ist das Leben.
Solonotix

157

Mit der org.openqa.selenium.interactions.ActionsKlasse können Sie zu einem Element wechseln.

Java:

WebElement element = driver.findElement(By.id("my-id"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();

Python:

from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(driver.sl.find_element_by_id('my-id')).perform()

7
Funktioniert dies, wenn sich das WebElement nicht im Ansichtsport befindet?
Virusrocks

9
@Dominik: Wie bewegt Selen die Maus zu einem Element außerhalb des Bildschirms? Offensichtlich muss es zuerst das Element in die Ansicht scrollen und dann die Maus dorthin bewegen. Ich habe es getestet. Dieser Code funktioniert unter Firefox Webdriver 2.48, aber es gibt einen Fehler: Wenn Sie einen Iframe auf einer Seite haben, funktioniert das Scrollen im iframe while-Element nicht korrekt. LocationOnScreenOnceScrolledIntoView scrollt korrekt. (Obwohl die Dokumentation besagt, dass dieser Befehl nur einen Speicherort zurückgibt, scrollt er auch!)
Elmue

7
In den Dokumenten unter seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… heißt es jetzt deutlich: "Bewegt die Maus in die Mitte des Elements. Das Element wird in die Ansicht gescrollt und seine Position wird mit berechnet." getBoundingClientRect. "
George Pantazes

5
Der obige Code ist "der offizielle Weg" Java Selenium möchte, dass Sie ein Element in das Ansichtsfenster scrollen. Nachdem ich jedoch viele Dinge ausprobiert hatte, schien die JS-Implementierung für mich zuverlässiger zu funktionieren. Insbesondere diese Methode .
Kenji Miwa

2
Hat bei mir nicht funktioniert: - | Verwendet stattdessen stackoverflow.com/a/23902068/661414 .
Leukipp

28
JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("javascript:window.scrollBy(250,350)");

Vielleicht möchten Sie dies versuchen.


1
Vielen Dank. Ich musste diese Methode in einem Fall verwenden, in dem das automatische Scrollen eines Selens dazu führte, dass ein anderes Element das Element verdeckte, auf das ich klicken musste. Ich konnte einen beliebigen Betrag scrollen, um das Element im Ansichtsfenster sichtbar zu machen, ohne verdeckt zu werden.
Daniel Richnak

Dies funktioniert nur in FIrefox, Chrome und IE unterstützen diese Methode nicht
Virusrocks

Aus diesem Grund verwenden Sie js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e);für IE und Firefox sowie js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e);für Chrome. Einfach.
IamBatman

((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)");Dies funktionierte in Chrome. Und die einzige Lösung, die tatsächlich für mich funktioniert hat. In der gleichen Situation wie beim ersten Kommentator hatte ich unten ein festes Element, das das Element, auf das ich klicken musste, immer wieder verdeckte.
Silber


15

Wenn Sie mit dem Selenium-Webdriver im Firefox-Fenster scrollen möchten, können Sie unter anderem JavaScript im Java-Code verwenden. Der JavaScript-Code zum Scrollen nach unten (zum Ende der Webseite) lautet wie folgt:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0, Math.max(document.documentElement.scrollHeight, document.body.scrollHeight, document.documentElement.clientHeight));");

10

Das Targeting eines Elements und das Senden von Tasten nach unten (oder nach oben / links / rechts) scheint ebenfalls zu funktionieren. Ich weiß, dass dies ein kleiner Hack ist, aber ich bin nicht wirklich begeistert von der Verwendung von JavaScript, um das Bildlaufproblem zu lösen.

Beispielsweise:

WebElement.sendKeys(Keys.DOWN);

Dies ist nicht weniger ein Hack als die Verwendung von js und es ist wirklich die einfachste Sache. Ich fand dies hauptsächlich ein Problem mit dem IE, bei dem ein Klick versucht, das Element in die Ansicht zu scrollen, es aber nicht ganz schafft. Die Lösung ist mit {PGUP} genauso elegant, wenn das richtige Try / Catch / Loop-Szenario verwendet wird.
Jibbs

Du hast meinen Tag gerettet! Danke
Jesko R.

In meinem Fall war Seite runter das, was funktioniert hat. Dies ist ein schöner Hack (gegen alle js Hacks).
Akostadinov

Danke @DevDave! Äquivalent in C #:var elem = driver.FindElement(By.Id("element_id")); elem.SendKeys(Keys.PageDown);
Watth

9
webElement = driver.findElement(By.xpath("bla-bla-bla"));
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", webElement);

Weitere Beispiele finden Sie hier . Alles auf Russisch, aber Java-Code ist interkulturell :)


Kann ich verstehen, warum es für diese Lösung eine -1 gibt?
Josephnvu

Weil es nur in Firefox funktioniert. Kein anderer Browser unterstützt diese Methode.
Wayne Allen

Wenn jemand eine Übersetzung aus dem Russischen für das oben genannte Dokument benötigt, hilft er gerne weiter.
monkrus

8

In Selenium müssen wir die Hilfe eines JavaScript-Executors verwenden, um zu einem Element zu scrollen oder die Seite zu scrollen:

je.executeScript("arguments[0].scrollIntoView(true);", element);

In der obigen Anweisung elementist das genaue Element, wo wir scrollen müssen. Ich habe den obigen Code ausprobiert und er hat bei mir funktioniert.

Ich habe einen vollständigen Beitrag und ein Video dazu:

http://learn-automation.com/how-to-scroll-into-view-in-selenium-webdriver/


@Mukesh otwani der obige Code wird nach unten scrollen, aber wie schnell nach oben scrollen, ohne die darin definierten Pixel zu verwenden.
Khan

6

Mit diesem Codeausschnitt können Sie scrollen:

C #

var element = Driver.FindElement(By.Id("element-id"));
Actions actions = new Actions(Driver);
actions.MoveToElement(element).Perform();

Hier hast du es


6

Das hat bei mir funktioniert:

IWebElement element = driver.FindElements(getApplicationObject(currentObjectName, currentObjectType, currentObjectUniqueId))[0];
 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", element);

5

Selen 2 versucht, zum Element zu scrollen und dann darauf zu klicken. Dies liegt daran, dass Selen 2 nicht mit einem Element interagiert, es sei denn, es glaubt, dass es sichtbar ist.

Das Scrollen zum Element erfolgt implizit, sodass Sie nur das Element suchen und dann damit arbeiten müssen.


19
Wie ist das eine Antwort auf die Frage?
Reinierpost

57
scheint bei mir nicht so zu funktionieren.
Ich erhalte die Meldung

5
@DevDave Ich habe das gleiche Problem, außer in meinem Fall führt Selen keine Klickaktion für das Element aus und es gibt keine Ausnahmen. Ich hatte das Problem vorher nicht und ich weiß nicht, was das verursacht hat.
Zeinab Abbasimazar

5
Das implizite Scrollen variiert zwischen den Browsern. Ich habe einen Test eines Elements in einem Popup-Menü auf einer Seite. Mit dem Ruby gem selenium_webdriver 2.43 finde ich, dass der Chrom-Browser 37 (und ich glaube, der Internet Explorer) den Menüpunkt tatsächlich in die Ansicht scrollt und darauf klickt. Firefox 32 scheint jedoch überhaupt nicht zu scrollen und schlägt dann mit "Element ist derzeit nicht sichtbar und kann daher möglicherweise nicht interagiert werden" fehl.
Skifahrerseite

9
Diese Antwort ist falsch. Gemäß der Spezifikation für Selen 2.0 WebElement.click()muss das Element sichtbar sein, um darauf klicken zu können. Es wird nicht in Ihrem Namen gescrollt.
Gili

5

Verwenden Sie den Treiber, um Schlüssel wie den Schlüssel pagedownoder zu senden downarrow, um das Element anzuzeigen. Ich weiß, dass es eine zu einfache Lösung ist und möglicherweise nicht in allen Fällen anwendbar ist.


1
Das ist schwachsinn. Möglicherweise müssen Sie ein Dutzend Seiten auf einer großen Seite nach unten senden. Es ist langsam und nicht zuverlässig.
Elmue

2
Ja. Genau. Aber ich sagte "nicht in allen Fällen anwendbar"
Ganesh S

Einige elementauf der sichtbaren Seite bekannte zu finden und PageDown zu senden, hat element.SendKeys(Keys.PageDown);bei mir funktioniert.
Gokul

Ich würde empfehlen, die Alt-Taste zu verwenden, damit Sie nicht durch die Seite scrollen und die try / exception (Python) -Klausel verwenden, um Fehler zu behandeln, die beim Senden von Tasten an einige Elemente auftreten können.
Alex K.

4

Nach meiner Erfahrung scrollt Selenium Webdriver beim Klicken nicht automatisch zu einem Element, wenn mehr als ein scrollbarer Abschnitt auf der Seite vorhanden ist (was durchaus üblich ist).

Ich verwende Ruby und für mein AUT musste ich die Klickmethode wie folgt patchen.

class Element

      #
      # Alias the original click method to use later on
      #
      alias_method :base_click, :click

      # Override the base click method to scroll into view if the element is not visible
      # and then retry click
      #
      def click
        begin
          base_click
        rescue Selenium::WebDriver::Error::ElementNotVisibleError
          location_once_scrolled_into_view
          base_click
        end
      end

Die Methode 'location_once_scrolled_into_view' ist eine vorhandene Methode für die WebElement-Klasse.

Ich schätze, dass Sie Ruby möglicherweise nicht verwenden, aber es sollte Ihnen einige Ideen geben.


Ich erklärte das oben in module Capybara :: module Node, und ich musste anrufen, native.location_once_scrolled_into_viewanstatt nur location_once_scrolled_into_view. Ich habe auch gerettet ::Selenium::WebDriver::Error::UnknownError, was ich in Firefox 44.0.2 oft bekomme. Ich finde diese Lösung jedoch nicht flexibel genug und stelle die <Element>.native.location_once_scrolled_into_viewAnrufe letztendlich selbst in den Abnahmetest, gefolgt von der page.execute_script('window.scrollByPages(-1)')erforderlichen Anforderung.
Al Chou

Watir hat die Methode, Element#scroll_into_viewdie an Selen delegiert location_once_scrolled_into_view. Beide unterscheiden sich jedoch nicht vom Standardverhalten von Selen, sodass Überlaufelemente immer noch das blockieren können, worauf wir klicken möchten.
Akostadinov

3

Das Ruby-Skript zum Scrollen eines Elements in die Ansicht lautet wie folgt.

$driver.execute_script("arguments[0].scrollIntoView(true);", element)
sleep(3)
element.click

2

Manchmal hatte ich auch das Problem, mit Selen zu scrollen. Also habe ich javaScriptExecuter verwendet, um dies zu erreichen.

Zum Scrollen nach unten:

WebDriver driver = new ChromeDriver();
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.scrollBy(0, 250)", "");

Oder auch

js.executeScript("scroll(0, 250);");

Zum Scrollen:

js.executeScript("window.scrollBy(0,-250)", "");

Oder,

js.executeScript("scroll(0, -250);");

2

Wenn Sie der Meinung sind, dass andere Antworten zu hackig waren, ist dies auch der Fall, aber es ist keine JavaScript-Injektion erforderlich.

Wenn die Schaltfläche nicht auf dem Bildschirm angezeigt wird, wird sie unterbrochen und zu ihr gescrollt. Versuchen Sie es erneut ... ¯ \ _ (ツ) _ / ¯

try
{
    element.Click();
}
catch {
    element.Click();
}

2

Dies ist eine wiederholte Lösung mit JavaScript, jedoch mit einem zusätzlichen Warten auf Element.

Andernfalls ElementNotVisibleExceptionkann es vorkommen, dass eine Aktion für das Element ausgeführt wird.

this.executeJavaScriptFunction("arguments[0].scrollIntoView(true);", elementToBeViewable);
WebDriverWait wait = new WebDriverWait(getDriver(), 5);
wait.until(ExpectedConditions.visibilityOf(elementToBeViewable));

?? <- was ist gemein?
Choi

1

Ich habe diese Methode zum Scrollen des Elements und zum Klicken verwendet:

List<WebElement> image = state.getDriver().findElements(By.xpath("//*[contains(@src,'image/plus_btn.jpg')]"));

for (WebElement clickimg : image)
{
  ((JavascriptExecutor) state.getDriver()).executeScript("arguments[0].scrollIntoView(false);", clickimg);
  clickimg.click();
}

In meinem Fall hat scrollIntoView(false)funktioniert, aber scrollIntoView(true)nicht. Beides kann funktionieren , es hängt von Ihrem Szenario ab.
Rsenna

Mein Fall ist das Gegenteil - wahr funktioniert, falsch schlägt fehl, aber nur so weit wie der Klick geht. Es wird für false korrekt gescrollt, und es ist das, was ich bevorzuge, aber aus irgendeinem Grund kann Selenium es immer noch nicht zum Klicken sehen. Mit echten Schriftrollen ist alles viel zu hoch, aber zumindest funktioniert es.
Bill Hileman

Benutzer-Sendkeys geben nach Möglichkeit ein, anstatt zu klicken. Dadurch werden Probleme vermieden, wenn der Browser nicht zu 100% zoomt.
Zunair

1
def scrollToElement(element: WebElement) = {
  val location = element.getLocation
  driver.asInstanceOf[JavascriptExecutor].executeScript(s"window.scrollTo(${location.getX},${location.getY});")
}

1

Möglicherweise möchten Sie die Seite Scroll-Webelemente und die Webseite Selenium WebDriver mit Javascript besuchen :

public static void main(String[] args) throws Exception {

    // TODO Auto-generated method stub
    FirefoxDriver ff = new FirefoxDriver();
    ff.get("http://toolsqa.com");
    Thread.sleep(5000);
    ff.executeScript("document.getElementById('text-8').scrollIntoView(true);");
}

@AbhishekBedi Ich erinnere mich, dass es auch in Chrome unterstützt wird. Haben Sie ein spezifisches Problem?
Virusrocks

1

In den meisten Fällen funktioniert dieser Code beim Scrollen.

WebElement element = driver.findElement(By.xpath("xpath_Of_Element"));                 
js.executeScript("arguments[0].click();",element);

1

JAVA

Versuchen Sie, zum Element zu scrollen, verwenden Sie die x yPosition, und verwenden Sie JavascriptExecutordieses Argument : "window.scrollBy(x, y)".

Nach dem Import:

import org.openqa.selenium.WebElement;
import org.openqa.selenium.JavascriptExecutor;

Zuerst müssen Sie x ydas Element lokalisieren.

//initialize element
WebElement element = driver.findElement(By.id("..."));

//get position
int x = element.getLocation().getX();
int y = element.getLocation().getY();

//scroll to x y 
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(" +x +", " +y +")");

1

Ich bin nicht sicher, ob die Frage noch relevant ist, aber nachdem ich auf die scrollIntoView-Dokumentation unter https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView verwiesen habe .

Die einfachste Lösung wäre

executor.executeScript("arguments[0].scrollIntoView({block: \"center\",inline: \"center\",behavior: \"smooth\"});",element);

Dadurch wird das Element in die Mitte der Seite gescrollt.


0

Das Standardverhalten von Selenium ist das Scrollen, sodass das Element oben im Ansichtsfenster kaum sichtbar ist. Außerdem haben nicht alle Browser genau das gleiche Verhalten. Das ist sehr unbefriedigend. Wenn Sie wie ich Videos Ihrer Browsertests aufzeichnen, soll das Element in die Ansicht gescrollt und vertikal zentriert werden .

Hier ist meine Lösung für Java:

public List<String> getBoundedRectangleOfElement(WebElement we)
{
    JavascriptExecutor je = (JavascriptExecutor) driver;
    List<String> bounds = (ArrayList<String>) je.executeScript(
            "var rect = arguments[0].getBoundingClientRect();" +
                    "return [ '' + parseInt(rect.left), '' + parseInt(rect.top), '' + parseInt(rect.width), '' + parseInt(rect.height) ]", we);
    System.out.println("top: " + bounds.get(1));
    return bounds;
}

Und dann, um zu scrollen, nennen Sie es so:

public void scrollToElementAndCenterVertically(WebElement we)
{
    List<String> bounds = getBoundedRectangleOfElement(we);
    Long totalInnerPageHeight = getViewPortHeight(driver);
    JavascriptExecutor je = (JavascriptExecutor) driver;
    je.executeScript("window.scrollTo(0, " + (Integer.parseInt(bounds.get(1)) - (totalInnerPageHeight/2)) + ");");
    je.executeScript("arguments[0].style.outline = \"thick solid #0000FF\";", we);
}

getViewPortHeight Funktion fehlt ... In einer Annahme nehmen Sie die Höhe des
Zielelements

0

So mache ich das mit PHP webDriver for Selenium. Es funktioniert für den eigenständigen Selenium-Server 2.39.0 + https://github.com/Element-34/php-webdriver + Firefox 25.0

$element=$session->welement("xpath", "//input[@value='my val']");
$element->click();
$element=$session->welement("xpath", "//input[@value='ma val2']");
$element->location_in_view(); // < -- this is the candy
$element->click();

Hinweis: Ich verwende eine angepasste Version des Element34 PHP-Webdrivers. Aber es gibt keine Veränderung im Kern. Ich benutze nur mein "Willkommen" anstelle von "Element". Es hat jedoch keinen Einfluss auf den fraglichen Fall. Der Autor des Treibers sagt, "damit fast alle API-Aufrufe eine direkte Transformation dessen darstellen, was im WebDriver-Protokoll selbst definiert ist." Sie sollten also kein Problem mit anderen Programmiersprachen haben.

Ein Klick funktioniert in meinem Setup nicht. Es wird ein Bildlauf anstelle eines Klicks ausgeführt, sodass ich zweimal klicken musste, ohne "location_in_view ()" aufzurufen.

Hinweis: Diese Methode funktioniert für Elemente, die angezeigt werden können, z. B. eine Eingabe vom Typ.

Schauen Sie sich Folgendes an: http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/location

Die Beschreibung für JsonWireProtocol # schlägt die Verwendung von location + moveto vor, da location _in_view eine interne Methode ist.


0

Für mich hat es funktioniert, die Browser.MoveMouseToElement-Methode für ein Element am unteren Rand des Browserfensters zu verwenden. Wie durch ein Wunder funktionierte es in Internet Explorer, Firefox und Chrome.

Ich habe dies der JavaScript-Injektionstechnik vorgezogen, nur weil es sich weniger hackig anfühlte.


Welche Programmiersprache ist das?
Akostadinov

0

Ich habe Tests mit ADF-Komponenten durchgeführt und Sie müssen einen separaten Befehl zum Scrollen haben, wenn das verzögerte Laden verwendet wird. Wenn das Objekt nicht geladen ist und Sie versuchen, es mit Selenium zu finden, löst Selenium eine Ausnahme aus, bei der das Element nicht gefunden wurde.


0

Wenn nichts funktioniert, versuchen Sie dies, bevor Sie auf Folgendes klicken:

public void mouseHoverJScript(WebElement HoverElement) {

    String mouseOverScript = "if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onmouseover');}";
    ((JavascriptExecutor) driver).executeScript(mouseOverScript, HoverElement);
}

0

In Java können wir mit JavaScript scrollen, wie im folgenden Code:

driver.getEval("var elm = window.document.getElementById('scrollDiv'); if (elm.scrollHeight > elm.clientHeight){elm.scrollTop = elm.scrollHeight;}");

Sie können der Variablen "elm.scrollTop" einen gewünschten Wert zuweisen.


0

Eine Lösung ist:

public void javascriptclick(String element)
{
    WebElement webElement = driver.findElement(By.xpath(element));
    JavascriptExecutor js = (JavascriptExecutor) driver;

    js.executeScript("arguments[0].click();", webElement);
    System.out.println("javascriptclick" + " " + element);
}

0

Dieser Code funktioniert für mich:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(250, 350)");

Funktioniert bei mir. Die Dart WebDriver-Implementierung verfügt noch nicht über Aktionen.
Günter Zöchbauer
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.