Desplazar elemento a la vista con selenio


208

¿Hay alguna forma en Selenium 1.xo 2.x para desplazar la ventana del navegador de modo que un elemento particular identificado por un XPath esté a la vista del navegador? Hay un método de enfoque en Selenium, pero no parece desplazar físicamente la vista en Firefox. ¿Alguien tiene alguna sugerencia sobre cómo hacer esto?

La razón por la que necesito esto es porque estoy probando el clic de un elemento en la página. Lamentablemente, el evento no parece funcionar a menos que el elemento sea visible. No tengo control del código que se activa cuando se hace clic en el elemento, por lo que no puedo depurarlo ni modificarlo, por lo que la solución más fácil es desplazar el elemento a la vista.


Puede probar este hacky si nada más le funciona : stackoverflow.com/a/53771434/7093031
YB Porque el

Respuestas:


215

He intentado muchas cosas con respecto al desplazamiento, pero el siguiente código ha proporcionado mejores resultados.

Esto se desplazará hasta que el elemento esté a la vista:

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

66
Esta es una solución ordenada para cuando puede tener un elemento position: fixeden su página y está ocultando el elemento que Selenium quiere hacer clic. Muy a menudo, estos elementos fijos van en la parte inferior, por lo que la configuración lo scrollIntoView(true)mueve muy bien a la parte superior de la ventana gráfica.
Mandible79

3
Basado en la versión más nueva de selenio (2.53), esta es ahora una excelente solución auxiliar. El selenio no siempre desplaza el elemento a la vista, por lo que definitivamente es útil.
Zoidberg

20
Pase truea scrollIntoViewsi el objeto al que se desplaza está debajo de donde está actualmente, falsesi el objeto al que se desplaza está arriba de donde está actualmente. Me costó mucho descubrirlo.
Big Money

2
¿Por qué necesitas dormir con hilos? executeScript debería ser síncrono
riccardo.tasso

1
@ riccardo.tasso un sueño podría haberse implementado para tratar con lo desconocido de la aplicación de destino. Si tiene desplazamiento dinámico, o una aplicación de una sola página que carga el siguiente bit de la página después del desplazamiento, entre otras posibilidades. Hablando por experiencia, Selenium frecuentemente ha roto el sitio de mi compañía porque la acción automatizada ocurrió más rápido de lo que el Javascript podría completar, y por lo tanto pasó un modelo de datos incompleto. Algunos lugares pueden considerarlo un error, pero me dijeron "Ningún ser humano podría invocar tal situación, por lo que no es un error real". Así es la vida.
Solonotix

157

Puede usar la org.openqa.selenium.interactions.Actionsclase para moverse a un elemento.

Java:

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

Pitón:

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

77
¿Funcionará esto si WebElement no está en el Puerto de visualización?
virusrocks el

9
@Dominik: ¿Cómo moverá Selenium el mouse a un elemento que esté fuera de la pantalla? OBVIAMENTE, primero debe desplazar el elemento a la vista y luego mover el mouse hacia él. Lo probé Este código funciona en Firefox Webdriver 2.48 pero hay un error: cuando tiene un iframe en una página, el desplazamiento no funciona correctamente en el iframe while element.LocationOnScreenOnceScrolledIntoView se desplaza correctamente. (¡Aunque la documentación dice que este comando solo devuelve una ubicación, también se desplaza!)
Elmue

8
Los documentos en seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… ahora dicen claramente "Mueve el mouse al centro del elemento. El elemento se desplaza a la vista y su ubicación se calcula usando getBoundingClientRect ".
George Pantazes

55
El código anterior es "la forma oficial" Java Selenium quiere que desplace un elemento a la ventana gráfica, sin embargo, después de probar muchas cosas, la implementación de JS me pareció más confiable. Este método en particular.
Kenji Miwa

2
No funcionó para mí: - | Usó stackoverflow.com/a/23902068/661414 en su lugar.
Leukipp

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

Es posible que desee probar esto.


1
Gracias. Necesitaba usar este método en un caso en el que el desplazamiento automático de un Selenium estaba causando que otro elemento oscureciera el elemento en el que necesitaba hacer clic. Pude desplazar una cantidad arbitraria para hacer que el elemento sea visible en la ventana gráfica, sin quedar oculto.
Daniel Richnak

Esto solo funcionará en FIrefox, Chrome e IE no admiten este método
virusrocks

Es por eso que usa js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e);para IE y Firefox y js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e);para Chrome. Sencillo.
IamBatman

