web-dev-qa-db-fra.com

élément.click () ne fonctionne pas et ne génère pas d'erreur

Je me trouve dans une situation où un bouton, sur un formulaire, qui est animé en vue, si element.click () se produit pendant que l'animation est en cours, cela ne fonctionne pas.

element.click () ne génère pas d'erreur, ne renvoie pas un statut ayant échoué (il renvoie non défini), il ne fonctionne tout simplement pas.

J'ai essayé de vérifier que l'élément sur lequel vous cliquez n'est pas désactivé et est affiché (visible), mais même si ces deux tests réussissent, le clic échoue.

Si j'attends 0.4s avant de cliquer, cela fonctionne car l'animation est terminée.

Je ne veux pas avoir à ajouter de retards (qui ne sont pas fiables, et un bodge pour être franc), si je peux détecter quand un clic a fonctionné, et si ce n'est pas automatiquement réessayer.

Existe-t-il un moyen générique de détecter si un click () a été réellement activé afin que je puisse utiliser une boucle de nouvelle tentative jusqu'à ce qu'il le soit? 

6
Austin France

J'ai déterminé ce qui se passe, pourquoi je ne reçois pas d'erreur et comment résoudre ce problème.

Le problème principal concerne le fonctionnement de element.click(). En utilisant DEBUG="puppeteer:*", j'ai pu voir ce qui se passait en interne. Ce que element.click() fait réellement est: -

const box = element.boundingBox();
const x = box.x + (box.width/2);
const y = box.y + (box.height/2);
page.mouse.move(x,y);
page.mouse.down();
sleep(delay);
page.mouse.up();

Le problème est que, parce que la vue (div) anime l'élément boundingBox () de l'élément, et entre le moment où vous demandez la position de la boîte et la fin du clic (), l'élément s'est déplacé ou n'est pas cliquable.

Une erreur n'est pas générée (promesse rejetée) car il suffit d'un clic de souris sur un point de la fenêtre d'affichage et n'est liée à aucun élément. L'événement de souris est envoyé, juste que rien n'y répond.

Une solution de contournement consiste à ajouter un délai suffisant pour permettre à l'animation de se terminer. Une autre consiste à désactiver les animations pendant les tests.

La solution pour moi était d’attendre que la position de l’élément soit réglée à la position de destination, c’est-à-dire interroger le boundingBox () et d’attendre que x, y rende compte de la position précédemment déterminée.

Dans mon cas, c’est aussi simple que d’ajouter at 10,10 à mon script de test juste avant le clic, ou plus précisément

test-id "form1.button3" at 10,10 click

Et cela fonctionne comme suit, dans ce cas, la vue est animée à partir de la gauche.

 00.571 [selector.test, 61] à 8 410 
 Test-id "main.add" bouton de balise d'info affiché à -84 410 taille 116,33 activé non sélectionné cocher "Ajouter" 
 Test. .add "bouton de balise d'info affiché à -11 410 taille 116,33 activé non sélectionné cocher" Ajouter "
 test-id" main.add "bouton de balise info affiché à 8 410 taille 116,33 activé non sélectionné cocher" Ajouter "
 00.947 [selector.test, 61] cliquez sur 

Cela ne fonctionnerait pas pour un élément qui bougeait continuellement ou pour un élément qui est couvert par autre chose. Dans ce cas, essayez page.evaluate(el => el.click(), element).

4
Austin France

Page.click () renvoie une promesse, assurez-vous de la gérer comme telle, mais notez également que des problèmes peuvent survenir si vous ne la référez pas comme un xpath. C'est ce que je devais faire pour que cela fonctionne. J'ai essayé d'utiliser querySelectors et d'interagir avec les objets de cette façon, mais j'ai rencontré des problèmes.

page.evaluate(()=>{
await Promise.all([
    page.click("a[id=tab-default-2__item]"),
    //The page.waitFor is set to 15000 for my personal use. 
    //Feel free to play around with this.
    page.waitFor(15000)
]);
});    

J'espère que ça aide.

1
ElementCR