web-dev-qa-db-fra.com

Selenium WebDriver ne peut pas cliquer sur un lien en dehors de la page

J'ai un problème avec Selenium WebDriver. J'essaie de cliquer sur un lien qui se trouve en dehors de la page de la fenêtre (vous devez faire défiler l'écran pour le voir). Mon code actuel est assez standard: 

menuItem = driver.findElement(By.id("MTP"));
menuItem.click();
// I also tried menuItem.sendKeys(Keys.RETURN);

Je sais que je pourrais faire défiler vers le haut, et cela fonctionnerait dans ce cas. Mais dans le cas où vous avez une longue liste d'éléments, vous ne savez pas nécessairement à quel point vous devez faire défiler l'écran. 

Est-il possible de cliquer sur un lien qui ne se trouve pas sur la partie visible de la page (mais qui serait visible si vous faites défiler)?

En passant, j'utilise Firefox, mais je prévois également utiliser IE7/8/9 et Chrome.

Toute aide serait grandement appréciée.

Edit: J'ai bien peur de ne pas pouvoir donner le code source, car l'entreprise pour laquelle je travaille ne le permet pas, mais je peux donner le code du lien sur lequel je veux cliquer:

<div class="submenu">
  <div id="MTP">Link title</div>
</div>

Le même code fonctionne lorsque le lien est visible, mais ne fonctionne pas quand il ne l'est pas.

Edit2: En fait, assez curieusement, il ne soulève aucune exception et passe simplement à l'instruction suivante. Donc, fondamentalement, ce qui se passe est:

menuItem = driver.findElement(By.id("MTP")); // no exception
menuItem.click();  // no exception
//... some code ensuring we got to the next page: timeout reached
driver.findElement(By.id("smLH")).click(); // NoSuchElementException, as we're on the wrong page.
19
Stilltorik

Il est effectivement possible de faire défiler automatiquement l'élément. Bien que ce ne soit pas une bonne solution dans ce cas (il doit y avoir un moyen de le faire fonctionner sans défilement), je le posterai comme solution de contournement. J'espère que quelqu'un aura une meilleure idée ...

public void scrollAndClick(By by)
{
   WebElement element = driver.findElement(by);
   int elementPosition = element.getLocation().getY();
   String js = String.format("window.scroll(0, %s)", elementPosition);
   ((JavascriptExecutor)driver).executeScript(js);
   element.click();
}
13
JacekM

J'ai posté cette même réponse dans une autre question donc c'est juste un copier-coller.

J'ai eu une fois une zone de liste déroulante qui n'était pas en vue que je devais développer. Ce que j'ai fait, c'est utiliser le générateur Actions car la fonction moveToElement () fera défiler automatiquement l'objet dans la vue. Ensuite, il peut être cliqué sur.

WebElement element = panel.findElement(By.className("tabComboBoxButton"));

Actions builder = new Actions(this.driver);

builder.moveToElement(element);
builder.click();
builder.build().perform();

(le panneau est simplement un élément encapsulé dans mon POM)

7
Bill Thayer

Au lieu de déplacer la barre de défilement vers la position du bouton, ce qui parfois ne fonctionnait pas pour moi, j'envoie la touche Entrée au bouton

var element = driver.FindElement(By.Id("button"));
element.SendKeys(Keys.Enter);
7
David Garcia

J'ai rencontré un problème similaire récemment quand il y avait une liste d'objets sélectionnables dans une boîte de dialogue JS. Parfois, Selenium ne sélectionnerait pas le bon objet dans la liste. J'ai donc trouvé cette suggestion javascript:

WebElement target = driver.findElement(By.id("myId"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", target);
Thread.sleep(500); //not sure why the sleep was needed, but it was needed or it wouldnt work :(
target.click();

Cela a résolu mon problème

7
Brian Gleeson - IBM

Hé, tu peux utiliser ça pour Ruby

variable.element.location_once_scrolled_into_view

Stocke l'élément à trouver dans la variable 

5
The Rookie

Cela peut être dû au fait que votre élément d’en-tête ou de bas de page bloque la vue de l’élément sur lequel vous souhaitez effectuer une action. Selenium essaie de faire défiler jusqu'à la position de l'élément lorsqu'il doit effectuer une action sur l'élément (j'utilise Selenium WebDriver v3.4.0). 

Voici une solution de contournement - 

private WebElement scrollToElementByOffset(WebElement element, int offset) {
    JavascriptExecutor jse = (JavascriptExecutor) driver;
    jse.executeScript("window.scrollTo(" + element.getLocation().getX() + "," + (element.getLocation().getY()
            + offset) + ");");

    return element;
}

La fonction ci-dessus fait défiler la vue vers l'élément, puis continue de défiler en fonction du décalage que vous avez fourni. Et vous pouvez appeler cette méthode en faisant quelque chose comme: 

WebElement webElement = driver.findElement(By.id("element1"));
scrollToElementByOffset(webElement, -200).click();

Maintenant, ceci est juste une solution de contournement. J'accueillerai volontiers de meilleures solutions à ce problème. 

3
yuva

Cette solution a fonctionné comme un charme pour moi:

public void click(By by) throws Exception{
    WebElement element = driver.findElement(by);
    ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
    Thread.sleep(500);
    element.click();
}
3
rafaat123

Cela fonctionne pour moi (en c #) -

item = driver.findelement(by.....);
item.SendKeys(Keys.LeftControl);
item.Click();
1
NahkT

Juste un ajout: Dans mon cas, le bouton était recouvert par un autre bouton flottant.

Le simple redimensionnement de la fenêtre du navigateur a résolu le problème!

0
Kurt Ludikovsky

J'ai utilisé la méthode ci-dessous pour résoudre un problème similaire avec Selenium Java:

public static void scrollToElementByElement(WebElement element) {

    Coordinates coordinates = ((Locatable)element).getCoordinates();
    coordinates.inViewPort();
    coordinates.click(); //if needed

}

Puis appelé la méthode sur ma classe de test principale

0
BlueGunner