Maîtrisez la sélection des éléments avec Cypress
Fondamentaux de la sélection des éléments
1. Comprendre le DOM (Document Object Model)
Le Document Object Model (DOM) sert de pont entre les pages web et les scripts ou langages de programmation. Dans le contexte des tests automatisés avec Cypress, comprendre le DOM est la première étape, car c’est à travers lui que toutes les interactions avec l’interface utilisateur sont réalisées.
Le DOM est une représentation structurée de documents HTML et XML, présentée sous une forme arborescente qui imite la structure du document. Chaque élément du document, comme les en-têtes, paragraphes, liens, et images, est représenté par un objet dans cette arborescence, permettant aux développeurs d’accéder, de modifier, ou de supprimer des contenus et des structures de la page web. Le DOM n’est pas une caractéristique du langage HTML ou JavaScript, mais plutôt une interface normalisée par laquelle ces langages peuvent interagir avec les documents.
Voici un exemple sous forme de schéma :
L’importance du DOM dans le développement web et les tests ne peut être sous-estimée. Premièrement, il permet une interaction dynamique avec la structure de la page. Grâce au DOM, les scripts peuvent modifier le document, changer le style CSS, ajouter ou supprimer des éléments, créer des événements, et même construire de nouvelles pages web dynamiquement. Cette interaction est au cœur des applications web modernes qui s’appuient sur des interactions client complexes et des contenus dynamiques.
Dans le domaine des tests automatisés, et notamment avec des outils comme Cypress, le DOM joue un rôle capital. Cypress s’appuie sur le DOM pour réaliser des assertions, des interactions, et pour accéder aux éléments de la page web. Par exemple, lorsqu’un test nécessite de cliquer sur un bouton, Cypress va d’abord interroger le DOM pour localiser l’élément, puis simuler l’action de clic.
La capacité de Cypress...
Sélecteurs CSS
Après avoir exploré les fondamentaux de la sélection des éléments et l’importance d’une précision accrue dans le DOM, il est opportun de se tourner vers la sélection des éléments grâce au CSS.
Nous verrons dans un second temps la recommandation de Cypress, qui est l’ajout d’attribut.
Dans certains cas, vous ne pouvez pas changer le code car vous n’y avez pas accès. C’est le cas lors de l’utilisation d’une bibliothèque que vous importez.
Material-UI est une bibliothèque populaire de composants d’interface utilisateur pour React (bibliothèque JavaScript qui permet de créer des interfaces utilisateurs), mais elle pouvait parfois poser des défis en matière d’ajout d’attributs personnalisés. Le problème n’est pas qu’il est impossible d’ajouter des attributs, mais plutôt que l’architecture de certains composants de Material-UI peut rendre cela plus compliqué. Par exemple, lors de l’utilisation de composants de plus haut niveau qui encapsulaient plusieurs éléments DOM, il n’était pas toujours évident de savoir où exactement l’attribut personnalisé serait appliqué, ou bien s’il était propagé correctement à l’élément...
Recommandation de Cypress
Cypress recommande l’utilisation d’attributs data-* pour vos sélecteurs, et cette approche est considérée comme une meilleure pratique dans le développement et le test de logiciels modernes.
Les attributs sont des spécifications qui définissent les propriétés des éléments HTML. Ils sont insérés dans les balises de début d’un élément et servent à fournir des informations supplémentaires sur cet élément. Par exemple, dans le code suivant :
<input type="text">
type est un attribut qui indique le type de l’élément input.
Les attributs data-* sont conçus pour être utilisés spécifiquement pour les sélecteurs dans les tests, plutôt que pour le style ou le comportement du document. L’avantage principal de cette approche est que ces attributs ne changent pas avec les modifications du style ou de la structure HTML et restent stables, rendant les tests plus fiables.
Préférez les attributs data-* aux sélecteurs CSS traditionnels car ils permettent une :
-
Isolation des changements de style et de comportement :
-
Les attributs data-* sont indépendants de la présentation visuelle et du comportement de l’application. Ils ne sont pas affectés par les modifications de style (CSS) ou les changements...
Pièges courants et comment les éviter
Même avec les meilleures pratiques, certains pièges courants peuvent compromettre la fiabilité des sélecteurs dans vos tests.
Dépendance à la structure du DOM : si vos sélecteurs sont trop couplés à la structure du DOM, même un petit changement peut les casser.
Par exemple, si vous utilisez des sélecteurs enfants (comme div > p), l’ajout d’un élément entre div et p brisera le sélecteur.
Sélecteurs basés sur le style : les classes CSS utilisées pour le style sont souvent réutilisées et modifiées, rendant les sélecteurs basés sur ces classes instables.
Par exemple, un bouton avec la classe btn-primary pourrait être changé en btn-secondary pour des raisons de style, altérant le sélecteur original.
Surutilisation des sélecteurs ID : bien que très spécifiques, les sélecteurs ID ne doivent pas être surutilisés, surtout s’il y a une chance que l’ID soit dynamique ou modifié dans différentes instances de la même page.
Sélecteurs basés sur le texte : s’appuyer sur le texte visible pour les sélecteurs peut être problématique, surtout dans les applications multilingues.
Par exemple, si un bouton est sélectionné par le texte...
Utilisation des commandes de Cypress pour la sélection des éléments
Cypress offre plusieurs commandes pour interagir avec le DOM, et savoir comment elles fonctionnent avec les sélecteurs peut améliorer l’efficacité des tests. Voici une liste non exhaustive, nous les utiliserons tout au long du livre avec des exemples plus concrets.
En premier lieu, vous devez récupérer votre élément afin d’effectuer différentes actions.
cy.get() : cette commande est l’une des plus utilisées dans Cypress pour la récupération des éléments. Elle accepte les sélecteurs CSS et est très pratique pour accéder directement aux éléments.
Par exemple en utilisant un sélecteur de classe :
cy.get('.submit-button')
Par exemple en utilisant un sélecteur d’attribut :
cy.get('[data-cy="submit-button"]')
1. Les tests avec Chai
Avec Cypress, vous utiliserez souvent Chai (bibliothèque d’assertion principalement utilisée pour les tests) pour les assertions dans vos tests. Chai offre une variété de méthodes d’assertion qui vous permettent de vérifier si certaines conditions sont remplies dans votre application web.
Reprenons l’exemple de notre bouton :
cy.get('[data-cy="submit-button"]')
Vous pouvez vérifier qu’il soit bien visible :
cy.get('[data-cy="submit-button"]').should('be.visible');
La fonction should() permet d’effectuer une assertion sur l’élément sélectionné. Vous pouvez ainsi l’utiliser avec différents arguments comme nous venons de le voir avec ’be.visible’.
Vous pouvez également vérifier que l’élément n’existe pas :
cy.get('[data-cy="submit-button"]').should('not.exist');
ou qu’il a une certaine classe CSS :
cy.get('[data-cy="submit-button"]').should('have.class',
'ma-classe-css');
ou qu’il contient un certain texte :
cy.get('[data-cy="submit-button"]').should('contain',
'certain texte');
2. Interaction avec un champ input
Après avoir récupéré votre élément, vous pouvez réaliser...
Gérer les éléments dynamiques et asynchrones
Les éléments dynamiques sont des composants de l’interface utilisateur qui changent en réponse à des interactions de l’utilisateur ou à des événements du système.
Par exemple, un menu déroulant qui apparaît lorsqu’on clique sur un bouton ou un message d’erreur qui s’affiche suite à une validation de formulaire ratée.
Les éléments asynchrones, quant à eux, sont ceux qui ne sont pas immédiatement présents lors du chargement initial de la page, mais qui apparaissent ou se mettent à jour après un certain délai, souvent en réponse à des appels de données depuis un serveur.
Par exemple, une liste de produits chargée après un appel API.
Cypress offre plusieurs stratégies pour gérer ces éléments, assurant que les tests restent robustes et fiables même en présence de contenu changeant ou se chargeant de manière asynchrone.
1. Attente explicite et implicite
Cypress gère automatiquement certaines attentes, mais dans certains cas il est nécessaire de spécifier des attentes explicites. Pour les éléments asynchrones, l’utilisation de .wait() permet d’attendre un délai spécifique. Cependant, son utilisation doit être minimisée au profit des attentes implicites, qui attendent qu’un élément soit dans un état spécifique avant de continuer.
Un exemple d’attente implicite :
// Visite une page
cy.visit('https://exemple.com');...
Meilleures pratiques pour interagir avec les éléments
Voici résumées les meilleures pratiques pour interagir avec les éléments du DOM.
-
Privilégiez les attributs data-*, comme data-test ou data-cy, pour vos sélecteurs, car ils ne changent généralement pas avec le style ou la structure du DOM, assurant ainsi la stabilité des tests.
-
Évitez les sélecteurs basés sur des noms de classe CSS susceptibles de changer en raison de modifications visuelles, ou des sélecteurs trop génériques qui pourraient cibler de multiples éléments.
-
Cypress gère automatiquement l’attente des assertions jusqu’à ce qu’elles passent ou jusqu’à ce qu’un délai d’attente soit atteint. Utilisez cy.get() avec les délais d’attente appropriés pour attendre explicitement les éléments.
-
Évitez les anti-modèles comme les attentes explicites (cy.wait()) sans cible spécifique, car ils peuvent conduire à des échecs de tests si l’application est plus lente que prévu.
-
Lorsque vous utilisez des commandes comme .click() ou .type(), assurez-vous que l’élément est dans un état interactif (par exemple, non masqué, non recouvert, et activable).
-
Utilisez les assertions pour vérifier l’état des éléments...