((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)");Esto funcionó en Chrome. Y la única solución que realmente funcionó para mí. En la misma situación que el primer comentarista, tenía un elemento fijo en la parte inferior que seguía ocultando el elemento que necesitaba hacer clic.
plata


15

Si desea desplazarse por la ventana de Firefox con el controlador web Selenium, una de las formas es usar JavaScript en el código Java. El código JavaScript para desplazarse hacia abajo (hasta la parte inferior de la página web) es el siguiente:

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

10

La orientación a cualquier elemento y el envío de teclas hacia abajo (o arriba / izquierda / derecha) parece funcionar también. Sé que esto es un truco, pero tampoco estoy realmente en la idea de usar JavaScript para resolver el problema de desplazamiento.

Por ejemplo:

WebElement.sendKeys(Keys.DOWN);

Esto no es menos hackear que usar js y realmente es lo más simple. Encontré esto principalmente un problema con IE donde un clic intenta desplazar el elemento a la vista pero no lo logra. La solución es igual de elegante usando {PGUP} si se hace con el escenario de prueba / captura / bucle adecuado.
jibbs

¡Salvaste mi día! Gracias
Jesko R.

En mi caso, la página abajo fue lo que funcionó. Este es un buen truco (frente a todos los hacks js).
akostadinov

Gracias @DevDave! Equivalente en 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);

Para más ejemplos, vaya aquí . Todo en ruso, pero el código Java es transcultural :)


¿Puedo entender por qué hay un -1 para esta solución?
josephnvu

Porque solo funciona en Firefox. Ningún otro navegador admite este método.
Wayne Allen

Si alguien necesita una traducción del ruso para el documento mencionado anteriormente, estará encantado de ayudarlo.
monkrus

8

En Selenium necesitamos la ayuda de un ejecutor de JavaScript para desplazarnos a un elemento o desplazar la página:

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

En la declaración anterior elementes el elemento exacto donde necesitamos desplazarnos. Probé el código anterior y funcionó para mí.

Tengo una publicación completa y un video sobre esto:

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


@Mukesh otwani, el código anterior se desplazará hacia abajo, pero ¿cómo se desplazará hacia arriba sin usar los píxeles definidos en él?
khan

6

Puede usar este fragmento de código para desplazarse:

C#

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

ahí tienes


6

Esto funcionó para mí:

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

5

Selenium 2 intenta desplazarse al elemento y luego hacer clic en él. Esto se debe a que Selenium 2 no interactuará con un elemento a menos que piense que es visible.

Desplazarse al elemento ocurre implícitamente, por lo que solo necesita encontrar el elemento y luego trabajar con él.


19
¿Cómo es esto una respuesta a la pregunta?
reinierpost

57
No parece estar funcionando de esa manera para mí.
Recibo

55
@DevDave Tengo el mismo problema, excepto en mi caso, el selenio no realiza una acción de clic en el elemento y no hay excepciones. No tenía el problema antes y no sé qué ha causado eso.
Zeinab Abbasimazar

55
El desplazamiento implícito varía entre los navegadores. Tengo una prueba de un elemento en un menú emergente en la mitad de una página. Con la gema Ruby selenium_webdriver 2.43 encuentro el navegador de cromo 37 (y creo que Internet Explorer) desplaza el elemento del menú a la vista y hace clic en él. Pero Firefox 32 no parece desplazarse en absoluto, y luego falla con "El elemento no está visible actualmente y, por lo tanto, no se puede interactuar con él".
skierpage

9
Esta respuesta es incorrecta. De acuerdo con la especificación para Selenium 2.0 WebElement.click(), el elemento debe estar visible para hacer clic en él. No se desplazará en su nombre.
Gili

5

Use el controlador para enviar claves como la tecla pagedowno downarrowpara mostrar el elemento. Sé que es una solución demasiado simple y podría no ser aplicable en todos los casos.


1
Esto no tiene sentido. Es posible que deba enviar una docena de páginas hacia abajo en una página grande. Es lento y no confiable.
Elmue

2
Si. Estoy de acuerdo. Pero sí dije "no aplicable en todos los casos"
Ganesh S

Encontrar algo conocido elementen la página visible y enviar PageDown element.SendKeys(Keys.PageDown);funcionó para mí.
Gokul

Aconsejaría usar la tecla Alt para no desplazar la página y usar la cláusula try / except (Python) para manejar los errores que pueden ocurrir al intentar enviar claves a algunos elementos.
Alex K.

4

Desde mi experiencia, Selenium Webdriver no se desplaza automáticamente a un elemento al hacer clic cuando hay más de una sección desplazable en la página (lo cual es bastante común).

Estoy usando Ruby, y para mi AUT, tuve que parchear el método de clic de la siguiente manera;

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

El método 'location_once_scrolled_into_view' es un método existente en la clase WebElement.

Aprecio que no estés usando Ruby, pero debería darte algunas ideas.


Declaré lo anterior en module Capybara :: module Node, y necesitaba llamar en native.location_once_scrolled_into_viewlugar de solo location_once_scrolled_into_view. También rescaté ::Selenium::WebDriver::Error::UnknownError, que es lo que obtengo a menudo en Firefox 44.0.2. Pero creo que esta solución no es lo suficientemente flexible y, en última instancia, coloca las <Element>.native.location_once_scrolled_into_viewllamadas en la prueba de aceptación en sí, seguida inmediatamente de page.execute_script('window.scrollByPages(-1)')donde sea necesario.
Al Chou

