WebDriver cliquez sur() vs JavaScript cliquez sur()
L'Histoire:
Ici sur StackOverflow, j'ai vu des utilisateurs rapportent qu'ils ne peuvent pas cliquer sur un élément via selenium WebDriver ", cliquez sur la commande", et permet de travailler autour d'elle avec un JavaScript cliquez par l'exécution d'un script.
Exemple en Python:
element = driver.find_element_by_id("myid")
driver.execute_script("arguments[0].click();", element)
Exemple dans WebDriverJS/Rapporteur:
var elm = $("#myid");
browser.executeScript("arguments[0].click();", elm.getWebElement());
La Question:
Pourquoi en cliquant sur "via JavaScript" fonctionne lorsque régulière WebDriver cliquez sur ne pas? Quand exactement est-ce qui se passe et quel est l'inconvénient de cette solution (le cas échéant)?
j'ai personnellement utilisé cette solution de contournement sans bien comprendre pourquoi j'ai à faire et les problèmes qu'elle peut engendrer.
Vous devez vous connecter pour publier un commentaire.
Contrairement à ce que l' actuellement accepté de répondre à l'indique, il n'y a rien de spécifique à PhantomJS quand il s'agit de la différence entre le fait d'avoir WebDriver faire un clic et de le faire en JavaScript.
La Différence
La différence essentielle entre les deux méthodes est commun à tous les navigateurs et peut être expliqué assez simplement:
WebDriver: Quand WebDriver pour le clic, il tente du mieux qu'il peut pour simuler ce qui se passe lorsqu'un utilisateur réel utilise le navigateur. Supposons que vous avez Un élément qui est un bouton qui dit "Cliquez-moi" et un élément B qui est un
div
élément qui est transparente, mais a ses dimensions etzIndex
réglé de sorte qu'il couvre complètement A. Puis vous dire WebDriver de cliquer sur A. WebDriver permettra de simuler le clic afin que les B reçoit le clic première. Pourquoi? Parce que B couvre Un, et si un utilisateur à essayer de cliquer sur A, puis B, serait d'obtenir le premier événement. Si oui ou non Un finirait par le clic de l'événement dépend de la façon dont B gère l'événement. En tout cas, le comportement avec WebDriver dans ce cas est le même que lorsqu'un utilisateur réel essaie de cliquer sur A.JavaScript: Maintenant, supposons que vous utilisez JavaScript pour faire
A.click()
. Cette méthode de clic ne permet pas de reproduire ce qui se passe réellement lorsque l'utilisateur essaie de cliquer sur A. JavaScript envoie leclick
événement directement à A et B ne sera pas obtenir tous les cas.Pourquoi un JavaScript Cliquez sur les Œuvres, Lorsqu'un WebDriver Cliquez sur Ne Pas?
Comme je l'ai mentionné ci-dessus WebDriver va essayer de simuler le mieux possible ce qui se passe lorsqu'un utilisateur réel est à l'aide d'un navigateur. Le fait de la question est que le DOM peut contenir des éléments qu'un utilisateur ne peut pas interagir avec, et WebDriver ne vous permettra pas de cliquer sur ces éléments. Outre le cumul cas je l'ai mentionné, cela implique aussi que les éléments invisibles ne peut pas être cliqué. Un cas courant je vois dans le Débordement de Pile questions est quelqu'un qui est en train d'interagir avec un élément graphique qui existe déjà dans les DOM, mais devient visible seulement quand un autre élément a été manipulé. Cela arrive parfois avec des menus déroulants: vous devez d'abord cliquer sur le bouton ouvre la liste déroulante avant un élément de menu peut être sélectionné. Si quelqu'un essaie de cliquer sur le menu avant de le menu est visible, WebDriver rechignent et dire que l'élément ne peut pas être manipulé. Si la personne essaie de le faire avec JavaScript, il va fonctionner parce que l'événement est remis directement à l'élément, indépendamment de la visibilité.
Quand Devez-Vous Utiliser JavaScript pour Cliquer?
Si vous utilisez le Sélénium pour test d'une application, ma réponse à cette question est "presque jamais". En gros, votre Sélénium test doit reproduire ce qu'un utilisateur pourrait le faire avec le navigateur. Prenant l'exemple du menu déroulant: un test doit cliquer sur le bouton qui ouvre la liste déroulante, d'abord, et ensuite cliquez sur l'élément de menu. Si il y a un problème avec l'interface graphique car le bouton est invisible, ou l'échec de bouton pour afficher les éléments de menu, ou quelque chose de similaire, puis votre test échouera et vous aurez détecté un bug. Si vous utilisez JavaScript pour cliquer, vous ne serez pas en mesure de détecter ces bugs au moyen de tests automatisés.
Je dis "presque jamais", car il peut y avoir des exceptions où il est logique d'utiliser le JavaScript. Ils doivent être très rares, cependant.
Si vous utilisez le Sélénium pour grattage sites, alors il n'est pas indispensable pour tenter de reproduire le comportement de l'utilisateur. Donc, l'utilisation de JavaScript pour contourner le GUI est moins un problème.
click
ousendKeys
travaillé, mais pas toujours. Il n'y a pas de localiser le problème ou l'autre exception, le cas de test tout simplement n'a pas progressé davantage. L'exploitation forestière a montré que l'action a été exécutée. Parfois, à l'aide deAction
aidé. Si j'ai cliqué sur l'élément manuellement (après de cas de test avait arrêté), tout a bien fonctionné. Nous avons donc passé à raw JS sur que les occasions. Je n'ai pas travaillé avec AngularJS pour les 2 dernières années, de sorte que les choses pourraient être mieux maintenant.Cliquez sur exécutée par le pilote essaie de simuler le comportement d'un utilisateur réel, aussi près que possible pendant que le JavaScript
HTMLElement.click()
exécute l'action par défaut pour lesclick
événement, même si l'élément n'est pas interactable.Les différences sont:
Le pilote s'assure que l'élément est visible en le faisant défiler dans la vue, et vérifie que l'élément est interactable.
Le pilote va générer une erreur:
disabled
esttrue
)pointer-events
estnone
)Un JavaScript
HTMLElement.click()
sera toujours effectuer l'action par défaut ou au mieux, en silence échouer si l'élément est désactivé.Le pilote est prévu pour apporter l'élément dans le foyer si elle peut recevoir le focus.
Un JavaScript
HTMLElement.click()
ne sera pas.Le pilote est prévu pour émettent tous les événements (mousemove, mousedown, mouseup, clic, ...), tout comme comme un vrai utilisateur.
Un JavaScript
HTMLElement.click()
n'émet que de laclick
événement.La page peut compter sur ces événements supplémentaires et peuvent se comporter différemment si elles ne sont pas émis.
Ce sont les événements émis par le pilote pour un clic avec google Chrome:
Et c'est l'événement émis avec une injection JavaScript:
L'événement émise par un JavaScript
.click()
n'est pas digne de confiance et l'action par défaut ne peuvent pas être invoquées:https://developer.mozilla.org/en/docs/Web/API/Event/isTrusted
https://googlechrome.github.io/samples/event-istrusted/index.html
Noter que certains pilotes ont encore des non fiables événements. C'est le cas avec PhantomJS à partir de la version 2.1.
L'événement émise par un JavaScript
.click()
n'a pas les coordonnées du clic.Les propriétés
clientX, clientY, screenX, screenY, layerX, layerY
sont mis à0
. La page peut compter sur eux et peuvent se comporter différemment.Il peut être ok pour utiliser un JavaScript
.click()
à la ferraille de certaines données, mais il n'est pas dans un cadre test. Il défait le but de le tester car il n'a pas de simuler le comportement d'un utilisateur. Donc, si le clic du pilote échoue, alors un utilisateur réel sera probablement aussi ne parviennent pas à effectuer les mêmes cliquez dans les mêmes conditions.Ciblées élément n'est pas encore visible/interactable en raison d'un retard ou d'un effet de transition.
Quelques exemples :
https://developer.mozilla.org/fr/docs/Web (dropdown menu de navigation)
http://materializecss.com/side-nav.html (liste déroulante de la barre latérale)
Workarrounds:
Ajouter un serveur à attendre pour la visibilité, la taille minimale ou la position est stable :
Réessayer à cliquer jusqu'à ce qu'il réussit :
Ajouter un délai correspondant à la durée de l'animation et de transition :
Ciblées élément se retrouve recouverte par un élément flottant une fois défile dans l'affichage:
Le pilote défile automatiquement l'élément dans le but de le rendre visible. Si la page contient un taux variable/collant élément (menu, annonces, pied de page, la notification, la politique en matière de cookies..), l'élément peut se retrouver couvert et ne sera plus visible/interactable.
Exemple: https://twitter.com/?lang=en
Solutions de contournement:
Définir la taille de la fenêtre pour une plus grande pour éviter le défilement ou de l'élément flottant.
Déménageur-dessus de l'élément négatif
Y
offset et cliquez dessus:De défilement de l'élément au centre de la fenêtre avant de cliquer sur:
Masquer l'élément flottant s'il ne peut pas être évitée:
REMARQUE: appelez le "clic" est fin-clic de l'utilisateur. 'js cliquez sur" cliquez via JS
Il y a 2 cas pour ce faire:
I. Si vous utilisez PhamtomJS
Puis c'est le plus commun comportement connu de
PhantomJS
. Certains éléments sont parfois pas cliquable, par exemple<div>
. C'est parce quePhantomJS
original a été fait pour simuler le moteur de navigateurs (comme initiale HTML + CSS -> informatique CSS -> rendu). Mais cela ne signifie pas pour être en interaction avec un utilisateur final moyen (affichage, cliquer, glisser). DoncPhamtomJS
est que partiellement pris en charge avec les utilisateurs finaux de l'interaction.POURQUOI EST-JS SUR LE TRAVAIL? Que ce soit pour de clic, ils sont tous sur. C'est comme une arme à feu avec 1 baril et 2 déclencheurs. L'une à partir de la fenêtre d'affichage, un JS. Depuis
PhamtomJS
grande dans la simulation de navigateur du moteur, un JS cliquez sur devrait fonctionner parfaitement.II. Le gestionnaire d'événements ", cliquez sur" got to bind dans la mauvaise période de temps.
Par exemple, nous avons obtenu un
<div>
-> Nous faisons un peu de calcul
-> puis nous lier cas de cliquez sur le
<div>
.-> qui Plus est, avec quelques mauvais codage angulaire (par exemple, traitement des portée du cycle correctement)
Nous peut se retrouver avec le même résultat. Cliquez sur ne fonctionne pas, parce que WebdriverJS essayez de cliquer sur l'élément quand il n'a pas de gestionnaire d'événements click.
POURQUOI EST-JS SUR LE TRAVAIL? Js cliquez est comme l'injection de js directement dans le navigateur. Possible avec 2 façons,
Poing est par le biais de devtools de la console (oui, WebdriverJS communique avec les devtools' de la console).
Deuxième est d'injecter une
<script>
tag directement dans le HTML.Pour chaque navigateur, le comportement sera différent. Mais peu importe, ces méthodes sont plus compliquer que de cliquer sur le bouton. Cliquez sur est en utilisant ce qui existe déjà (les utilisateurs finaux de la souris), js cliquez sur passe par une porte dérobée.
Et pour js cliquez sur semble être une tâche asynchrone. Ceci est lié avec un peu complexe sujet de " navigateur tâche asynchrone et CPU de la planification des tâches' (lire à un moment de retour ne peut pas trouver l'article à nouveau). Pour faire court ce sera surtout le résultat que js cliquez sur devrez attendre un cycle de la planification des tâches de CPU et il sera couru un peu plus lent après la liaison de l'événement click.
(Vous saviez ce cas, lorsque vous avez trouvé l'élément parfois cliquable, parfois pas.
)
=> Comme mentionné ci-dessus, à la fois moyen pour une fin, mais sur l'utilisation de l'entrée principale:
=> Pour la performance, c'est difficile à dire parce qu'il s'appuie sur les navigateurs. Mais en général:
=> Inconvénients:
P. S. si vous êtes à la recherche d'une solution.
browser.wait()
(cochez cette pour plus d'informations)(Je veux faire court, mais il a fini mal. Tout ce qui est lié à la théorie est compliqué à expliquer...)