Quand devriez-vous utiliser render et shallow dans les tests Enzyme / React?

95

avant de poster cette question, j'ai essayé de rechercher dans sqa stackexchange mais je n'ai trouvé aucun article sur shallow et rendu là-bas, donc j'espère que quelqu'un pourra m'aider ici.

Quand dois-je utiliser le rendu peu profond pour tester les composants de réaction? Sur la base de la documentation airbnb, j'ai fait quelques opinions sur la différence des deux:

  1. Étant donné que peu profond teste les composants en tant qu'unité , il doit donc être utilisé pour les composants «parents». (ex. tableaux, emballages, etc.)

  2. Le rendu est destiné aux composants enfants.

La raison pour laquelle j'ai posé cette question, c'est que j'ai du mal à déterminer lequel je devrais utiliser (bien que la documentation dise qu'ils sont très similaires)

Alors, comment savoir lequel utiliser dans un scénario spécifique?

Cyval
la source
2
La différence entre shallow () et mount () est que shallow () teste les composants indépendamment des composants enfants qu'ils rendent tandis que mount () approfondit et teste les enfants d'un composant. Pour shallow (), cela signifie que si le composant parent rend un autre composant dont le rendu échoue, alors un rendu shallow () sur le parent passera toujours.
Shyam Kumar

Réponses:

160

Selon la documentation Enzyme :

mount(<Component />) pour le rendu DOM complet est idéal pour les cas d'utilisation où vous avez des composants qui peuvent interagir avec les API DOM, ou peuvent nécessiter le cycle de vie complet afin de tester complètement le composant (par exemple, componentDidMount, etc.)

contre.

shallow(<Component />) pour le rendu peu profond est utile pour vous contraindre à tester un composant en tant qu'unité et pour vous assurer que vos tests n'affirment pas indirectement le comportement des composants enfants.

contre.

renderqui est utilisé pour rendre les composants de réaction en HTML statique et analyser la structure HTML résultante.

Vous pouvez toujours voir les "nœuds" sous-jacents dans un rendu peu profond, donc par exemple, vous pouvez faire quelque chose comme cet exemple (légèrement artificiel) en utilisant AVA comme lanceur de spécifications:

let wrapper = shallow(<TagBox />);

const props = {
    toggleValue: sinon.spy()
};

test('it should render two top level nodes', t => {
    t.is(wrapper.children().length, 2);
});

test('it should safely set all props and still render two nodes', t => {
    wrapper.setProps({...props});
    t.is(wrapper.children().length, 2);
});

test('it should call toggleValue when an x class is clicked', t => {
    wrapper.setProps({...props});
    wrapper.find('.x').last().simulate('click');
    t.true(props.toggleValue.calledWith(3));
});

Notez que le rendu , la configuration des accessoires et la recherche de sélecteurs et même les événements synthétiques sont tous pris en charge par un rendu superficiel, donc la plupart du temps, vous pouvez simplement l'utiliser.

Mais, vous ne pourrez pas obtenir le cycle de vie complet du composant, donc si vous vous attendez à ce que des choses se produisent dans componentDidMount, vous devez utiliser mount(<Component />);

Ce test utilise Sinon pour espionner les composantscomponentDidMount

test.only('mount calls componentDidMount', t => {

    class Test extends Component {
        constructor (props) {
            super(props);
        }
        componentDidMount() {
            console.log('componentDidMount!');
        }
        render () {
            return (
                <div />
            );
        }
    };

    const componentDidMount = sinon.spy(Test.prototype, 'componentDidMount');
    const wrapper = mount(<Test />);

    t.true(componentDidMount.calledOnce);

    componentDidMount.restore();
});

Ce qui précède ne passera pas avec le rendu superficiel ou rendre

render vous fournira uniquement le html, vous pouvez donc toujours faire des choses comme ceci:

test.only('render works', t => {

    // insert Test component here...

    const rendered = render(<Test />);
    const len = rendered.find('div').length;
    t.is(len, 1);
});

J'espère que cela t'aides!

4m1r
la source
1
Je n'obtiens toujours pas 100%, pourquoi les trois verbes apportent des méthodes différentes avec eux. Par exemple, on peut utiliser wrapper.getNode () en shallow mais pas en render. des explications / lien / docs / blogs, qui m'aident à obtenir ce togehter?
Paulquappe
@HenryZhu, il devrait être clair d'après la documentation que le rendu est plus complexe que superficiel, car il essaie en fait d'imiter l'arborescence DOM pour ce nœud de composant particulier
AGE
11
la migration enzymatique de la v2 vers la v3 a également activé les
Abhinav Singi
Une bonne explication supplémentaire des différences est ici github.com/airbnb/enzyme/issues/465#issuecomment-227697726 et ici github.com/airbnb/enzyme/issues/465#issuecomment-229116418
Dmitry
9

La différence entre shallow () et mount () est que shallow () teste les composants indépendamment des composants enfants qu'ils rendent tandis que mount () approfondit et teste les enfants d'un composant.

Pour shallow (), cela signifie que si le composant parent rend un autre composant dont le rendu échoue, alors un rendu shallow () sur le parent passera toujours.

Shyam Kumar
la source