最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jest, enzyme - testing a method that returns jsx - Stack Overflow

programmeradmin3浏览0评论

I have the following component:

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;

Now I am trying to write a unit test that will check the if condition (returning IndexLink or Link depending on the .to property):

But I can't seem to test for the exact jsx return of the function, since when I console.log one of the returns I get this:

{ '$$typeof': Symbol(react.element), type: 'div', key: '/', ref: null, props: { className: 'navbar-link-container', children: { '$$typeof': Symbol(react.element), type: [Object], key: null, ref: null, props: [Object], _owner: null, _store: {} } }, _owner: null, _store: {} }

This is the test I have written so far:

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);
  })

Now I do not know what to test against to see if the function is running correctly. Is there a way to 'mount' the return of the function like a component? Or is there a simple method to return a html string of the actual return that I can check against?

I have the following component:

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;

Now I am trying to write a unit test that will check the if condition (returning IndexLink or Link depending on the .to property):

But I can't seem to test for the exact jsx return of the function, since when I console.log one of the returns I get this:

{ '$$typeof': Symbol(react.element), type: 'div', key: '/', ref: null, props: { className: 'navbar-link-container', children: { '$$typeof': Symbol(react.element), type: [Object], key: null, ref: null, props: [Object], _owner: null, _store: {} } }, _owner: null, _store: {} }

This is the test I have written so far:

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);
  })

Now I do not know what to test against to see if the function is running correctly. Is there a way to 'mount' the return of the function like a component? Or is there a simple method to return a html string of the actual return that I can check against?

Share Improve this question edited Sep 12, 2018 at 12:02 Canta 1,4802 gold badges13 silver badges26 bronze badges asked Mar 16, 2017 at 14:13 Miha ŠušteršičMiha Šušteršič 10k27 gold badges96 silver badges175 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 21

Faced similar issue where we were passing a jsx component to another component as a prop.

You can shallow render the returned jsx since it's like a valid React Function/Stateless Component. eg:

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

And continue with your usual enzyme assertions.

To build on top of @Nachiketha 's answer, that syntax won't work when what's returned is a fragment, this can be solved by wrapping the result in a div like:

const renderLinks = shallow(<div>
    {wrapper.instance().renderLinks(mockLinksData)
    </div>
)}

as suggested in this tread.

I think you don't need to call

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

as it will be called when Navbar will be rendered.

Your solution is correct but in case you want some alternative robust ways to test it.

Since this test specifically tests for IndexLink and assumes that mockLinksData contains 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);


 });

Turns out that the type of the element is stored in the object. So the condition is:

props.children.type.displayName

And the final test I wrote looks like this for 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);
  });
发布评论

评论列表(0)

  1. 暂无评论