Watir tiene el método Element#scroll_into_viewque delega a Selenium's location_once_scrolled_into_view. Pero ambos no hacen nada diferente del comportamiento predeterminado de Selenium, por lo que los elementos de desbordamiento aún pueden obstruir cualquier cosa que intentemos hacer clic.
akostadinov

3

El script de Ruby para desplazar un elemento a la vista es el siguiente.

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

2

Algunas veces también enfrenté el problema de desplazarme con selenio. Entonces utilicé javaScriptExecuter para lograr esto.

Para desplazarse hacia abajo:

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

O también

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

Para desplazarse hacia arriba:

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

O,

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

2

Si crees que otras respuestas fueron demasiado extravagantes, esta también lo es, pero no hay una inyección de JavaScript involucrada.

Cuando el botón está fuera de la pantalla, se rompe y se desplaza hacia él, así que vuelva a intentarlo ... ¯ \ _ (ツ) _ / ¯

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

2

Esta es una solución repetida con JavaScript, pero con un elemento de espera agregado.

De ElementNotVisibleExceptionlo contrario, puede aparecer si se está realizando alguna acción sobre el elemento.

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

?? <- ¿Qué significa?
Choi

1

He utilizado esta manera para desplazar el elemento y hacer clic:

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

En mi caso, scrollIntoView(false)funcionó, pero scrollIntoView(true)no lo hice. Cualquiera puede funcionar , depende de su escenario.
rsenna

Mi caso es todo lo contrario: verdadero funciona, falso falla, pero solo en lo que respecta al clic. Se desplaza correctamente por falso, y es lo que prefiero, pero por cualquier razón, Selenium todavía no puede verlo con un clic. Usar verdaderos pergaminos todo demasiado alto, pero al menos funciona.
Bill Hileman

Las teclas de envío del usuario ingresan en lugar de hacer clic cuando sea posible: evita problemas si el navegador no está al 100% de zoom.
Zunair

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

1

Es posible que desee visitar la página Desplazarse por los elementos web y la página web - Selenium WebDriver usando Javascript :

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 Recuerdo que también es compatible con Chrome. ¿Algún problema específico que puedas haber enfrentado?
virusrocks

1

En la mayoría de las situaciones para desplazarse, este código funcionará.

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

1

JAVA

Intente desplazarse hasta la x yposición de uso del elemento , y use JavascriptExecutorcon este argumento:"window.scrollBy(x, y)" .

Siguiente importación:

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

Primero necesitas x yubicar el elemento.

//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 +")");


0

El comportamiento predeterminado de Selenium nos permite desplazarnos para que el elemento apenas se vea en la parte superior de la ventana gráfica. Además, no todos los navegadores tienen exactamente el mismo comportamiento. Esto es muy insatisfactorio. Si graba videos de las pruebas de su navegador, como yo, lo que quiere es que el elemento se desplace hacia la vista y se centre verticalmente .

Aquí está mi solución para 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;
}

Y luego, para desplazarte, lo llamas así:

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);
}

Falta la función getViewPortHeight ... Suponiendo que está tomando la altura del elemento objetivo
Shubham Jain

0

Así es como lo hago con PHP webDriver para Selenium. Funciona para el servidor independiente Selenium 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();

Nota: Yo uso una versión personalizada del Element34 PHP-webdriver. Pero no hay ningún cambio en el núcleo. Solo uso mi "welement" en lugar de "element". Pero no influye en el caso en cuestión. El autor del controlador dice "permitir que casi todas las llamadas API sean una transformación directa de lo que se define en el protocolo WebDriver". Por lo tanto, no debería tener problemas con otros lenguajes de programación.

Simplemente hacer clic no funcionará en mi configuración. Hará un desplazamiento en lugar de hacer clic, así que tuve que hacer clic dos veces sin llamar a "location_in_view ()".

Nota: Este método funciona para elementos que se pueden ver, como una entrada de tipo botón.

Echa un vistazo a: http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/location

La descripción de JsonWireProtocol # sugiere el uso de location + moveto, porque location _in_view es un método interno.


0

Algo que funcionó para mí fue usar el método Browser.MoveMouseToElement en un elemento en la parte inferior de la ventana del navegador. Milagrosamente funcionó en Internet Explorer, Firefox y Chrome.

Elegí esto sobre la técnica de inyección de JavaScript solo porque se sentía menos hacky.


¿Qué lenguaje de programación es este?
akostadinov

0

He estado haciendo pruebas con componentes ADF y debes tener un comando separado para desplazarte si se usa carga diferida. Si el objeto no está cargado e intenta encontrarlo usando Selenium, Selenium lanzará una excepción de elemento no encontrado.


0

Si nada funciona, intente esto antes de hacer clic en:

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

En Java podemos desplazarnos usando JavaScript, como en el siguiente código:

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

Puede asignar un valor deseado a la variable "elm.scrollTop".


0

Una solución es:

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

Este código me está funcionando:

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

Funciona para mi. La implementación de Dart WebDriver aún no tiene acciones.
Günter Zöchbauer
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.