Moteur de rendu de test

Importation

import TestRenderer from 'react-test-renderer'; // ES6
const TestRenderer = require('react-test-renderer'); // ES5 avec npm

Aperçu

Ce paquet fournit un moteur de rendu (dans la suite de cet article, pour des raisons de concision, nous emploierons le terme générique anglais renderer sans italiques, NdT) capable de produire un rendu de composants React sous forme d’objets JavaScript nus, sans dépendre du DOM ou d’un environnement mobile natif.

Fondamentalement, ce paquet facilite la création d’un instantané de la hiérarchie produite par un renderer React DOM ou React Native (similaire à un arbre DOM) sans recourir à un navigateur ou à jsdom.

Exemple :

import TestRenderer from 'react-test-renderer';

function Link(props) {
  return <a href={props.page}>{props.children}</a>;
}

const testRenderer = TestRenderer.create(
  <Link page="https://www.facebook.com/">Facebook</Link>
);

console.log(testRenderer.toJSON());
// { type: 'a',
//   props: { href: 'https://www.facebook.com/' },
//   children: [ 'Facebook' ] }

Vous pouvez utiliser la fonctionnalité de test par instantanés (snapshot testing, NdT) de Jest pour sauvegarder automatiquement une copie de l’arbre JSON obtenu dans un fichier, puis vérifier dans vos tests qu’il n’a pas changé : vous trouverez plus de détails ici.

Vous pouvez également explorer le résultat pour trouver des nœuds spécifiques et vérifier vos attentes les concernant.

import TestRenderer from 'react-test-renderer';

function MyComponent() {
  return (
    <div>
      <SubComponent foo="bar" />
      <p className="my">Salut</p>
    </div>
  )
}

function SubComponent() {
  return (
    <p className="sub">Sous-Composant</p>
  );
}

const testRenderer = TestRenderer.create(<MyComponent />);
const testInstance = testRenderer.root;

expect(testInstance.findByType(SubComponent).props.foo).toBe('bar');
expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Sous-Composant']);

TestRenderer

Instance de TestRenderer

TestInstance

Référence de l’API

TestRenderer.create()

TestRenderer.create(element, options);

Crée une instance de TestRenderer avec l’élément React passé en argument. Ça n’utilise pas un véritable DOM, mais ça ne l’empêche pas de produire l’arbre intégral des composants en mémoire pour pouvoir vérifier vos attentes dessus. L’instance renvoyée possède les méthodes et propriétés suivantes.

testRenderer.toJSON()

testRenderer.toJSON()

Renvoie un objet représentant l’arbre obtenu. Cet arbre contient uniquement les nœuds spécifiques à la plateforme comme <div> ou <View> avec leur props mais ne contient aucun composant écrit par l’utilisateur. C’est pratique pour le test par instantanés.

testRenderer.toTree()

testRenderer.toTree()

Renvoie un objet représentant l’arbre obtenu. Contrairement à toJSON() la représentation y est plus détaillée et contient les composants écrits par l’utilisateur. Vous n’aurez probablement pas besoin de cette méthode à moins que vous n’écriviez votre propre bibliothèque de vérification d’attentes construite au-dessus du renderer de test.

testRenderer.update()

testRenderer.update(element)

Effectue à nouveau le rendu de l’arbre en mémoire, avec un nouvel élément racine. Ça simule une mise à jour de l’arbre React à la racine. Si le nouvel élément a le même type et la même clé que l’élément précédent, l’arbre sera mis à jour ; dans le cas contraire, un nouvel arbre sera re-monté.

testRenderer.unmount()

testRenderer.unmount()

Démonte l’arbre en mémoire, en déclenchant les événements de cycle de vie appropriés.

testRenderer.getInstance()

testRenderer.getInstance()

Renvoie l’instance correspondant à l’élément racine, s’il est disponible. Ça ne marchera pas si l’élément racine est une fonction composant car celles-ci n’ont pas d’instance.

testRenderer.root

testRenderer.root

Renvoie l’objet « instance de test » racine, qui est utile pour faire des vérifications d’attentes à propos de nœuds spécifiques dans l’arbre. Vous pouvez l’utiliser pour trouver d’autres « instances de test » présentes plus profond dans l’arbre.

testInstance.find()

testInstance.find(test)

Trouve une unique « instance de test » descendante pour laquelle test(testInstance) renvoie true. Si test(testInstance) ne renvoie pas true pour exactement une « instance de test », une erreur est levée.

testInstance.findByType()

testInstance.findByType(type)

Trouve une unique « instance de test » avec le type donné. Si il n’y a pas exactement une « instance de test » avec le type donné, une erreur est levée.

testInstance.findByProps()

testInstance.findByProps(props)

Trouve une unique « instance de test » avec les props données. Si il n’y a pas exactement une « instance de test » avec les props données, une erreur est levée.

testInstance.findAll()

testInstance.findAll(test)

Trouve toutes les « instances de test » descendantes pour lesquelles test(testInstance) renvoie true.

testInstance.findAllByType()

testInstance.findAllByType(type)

Trouve toutes les « instances de test » descendantes avec le type donné.

testInstance.findAllByProps()

testInstance.findAllByProps(props)

Trouve toutes les « instances de test » descendantes avec les props données.

testInstance.instance

testInstance.instance

L’instance de composant correspondant à cette « instance de test ». Ça n’est disponible que pour les composants à base de classe, vu que les fonctions composants n’ont pas d’instances. Ça correspond à la valeur de this au sein du composant donné.

testInstance.type

testInstance.type

Le type de composant correspondant à cette « instance de test ». Par exemple, un composant <Button /> a pour type Button.

testInstance.props

testInstance.props

Les props correspondant à cette « instance de test ». Par exemple, un composant <Button size="small" /> a comme props {size: 'small'}.

testInstance.parent

testInstance.parent

L’« instance de test » parente de cette « instance de test ».

testInstance.children

testInstance.children

Les « instances de test » enfants de cette « instance de test ».

Idées

Vous pouvez passer la fonction createNodeMock à TestRenderer.create comme option pour créer des simulations personnalisées de refs. createNodeMock accepte l’élément courant et doit retourner une imitation de ref. C’est utile quand vous testez un composant qui utilise des refs.

import TestRenderer from 'react-test-renderer';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.input = null;
  }
  componentDidMount() {
    this.input.focus();
  }
  render() {
    return <input type="text" ref={el => this.input = el} />
  }
}

let focused = false;
TestRenderer.create(
  <MyComponent />,
  {
    createNodeMock: (element) => {
      if (element.type === 'input') {
        // simule une fonction focus
        return {
          focus: () => {
            focused = true;
          }
        };
      }
      return null;
    }
  }
);
expect(focused).toBe(true);