• 12 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 2/23/24

Testez vos composants avec React Testing Library

Pour l'instant, nous avons appris à faire de simples tests unitaires pour tester des fonctions simples. Mais qu'en est-il du comportement de nos composants ? Comment vérifier que ce qui est affiché pour l'utilisateur fonctionne bien comme on le souhaite, et qu'il n'y a pas de régression ?

En d'autres mots, comment faire pour tester nos composants ? 🙈

Vous avez pu voir dans le chapitre précédent que pour tester, on exécute, et on compare avec ce qui était attendu. Or, nos composants React fournissent des instructions permettant de mettre à jour le DOM. Pour tester nos composants, il faudra donc faire un render, vérifier le DOM généré, et le comparer avec ce qui était attendu.

Pour faire ça, nous allons pouvoir utiliser React Testing Library, la bibliothèque dont je vous ai déjà parlé. 🚀

Découvrez React Testing Library

React Testing Library nous donne accès à des outils basés sur react-dom  et react-dom/test-utils  qui nous permettent de respecter les bonnes pratiques des tests, et de profiter de messages d'erreur lisibles.

Cette solution ne remplace pas Jest, au contraire, elle est complémentaire à Jest. React Test Library nous permet de vraiment nous concentrer sur le DOM, en le recréant, en permettant de simuler des interactions et de vérifier ce qui est rendu. Cela nous aide à nous mettre dans la peau de nos utilisateurs, et à anticiper ce qu'ils verront.

Par exemple, lorsqu'on veut tester un composant qui fait un call API, on n'a pas forcément besoin de vérifier le useEffect  et le state  qui nous permettent de faire tout ça. La logique de React Testing Library est de vérifier qu'on a bien notre composant, qu'il est remplacé par un loader le temps que les datas chargent, puis qu'il est complété avec les datas qu'on a récupérées.

Mais ici… On a affaire à des tests d'intégration ou des tests unitaires ?

Eh bien, React Testing Library nous permet de faire les deux. On va pouvoir tester nos hooks en isolation pour faire des tests unitaires dessus, et tester les interactions entre nos différents composants, faisant ainsi des tests d'intégration.

Lançons-nous dès maintenant dans le test de nos composants avec React Testing Library... !

Créez un test simple d'un composant

Mais… on n'a même pas installé la bibliothèque ?

C'est normal, pas besoin d'installation ici puisque React Testing Library fait maintenant partie des outils installés de base par Create React App. Il nous suffit juste d'importer ce dont on a besoin dans notre fichier de test.

Nous allons commencer par tester notre composant Footer qui permet de changer de thème. Dans /components/Footer  , on crée donc un fichier index.test.js  .

Nous allons tout d'abord nous assurer que Footer  render bien, sans crasher. Pour cela, on importe Footer  , le render  de React Testing Library, et on utilise render  :

import Footer from './'
import { render } from '@testing-library/react'
 
describe('Footer', () => {
    test('Should render without crash', async () => {
        render(<Footer />;)
    })
})

Si vous n'avez pas quitté le mode watch, vos tests se lancent automatiquement… Ou sinon, vous pouvez refaire  yarn run  test  . Et on a une erreur

TypeError: Cannot destructure property toggleTheme of '(0 , _react.useContext)(...)' as it is undefined.

Évidemment ! Notre composant fait partie d'un ensemble qui utilise le Contexte… Or, ici, notre composant n'est pas englobé par notre Provider de thème light  /  dark  . 🤦‍♀️

Pas de panique, vous vous en doutez : React Testing Library nous permet de gérer ça. Il y a un moyen plus propre de le faire que nous verrons un peu plus tard, mais pour l'instant, contentons-nous de wrapper le composant   Footer  avec  ThemeProvider  directement dans notre test :

import Footer from './'
import { render } from '@testing-library/react'
import { ThemeProvider } from '../../utils/context'

describe('Footer', () => {
    test('Should render without crashing', async () => {
        render(
            <ThemeProvider>
                <Footer />
            </ThemeProvider>
        )
    })
})

Et bravo ! Ainsi le retour de notre test est tout vert. ✅

Profitons-en pour aller un peu plus loin dans ce que l'on teste dans notre composant.

Testez les événements de vos composants

Je vous ai déjà parlé du fait que la philosophie React Testing Library est de se mettre dans la peau de votre utilisateur.

Alors comment faire pour tester que notre NightModeButton  fonctionne bien ?

Ici, il n'est pas question de vérifier le state interne de notre Contexte. Au lieu de ça, regardons ce que l'utilisateur voit.

Le bouton affiche "☀️" lorsque nous sommes en mode jour et "🌙" pour le mode nuit. Il faut donc que l'on vérifie ce qui est affiché.

On va donc récupérer le contenu de notre bouton, et comparer le texte affiché – allons-y !

Interagissez avec un élément

La bibliothèque met à votre disposition toute une série de sélecteurs permettant d'accéder à un élément spécifique (comme en JavaScript). N'hésitez pas à jeter un œil à la documentation de React Testing Library (en anglais) pour découvrir tous les sélecteurs auxquels vous avez accès.

Vous pouvez sélectionner un élément selon son rôle, son label, son placeholder, etc. Dans notre cas, notre Footer  ne contient qu'un seul bouton. On peut donc très simplement utiliser getByRole  .

