Contrairement à ce que suggère la réponse actuellement acceptée , il n'y a rien de spécifique à PhantomJS en ce qui concerne la différence entre le fait que WebDriver fasse un clic et le fasse en JavaScript.
La différence
La différence essentielle entre les deux méthodes est commune à tous les navigateurs et peut être expliquée assez simplement:
WebDriver: lorsque WebDriver fait le clic, il essaie du mieux qu'il peut de simuler ce qui se passe lorsqu'un utilisateur réel utilise le navigateur. Supposons que vous ayez un élément A qui est un bouton qui dit "Cliquez sur moi" et un élément B qui est un div
élément qui est transparent mais a ses dimensions et zIndex
défini de manière à couvrir complètement A. Ensuite, vous dites à WebDriver de cliquer A. WebDriver va simulez le clic pour que B reçoive le clic en premier . Pourquoi? Parce que B couvre A, et si un utilisateur essayait de cliquer sur A, alors B obtiendrait l'événement en premier. Le fait que A obtienne ou non l'événement de clic dépend de la manière dont B gère l'événement. Dans tous les 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 utilisiez JavaScript pour le faire A.click()
. Cette méthode de clic ne reproduit pas ce qui se passe réellement lorsque l'utilisateur essaie de cliquer A. JavaScript envoie l' click
événement directement à A, et B n'obtiendra aucun événement.
Pourquoi un clic JavaScript fonctionne alors qu'un clic WebDriver ne fonctionne pas?
Comme je l'ai mentionné ci-dessus, WebDriver essaiera de simuler au mieux ce qui se passe lorsqu'un utilisateur réel utilise un navigateur. Le fait est que le DOM peut contenir des éléments avec lesquels un utilisateur ne peut pas interagir, et WebDriver ne vous permettra pas de cliquer sur ces éléments. Outre le cas de chevauchement que j'ai mentionné, cela implique également que les éléments invisibles ne peuvent pas être cliqués. Un cas courant que je vois dans les questions de Stack Overflow est quelqu'un qui essaie d'interagir avec un élément GUI qui existe déjà dans le DOM mais qui ne devient visible que lorsqu'un autre élément a été manipulé. Cela se produit parfois avec les menus déroulants: vous devez d'abord cliquer sur le bouton pour faire apparaître la liste déroulante avant de pouvoir sélectionner un élément de menu. Si quelqu'un essaie de cliquer sur l'élément de menu avant que le menu ne soit visible,Si la personne essaie ensuite de le faire avec JavaScript, cela fonctionnera car l'événement est livré directement à l'élément, quelle que soit la visibilité.
Quand devriez-vous utiliser JavaScript pour cliquer?
Si vous utilisez Selenium pour tester une application , ma réponse à cette question est "presque jamais". Dans l'ensemble, votre test Selenium devrait reproduire ce qu'un utilisateur ferait avec le navigateur. Prenons l'exemple du menu déroulant: un test doit d'abord cliquer sur le bouton qui fait apparaître le menu déroulant, puis cliquer sur l'élément de menu. S'il y a un problème avec l'interface graphique parce que le bouton est invisible, ou si le bouton n'affiche pas les éléments de menu, ou quelque chose de similaire, votre test échouera et vous aurez détecté le bogue. Si vous utilisez JavaScript pour cliquer, vous ne pourrez pas détecter ces bogues grâce à des tests automatisés.
Je dis «presque jamais» car il peut y avoir des exceptions où il est logique d'utiliser JavaScript. Ils devraient cependant être très rares.
Si vous utilisez Selenium pour gratter des sites , il n'est pas aussi critique d'essayer de reproduire le comportement de l'utilisateur. Donc, utiliser JavaScript pour contourner l'interface graphique est moins problématique.
click
ousendKeys
fonctionnent - mais pas toujours. Il n'y a eu aucun problème de localisation ou autre exception, le cas de test n'a tout simplement pas progressé. La journalisation a montré que l'action était exécutée. Parfois, l'utilisation aAction
aidé. Si j'ai cliqué sur l'élément manuellement (après l'arrêt du scénario de test), tout fonctionnait bien. Nous sommes donc passés au JS brut à cette occasion. Je n'ai pas travaillé avec AngularJS depuis 2 ans, donc les choses pourraient être mieux maintenant.Le clic exécuté par le pilote tente de simuler le comportement d'un utilisateur réel aussi près que possible tandis que le JavaScript
HTMLElement.click()
exécute l'action par défaut pour l'click
événement, même si l'élément n'est pas interactif.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 interactif .
Le pilote lèvera une erreur:
disabled
esttrue
)pointer-events
estnone
)Un JavaScript
HTMLElement.click()
effectuera toujours l'action par défaut ou, au mieux, échouera silencieusement si l'élément est désactivé.Le pilote est censé mettre l'élément au point s'il est focalisable.
Un JavaScript
HTMLElement.click()
ne le fera pas.Le pilote est censé émettre tous les événements (mousemove, mousedown, mouseup, click, ...) comme un vrai utilisateur.
Un JavaScript
HTMLElement.click()
émet uniquement l'click
événement. La page peut s'appuyer sur ces événements supplémentaires et peut se comporter différemment s'ils ne sont pas émis.Voici les événements émis par le pilote pour un clic avec Chrome:
Et voici l'événement émis avec une injection JavaScript:
L'événement émis par un JavaScript
.click()
n'est pas approuvé et l'action par défaut ne peut pas être appelée:https://developer.mozilla.org/en/docs/Web/API/Event/isTrusted
https://googlechrome.github.io/samples/event-istrusted/index.html
Notez que certains des pilotes génèrent toujours des événements non approuvés. C'est le cas de PhantomJS à partir de la version 2.1.
L'événement émis par un JavaScript
.click()
n'a pas les coordonnées du clic .Les propriétés
clientX, clientY, screenX, screenY, layerX, layerY
sont définies sur0
. La page peut s'appuyer sur eux et se comporter différemment.Il peut être acceptable d'utiliser un JavaScript
.click()
pour supprimer certaines données, mais ce n'est pas dans un contexte de test. Il va à l'encontre de l'objectif du test car il ne simule pas le comportement d'un utilisateur. Ainsi, si le clic du pilote échoue, un utilisateur réel échouera probablement également à effectuer le même clic dans les mêmes conditions.L'élément ciblé n'est pas encore visible / interactif en raison d'un retard ou d'un effet de transition.
Quelques exemples :
https://developer.mozilla.org/fr/docs/Web (menu de navigation déroulant) http://materializecss.com/side-nav.html (barre latérale déroulante)
Solutions de contournement:
Ajoutez un serveur pour attendre la visibilité, une taille minimum ou une position stable:
Réessayez de cliquer jusqu'à ce que cela réussisse:
Ajoutez un délai correspondant à la durée de l'animation / transition:
L'élément ciblé est recouvert par un élément flottant une fois défilé dans la vue:
Le pilote fait automatiquement défiler l'élément dans la vue pour le rendre visible. Si la page contient un élément flottant / collant (menu, publicités, pied de page, notification, politique de cookies ..), l'élément peut finir couvert et ne sera plus visible / interactif.
Exemple: https://twitter.com/?lang=en
Solutions de contournement:
Définissez la taille de la fenêtre sur une plus grande pour éviter le défilement ou l'élément flottant.
Déplacez-vous sur l'élément avec un
Y
décalage négatif , puis cliquez dessus:Faites défiler l'élément jusqu'au centre de la fenêtre avant le clic:
Cachez l'élément flottant s'il ne peut pas être évité:
la source
REMARQUE: appelons «clic» est un clic de l'utilisateur final. 'js click' est un clic via JS
Il y a 2 cas pour que cela se produise:
I. Si vous utilisez PhamtomJS
C'est alors le comportement connu le plus courant de
PhantomJS
. Certains éléments ne sont parfois pas cliquables, par exemple<div>
. En effet, ilPhantomJS
a été conçu à l'origine pour simuler le moteur des navigateurs (comme HTML + CSS initial -> calcul CSS -> rendu). Mais cela ne signifie pas être interagi avec la manière d'un utilisateur final (voir, cliquer, faire glisser). Par conséquent,PhamtomJS
n'est que partiellement pris en charge avec l'interaction des utilisateurs finaux.POURQUOI JS CLICK FONCTIONNE-T-IL? Quant à chaque clic, ils sont tous un clic moyen. C'est comme une arme à feu avec 1 canon et 2 déclencheurs . Un de la fenêtre, un de JS. Comme il est
PhamtomJS
excellent pour simuler le moteur du navigateur, un clic JS devrait fonctionner parfaitement.II. Le gestionnaire d'événements de "click" a pu se lier dans la mauvaise période.
Par exemple, nous avons un
<div>
-> Nous faisons quelques calculs
-> puis nous lions l'événement de clic au
<div>
.-> Plus avec un mauvais codage angulaire (par exemple, ne pas gérer correctement le cycle de l'oscilloscope)
Nous pouvons aboutir au même résultat. Le clic ne fonctionnera pas, car WebdriverJS essaie de cliquer sur l'élément alors qu'il n'a pas de gestionnaire d'événements de clic.
POURQUOI JS CLICK FONCTIONNE-T-IL? Js click revient à injecter js directement dans le navigateur. Possible de 2 façons,
Le premier est via la console devtools (oui, WebdriverJS communique avec la console de devtools).
La deuxième consiste à injecter une
<script>
balise directement dans le HTML.Pour chaque navigateur, le comportement sera différent. Mais peu importe, ces méthodes sont plus compliquées que de cliquer sur le bouton. Click utilise ce qui est déjà là (les utilisateurs finaux cliquent), js click passe par la porte dérobée.
Et pour js, le clic apparaîtra comme une tâche asynchrone. Ceci est lié à un sujet un peu complexe de « tâche asynchrone du navigateur et planification des tâches CPU » (lisez-le il y a quelque temps, je ne trouve pas l'article à nouveau). Pour faire court, cela se traduira principalement par le fait que js click devra attendre un cycle de planification des tâches du processeur et il sera exécuté un peu plus lentement après la liaison de l'événement de clic. (Vous pourriez connaître ce cas lorsque vous avez trouvé l'élément parfois cliquable, parfois non.)
=> Comme mentionné ci-dessus, les deux signifient dans un seul but, mais sur l'utilisation de quelle entrée:
=> Pour les performances, c'est difficile à dire car il repose sur les navigateurs. Mais généralement:
=> Inconvénients:
PS si vous cherchez une solution.
browser.wait()
( vérifiez ceci pour plus d'informations )(Je veux faire court, mais j'ai mal fini. Tout ce qui a trait à la théorie est compliqué à expliquer ...)
la source