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.

Dan a la carta
fuente
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
Amith
fuente
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()
Sascha
fuente
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.

Mayur
fuente
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));");
Ankit Pandey
fuente
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);
DevDave
fuente
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 :)

VovecUdalec
fuente
¿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
fuente
@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

Mohsin Awan
fuente
6

Esto funcionó para mí:

IWebElement element = driver.FindElements(getApplicationObject(currentObjectName, currentObjectType, currentObjectUniqueId))[0];
 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", element);
ULKSSS
fuente
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.

Probador automatizado
fuente
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.

Ganesh S
fuente
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.

Robbie Wareham
fuente
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
Satheesh kumar
fuente
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);");
Anuraj R
fuente
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();
}
vicentedealencar
fuente
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));
Lukasz
fuente
?? <- ¿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();
}
Bibek
fuente
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});")
}
Om nom nom
fuente
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);");
}
rocas de virus
fuente
@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);
SarojPurbey
fuente
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 +")");
viernes
fuente
1

No estoy seguro de si la pregunta sigue siendo relevante, pero después de consultar la documentación de scrollIntoView de https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView .

La solución más fácil sería

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

Esto desplaza el elemento al centro de la página.

kiranjith
fuente
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);
}
djangofan
fuente
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.

Konstantin Ivanov
fuente
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.

David Peters
fuente
¿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.

usuario3781490
fuente
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);
}
Prateek
fuente
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".

Hemant
fuente
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);
}
akhilesh gulati
fuente
0

Este código me está funcionando:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(250, 350)");
vishal Singh
fuente
Funciona para mi. La implementación de Dart WebDriver aún no tiene acciones.
Günter Zöchbauer