web-dev-qa-db-fra.com

jest, enzyme - tester une méthode qui retourne jsx

J'ai le composant suivant:

import React, { Component } from 'react';
import {Link, IndexLink} from 'react-router';

class Navbar extends Component {

  renderLinks = (linksData) => {
    return linksData.map((linkData) => {
      if(linkData.to === '/') {
        return(
          <div className="navbar-link-container" key={linkData.to}>
            <IndexLink activeClassName="navbar-active-link" to={linkData.to}>
              <i className="navbar-icon material-icons">{linkData.icon}</i>
              <span className="navbar-link-text">{linkData.text}</span>
            </IndexLink>
          </div>
        )
      }
      else {
        return(
          <div className="navbar-link-container" key={linkData.to}>
            <Link activeClassName="navbar-active-link" to={linkData.to}>
              <i className="navbar-icon material-icons">{linkData.icon}</i>
              <span className="navbar-link-text">{linkData.text}</span>
            </Link>
          </div>
        )
      }
    })
  };

  render() {
    return (
      <div className={`navbar navbar-${this.props.linksData.length}`}>
        {this.renderLinks(this.props.linksData)}
      </div>
    )
  }
}

Navbar.propTypes = {
  linksData: React.PropTypes.array.isRequired,
};

export default Navbar;

Maintenant, j'essaie d'écrire un test unitaire qui vérifiera la condition if (renvoyant IndexLink ou Link en fonction de la propriété .to):

Mais je n'arrive pas à tester le retour exact de jsx de la fonction, car lorsque je console.log un des retours, je reçois ceci:

{'$$ typeof': Symbole (élément réactif), type: 'div', clé: '/' , ref: null, props: {className: 'navbar-link-container', enfants: {'$$ typeof': Symbol (react.element), type : [Object], Clé: null, Ref: null, Props: [Object], _Owner: null, _Store: {}}}, _positif: null, _store: {}}

C'est le test que j'ai écrit jusqu'à présent:

it('renderLinks should return a IndexLink', () => {
    const wrapper = shallow(<Navbar linksData={mockLinksData}/>);
    const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);
    let foundIndexLink = false;
    renderLinksReturn.map((linkHtml) => {
      console.log(linkHtml);
    });
    expect(foundIndexLink).toBe(true);
  })

Maintenant, je ne sais pas contre quoi tester pour voir si la fonction s'exécute correctement. Existe-t-il un moyen de "monter" le retour de la fonction comme un composant? Ou y a-t-il une méthode simple pour renvoyer une chaîne html du retour que je peux vérifier?

7
Miha Šušteršič

Je pense que tu n'as pas besoin d'appeler 

const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);

comme il sera appelé quand Navbar sera rendu.

Votre solution est correcte, mais dans le cas où vous voudriez d’autres méthodes robustes pour la tester.

Puisque ce test teste spécifiquement IndexLink et suppose que mockLinksData contient to = "/"

it('renderLinks should return a IndexLink when passed a link with to:\"/\"', () => {
    const wrapper = shallow(<Navbar linksData={mockLinksData}/>);

    // You can use both component name or component displayname
    // IndexLink or "IndexLink"
    expect(wrapper.find('IndexLink')).to.have.length(1);

    // In case you want to test whether indexLink has appropriate props or classes.
    const indexLink = wrapper.find(IndexLink).first();

   // Check whether indexLink has pass prop
   expect(indexLink.props().to).to.equal("/");

   // Check whether indexLink has correct classes set.
   expect(indexLink.hasClass('navbar-active-link')).to.equal(true);

  // Check whether indexLink displays the link test correctly
  expect(indexLink.find('navbar-link-text').text()).to.equal(mockLinksData.text);


 });
2
WitVault

Face à un problème similaire où nous passions un composant jsx à un autre composant en tant que prop.

Vous pouvez peu profond rendre le jsx retourné car il ressemble à un composant React Stateless valide. , Par exemple:

const renderLinks = shallow(wrapper.instance().renderLinks(mockLinksData))

Et continuez avec vos affirmations enzymatiques habituelles.

7
Nachiketha

Il s'avère que le type de l'élément est stocké dans l'objet. Donc, la condition est:

props.children.type.displayName

Et le test final que j'ai écrit ressemble à ceci pour IndexLink:

it('renderLinks should return a IndexLink when passed a link with to:\"/\"', () => {
    const wrapper = shallow(<Navbar linksData={mockLinksData}/>);
    const renderLinksReturn = wrapper.instance().renderLinks(mockLinksData);
    let foundIndexLink = false;
    renderLinksReturn.map((linkHtml) => {
      {linkHtml.props.children.type.displayName === 'IndexLink' ? foundIndexLink = true : null};
    });
    expect(foundIndexLink).toBe(true);
  });
1
Miha Šušteršič