Faire défiler l'élément dans la vue avec le sélénium


208

Existe-t-il un moyen dans Selenium 1.x ou 2.x de faire défiler la fenêtre du navigateur afin qu'un élément particulier identifié par un XPath soit en vue du navigateur? Il existe une méthode de mise au point dans Selenium, mais elle ne semble pas faire défiler physiquement la vue dans FireFox. Quelqu'un at-il des suggestions sur la façon de procéder?

La raison pour laquelle j'en ai besoin est que je teste le clic d'un élément sur la page. Malheureusement, l'événement ne semble fonctionner que si l'élément est visible. Je n'ai pas le contrôle du code qui se déclenche lorsque l'élément est cliqué, je ne peux donc pas le déboguer ou y apporter des modifications.La solution la plus simple consiste donc à faire défiler l'élément en vue.


Vous pouvez essayer celui-ci si rien d'autre ne fonctionne pour vous : stackoverflow.com/a/53771434/7093031
YB Cause

Réponses:


215

J'ai essayé beaucoup de choses en ce qui concerne le défilement, mais le code ci-dessous a fourni de meilleurs résultats.

Cela défilera jusqu'à ce que l'élément soit visible:

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
Ceci est une solution intéressante lorsque vous pouvez avoir un élément position: fixedsur votre page et qu'il obscurcit l'élément sur lequel Selenium veut cliquer. Très souvent, ces éléments fixes vont en bas, donc le réglage le scrollIntoView(true)déplace bien vers le haut de la fenêtre.
Mandible79

3
Basé sur la dernière version de sélénium (2.53), c'est maintenant une excellente solution d'assistance. Le sélénium ne fait pas toujours défiler l'élément en vue, cela est donc très pratique.
Zoidberg

20
Passer trueà scrollIntoViewsi l'objet que vous faites défiler jusqu'à est au- dessous où vous êtes, falsesi l'objet que vous faites défiler jusqu'à est au- dessus où vous êtes actuellement. J'ai eu du mal à comprendre cela.
Big Money

2
Pourquoi avez-vous besoin de sommeil de fil? executeScript doit être synchrone
riccardo.tasso

1
@ riccardo.tasso, un sommeil peut avoir été implémenté pour faire face à l'inconnu de l'application cible. S'il a un défilement dynamique ou une application d'une seule page qui charge le bit suivant de la page après le défilement, entre autres possibilités. Par expérience, Selenium a fréquemment cassé le site de mon entreprise parce que l'action automatisée s'est produite plus rapidement que Javascript ne pouvait terminer, et a donc passé un modèle de données incomplet. Certains endroits peuvent le considérer comme un bug, mais on m'a dit "Aucun humain ne pourrait jamais invoquer un tel scénario, donc ce n'est pas un vrai bug." C'est la vie.
Solonotix

157

Vous pouvez utiliser la org.openqa.selenium.interactions.Actionsclasse pour passer à un élément.

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
Cela fonctionnera-t-il si WebElement n'est pas dans le port d'affichage?
virusrocks

9
@Dominik: Comment Selenium déplacera-t-il la souris vers un élément en dehors de l'écran? Évidemment, il doit d'abord faire défiler l'élément en vue, puis déplacer la souris dessus. Je l'ai testé. Ce code fonctionne sur Firefox Webdriver 2.48 mais il y a un bogue: lorsque vous avez une iframe dans une page, le défilement ne fonctionne pas correctement dans l'élément iframe while.LocationOnScreenOnceScrolledIntoView défile correctement. (Bien que la documentation indique que cette commande ne renvoie qu'un emplacement, elle défile également!)
Elmue

8
Les documents sur seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… indiquent désormais clairement "Déplace la souris au milieu de l'élément. L'élément défile dans la vue et son emplacement est calculé à l'aide de getBoundingClientRect. "
George Pantazes

5
Le code ci-dessus est "la manière officielle" Java Selenium veut que vous fassiez défiler un élément dans la fenêtre de visualisation, mais après avoir essayé beaucoup de choses, l'implémentation JS a semblé fonctionner de manière plus fiable pour moi. Cette méthode en particulier.
Kenji Miwa