On va également avoir besoin de screen  qu'on importe avec  render  :

import { render, screen } from '@testing-library/react'

C'est quoi encore ça, screen  ?

Eh bien, screen  est en quelque sorte le body  qui contient notre composant, à partir duquel on va pouvoir utiliser nos sélecteurs.

Pour accéder à notre bouton, on a donc :

test('Change theme', async () => {
    render(
        <ThemeProvider>
            <Footer />
        </ThemeProvider>
    )
    const nightModeButton = screen.getByRole('button')
})

Et à partir de là, les choses sérieuses commencent ! 👩‍💻👨‍💻

Comme pour le test du chapitre précédent, on va comparer ce qui est attendu avec ce qui se passe vraiment. Alors réfléchissons.

Au départ, notre thème est récupéré. Sa valeur initiale est light  : le "☀️" est affiché. Lorsqu'on clique sur le bouton, la valeur du thème change (avec toggleTheme  ), et le thème devient dark  . Le bouton affiche alors "🌙". Un bon test est de :

1- Vérifier la présence de "☀️".

2- Cliquer sur le bouton.

3- Vérifier s'il y a bien "🌙".

Commençons donc par la première étape, la présence de "☀️" :

test('Change theme', async () => {
    render(
        <ThemeProvider>
            <Footer />
        </ThemeProvider>
    )
    const nightModeButton = screen.getByRole('button')
    expect(nightModeButton.textContent).toBe('Changer de mode : ☀️')
})

En vérifiant dans notre terminal, ce test fonctionne bien. Yay !

On passe donc à l'étape 2, et on peut enchaîner directement avec l'étape 3 puisqu'elle ressemble très fortement à l'étape 1.

Pour interagir avec notre composant, on a besoin de fireEvent  qui va nous permettre de déclencher des événements du DOM, ici click  . On fait donc :

import { render, screen, fireEvent } from '@testing-library/react'
import { ThemeProvider } from '../../utils/context'
import Footer from './'
 
test('Change theme', async () => {
    render(
        <ThemeProvider>
            <Footer />
        </ThemeProvider>
    )
    const nightModeButton = screen.getByRole('button')
    expect(nightModeButton.textContent).toBe('Changer de mode : ☀️')
    fireEvent.click(nightModeButton)
    expect(nightModeButton.textContent).toBe('Changer de mode : 🌙')
})

Bravo à vous ! Vous venez de tester avec succès votre composant Footer  !

Voyons maintenant quelques méthodes supplémentaires pour faire des tests, dans le screencast ci-dessous 👇 :

Testez vos hooks

Dans la partie précédente, vous avez appris à créer vos propres hooks personnalisés. Mais comment tester ses hooks ? ⚓️

Il pourrait être tentant de les tester indépendamment, mais la plupart du temps, ça ne correspond pas à la philosophie de React Testing Library. En effet, ces tests peuvent être considérés comme des "tests de détails d'implémentation", qui prennent du temps, pour ne pas être forcément très pertinents, précisément ce qu'on cherche à éviter.

De toute manière, ici, vous avez déjà testé un de vos hooks sans vous en rendre compte.
Allez-y, lancez la commande  yarn test -- --coverage   pour voir. 

screenshot du coverage
Voilà un screenshot du coverage

Vous voyez que votre fichier utils/hooks/index.jsx  est effectivement testé  (le pourcentage est bas, car le hook qui est dans le même fichier useFetch  n'a pas été testé). En effet, votre composant Footer  utilise le hook useTheme pour accéder à theme  et toggleTheme  . Et la plupart du temps, c'est la méthode à privilégier.

La leçon à retenir est donc que pour tester un hook, le meilleur moyen est de tester un composant qui utilise ce hook

Exercez-vous

C'est maintenant le moment de mettre en pratique ce que vous avez appris dans ce chapitre. Comme d'habitude, vous pourrez commencer l'exercice depuis la branche P3C2-begin du repository GitHub.

screenshot de la nouvelle fonction permettant de mettre en favori
Voilà à quoi ressemble la nouvelle fonction permettant de mettre en favori

Ici, vous devrez :

  • Créer un fichier de test pour Card  . 

  • Vérifier que Card utilise bien la picture  que vous lui passez en props.

  • Tester que lorsque vous lui passez une props title  , elle s'affiche bien.

  • Vérifier que le titre change bien lorsqu'un profil est sélectionné dans les favoris (pour cela, vous pouvez utiliser la méthode closest  (dont je vous mets le lien de la documentation ici), qui vous permettra d'accéder à la div  parente la plus proche).

Vous trouverez les solutions sur la branche P3C2-solution.

En résumé

  • React Testing Library est une solution complémentaire à Jest qui permet de tester les composants React.

  • Il ne faut pas tester le moindre détail d'un composant (pas la peine de tester ses hooks individuellement ou le state interne), mais essayer de se mettre à la place d'un utilisateur.

  • render  permet de générer notre élément en simulant le comportement du navigateur.

  • screen  nous permet d'accéder aux sélecteurs afin de tester nos composants.

Qu'avez-vous pensé de React Testing Library ? Pas mal, n'est-ce pas ? Dans le prochain chapitre, on va continuer à l'utiliser pour tester nos composants qui font des appels API ! Alors à tout de suite ! 🚀

Example of certificate of achievement
Example of certificate of achievement