cosmosb
cosmosb

Reputation: 325

Unit testing React Bootstrap modal dialog

I'm trying to unit test React Bootstrap modal dialog using Jasmine. But it is not working as expected.

Here is jsfiddle link using latest versions of React, React Bootstrap, Jasmine.: http://jsfiddle.net/30qmcLyf/3/

Test which fails:

line# 27-28

// This test fails. Find DOM Node.
var instanceDomNode = ReactDOM.findDOMNode(instance);
expect(instanceDomNode).not.toBe(null);

line# 39-40

//This test fails. Find modal header.
var headerComponents = TestUtils.scryRenderedComponentsWithType(component, ReactBootstrap.Modal.Header);
expect(headerComponents.length).not.toBe(0);

Also what is wrong with line#35-36. If I uncomment lines I get error shown in comments.

// Error: Did not find exactly one match for componentType:function ModalHeader()...
//var headerComponent = TestUtils.findRenderedComponentWithType(component, ReactBootstrap.Modal.Header);
//expect(headerComponent).not.toBe(null);

As per latest official documentation for test utilities (link), you are supposed to pass ReactComponent as first argument.

Can somebody tell me what is wrong?

Upvotes: 3

Views: 10460

Answers (3)

Shivam Latawa
Shivam Latawa

Reputation: 96

In case you are using an older version of Enzyme, you can pass the container element to mount where you want your Modal to be rendered, like this:

Actual Code:
------------
import React from 'react'
import { Modal } from 'reactstrap'

export default MyModal = () => {
    return (
        <Modal isOpen={props.isOpen}>
            <ModalHeader>Header</ModalHeader>
            <ModalBody>Body</ModalBody>
        </Modal>
     );
} 

Unit Test:
----------
import React from 'react'
import MyModal  from './MyModal'
import { mount } from 'enzyme'

describe(() => {
    let wrapper;
    beforeEach(() => {
        const container = document.createElement("div");
        document.body.appendChild(container);
        wrapper = mount( <MyModal isOpen={true}/> , {attachTo: container});
    });

    it('renders correctly', () => {
        expect(wrapper).toMatchSnapshot();

        expect(wrapper.find('ModalHeader')).toHaveLength(1);

        expect(wrapper.find('ModalBody')).toHaveLength(1);
    });

})

Upvotes: 1

Yuvraj Patil
Yuvraj Patil

Reputation: 8726

React-Bootstrap modal can be unit tested using mount of enzyme

it(componentToTest.title + 'renders Modal component', () => {  
  expect(wrapper.find(UVModal).length).toEqual(1);  
 });
  
 it(componentToTest.title + 'renders major html elements', () => {  
  // Test whether modal-content element has 3 html children elements.  
  expect(wrapper.find('.modal-content').length).toEqual(1);  
  expect(wrapper.find('.modal-content').children()).toHaveLength(3);  

  // Test whether modal-header element has 2 html children elements.  
  expect(wrapper.find('.modal-header').length).toEqual(1);  
  expect(wrapper.find('.modal-header').children()).toHaveLength(2);  

  // Test whether modal-body element has 1 html child element.  
  expect(wrapper.find('.modal-body').length).toEqual(1);  
  expect(wrapper.find('.modal-body').children()).toHaveLength(1);  

  // Test whether modal-footer element has 1 html child element.  
  expect(wrapper.find('.modal-footer').length).toEqual(1);  
  expect(wrapper.find('.modal-footer').children()).toHaveLength(1);  

  elementToSearch = <p>Lannisters always pay their debt</p>;  
  expect(wrapper.contains(elementToSearch)).toEqual(false);  
 });

Check following blog for details:

https://medium.com/@yuvi1422/unit-test-react-bootstrap-modal-a37bf59732ab

Upvotes: 1

monastic-panic
monastic-panic

Reputation: 3997

Check out how the react-bootstrap team writes tests for this. The modal is rendered into a different subtree which is how it gets rendered to the document body and not directly as a child of its parent. In other words your srcying fails because the component is not in that Component tree.

You can use refs on the modal or look for the DOM nodes directly in the document.

Upvotes: 5

Related Questions