2
N'a pas fonctionné pour moi: - | Utilisez plutôt stackoverflow.com/a/23902068/661414 .
Leukipp

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

Vous voudrez peut-être essayer ceci.


1
Merci. J'avais besoin d'utiliser cette méthode dans un cas où le défilement automatique d'un sélénium faisait en sorte qu'un autre élément obscurcissait l'élément sur lequel je devais cliquer. J'ai pu faire défiler une quantité arbitraire pour rendre l'élément visible dans la fenêtre, sans être obscurci.
Daniel Richnak

Cela ne fonctionnera que dans FIrefox, Chrome et IE ne prend pas en charge cette méthode
virusrocks

C'est pourquoi vous utilisez js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e);pour IE et Firefox et js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e);pour Chrome. Facile.
IamBatman

((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)");Cela a fonctionné dans Chrome. Et la seule solution qui a réellement fonctionné pour moi. Même situation que le premier commentateur, j'avais un élément fixe en bas qui obscurcissait toujours l'élément sur lequel je devais cliquer.
argent


15

Si vous souhaitez faire défiler la fenêtre Firefox à l'aide du pilote Web Selenium, l'une des façons consiste à utiliser JavaScript dans le code Java. Le code JavaScript pour faire défiler vers le bas (en bas de la page Web) est le suivant:

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

10

Cibler n'importe quel élément et envoyer des touches vers le bas (ou vers le haut / gauche / droite) semble également fonctionner. Je sais que c'est un peu un hack, mais je ne suis pas vraiment dans l'idée d'utiliser JavaScript pour résoudre le problème de défilement non plus.

Par exemple:

WebElement.sendKeys(Keys.DOWN);

Ce n'est pas moins un hack que d'utiliser js et c'est vraiment la chose la plus simple. J'ai trouvé cela principalement un problème avec IE où un clic essaie de faire défiler l'élément en vue mais ne le fait pas tout à fait. La solution est tout aussi élégante en utilisant {PGUP} si elle est effectuée avec le scénario try / catch / loop approprié.
jibbs

Tu m'as sauvé la journée! Merci
Jesko R.

Dans mon cas, la page suivante était la chose qui fonctionnait. C'est un bon hack (vs tous les hacks js).
akostadinov

Merci @DevDave! Équivalent 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);

Pour plus d'exemples, allez ici . Tout en russe, mais le code Java est interculturel :)


Puis-je comprendre pourquoi il y a un -1 pour cette solution?
josephnvu

Parce que cela ne fonctionne que dans Firefox. Aucun autre navigateur ne prend en charge cette méthode.
Wayne Allen

Si quelqu'un a besoin d'une traduction du russe pour le document susmentionné, il se fera un plaisir de vous aider.
moine

8

Dans Selenium, nous devons prendre l'aide d'un exécuteur JavaScript pour faire défiler jusqu'à un élément ou faire défiler la page:

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

Dans la déclaration ci-dessus se elementtrouve l'élément exact où nous devons faire défiler. J'ai essayé le code ci-dessus, et cela a fonctionné pour moi.

J'ai un post complet et une vidéo à ce sujet:

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


@Mukesh otwani le code ci-dessus va défiler vers le bas, mais comment abt faire défiler vers le haut sans utiliser les pixels définis.
khan

6

Vous pouvez utiliser cet extrait de code pour faire défiler:

C #

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

Voilà


6

Cela a fonctionné pour moi:

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

5

Selenium 2 essaie de faire défiler jusqu'à l'élément puis de cliquer dessus. En effet, Selenium 2 n'interagira pas avec un élément à moins qu'il ne pense qu'il est visible.

Le défilement vers l'élément se fait implicitement, il vous suffit donc de rechercher l'élément, puis de travailler avec lui.


19
Comment est-ce une réponse à la question?
reinierpost

57
ne semble pas fonctionner de cette façon pour moi. Je reçois des erreurs «élément non cliquable» pour les éléments qui ne sont pas
visibles

5
@DevDave J'ai le même problème, sauf que dans mon cas, le sélénium n'effectue pas d'action de clic sur l'élément et il n'y a aucune exception. Je n'ai pas eu le problème avant et je ne sais pas ce qui a causé cela.
Zeinab Abbasimazar

