Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find element with Enzyme in nested React component

I am trying to write a for my component TestComponent that ensures the callback is fired when the user clicks on a button. However, the button is not found (though I can see it in the HTML by calling console.log(wrapper.html()).

The button is inside another component that is used within TestComponent, if that matters.

Here is my test:

import React from 'react';
import expect from 'expect';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import TestComponent from './test-component.jsx';

describe('<TestComponent/>', () => {
  it('clicking "continue" button fires the callback', () => {
    const onClickContinue = sinon.spy();
    const wrapper = shallow(<TestComponent />);
    console.log(wrapper.find('.btn-primary').length); // 0
    console.log(wrapper.html());                      // does have `.btn-primary`

    // wrapper.find('.btn-primary').simulate('click');
    // expect(onClickContinue.calledOnce).toBe(true);
  });
});

What am I doing wrong? Thank you.

like image 384
Alan P. Avatar asked Sep 16 '17 19:09

Alan P.


Video Answer


1 Answers

Figured it out. From https://facebook.github.io/react/docs/test-utils.html:

Shallow rendering lets you render a component "one level deep" and assert facts about what its render method returns, without worrying about the behavior of child components, which are not instantiated or rendered.

This test needs to work with child components, so must use mount instead of shallow. Here is the working code:

import React from 'react';
import expect from 'expect';
import { mount } from 'enzyme';
import sinon from 'sinon';
import TestComponent from './test-component.jsx';

describe('<TestComponent/>', () => {
  it('clicking "continue" button fires the callback', () => {
    const wrapper = mount(<TestComponent />);
    const handleClickContinue = sinon.spy(wrapper.instance(), 'handleClickContinue');
    wrapper.find('.btn-primary').first().simulate('click');
    expect(handleClickContinue.calledOnce).toBe(true);
  });
});

Also notice I changed from onClickContinue to handleClickContinue, as this method must exist in the component (not what its called in the prop).

like image 129
Alan P. Avatar answered Oct 18 '22 23:10

Alan P.