À propos des requêtes
Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →
Vue d'ensemble
Les requêtes sont les méthodes fournies par Testing Library pour localiser des éléments dans la page. Il existe plusieurs types de requêtes ("get", "find", "query") qui se distinguent par leur comportement lorsqu'aucun élément n'est trouvé : certaines lèvent une erreur tandis que d'autres retournent une Promise avec mécanisme de réessai. Selon le contenu visé, différentes requêtes peuvent être plus ou moins appropriées. Consultez le guide de priorité pour utiliser des requêtes sémantiques afin de tester vos pages de manière accessible.
Après avoir sélectionné un élément, vous pouvez utiliser l'API Events ou user-event pour déclencher des événements simulant des interactions utilisateur, ou utiliser Jest avec jest-dom pour formuler des assertions sur l'élément.
Testing Library propose des méthodes utilitaires fonctionnant avec les requêtes. Lorsque des éléments apparaissent ou disparaissent dynamiquement, les API asynchrones comme waitFor ou les requêtes findBy permettent d'attendre les modifications du DOM. Pour cibler uniquement les enfants d'un élément spécifique, utilisez within. Vous pouvez également configurer certaines options comme le timeout des réessais ou l'attribut testID par défaut.
Exemple
import {render, screen} from '@testing-library/react' // (or /dom, /vue, ...)
test('should show login form', () => {
render(<Login />)
const input = screen.getByLabelText('Username')
// Events and assertions...
})
Types de requêtes
Éléments uniques
getBy...: Retourne le nœud correspondant à la requête et lève une erreur descriptive si aucun élément ne correspond ou si plusieurs correspondances existent (préférezgetAllBypour plusieurs éléments attendus).queryBy...: Retourne le nœud correspondant ounullsi aucun élément ne correspond. Utile pour vérifier l'absence d'un élément. Lève une erreur en cas de correspondances multiples (utilisezqueryAllBysi acceptable).findBy...: Retourne une Promise résolue lorsqu'un élément correspondant est trouvé. Rejetée si aucun élément n'est trouvé ou si plusieurs correspondances existent après un timeout par défaut de 1000ms. Pour plusieurs éléments, utilisezfindAllBy.
Éléments multiples
getAllBy...: Retourne un tableau de tous les nœuds correspondants et lève une erreur si aucun élément ne correspond.queryAllBy...: Retourne un tableau de tous les nœuds correspondants ou un tableau vide ([]) si aucun élément ne correspond.findAllBy...: Retourne une Promise résolue en tableau d'éléments lorsque des correspondances sont trouvées. Rejetée si aucun élément n'est trouvé après un timeout par défaut de1000ms.- Les méthodes
findBycombinent les requêtesgetBy*etwaitFor. Elles acceptent les options dewaitForcomme dernier argument (ex:await screen.findByText('text', queryOptions, waitForOptions)).
- Les méthodes
Summary Table
| Type of Query | 0 Matches | 1 Match | >1 Matches | Retry (Async/Await) |
|---|---|---|---|---|
| Single Element | ||||
getBy... | Throw error | Return element | Throw error | No |
queryBy... | Return null | Return element | Throw error | No |
findBy... | Throw error | Return element | Throw error | Yes |
| Multiple Elements | ||||
getAllBy... | Throw error | Return array | Return array | No |
queryAllBy... | Return [] | Return array | Return array | No |
findAllBy... | Throw error | Return array | Return array | Yes |
Priorité
Conformément aux Principes directeurs, vos tests doivent refléter au maximum les interactions utilisateur réelles. Nous recommandons cet ordre de priorité :
Requêtes Accessibles à Tous Requêtes reflétant l'expérience des utilisateurs visuels/souris ainsi que ceux utilisant des technologies d'assistance.
getByRole: Permet d'interroger tout élément exposé dans l'arbre d'accessibilité. Avec l'optionname, vous pouvez filtrer les éléments par leur nom accessible. C'est la méthode privilégiée dans presque tous les cas. Le plus souvent, cela est utilisé avec l'optionnamecomme ceci :getByRole('button', {name: /submit/i}). Consultez la liste des rôles.getByLabelText: Idéal pour les champs de formulaire, reproduisant le comportement des utilisateurs naviguant via les libellés.getByPlaceholderText: Un placeholder ne remplace pas un libellé. À utiliser uniquement si aucune alternative n'existe.getByText: Méthode principale pour localiser des éléments non interactifs (divs, spans, paragraphes) via leur contenu textuel.getByDisplayValue: Utile pour naviguer dans des pages avec des formulaires pré-remplis.
Requêtes Sémantiques Sélecteurs conformes au HTML5 et ARIA. Notez que leur expérience utilisateur varie selon les navigateurs et technologies d'assistance.
getByAltText: Pour les éléments supportant le textealt(img,area,inputet éléments personnalisés).getByTitle: L'attribut title n'est pas lu systématiquement par les lecteurs d'écran et est invisible par défaut.
Identifiants de Test
getByTestId: Invisible/inaudible pour l'utilisateur. À réserver aux cas où les autres méthodes échouent ou sont inadaptées (ex: texte dynamique).
Utilisation des Requêtes
Les requêtes de base de DOM Testing Library nécessitent de passer un container comme premier argument. La plupart des implémentations framework fournissent des versions pré-liées lors du rendu des composants, évitant ainsi de spécifier le container. Pour interroger document.body, utilisez l'export screen comme ci-dessous (l'usage de screen est recommandé).
L'argument principal d'une requête peut être une chaîne, une expression régulière ou une fonction. Des options permettent d'ajuster l'analyse du texte. Voir TextMatch pour la documentation.
Avec les éléments DOM suivants (rendus via React, Vue, Angular ou HTML natif) :
<body>
<div id="app">
<label for="username-input">Username</label>
<input id="username-input" />
</div>
</body>
Vous pouvez utiliser une requête pour trouver un élément (ici byLabelText) :
import {screen, getByLabelText} from '@testing-library/dom'
// With screen:
const inputNode1 = screen.getByLabelText('Username')
// Without screen, you need to provide a container:
const container = document.querySelector('#app')
const inputNode2 = getByLabelText(container, 'Username')
queryOptions
Un objet queryOptions peut être passé avec le type de requête. Consultez la documentation de chaque requête pour les options disponibles, ex: API byRole.
screen
Toutes les requêtes exportées par DOM Testing Library acceptent un container comme premier argument. Étant donné que l'interrogation de l'ensemble du document.body est très courante, DOM Testing Library exporte également un objet screen qui contient toutes les requêtes pré-liées à document.body (en utilisant la fonctionnalité within). Les wrappers comme React Testing Library réexportent screen pour une utilisation identique.
Voici comment l'utiliser :
- Native
- React
- Angular
- Cypress
import {screen} from '@testing-library/dom'
document.body.innerHTML = `
<label for="example">Example</label>
<input id="example" />
`
const exampleInput = screen.getByLabelText('Example')
import {render, screen} from '@testing-library/react'
render(
<div>
<label htmlFor="example">Example</label>
<input id="example" />
</div>,
)
const exampleInput = screen.getByLabelText('Example')
import {render, screen} from '@testing-library/angular'
await render(`
<div>
<label for="example">Example</label>
<input id="example" />
</div>
`)
const exampleInput = screen.getByLabelText('Example')
cy.findByLabelText('Example').should('exist')
Note
Vous avez besoin d'un environnement DOM global pour utiliser
screen. Si vous utilisez Jest avec le paramètre testEnvironment défini surjsdom, un environnement DOM global sera disponible.Si vous chargez votre test via une balise
script, assurez-vous qu'elle se trouve aprèsbody. Un exemple est disponible ici.
TextMatch
La plupart des API de requête acceptent un TextMatch comme argument, ce qui signifie que l'argument peut être une chaîne, une expression régulière ou une fonction de signature (content?: string, element?: Element | null) => boolean qui renvoie true pour une correspondance et false sinon.
Exemples de TextMatch
Étant donné le HTML suivant :
<div>Hello World</div>
Trouvera le div :
// Matching a string:
screen.getByText('Hello World') // full string match
screen.getByText('llo Worl', {exact: false}) // substring match
screen.getByText('hello world', {exact: false}) // ignore case
// Matching a regex:
screen.getByText(/World/) // substring match
screen.getByText(/world/i) // substring match, ignore case
screen.getByText(/^hello world$/i) // full string match, ignore case
screen.getByText(/Hello W?oRlD/i) // substring match, ignore case, searches for "hello world" or "hello orld"
// Matching with a custom function:
screen.getByText((content, element) => content.startsWith('Hello'))
Ne trouvera pas le div :
// full string does not match
screen.getByText('Goodbye World')
// case-sensitive regex with different case
screen.getByText(/hello world/)
// function looking for a span when it's actually a div:
screen.getByText((content, element) => {
return element.tagName.toLowerCase() === 'span' && content.startsWith('Hello')
})
Précision
Les requêtes acceptant un TextMatch prennent également un objet comme dernier argument avec des options affectant la précision du matching textuel :
exact: Par défauttrue; correspondance complète et sensible à la casse. Quand false, recherche des sous-chaînes insensibles à la casse.- Sans effet avec des arguments
regexoufunction. - Dans la plupart des cas, utiliser une regex plutôt qu'une chaîne avec
{ exact: false }offre plus de contrôle sur le matching flou.
- Sans effet avec des arguments
normalizer: Fonction optionnelle modifiant le comportement de normalisation. VoirNormalization.
Normalisation
Avant tout matching textuel dans le DOM, DOM Testing Library normalise automatiquement le texte. Par défaut, la normalisation supprime les espaces en début/fin de chaîne et fusionne les espaces blancs adjacents en un seul espace.
Pour empêcher cette normalisation ou fournir une alternative (ex: supprimer des caractères Unicode), vous pouvez spécifier une fonction normalizer dans l'objet d'options. Cette fonction reçoit une chaîne et doit renvoyer sa version normalisée.
Note
Spécifier une
normalizerremplace la normalisation native, mais vous pouvez appelergetDefaultNormalizerpour obtenir le normalisateur par défaut et l'adapter ou l'utiliser dans votre propre fonction.
getDefaultNormalizer accepte un objet d'options permettant de configurer son comportement :
trim: Par défauttrue. Supprime les espaces en début/fin de chaîne.collapseWhitespace: Par défauttrue. Fusionne les espaces internes (retours chariot, tabulations, espaces multiples) en un seul espace.
Exemples de normalisation
Pour effectuer un matching sans suppression des espaces :
screen.getByText('text', {
normalizer: getDefaultNormalizer({trim: false}),
})
Pour supprimer certains caractères Unicode tout en conservant partiellement le comportement natif :
screen.getByText('text', {
normalizer: str =>
getDefaultNormalizer({trim: false})(str).replace(/[\u200E-\u200F]*/g, ''),
})
Requêtes manuelles
En complément des requêtes fournies par la bibliothèque de test, vous pouvez utiliser l'API DOM standard querySelector pour interroger des éléments. Notez que l'utilisation de cette méthode comme échappatoire pour interroger par classe ou id est déconseillée car ces attributs sont invisibles pour l'utilisateur. Utilisez un testid si nécessaire pour clarifier votre intention de recourir à des requêtes non sémantiques et établir un contrat d'API stable dans le HTML.
// @testing-library/react
const {container} = render(<MyComponent />)
const foo = container.querySelector('[data-foo="bar"]')
Extension navigateur
Rencontrez-vous toujours des difficultés pour savoir comment utiliser les requêtes de Testing Library ?
Il existe une extension Chrome très pratique nommée Testing Playground qui vous aide à trouver les meilleures requêtes pour sélectionner des éléments. Elle permet d'inspecter les hiérarchies d'éléments dans les outils de développement du navigateur et propose des suggestions de sélection tout en encourageant les bonnes pratiques de test.
Bac à sable
Pour vous familiariser davantage avec ces requêtes, vous pouvez les expérimenter sur testing-playground.com. Testing Playground est un bac à sable interactif où vous pouvez exécuter différentes requêtes sur votre propre HTML et obtenir un retour visuel correspondant aux règles mentionnées ci-dessus.