5
Le défilement implicite varie selon les navigateurs. J'ai un test d'un élément dans un menu contextuel au milieu d'une page. Avec la gemme Ruby selenium_webdriver 2.43, je trouve que chrome-browser 37 (et je crois qu'Internet Explorer) fait effectivement défiler l'élément de menu en vue et clique dessus. Mais Firefox 32 ne semble pas du tout défiler, puis échoue avec "L'élément n'est pas actuellement visible et ne peut donc pas interagir avec".
skierpage

9
Cette réponse est fausse. Selon les spécifications de Selenium 2.0, WebElement.click()l'élément doit être visible pour pouvoir cliquer dessus. Il ne défilera pas en votre nom.
Gili

5

Utilisez le pilote pour envoyer des clés comme la touche pagedownou downarrowpour afficher l'élément. Je sais que c'est une solution trop simple et pourrait ne pas être applicable dans tous les cas.


1
Ça n'a pas de sens. Vous devrez peut-être envoyer une douzaine de pages sur une grande page. C'est lent et pas fiable.
Elmue

2
Oui. Je suis d'accord. Mais j'ai dit "non applicable dans tous les cas"
Ganesh S

Trouver des éléments connus elementsur la page consultable et envoyer PageDown a element.SendKeys(Keys.PageDown);fonctionné pour moi.
Gokul

Je vous conseille d'utiliser la touche Alt pour ne pas faire défiler la page et d'utiliser la clause try / except (Python) pour gérer les erreurs qui peuvent se produire lors de l'envoi de clés à certains éléments.
Alex K.

4

D'après mon expérience, Selenium Webdriver ne fait pas défiler automatiquement jusqu'à un élément au clic lorsqu'il y a plus d'une section déroulante sur la page (ce qui est assez courant).

J'utilise Ruby, et pour mon AUT, j'ai dû patcher la méthode click comme suit;

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

La méthode 'location_once_scrolled_into_view' est une méthode existante sur la classe WebElement.

Je comprends que vous n'utilisiez peut-être pas Ruby, mais cela devrait vous donner quelques idées.


J'ai déclaré ce qui précède module Capybara :: module Nodeet j'ai dû appeler native.location_once_scrolled_into_viewau lieu de juste location_once_scrolled_into_view. J'ai également sauvé ::Selenium::WebDriver::Error::UnknownError, ce que j'obtiens souvent dans Firefox 44.0.2. Mais je trouve que cette solution n'est pas assez flexible et, finalement, je mets les <Element>.native.location_once_scrolled_into_viewappels dans le test d'acceptation lui-même, suivi immédiatement par les page.execute_script('window.scrollByPages(-1)')besoins.
Al Chou

Watir a la méthode Element#scroll_into_viewqui délègue à Selenium location_once_scrolled_into_view. Mais les deux ne font rien de différent du comportement par défaut de Selenium, donc les éléments de débordement peuvent toujours obstruer tout ce que nous essayons de cliquer.
akostadinov

3

Le script Ruby pour faire défiler un élément dans la vue est comme ci-dessous.

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

2

Parfois, j'ai également été confronté au problème de défilement avec Selenium. J'ai donc utilisé javaScriptExecuter pour y parvenir.

Pour faire défiler vers le bas:

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

Ou aussi

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

Pour faire défiler vers le haut:

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

Ou,

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

2

Si vous pensez que d'autres réponses étaient trop hacky, celle-ci l'est aussi, mais aucune injection JavaScript n'est impliquée.

Lorsque le bouton est hors de l'écran, il se casse et défile jusqu'à lui, alors réessayez ... ¯ \ _ (ツ) _ / ¯

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

2

Il s'agit d'une solution répétée avec JavaScript, mais avec un élément d'attente supplémentaire.

Sinon ElementNotVisibleExceptionpeut apparaître si une action sur l'élément est en cours.

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

?? <- qu'est-ce que ça veut dire?
Choi

1

J'ai utilisé cette méthode pour faire défiler l'élément et cliquer:

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

