How to use Enzyme Shallow with Jest snapshots

I'm trying to use shallow from enzyme and also use snapshots from jest together.

The problem I'm facing is that I need to change something from the state using setState() from enzyme and then match the result with the snapshot.

See the code of my component:

....

getPrevProduct = () => {
  const key = this.state.indexCurrent > 0 &&
   this.productsKeys[this.state.indexCurrent - 1];

  let product = null;

  if (key) {
    product = this.props.products[key];
  }

  return product;
}

renderPrev = () => this.getPrevProduct() && <PrevButton />;

render() {
  return (
    <div>
      ...
      {this.renderPrev()}
      ...
    <div>
  )
}

The previous code checks if the product, passed from props in the currentIndex, exists.

That's why I need Enzyme to change the state. Then, if it matches, <PrevButton /> has to be rendered.

This test is when I want to match the component with the snapshot:

const nextProps = {
  products: {
    test: 'test'
  }
};

const tree = create(<Component nextProps={nextProps} />).toJSON();

expect(tree).toMatchSnapshot();

But I need to change the state. How I can do that? This doesn't work:

it('should render component with prev button', () => {
  const nextProps = {
    products: {
      test: 'test'
    }
  };
  const instance = shallow(<Component nextProps={nextProps} />).instance()

  instance.setState({
    indexCurrent: 1
  });

  const tree = create(<Component nextProps={nextProps} />).toJSON();

  expect(tree).toMatchSnapshot();
});

I also tried to save the declaration of the component into a variable like the next uncompleted code and use it in shallow and create:

const component = <Component nextProps={nextProps} />;

 shallow(component).instance()).instance()
 create(component).toJSON()`

I also tried with no luck enzyme-to-json.

What would you do?

Upvotes: 5

Views: 5981

Answers (3)

unlimittt
unlimittt

Reputation: 401

Install enzyme-to-json

npm install --save-dev enzyme-to-json

Update your jest config:

"jest": {
  "snapshotSerializers": [
    "enzyme-to-json/serializer"
  ]
}

Test

it('works', () => {
  const wrapper = shallow(<MyComponent />)
  expect(wrapper).toMatchSnapshot()
})

Original: https://devhints.io/enzyme#installing

Upvotes: 5

Fawaz
Fawaz

Reputation: 3560

Probably, its not the way enzyme-to-json is supposed to be used. Try this way :

import { shallowToJson  } from 'enzyme-to-json';
import { shallow } from 'enzyme';

and then in your test :

const wrapper = shallow(<Component />);
expect(shallowToJson(wrapper)).toMatchSnapshot();

Upvotes: 7

After trial and error, I found that enzyme has a method, not documented (or I didn't find it) called getRenderOutput.

That method return the component in JSON format so I can do that:

it('should render component with prev button', () => {
  const nextProps = {
    products: {
      test: 'test'
    }
  };
  const render = shallow(mockComponent(nextProps))
  const instance = render.instance();

  instance.setState({
    indexCurrent: 1
  });

  const tree = render.renderer.getRenderOutput();

  expect(tree).toMatchSnapshot();
});

That's how I can use snapshots from Jest with enzyme.

The only problem with getRenderOutput is that if I put a console log, it will be printed twice. That's because instance() and getRenderOutput(), both fires the test.

This is the output of the snapshot:

exports[`ProductNavigator should render component with prev button 1`] = `
  <div>
    <FloatingActionButton
      className="NavigatorButton left"
      onTouchTap={[Function]}
      secondary={true}
    >
      <KeyboardArrowLeft />
    </FloatingActionButton>
  </div>
`;

If someone knows a better way to do that, please, add a comment.

Thanks!

Upvotes: 2

Related Questions