Dans mon cas, cela a scrollIntoView(false)fonctionné, mais scrollIntoView(true)pas. L'un ou l'autre peut fonctionner , cela dépend de votre scénario.
rsenna

Mon cas est le contraire - le vrai fonctionne, le faux échoue, mais seulement pour le clic. Il défile correctement pour faux, et c'est ce que je préfère, mais pour une raison quelconque, Selenium ne peut toujours pas le voir pour un clic. L'utilisation de vrais parchemins tout est trop élevé, mais au moins ça marche.
Bill Hileman

Les touches d'envoi utilisateur entrent au lieu de cliquer lorsque cela est possible - cela évite les problèmes si le navigateur n'est pas au zoom à 100%.
Zunair

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

1

Vous pouvez visiter la page Scroll Web elements and Web page- Selenium WebDriver utilisant 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 Je me souviens que sa prise en charge dans Chrome aussi. Avez-vous rencontré un problème spécifique?
virusrocks

1

Dans la plupart des situations de défilement, ce code fonctionnera.

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

1

JAVA

Essayez défilement à l' élément utiliser la x yposition et l' utilisation JavascriptExecutorde c'est l' argument: "window.scrollBy(x, y)".

Après l'importation:

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

Vous devez d'abord obtenir l' x yemplacement de l'élément.

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

Le comportement par défaut de Selenium nous fait défiler pour que l'élément soit à peine visible en haut de la fenêtre. De plus, tous les navigateurs n'ont pas exactement le même comportement. C'est très peu satisfaisant. Si vous enregistrez des vidéos des tests de votre navigateur, comme je le fais, ce que vous voulez, c'est que l'élément défile dans la vue et soit centré verticalement .

Voici ma solution pour 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;
}

Et puis, pour faire défiler, vous l'appelez comme ceci:

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

La fonction getViewPortHeight est manquante ... Dans l'hypothèse où vous prenez la hauteur de l'élément cible
Shubham Jain

0

Voici comment je le fais avec PHP webDriver pour Selenium. Cela fonctionne pour le serveur autonome 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();

Remarque: j'utilise une version personnalisée du pilote Web Element34 PHP. Mais il n'y a aucun changement dans le noyau. J'utilise juste mon "welement" au lieu de "element". Mais cela n'a aucune influence sur le cas en question. L'auteur du pilote dit «de permettre à presque tous les appels d'API d'être une transformation directe de ce qui est défini dans le protocole WebDriver lui-même». Vous ne devriez donc avoir aucun problème avec d'autres langages de programmation.

Un simple clic ne fonctionnera pas dans ma configuration. Il fera un défilement au lieu de cliquer, j'ai donc dû cliquer deux fois sans appeler "location_in_view ()".

Remarque: Cette méthode fonctionne pour les éléments qui peuvent être affichés, comme une entrée de type bouton.

Jetez un œil à: http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/location

La description de JsonWireProtocol # suggère l'utilisation de location + moveto, car location _in_view est une méthode interne.


0

Quelque chose qui a fonctionné pour moi a été d'utiliser la méthode Browser.MoveMouseToElement sur un élément en bas de la fenêtre du navigateur. Miraculeusement, cela a fonctionné dans Internet Explorer, Firefox et Chrome.

J'ai choisi cela plutôt que la technique d'injection JavaScript simplement parce qu'elle était moins hacky.


De quel langage de programmation s'agit-il?
akostadinov

0

J'ai fait des tests avec des composants ADF et vous devez avoir une commande distincte pour le défilement si le chargement paresseux est utilisé. Si l'objet n'est pas chargé et que vous essayez de le trouver à l'aide de Selenium, Selenium lèvera une exception d'élément introuvable.


0

Si rien ne fonctionne, essayez ceci avant de cliquer:

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, nous pouvons faire défiler en utilisant JavaScript, comme dans le code suivant:

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

Vous pouvez affecter une valeur souhaitée à la variable "elm.scrollTop".


0

Une solution est:

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

Ce code fonctionne pour moi:

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

Travaille pour moi. L'implémentation de Dart WebDriver n'a pas encore d'actions.
Günter Zöchbauer
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.