<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Alona Pysarenko on Medium]]></title>
        <description><![CDATA[Stories by Alona Pysarenko on Medium]]></description>
        <link>https://medium.com/@alona.pysarenko?source=rss-a7a1561e430f------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*qWVJs2MFB-3mizZtoF2yzA.png</url>
            <title>Stories by Alona Pysarenko on Medium</title>
            <link>https://medium.com/@alona.pysarenko?source=rss-a7a1561e430f------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 16:04:49 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@alona.pysarenko/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Complete Guide on Unit and Integration Testing of React/Redux Connected Forms]]></title>
            <link>https://medium.com/bitsrc/complete-guide-on-unit-and-integration-testing-of-react-redux-connected-forms-cd6f8476161?source=rss-a7a1561e430f------2</link>
            <guid isPermaLink="false">https://medium.com/p/cd6f8476161</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[frontend]]></category>
            <category><![CDATA[component-testing]]></category>
            <category><![CDATA[react-redux]]></category>
            <dc:creator><![CDATA[Alona Pysarenko]]></dc:creator>
            <pubDate>Thu, 14 Nov 2019 15:52:15 GMT</pubDate>
            <atom:updated>2019-11-18T14:13:38.886Z</atom:updated>
            <content:encoded><![CDATA[<p><em>After seeing the amazing feedback and requests that followed our latest article on </em><a href="https://djangostars.com/blog/what-and-how-to-test-with-enzyme-and-jest-full-instruction-on-react-component-testing/?utm_source=blog.bitsrc.io&amp;utm_medium=medium&amp;utm_campaign=unit%20and%20integration%20testing&amp;utm_content=components%20testing"><em>What and How to Test with Jest and Enzyme</em></a><em>, I’d love to share a couple of other test cases. Today, we’ll talk about testing React forms that are connected with Redux, considering both unit and integration testing. Hopefully, you’ll find something useful below.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*5ls9_QYVNPouiXvA.png" /></figure><h3>Unit vs. Integration Testing</h3><p>Before we dive deep into the subject, let’s make sure we all understand the basics. There are many different types of app testing, but a <a href="https://gojko.net/assets/201802-js-research.pdf">2018 survey</a> shows that automated unit and integration tests are at the top of the list.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qYccNhgbYp0DS7Gf.png" /></figure><p>For a better comparison, I’m only picking the two main automated testing methods. Let’s look at the definitions and characteristics of unit and integration testing:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*NvaNvfamzDbFVMt7.png" /></figure><h3>Test Preparations: Form Review</h3><p>Before you start any job, you want to know all about it. You don’t want any surprises, and you do want the best results. This is also true for testing. Which is why it’s better to <strong>get all the available information on the form that should be tested, and its related conditions </strong>beforehand. And, of course, to make sure you know what exactly should be tested.</p><p>To show you how it goes, I chose a form that contains information on <strong>Property Evaluation</strong>. It’s a form that customers fill in to describe the property they would like to purchase. It’s quite simple — it doesn’t have any complex logic or mandatory fields, and a few fields to fill in.</p><p>Check out the image below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xPRtkHTPnrbkzR38.png" /></figure><p>The only logic you can’t see in the image are different fields that are set depending on the choice in the `Property type` field. For instance:</p><ul><li>If a customer chooses ‘<strong>Apartment</strong>’, they get options like ‘<em>floor</em>’, ‘<em>parking conditions</em>’, etc.</li><li>If a customer chooses ‘<strong>House</strong>’, they get options like ‘<em>floor area</em>’, ‘<em>building standard</em>’, etc.</li></ul><p>Next, let’s dive into the form’s code. The implementation of the form is divided into two parts:</p><ol><li><strong>Template file</strong> — listing of all fields; we can also call it ‘view’ (Code Listing of <a href="https://github.com/ned-alyona/react-redux-forms-testing/blob/master/property-details/PropertySelfOwnedForm.js">PropertySelfOwnedForm.js</a> on github)</li><li><strong>Container file</strong> — form logic, stored in one place (Code Listing of <a href="https://github.com/ned-alyona/react-redux-forms-testing/blob/master/property-details/PropertySelfOwnedFormContainer.js">PropertySelfOwnedFormContainer.js</a> on github)</li></ol><h3>Testing Forms Connected with Redux</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ysbTZG-Li1GgVzog.png" /></figure><p>Depending on the type of testing, I use different processes to test forms connected with Redux.</p><p>For <strong>unit tests</strong>, I use shallow rendering (as opposed to deep tree rendering) and the Redux-mock-store library. For <strong>integration tests</strong>, I use mount rendering (deep tree rendering) and an actual Redux store.</p><h3>Unit Testing of Forms Connected with Redux</h3><p>As I said above, for unit testing I use shallow rendering. It’s a one-level rendering that doesn’t take into account child components inside the component in question. On top of this, the tested component doesn’t indirectly affect its child components behavior.</p><p><a href="https://github.com/dmitry-zaets/redux-mock-store">Redux-mock-store</a> is a library designed to test action logic, and provides a mocked Redux store. It’s easy to launch and to use, and doesn’t affect the Redux store itself.</p><p>Before you start testing, be sure to configure the form.</p><p>These are my imports:</p><ul><li>Rendering method: Enzyme’s shallow renderer</li><li>Include mocked data required for form rendering. In the example below it is json file djangoParamsChoices, containing mocked data for select options. This data is being passed to context on the backend side and fetched on the frontend side through the custom function `getDjangoParam`.</li><li>Include form view itself</li><li>Import additional tools for store mock</li><li>Import additional libraries for test needs (mainly required when writing the special test case)</li></ul><pre>import { shallow } from ‘enzyme’;<br>import djangoParamsChoices from ‘tests/__mocks__/djangoParamsChoices’;<br>import PropertySelfOwnedForm from ‘../PropertySelfOwnedForm’;<br>import configureStore from ‘redux-mock-store’;<br>const snapshotDiff = require(‘snapshot-diff’);</pre><ul><li>Initialize mockstore with empty state:</li></ul><pre>const initialState = {};</pre><ul><li>Set default props (they vary from the tested form requirements):</li></ul><p>The form view depends on the property type; that’s why I put in default props.</p><pre>const defaultProps = {<br>    propertyType: 1<br>};</pre><ul><li>Mock store and render form before each test:</li></ul><p>First, configure the mock store with the help of the redux-mock-store library.</p><pre>const mockStore = configureStore();</pre><ul><li>Configure function for execution before each test run using the ‘beforeEach’ method.</li></ul><pre>let store, PropertySelfOwnedFormComponentWrapper, PropertySelfOwnedFormComponent, receivedNamesList;beforeEach(() =&gt; {<br>    store = mockStore(initialState);<br>    PropertySelfOwnedFormComponentWrapper = (props) =&gt; (<br>        &lt;PropertySelfOwnedForm {...defaultProps} {...props} store={store} /&gt;<br>    );<br>    PropertySelfOwnedFormComponent = shallow(&lt;PropertySelfOwnedFormComponentWrapper /&gt;).dive();<br>});</pre><p>Inside the function, don’t forget to:</p><ol><li>Reset the store after every test: `store = mockStore(initialState)` returns an instance of the configured mock store.</li><li>Make Wrapper HOC to pass store, defaultProps and custom props for the special test case `.dive()` method to receive the rendered form structure one level deeper.</li></ol><p>Without the dive() method, ShallowWrapper looks like this:</p><pre>&lt;PropertySelfOwnedForm<br>     propertyType={1}<br>     onSubmit={[Function: mockConstructor]}<br>     onSubmitAndNavigate={[Function: mockConstructor]}<br>     onNavigate={[Function: mockConstructor]}<br>     store={{...}}<br>/&gt;</pre><p>Here’s what it looks like with the dive() method: <a href="https://github.com/ned-alyona/react-redux-forms-testing/blob/master/ShallowWrapperWithDiveMethod.js">ShallowWrapperWithDiveMethod.js</a></p><h3>Writing Tests for Unit Testing</h3><p>Now, you’re ready to write the test itself. Follow my process to see how you should proceed.</p><p>Check the Form Component that’s being rendered:</p><pre>it(&#39;render connected form component&#39;, () =&gt; {<br>    expect(PropertySelfOwnedFormComponent.length).toEqual(1);<br>});</pre><p>Check the list of fields rendered correctly for property type ‘House’:</p><pre>it(&#39;PropertySelfOwnedForm renders correctly with PropertyTypeHouse&#39;, () =&gt; {<br>    receivedNamesList = PropertySelfOwnedFormComponent.find(&#39;form&#39;).find(&#39;Col&#39;).children().map(node =&gt; node.props().name);<br>    const expectedNamesList = [<br>         &#39;building_volume&#39;,<br>         &#39;site_area&#39;,<br>         &#39;building_volume_standard&#39;,<br>         &#39;number_of_garages_house&#39;,<br>         &#39;number_of_garages_separate_building&#39;,<br>         &#39;number_of_parking_spots_covered&#39;,<br>         &#39;number_of_parking_spots_uncovered&#39;<br>    ];<br>    expect(receivedNamesList).toEqual(expect.arrayContaining(expectedNamesList));<br>});</pre><p>Create a snapshot to check the user interface for property type ‘House’:</p><pre>it(&#39;create snapshot for PropertySelfOwnedForm with PropertyTypeHouse fields&#39;, () =&gt; {<br>    expect(PropertySelfOwnedFormComponent).toMatchSnapshot();<br>});</pre><p>At this point, you must be asking yourself, “Why do we need two tests for one property type, both snapshot and field existence?” Here’s why: the two tests help us check logic and UI.</p><ul><li>According to the logic, we should receive an expected list of fields</li><li>According to the UI, we should obtain a defined order of fields with its own design.</li></ul><p>This is what we get from the two tests:</p><ul><li>No changes in field list / UI -&gt; Two tests passed</li><li>No changes in field list / Changes in UI -&gt; Snapshot test failed, i.e., the UI changed.</li><li>Changes in field list / Changes in UI -&gt; Both tests failed, i.e., the logic failed (or both logic and UI), as the field list differs from what was expected.</li></ul><p>Having gone through two tests, I see exactly what the problem was and where I should look for reasons for failure. I repeat the process with another property type — ‘Apartment’ and its expected array of fields. I follow the same steps:<br>Check the list of fields rendered correctly for property type ‘Apartment’:</p><pre>it(&#39;PropertySelfOwnedForm renders correctly with PropertyTypeApartment&#39;, () =&gt; {<br>    const props = {<br>            propertyType: 10<br>        },<br>        PropertySelfOwnedFormComponent = shallow(&lt;PropertySelfOwnedFormComponentWrapper {...props} /&gt;).dive();<br>    const receivedNamesList = PropertySelfOwnedFormComponent.find(&#39;form&#39;).find(&#39;Col&#39;).children().map(node =&gt; node.props().name);<br>    const expectedNamesList = [<br>        &#39;number_of_apartments&#39;,<br>        &#39;floor_number&#39;,<br>        &#39;balcony_terrace_place&#39;,<br>        &#39;apartments_number_of_outdoor_parking_spaces&#39;,<br>        &#39;apartments_number_of_garages&#39;,<br>        &#39;apartments_number_of_garages_individual&#39;<br>    ];<br>    expect(receivedNamesList).toEqual(expect.arrayContaining(expectedNamesList));</pre><p>Create a snapshot to check fields for property type ‘Apartment’:</p><pre>it(&#39;create snapshot for PropertySelfOwnedForm with PropertyTypeApartment fields&#39;, () =&gt; {<br>    const props = {<br>            propertyType: 10<br>        },<br>        PropertySelfOwnedFormComponent = shallow(&lt;PropertySelfOwnedFormComponentWrapper {...props} /&gt;).dive();<br>    expect(PropertySelfOwnedFormComponent).toMatchSnapshot();<br>});</pre><p>The next test is experimental. I decided to investigate a <a href="https://github.com/jest-community/snapshot-diff">diffing snapshot utility for Jest</a> that one reader of my recent article suggested.</p><p>First of all, let’s see how it works. It receives two rendered components with different states or props, and outputs their difference as a string. In the example below, I created a snapshot showing the difference between the forms with different property types — ‘House’ and ‘Apartment’.</p><pre>it(&#39;snapshot difference between 2 React forms state&#39;, () =&gt; {<br>    const props = {<br>            propertyType: 10<br>        },<br>        PropertySelfOwnedFormComponentApartment = shallow(&lt;PropertySelfOwnedFormComponentWrapper {...props} /&gt;).dive();<br>    expect(<br>        snapshotDiff(<br>            PropertySelfOwnedFormComponent,<br>            PropertySelfOwnedFormComponentApartment<br>        )<br>    ).toMatchSnapshot();<br>});</pre><p>This kind of test has its advantages. As you can see above, it covers two snapshots and minimizes code base — thus, instead of two snapshots, you can create just one showing the difference, and similarly, only write one test instead of two. It’s quite easy to use, and lets you cover different states with one test. But, looking at my case, I got a snapshot with 2841 rows, as shown on <a href="https://github.com/ned-alyona/react-redux-forms-testing/blob/master/SnapshotDiffBetween2Forms.js">github</a>. With a large amount of code like this, it’s too hard to see why the test had failed and where.</p><p>This only proves one thing: whatever you work with, use your tools and libraries wisely, and only in the places that really require it. This utility may be useful for testing differences in stateless components to find UI inconsistencies, and to define differences in simple functionality components that contain minimum logical conditions. But for testing large pieces of UI, it doesn’t seem to be appropriate.</p><p>Before we wrap up the part about unit testing of forms connected with Redux, there’s one more thing. There’s a reason why I didn’t include tests for events. Let’s look at the form structure PropertySelfOwnedForm.js that includes the <a href="https://github.com/ned-alyona/react-redux-forms-testing/blob/master/shared/buttons/ButtonsToolbar.js">ButtonsToolbar.js</a> component.</p><pre>import ButtonsToolbar from &#39;shared/widgets/buttons/ButtonsToolbar&#39;;<br>&lt;ButtonsToolbar {...restProps} /&gt;</pre><p>This component contains three buttons: ‘Save’, ‘Save and Next’ and ‘Next’, and is used in many forms. Shallow rendering doesn’t include child components, and at this point, I don’t care about their functionality. And rendered `ButtonsToolbar`component looks like this:</p><pre>&lt;ButtonsToolbar<br>      onNavigate={[MockFunction]}<br>      onSubmit={[MockFunction]}<br>      onSubmitAndNavigate={[MockFunction]}<br>      store={<br>        Object {<br>          &quot;clearActions&quot;: [Function],<br>          &quot;dispatch&quot;: [Function],<br>          &quot;getActions&quot;: [Function],<br>          &quot;getState&quot;: [Function],<br>          &quot;replaceReducer&quot;: [Function],<br>          &quot;subscribe&quot;: [Function],<br>        }<br>      }<br>    /&gt;</pre><p>The truth is, I don’t need to test it as a part of unit form tests. I will test the button events separately in <a href="https://github.com/ned-alyona/react-redux-forms-testing/blob/master/shared/buttons/__tests__/ButtonsToolbar.test.js">ButtonsToolbar.test.js</a>.</p><p><strong>You can find the full tests listing here</strong>: <a href="https://github.com/ned-alyona/react-redux-forms-testing/blob/master/property-details/__tests__/PropertySelfOwnedFormUnit.test.js">PropertySelfOwnedFormUnit.test.js</a></p><p><strong>You May Also Like:</strong></p><p><a href="https://djangostars.com/blog/how-to-develop-a-location-based-application-using-react-native/?utm_source=blog.bitsrc.io&amp;utm_medium=medium&amp;utm_campaign=unit%20and%20integration%20testing&amp;utm_content=you%20may%20also%20like">How to Develop a Location-based Application Using React Native</a></p><h3>Integration Testing of Forms Connected with Redux</h3><p>For integration testing — testing components in a working environment — I use mount rendering. Mount rendering is a type of deep level rendering that includes all the child components by mounting them all into the DOM.</p><p>This kind of rendering is actually quite similar to the real DOM tree, as its components’ behavior is interconnected. And the goal of the integration testing is to check this connection. Thus, an actual Redux store is in this case a great choice.</p><p>An actual Redux store is one created with the help of a `redux` library. In this case, there’s no need to mock anything, as you can use the real store the same way as in the app.</p><p>Next, I’m configuring my form for testing.</p><p>Here’s the list of imports:</p><ul><li>Rendering method: Enzyme’s mount renderer</li><li>Methods from Redux for creating a store and combining reducers into a single root reducer</li><li>Provider from react-redux library to make store available for nested components wrapped in the connect() function</li><li>Router from react-router-dom to provide React Router navigation</li><li>Redux-form for better managing the redux state of the form</li><li>propertyDetailsResource is an object with namespace and endpoint</li><li>Include json file djangoParamsChoices, containing mocked data passed from the backend</li><li>Include form view itself</li></ul><pre>import { mount } from &#39;enzyme&#39;;<br>import { createStore, combineReducers } from &#39;redux&#39;;<br>import { Provider } from &#39;react-redux&#39;;<br>import { Router } from &#39;react-router-dom&#39;;<br>import { reduxForm, reducer as formReducer } from &#39;redux-form&#39;;import propertyDetailsResource from &#39;store/propertyDetailsResource&#39;;<br>import djangoParamsChoices from &#39;tests/__mocks__/djangoParamsChoices&#39;;<br>import PropertySelfOwnedForm from &#39;../PropertySelfOwnedForm&#39;;</pre><p>Then, I prepare data for testing. To do so, it’s important to keep in mind that:</p><ul><li>There’s a configuration difference between defaultProps for unit and integration tests:</li><li>With integration tests, a resource with an actual endpoint is added to defaultProps</li><li>Mocked function handleSubmit is provided by the ‘redux-form’, because Redux-Form decorates the component with the handleSubmit prop</li><li>Three mocked functions for custom buttons submit events.</li><li>The store is created the same way as in the app</li><li>The imported form is decorated with reduxForm</li><li>The decorated form is wrapped by Router and Provider.</li></ul><p>If it makes it easier for you, the sequence of data preparation for integration testing is the same as it is for actions during the form integration with Redux.</p><pre>global.getDjangoParam = () =&gt; djangoParamsChoices;let PropertySelfOwnedFormComponent;<br>const history = {<br>        push: jest.fn(),<br>        location: {<br>            pathname: &#39;/en/data-collection/property-valuation/&#39;<br>        },<br>        listen: () =&gt; {}<br>    },<br>    defaultProps = {<br>        propertyType: 1,<br>        resource: propertyDetailsResource,<br>        handleSubmit: (fn) =&gt; fn,<br>        onSubmit: jest.fn(),<br>        onSubmitAndNavigate: jest.fn(),<br>        onNavigate: jest.fn()<br>    },<br>    store = createStore(combineReducers({ form: formReducer })),<br>    Decorated = reduxForm({<br>        form: &#39;property-details-form&#39;<br>    })(PropertySelfOwnedForm),<br>    PropertySelfOwnedFormComponentWrapper = (props) =&gt; (<br>        &lt;Provider store={store}&gt;<br>            &lt;Router history={history}&gt;<br>                &lt;Decorated {...defaultProps} {...props} /&gt;<br>            &lt;/Router&gt;<br>        &lt;/Provider&gt;<br>    );</pre><p>Render form before each test:</p><pre>beforeEach(() =&gt; {<br>    PropertySelfOwnedFormComponent = mount(<br>        &lt;PropertySelfOwnedFormComponentWrapper /&gt;<br>    );<br>});</pre><h3>Writing Tests for Integration Testing</h3><p>Now, let’s do the actual writing. The first step is to create snapshots of both property types. This means that, first, you create a snapshot to check the fields for property type House’:</p><pre>it(&#39;PropertySelfOwnedForm renders correctly with PropertyTypeHouse&#39;, () =&gt; {<br>    expect(PropertySelfOwnedFormComponent).toMatchSnapshot();<br>});</pre><p>Next, create a snapshot to check fields for property type ‘Apartment’:</p><pre>it(&#39;PropertySelfOwnedForm renders correctly with PropertyTypeApartment&#39;, () =&gt; {<br>    const props = {<br>            propertyType: 10<br>        },<br>        PropertyTypeApartmentWrapper = mount(&lt;PropertySelfOwnedFormComponentWrapper {...props} /&gt;);<br>    expect(PropertyTypeApartmentWrapper).toMatchSnapshot();<br>});</pre><p>The form buttons are disabled if the form is a pristine or in submitting state. The following test checks if the ‘Save’ button reacts to form changes and becomes active after losing the pristine state:</p><pre>it(&#39;check if `Save` button react to form changes&#39;, () =&gt; {<br>    expect(PropertySelfOwnedFormComponent.find(&#39;button.button--accent&#39;).props().disabled).toEqual(true);<br>    const streetNumberField = PropertySelfOwnedFormComponent.find(&#39;input[name=&quot;street_number&quot;]&#39;);<br>    streetNumberField.simulate(&#39;change&#39;, { target: {value: &#39;10&#39;} });<br>    expect(PropertySelfOwnedFormComponent.find(&#39;button.button--accent&#39;).props().disabled).toEqual(false);<br>});</pre><p>The last three tests check events that are called by clicking on the onSubmit, onSubmitAndNavigate, or the onNavigate button.</p><p>Check if an onSubmit event was called:</p><pre>it(&#39;check event on `Save` button&#39;, () =&gt; {<br>    const streetNumberField = PropertySelfOwnedFormComponent.find(&#39;input[name=&quot;street_number&quot;]&#39;);<br>    streetNumberField.simulate(&#39;change&#39;, { target: {value: &#39;10&#39;} });const propertySelfOwnedFormButton = PropertySelfOwnedFormComponent.find(&#39;button.button--accent&#39;);<br>    propertySelfOwnedFormButton.simulate(&#39;click&#39;);<br>    expect(defaultProps.onSubmit).toHaveBeenCalled();<br>});</pre><p>Check if an onSubmitAndNavigate event was called:</p><pre>it(&#39;check event on `Save &amp; continue` button&#39;, () =&gt; {<br>    const streetNumberField = PropertySelfOwnedFormComponent.find(&#39;input[name=&quot;street_number&quot;]&#39;);<br>    streetNumberField.simulate(&#39;change&#39;, { target: {value: &#39;10&#39;} });const propertySelfOwnedFormButton = PropertySelfOwnedFormComponent.find(&#39;button.button--secondary&#39;).at(0);<br>    propertySelfOwnedFormButton.simulate(&#39;click&#39;);<br>    expect(defaultProps.onSubmitAndNavigate).toHaveBeenCalled();<br>});</pre><p>Check if an onNavigate event was called:</p><pre>it(&#39;check event on `Next` button&#39;, () =&gt; {<br>    const propertySelfOwnedFormButton = PropertySelfOwnedFormComponent.find(&#39;button.button--secondary&#39;).at(1);<br>    propertySelfOwnedFormButton.simulate(&#39;click&#39;);<br>    expect(defaultProps.onNavigate).toHaveBeenCalled();<br>});</pre><p><strong>Full tests listing</strong>: <a href="https://github.com/ned-alyona/react-redux-forms-testing/blob/master/property-details/__tests__/PropertySelfOwnedFormIntegration.test.js">PropertySelfOwnedFormIntegration.test.js</a></p><p>Now the form is fully tested, including the inside components being rendered.</p><p>To conclude, I’d like to say that both unit and integration testing are equally important. Each type of testing does its own work and has its own purpose. Dismissing one can lead to a lot of troubleshooting work in the future.</p><p>Unit testing mainly covers the user interface, while integration tests dig deeper into functionality. Some people find it redundant to do both, but I’d say both are necessary if you want your product to look good to the user, be user-friendly, and also work smoothly. Unit testing alone will never cover the most important part of the product — the interactions among components. Besides, it’s better to be safe than sorry.</p><p>When it comes to testing, forms require special attention, as forms are an essential part of many projects and a way to communicate with customers. This is why it’s vital to be properly prepared and carefully go through all the stages — imports, mocks preparation, store creation, form decoration with Redux, and correct wrapper creation. But the tests themselves are not complicated. In most cases, they follow form logic and reflect field changes and button simulations (in the case of integration testing).</p><p>Thank you for your time. We look forward to reading your feedback!</p><blockquote>This guide on <a href="https://djangostars.com/blog/unit-integration-testing-redux-react-forms/?utm_source=blog.bitsrc.io&amp;utm_medium=medium&amp;utm_campaign=unit%20and%20integration%20testing&amp;utm_content=unit%20and%20integration%20testing"><strong>unit and integration testing of react/redux components</strong></a> was riginally published on <a href="https://djangostars.com/blog/?utm_source=blog.bitsrc.io&amp;utm_medium=medium&amp;utm_campaign=unit%20and%20integration%20testing&amp;utm_content=Django%20Stars%20blog"><strong>Django Stars blog</strong></a>.</blockquote><figure><a href="https://djangostars.com/services/react-native-development/?utm_source=blog.bitsrc.io&amp;utm_medium=medium&amp;utm_campaign=unit%20and%20integration%20testing&amp;utm_content=banner_end"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uXvQcmeNupo-iVkclcxrSg.png" /></a></figure><h3>Learn More</h3><ul><li><a href="https://blog.bitsrc.io/how-to-easily-share-react-components-between-projects-3dd42149c09">How to Share React UI Components between Projects and Apps</a></li><li><a href="https://blog.bitsrc.io/11-react-component-libraries-you-should-know-178eb1dd6aa4">11 React UI Component Libraries you Should Know in 2019</a></li><li><a href="https://blog.bitsrc.io/11-react-ui-component-playgrounds-for-2018-eef5a87a1bf8">11 React UI Component Playgrounds for 2019</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cd6f8476161" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bitsrc/complete-guide-on-unit-and-integration-testing-of-react-redux-connected-forms-cd6f8476161">Complete Guide on Unit and Integration Testing of React/Redux Connected Forms</a> was originally published in <a href="https://medium.com/bitsrc">Bits and Pieces</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Testing React Components with Jest and Enzyme- In Depth]]></title>
            <link>https://medium.com/bitsrc/how-to-test-react-components-with-jest-and-enzyme-in-depth-145fcd06b90?source=rss-a7a1561e430f------2</link>
            <guid isPermaLink="false">https://medium.com/p/145fcd06b90</guid>
            <category><![CDATA[react-components]]></category>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Alona Pysarenko]]></dc:creator>
            <pubDate>Tue, 27 Nov 2018 16:01:24 GMT</pubDate>
            <atom:updated>2019-06-06T10:09:04.623Z</atom:updated>
            <content:encoded><![CDATA[<h4>Everything you should know about testing React components using Jest &amp; Enzyme. With examples.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4gMyWFlVsVIL3b9MB4dUBQ.png" /></figure><blockquote>Note: the code samples may be displayed improperly because of markdown. I recommend to <a href="https://djangostars.com/blog/what-and-how-to-test-with-enzyme-and-jest-full-instruction-on-react-component-testing/#utm_source=medium&amp;utm_medium=blog.bitsrc.io&amp;utm_campaign=react%20components%20testing&amp;utm_content=continue%20reading%20the%20original%20article%20on%20our%C2%A0blog">continue reading the original article on our blog</a> to make sure all the examples are displayed properly.</blockquote><p>Testing React components may be challenging for beginners and <a href="https://djangostars.com/services/web-development/#utm_source=medium&amp;utm_medium=blog.bitsrc.io&amp;utm_campaign=react%20components%20testing&amp;utm_content=experienced%20developers">experienced developers</a> who have already worked with tests. It may be interesting to compare your own approaches with the ones we use in our project. In order to cover the codebase, you have to know which components must be tested and which code exactly in a component should be covered.</p><p><a href="https://djangostars.com/services/web-development/#utm_source=medium&amp;utm_medium=blog.bitsrc.io&amp;utm_campaign=react%20components%20testing&amp;utm_content=experienced%20developers">Custom Web Development Services. Hire Top Web Developers</a></p><p>During the reading, I’ll cover the next topics:</p><ul><li>Define the correct order of components’ testing based on project structure</li><li>Find what to omit in test coverage (what not to test)</li><li>Identify the necessity of Snapshot Testing</li><li>Define what to test in the component and in which order</li><li>Provide detailed custom code examples</li></ul><p>The article requires that the reader already has knowledge about Jest and Enzyme setup. Information about installation and configuration can be easily found on the web or official websites.</p><p>Assume the following case: You need to cover the project codebase with tests, so what should you start with and what should you get at the end of testing? 100% test coverage? It is the indicator to which you should aspire, but in most situations, you won’t get it. Why? Because you shouldn’t test all code. We will find out why and what should be left out of tests. Even more, 100% test coverage does not always ensure that the component is fully tested. As well, there is no guarantee it will notify you if something has been changed. Don’t strive for the percentages, avoid writing fake tests, and just try not to lose main component details.</p><h4>Shared in Bit’s blog: build faster with React components</h4><p><a href="https://github.com/teambit/bit"><strong>Bit</strong></a> turns components into Lego bricks you can easily share, organize, use and sync across all your different projects and applications- to build faster! Try it.</p><p><a href="https://bit.dev/">Bit. Composable software.</a></p><h3>Defining the correct order of components’ testing based on project structure</h3><p>Let’s discuss this question on the next part of the project structure:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3z4TeyTJt_o6_Ca1.png" /></figure><p>I took shared directory because it is the most important; it consists of the components that are used in several different pages of the project. They are reusable and normally, they are small and not complex. If one or another component fails, it will cause failure in other places. That’s why we should be confident whether they have been written correctly. The structure of this directory is divided into several folders, each containing components.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-8QXMbnFDyLCl81i.png" /></figure><p>How to define the correct order of component testing in shared the directory:</p><ul><li>Always follow the rule from simple to complex. Analyze each directory and define which components are independent - namely, their rendering doesn’t depend on the other components; they are self-completed and can be used separately as a single unit. From the structure above, it is input directory in forms folder. It contains input components to redux-forms, such as TextInput, SelectInput, CheckboxInput, DateInput, etc.</li><li>Next, I need to define auxiliary components that are often used in inputs components but should be tested apart from them. It is utils directory. Components in this folder are not complicated, but very important. They are frequently reusable and help with repeated actions.</li><li>The next step is to define which components can be used independently too. If any, take them for testing. From our structure, it iswidget little components with simple functionality. They will be the third item in the queue for test coverage.</li><li>Further, analyze the rest of the directories and define more complex components, which can be used independently or in conjunction with other components. It is modals directory in our case; these components will be explained in detail below.</li><li>The most complex for testing components are left in the end. They are hoc directory and fieldsfrom forms folder. How do you define which one should be tested first? I take the directory from which components have already been used in tested components. Thus, component from hocdirectory was present in widgets component; that’s why I already know where and with which purpose this directory and its component are used.</li><li>The last one is the fields folder; it contains components connected with redux-forms.</li></ul><p>The final components order (based on our example) will look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3uYj1A00ydreuO0L.png" /></figure><p>Following this order, you increase the complexity of the tested components step by step; thus, when it comes to operating with the more complex components, you already know how the smallest ones behave. Don’t take for testing, for example, ‘array’ field, if you are not sure how to test ‘text’ field; don’t take components decorated with redux-form if you haven’t tested ‘form’ field itself. Be consistent in your choices, don’t take the first component that comes into your mind, and switch on logic. Of course, the structure of your project can differ; it can have other directory names or can have additional components, actions, and reducers, but the logic of defining the order for testing the components is the same.</p><p><strong>Let’s define what should be omitted in test coverage:</strong></p><ul><li><strong><em>Third-party libraries</em></strong>. Don’t test functionality that is taken from another library; you are not responsible for that code. Skip it or imitate implementation if you need it to test your code.</li><li><strong><em>Constants</em></strong>. The name speaks for itself. They are not changeable; it is a set of static code that is not intended to vary.</li><li><strong><em>Inline styles</em></strong> (if you use them in component). In order to test inline styles, you need to duplicate object with styles in your test; if styles object changes, you must change it in the test too. Don’t duplicate component’s code in tests; you will never keep in mind to change it in tests. Moreover, your colleague will never guess about duplication. In most cases, inline styles don’t change the component’s behavior; consequently, they shouldn’t be tested. There can be an exception in case your styles change dynamically.</li><li><strong><em>Things not related to the tested component</em></strong>. Skip covering with tests components that were imported in the tested component; be careful if it is wrapped in another one. Don’t test the wrapper, just analyze and test them separately.</li></ul><p>So how do you actually write tests? I combine two testing approaches:</p><ul><li>Snapshot Testing</li><li>Component logic testing</li></ul><p>Snapshot Testing is a useful testing tool in case you want to be sure the user interface hasn’t changed. When facing this testing tool for the first time, questions arise concerning the organization and managing snapshots. The principle of work is very simple, but unfortunately, it has not been fully described anywhere; on the official website jestjs.io, description of Snapshot Testing work is very poor.</p><h3>How to test with snapshots</h3><p><strong>Step 1.</strong> Write test for the component and in the expect block, use .toMatchSnapshot() method that creates Snapshot itself.</p><pre>it(&#39;render correctly text component&#39;, () =&gt; {  <br>    const TextInputComponent = renderer.create(&lt;TextInput /&gt;).toJSON();<br>    expect(TextInputComponent).toMatchSnapshot();<br>});</pre><p><strong>Step 2.</strong> When you run test for the first time on the one level, along with the test, there will be a created directory named __snapshots__ with the autogenerated file inside with the extension.snap.</p><p>Snapshot looks like:</p><pre>// Jest Snapshot v1, <a href="https://goo.gl/fbAQLP">https://goo.gl/fbAQLP</a></pre><pre>exports[`Render TextInput correctly component 1`] = `  <br>&lt;input  <br>  className=&quot;input-custom&quot;<br>  disabled={undefined}<br>  id={undefined}<br>  name={undefined}<br>  onBlur={undefined}<br>  onChange={[Function]}<br>  pattern={undefined}<br>  placeholder={undefined}<br>  readOnly={false}<br>  required={undefined}<br>  type=&quot;text&quot;<br>  value={undefined}<br>/&gt;<br>`;</pre><p><strong>Step 3.</strong> Push snapshot into the repository and store it along with the test.</p><p>If component has been changed, you need just update snapshot with —updateSnapshot flag or using shot form u flag.</p><h3>Snapshot is created; how does it work?</h3><p>Let us consider two cases:</p><h4>1. The component has changed</h4><ul><li>Run tests</li><li>New snapshot is created, it compares with the auto generated snapshot stored in the directory __snapshots__</li><li>Tests failed because snapshot is different</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/0*sU9qGgZCbIQvnhIB.gif" /></figure><h4>2. The component has not changed</h4><ul><li>Run tests</li><li>New snapshot is created, it compares with the auto generated snapshot stored in the directory __snapshots__</li><li>Tests passed because snapshot is identical</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/0*FECOnZNmc2PRUIR5.gif" /></figure><p>Everything is fine when I test a small component without logic, just UI rendering, but as practice shows, there are no such components on real projects. If they are, they are in a small amount.</p><p><strong>Is there enough snapshot for full component testing?</strong></p><h3>Main instructions for component testing</h3><p><strong>1. One component should have only one snapshot.</strong> If one snapshot fails, most likely the others will fail too, so do not create and store a bunch of unnecessary snapshots clogging the space and confusing developers who will read your tests after you. Of course, there are exceptions when you need to test the behavior of a component in two states; for example, in the state of the component before opening the pop-up and after opening. However, even such variant can always be replaced by this one: the first test stores default state of the component without popup in snapshot, and the second test simulates event and checks the presence of a particular class. In this way, you can easily bypass the creation of several snapshots.</p><p><strong>2. Testing props:</strong> As a rule, I divide the testing of the props into two tests: — Firstly, check the render of default prop values; when the component is rendered, I expect a value to be equal from defaultPropsin case this prop has defaultProps. - Secondly, check the custom value of the prop; I set my own value and expect it to be received after the render of the component.</p><p><strong>3. Testing data types:</strong> In order to test what type of data comes in the props or what kind of data is obtained after certain actions, I use the special library jest-extended (Additional Jest matchers), which has an extended set of matches that are absent in the Jest. With this library, testing of data types is much easier and more enjoyable. Testing proptypes is a contradictory question. Some developers can argue against proptypes testing because it is a third-party package and shouldn’t be tested, but I insist on testing components’ proptypes because I don’t test the package functionality itself; I just ensure the proptypes are correct. Data type is a very important programming part and shouldn’t be skipped.</p><p><strong>4. Event testing:</strong> After creating a snapshot and covering props with tests, you can be sure in correct rendering of the component, but this is not enough for full coverage in case you have events in the component. You can check event in several ways; the most widely used are:</p><ul><li>mock event =&gt; simulate it =&gt; expect event was called</li><li>mock event =&gt; simulate event with params =&gt; expect event was called with passed params</li><li>pass necessary props =&gt; render component =&gt; simulate event =&gt; expect a certain behavior on called event</li></ul><p><strong>5. Testing conditions:</strong> Very often you can have conditions for the output of a particular class, rendering a certain section of the code, transferring the required props, and so on. Do not forget about this because with default values, only one branch will pass the test, while the second one will remain untested. In complex components with calculations and lots of conditions, you can miss some branches. To make sure all parts of the code are covered by tests, use test coverage tool and visually check which branches are covered and which are not.</p><p><strong>6. States’ testing:</strong> To check state, in most cases, it is necessary to write two tests:</p><ul><li>The first one checks current state.</li><li>The second one checks state after calling event. Render component =&gt; call function directly in the test =&gt; check how state has changed. To call function of the component, you need to get an instance of the component and only then call its methods (example is shown in <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/modals/__tests__/ModalTrigger.test.js#L30">next test</a>).</li></ul><p>After you walk through this list of instructions, your component will be covered from 90 to 100%. I leave 10% for special cases that were not described in the article, but can occur in the code.</p><h3>Examples of Testing</h3><p>Let’s move to examples and cover components with tests under described above structure step by step.</p><h4>1. Testing of a component from forms/inputs.</h4><p>Take one component from forms/inputs directory; let it be DateInput.js, the component for datepicker field.</p><p><strong>Code listing for tested component: </strong><a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/forms/inputs/DateInput.js"><strong>DateInput.js</strong></a><strong> <br>Looks like:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/628/0*iPgLFPVUUnqkPm2V.gif" /></figure><p>DateInput component uses library react-datepicker, with two utilities: valueToDate (converts value to date) and dateToValue is vice versa, moment package for manipulating with date and PropTypes for checking React props.</p><p>According to the component code, we can see the list of default props with the help of which the component should be rendered:</p><pre>const defaultProps = {  <br>    inputClassName: &#39;input-custom&#39;,<br>    monthsShown: 1,<br>    dateFormat: &#39;DD.MM.YYYY&#39;,<br>    showMonthYearsDropdowns: false,<br>    minDate: moment()<br>};</pre><p>All props are appropriate for creating snapshot, except one minDate: moment(), moment() will give us current date each time we run test and snapshot will fail because it stores outdated date. Solution is to mock this value:</p><pre>const defaultProps = {  <br>    minDate: moment(0)<br>}</pre><p>minDate prop I need in each rendered component; to avoid props duplication, I create HOC which receives defaultProps and returns pretty component:</p><pre>import TestDateInput from &#39;../DateInput&#39;;  <br>const DateInput = (props) =&gt;  <br>    &lt;TestDateInput<br>        {...defaultProps}<br>        {...props}<br>    /&gt;;</pre><p>Don’t forget about moment-timezone, especially if your tests will be run by developers from another country in a different time zone. They will receive mocked value, but with time zone shift. Solution is to set default time zone:</p><pre>const moment = require.requireActual(&#39;moment-timezone&#39;).tz.setDefault(&#39;America/Los_Angeles&#39;)</pre><p>Now date input component is ready for testing:</p><p><strong>1.Create snapshot first:</strong></p><pre>it(&#39;render correctly date component&#39;, () =&gt; {  <br>    const DateInputComponent = renderer.create(&lt;DateInput /&gt;).toJSON();<br>    expect(DateInputComponent).toMatchSnapshot();<br>});</pre><p><strong>2.Testing props:</strong></p><p>Look through props and find important; first prop to test is showMonthYearsDropdowns, if it set to true, the dropdown for month and years is shown:</p><pre>it(&#39;check month and years dropdowns displayed&#39;, () =&gt; {  <br>    const props = {<br>            showMonthYearsDropdowns: true<br>        },<br>        DateInputComponent = mount(&lt;DateInput {...props} /&gt;).find(&#39;.datepicker&#39;);<br>    expect(DateInputComponent.hasClass(&#39;react-datepicker-hide-month&#39;)).toEqual(true);<br>});</pre><p>Test null prop value; this check is required to ensure the component is rendered without defined value:</p><pre>it(&#39;render date input correctly with null value&#39;, () =&gt; {  <br>    const props = {<br>            value: null<br>        },<br>        DateInputComponent = mount(&lt;DateInput {...props} /&gt;);<br>    expect((DateInputComponent).prop(&#39;value&#39;)).toEqual(null);<br>});</pre><p><strong>3.Test proptypes for value, date expected to be string:</strong></p><pre>it(&#39;check the type of value&#39;, () =&gt; {  <br>    const props = {<br>            value: &#39;10.03.2018&#39;<br>        },<br>        DateInputComponent = mount(&lt;DateInput {...props} /&gt;);<br>    expect(DateInputComponent.prop(&#39;value&#39;)).toBeString();<br>});</pre><p><strong>4.Test events:</strong></p><p><strong>4.1.</strong> Check the onChange event, for that mock onChange callback =&gt; render date input component =&gt; then simulate change event with new target value =&gt; and finally check that onChange event have been called with new value.</p><pre>it(&#39;check the onChange callback&#39;, () =&gt; {  <br>    const onChange = jest.fn(),<br>        props = {<br>            value: &#39;20.01.2018&#39;,<br>            onChange<br>        },<br>        DateInputComponent = mount(&lt;DateInput {...props} /&gt;).find(&#39;input&#39;);<br>    DateInputComponent.simulate(&#39;change&#39;, { target: {value: moment(&#39;2018-01-22&#39;)} });<br>    expect(onChange).toHaveBeenCalledWith(&#39;22.01.2018&#39;);<br>});</pre><p><strong>4.2.</strong> Ensure datepicker popup opens after click on date input, for that find date input =&gt; simulate click event =&gt; and expect popup with class .react-datepicker is present.</p><pre>it(&#39;check DatePicker popup open&#39;, () =&gt; {  <br>    const DateComponent = mount(&lt;DateInput /&gt;),<br>        dateInput = DateComponent.find(&quot;input[type=&#39;text&#39;]&quot;);<br>    dateInput.simulate(&#39;click&#39;);<br>    expect(DateComponent.find(&#39;.react-datepicker&#39;)).toHaveLength(1);<br>});</pre><p><strong>Full tests listing:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/forms/inputs/__tests__/DateInput.test.js">DateInput.test.js</a></p><h4>2. Utility testing:</h4><p><strong>Code listing for tested utility:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/utils/valueToDate.js">valueToDate.js</a></p><p>Purpose of this utility is transforming value to date with custom format. <br>First of all, let’s analyze given utility and define the main cases for testing:</p><p><strong>1.</strong>According to the purpose of this utility, it transforms value, so we need to check this value:</p><ul><li>In case value is not defined: we need to be sure that utility will not return exception (error).</li><li>In case value defined: we need to check that utility returns moment date.</li></ul><p><strong>2.</strong>The returned value should belong to the moment class; that’s why it should be instance of moment.</p><p><strong>3.</strong>Second argument is dateFormat; set it as constant before tests. That’s why it will be passed in each test and return value according to date format. Should we test dateFormat separately? I suppose no. This argument is optional; if we don’t set dateFormat, the utility won’t break, and it’ll just return date in default format; it is a moment job, we shouldn’t test third-party libraries. As I mentioned before, we shouldn’t forget about moment-timezone; it is a very important point, especially for developers from different time zones.</p><p><strong>Let’s code:</strong></p><p><strong>1.Write test for first case; when we don’t have value, it is empty.</strong></p><pre>const format = &#39;DD.MM.YYYY&#39;;</pre><pre>it(&#39;render valueToDate utility with empty value&#39;, () =&gt; {  <br>    const value = valueToDate(&#39;&#39;, format);<br>    expect(value).toEqual(null);<br>});</pre><p><strong>2.Check if value is defined.</strong></p><pre>const date = &#39;21.11.2015&#39;,  <br>      format = ‘DD.MM.YYYY’;</pre><pre>it(&#39;render valueToDate utility with defined value&#39;, () =&gt; {  <br>    const value = valueToDate(date, format);<br>    expect(value).toEqual(moment(date, format));<br>});</pre><p><strong>3.Check the value’s belonging to the moment class.</strong></p><pre>const date = &#39;21.11.2015&#39;,  <br>    format = &#39;DD.MM.YYYY&#39;;</pre><pre>it(&#39;check value is instanceof moment&#39;, () =&gt; {  <br>    const value = valueToDate(date, format);<br>    expect(value instanceof moment).toBeTruthy();<br>});</pre><p><strong>Full tests listing:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/utils/__tests__/valueToDate.test.js">valueToDate.test.js</a></p><h4>3. Widgets testing</h4><p>For widgets testing, I took spinner component. <br><strong>Code listing for tested widget:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/widgets/Spinner.js">Spinner.js</a></p><p><strong><em>Looks like:</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*UM7UiX6_03MeuYmR.gif" /></figure><p>Spinner is not required in explanation, as almost all web resources have this component. <br>So go to write tests:</p><p><strong>1.First step — create snapshot:</strong></p><pre>it(&#39;render correctly Spinner component&#39;, () =&gt; {  <br>   const SpinnerComponent = mount(&lt;Spinner /&gt;);<br>   expect(SpinnerComponent).toMatchSnapshot();<br>});</pre><p><strong>2.Testing props:</strong></p><p><strong>2.1</strong> Default prop title, check if it renders correctly.</p><pre>it(&#39;check prop title by default&#39;, () =&gt; {  <br> const SpinnerComponent = mount(&lt;Spinner /&gt;);<br>    expect(SpinnerComponent.find(&#39;p&#39;).text()).toEqual(&#39;Please wait&#39;);<br>});</pre><p><strong>2.2</strong> Check custom prop title; I need to check that it returns correctly defined prop. Take a look at the code, the title wrapped in rawMarkup util, and outputs with the help of dangerouslySetInnerHTML property.</p><p>Code listing for rawMarkup util:</p><pre>export default function rawMarkup(template) {  <br>    return {__html: template};<br>}</pre><p>Do we need to include tests for rawMarkup in spinner component? No, it is a separate utility and it should be tested apart from the spinner. We don’t care how it works; we just need to know that title prop returns correct result.</p><p>Clarification: The reason of using dangerouslySetInnerHTML property is the following. Our site is multilingual, for which translations marketing team is responsible. They can translate it simply with combination of words or even decorate with the html tags, like &lt;strong&gt;, &lt;i&gt;, &lt;s&gt; or even slice text with the lists &lt;ol&gt;, &lt;ul&gt;; we don’t know for sure how they translate and decorate the text. We just need to correctly render all this stuff.</p><p>I combined two main test cases in one test:</p><ul><li>return correct custom prop title</li><li>render correctly prop title with html tags</li></ul><pre>it(&#39;check prop title with html tags&#39;, () =&gt; {  <br>    const props = {<br>            title: &#39;&lt;b&gt;Please wait&lt;/b&gt;&#39;<br>        },<br>        SpinnerComponent = mount(&lt;Spinner {...props} /&gt;);<br>    expect(SpinnerComponent.find(&#39;p&#39;).text()).toEqual(&#39;Please wait&#39;);<br>});</pre><p>Take next prop subTitle; it is optional and that’s why it doesn’t have default prop, so skip step with default props and test custom props:</p><ul><li>Check that text in subTitle prop renders correctly:</li></ul><pre>const props = {  <br>        subTitle: &#39;left 1 minute&#39;<br>    },<br>    SpinnerComponent = mount(&lt;Spinner {...props} /&gt;);</pre><pre>it(&#39;render correct text&#39;, () =&gt; {  <br>    expect(SpinnerComponent.find(&#39;p&#39;).at(1).text()).toEqual(props.subTitle);<br>});</pre><p>We know that subTitle is optional; that’s why we need to check whether it is not rendered with default props, according to the slicing markup. Just check the number of tags &lt;p&gt;:</p><pre>it(&#39;check subTitle is not rendered&#39;, () =&gt; {  <br>  const SpinnerComponent = mount(&lt;Spinner /&gt;);<br>    expect(SpinnerComponent.find(&#39;p&#39;).length).toEqual(1);<br>});</pre><p><strong>3.Testing prop types:</strong></p><ul><li>For title prop expected to be string:</li></ul><pre>it(&#39;check prop type for title is string&#39;, () =&gt; {  <br>    const props = {<br>            title: &#39;Wait&#39;<br>        },<br>        SpinnerComponent = mount(&lt;Spinner {...props} /&gt;);<br>    expect(SpinnerComponent.find(&#39;p&#39;).text()).toBeString();<br>});</pre><ul><li>For subTitle prop also expected to be string:</li></ul><pre>const props = {  <br>        subTitle: &#39;left 1 minute&#39;<br>    },<br>    SpinnerComponent = mount(&lt;Spinner {...props} /&gt;);</pre><pre>it(&#39;type for subTitle is string&#39;, () =&gt; {  <br>    expect(SpinnerComponent.find(&#39;p&#39;).at(1).text()).toBeString();<br>});</pre><p><strong>Full tests listing:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/widgets/__tests__/Spinner.test.js">Spinner.test.js</a></p><h4>4. Modals testing (ModalWrapper.js and ModalTrigger.js)</h4><p><strong><em>Looks like:</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*yHJepyEsUKrXjt9O.gif" /></figure><p>How to test modals: <br>First of all, I want to explain how modals are organized on our project. We have two components: <strong>ModalWrapper.js</strong> and <strong>ModalTrigger.js</strong>.</p><p><strong>ModalWrapper</strong> is responsible for popup layout. It contains modal container, button ‘close’, modal title and body.</p><p><strong>ModalTrigger</strong> is responsible for modal handling. It includes ModalWrapper layout and contains events for modal’s layout control (open, close actions).</p><p>I overview each component separately:</p><p><strong>1.Code listing for tested component:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/modals/ModalWrapper.js">ModalWrapper.js</a></p><p><strong>Let’s code:</strong></p><p><strong>1.1</strong> ModalWrapper receives component and renders it inside. First of all, check that ModalWrapper won’t fail without component. Create snapshot with default props:</p><pre>it(&#39;without component&#39;, () =&gt; {  <br>    const ModalWrapperComponent = shallow(&lt;ModalWrapper /&gt;);<br>    expect(ModalWrapperComponent).toMatchSnapshot();<br>});</pre><p><strong>1.2</strong> Next step is to simulate its actual condition with component rendering passed through props:</p><pre>it(&#39;with component&#39;, () =&gt; {  <br>   const props = {<br>           component: () =&gt; {}<br>        },<br>        ModalWrapperComponent = shallow(&lt;ModalWrapper {...props} /&gt;);<br>    expect(ModalWrapperComponent).toMatchSnapshot();<br>});</pre><p><strong>1.3</strong> Testing props:</p><p>Receiving custom class name prop:</p><pre>it(&#39;render correct class name&#39;, () =&gt; {  <br>    const props = {<br>            modalClassName: &#39;custom-class-name&#39;<br>        },<br>        ModalWrapperComponent = shallow(&lt;ModalWrapper {...props} /&gt;).find(&#39;Modal&#39;);<br>        expect(ModalWrapperComponent.hasClass(&#39;custom-class-name&#39;)).toEqual(true);<br>});</pre><p>Receiving custom title prop:</p><pre>it(&#39;render correct title&#39;, () =&gt; {  <br>    const props = {<br>           title: &#39;Modal Title&#39;<br>       },<br>       ModalWrapperComponent = shallow(&lt;ModalWrapper {...props} /&gt;).find(&#39;ModalTitle&#39;);<br>    expect(ModalWrapperComponent.props().children).toEqual(&#39;Modal Title&#39;);<br>});</pre><p>Receiving correct show prop:</p><pre>it(&#39;check prop value&#39;, () =&gt; {<br>        const props = {<br>               show: true<br>           },<br>           ModalWrapperComponent = shallow(&lt;ModalWrapper {...props} /&gt;).find(&#39;Modal&#39;);<br>        expect(ModalWrapperComponent.props().show).toEqual(true);<br>    });</pre><p><strong>1.4</strong> Testing proptypes:</p><ul><li>for show prop</li></ul><pre>it(&#39;check prop type&#39;, () =&gt; {  <br>    const props = {<br>           show: true<br>        },<br>        ModalWrapperComponent = shallow(&lt;ModalWrapper {...props} /&gt;).find(&#39;Modal&#39;);<br>    expect(ModalWrapperComponent.props().show).toBeBoolean();<br>});</pre><ul><li>for onHide prop</li></ul><pre>it(&#39;render correct onHide prop type&#39;, () =&gt; {  <br>    const props = {<br>            onHide: () =&gt; {}<br>        },<br>        ModalWrapperComponent = shallow(&lt;ModalWrapper {...props} /&gt;).find(&#39;Modal&#39;);<br>    expect(ModalWrapperComponent.props().onHide).toBeFunction();<br>});</pre><ul><li>for component prop</li></ul><pre>it(‘render correct component prop type’, () =&gt; {  <br>   const props = {<br>           component: () =&gt; {}<br>       },<br>       ModalWrapperComponent = mount(&lt;ModalWrapper {...props} /&gt;);<br>   expect(ModalWrapperComponent.props().component).toBeFunction();<br>});</pre><p><strong>Full tests listing:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/modals/__tests__/ModalWrapper.test.js">ModalWrapper.test.js</a></p><p><strong>2.Code listing for tested component:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/modals/ModalTrigger.js">ModalTrigger.js</a></p><p>The modal wrapper has covered with test; the second part is to cover modal trigger component. <br>Component overview: it is based on the state toggled that indicates visibility of ModalWrapper. If toggled: false, the popup is hidden, else visible. Function <strong>open()</strong> opens popup on child element; click event and function <strong>close()</strong> hides popup on button rendered in ModalWrapper.</p><p><strong>2.1</strong> Snapshot creation:</p><pre>it(&#39;render ModalTrigger component correctly&#39;, () =&gt; {  <br>    const ModalTriggerComponent = shallow(&lt;ModalTrigger&gt;&lt;div /&gt;&lt;/ModalTrigger&gt;);<br>    expect(ModalTriggerComponent).toMatchSnapshot();<br>});</pre><p>Should we test ModalTrigger with component prop rendering? No; because component will be rendered inside ModalWrapper component, it does not depend on the tested component. It was already covered with tests in the ModalWrapper tests.</p><p><strong>2.2</strong> Testing props. We have one prop children and we want to be sure that we have only one child.</p><pre>it(&#39;ensure to have only one child (control element)&#39;, () =&gt; {  <br>    expect(ModalTriggerComponent.findWhere(node =&gt; node.key() === &#39;modal-control&#39;).length).toEqual(1);<br>});</pre><p><strong>2.3</strong> Testing proptypes. Children prop should be object, check this in the next test:</p><pre>const ModalTriggerComponent = mount(&lt;ModalTrigger&gt;&lt;div /&gt;&lt;/ModalTrigger&gt;);</pre><pre>it(&#39;check children prop type&#39;, () =&gt; {  <br>      expect(ModalTriggerComponent.props().children).toBeObject();<br>});</pre><p>2.4 Important part of ModalTrigger component is to check states. <br>We have two states: <br>Popup is opened. To know that modal is opened, we need to check its state. For this, call open function from instance of the component and expect that toggled in state should be true.</p><pre>it(&#39;check the modal is opened&#39;, () =&gt; {  <br>    const event = {<br>        preventDefault: () =&gt; {},<br>        stopPropagation: () =&gt; {}<br>    };<br>    ModalTriggerComponent.instance().open(event);<br>    expect(ModalTriggerComponent.state().toggled).toBeTruthy();<br>});</pre><p>Popup is closed, is tested vice versa, toggled in state should be false.</p><pre>it(&#39;check the modal is closed&#39;, () =&gt; {  <br>   ModalTriggerComponent.instance().close();<br>   expect(ModalTriggerComponent.state().toggled).toBeFalsy();<br>});</pre><p><strong>Full tests listing:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/modals/__tests__/ModalTrigger.test.js">ModalTrigger.test.js</a></p><p>Now modals are fully tested. One piece of advice for testing the components that are dependent on each other: look through the components first and write test plan, define what you need to test in each component, check test cases for each component, and be sure you don’t repeat the same test case in both components. Carefully analyze possible and optimal variants for test coverage.</p><h4>5. HOC testing (Higher-Order Component)</h4><p>The last two parts (HOC and form’s fields testing) are interconnected. I would like to share with you how to test field layout with its HOC. <br>Explanation of what is the BaseFieldLayout, why we need this component, and where we use it:</p><ul><li>BaseFieldLayout.js is the wrapper for form input components like TextInput, CheckboxInput, DateInput, SelectInput, etc. Their names end with the -Input because we use redux-form package and these components are the input components to redux-form logic.</li><li>We need BaseFieldLayout for creating layout for form fields components, that is rendering label, tooltips, prefixes (currency, square meter abbreviations, etc.), icons, errors …</li><li>We use it in BaseFieldHOC.js for wrapping inputComponent in field layout and connect it with the redux-form with the help of &lt;Field/&gt; component.</li></ul><p><strong>Code listing for tested component:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/hoc/BaseFieldHOC.js">BaseFieldHOC.js</a></p><p>It is a HOC which receives form input component and returns component, connected with redux-form.</p><p>Analyze HOC:</p><ul><li>This component receives only one prop, component. First of all, I need to create this component and wrap it in the BaseFieldHOC.</li><li>Next, I need to decorate wrapped HOC with redux-form in order to get field connected with redux-form.</li><li>Render this field inside React Redux &lt;Provider&gt; component to make the store available to tested component. To mock store, just do:</li></ul><pre>const store = createStore(() =&gt; ({}));</pre><p>Now, before each test, I need to do the next:</p><pre>let BaseFieldHOCComponent;</pre><pre>beforeEach(() =&gt; {  <br>    const TextInput = () =&gt; { return &#39;text input&#39;; },<br>        BaseFieldHOCWrapper = BaseFieldHOC(TextInput),<br>        TextField = reduxForm({ form: &#39;testForm&#39; })(BaseFieldHOCWrapper);<br>    BaseFieldHOCComponent = renderer.create(<br>        &lt;Provider store={store}&gt;<br>            &lt;TextField name=&quot;text-input&quot; /&gt;<br>        &lt;/Provider&gt;<br>    ).toJSON();<br>});</pre><p>After that, the component is ready for testing:</p><p>1.Create snapshot:</p><pre>it(&#39;render correctly component&#39;, () =&gt; {  <br>    expect(BaseFieldHOCComponent).toMatchSnapshot();<br>});</pre><p>2.Ensure that input component is wrapped in BaseFieldLayout after rendering:</p><pre>it(&#39;check input component is wrapped in BaseFieldLayout&#39;, () =&gt; {  <br>    expect(BaseFieldHOCComponent.props.className).toEqual(&#39;form-group&#39;);<br>});</pre><p>That’s all, the HOC is covered. The most complicated part in testing connected with redux-form components is to make preparation of the field (decorate with redux form and setup store); the rest is easy, just follow the instructions and nothing else. <br><strong>Full tests listing:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/hoc/__tests__/BaseFieldHOC.test.js">BaseFieldHOC.test.js</a></p><h4>6. Forms/fields testing</h4><p>Field HOC has covered with tests and we can move to BaseFieldLayout component.</p><p><strong>Code listing for tested component:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/forms/fields/BaseFieldLayout.js">BaseFieldLayout.js</a></p><p>Let’s code BaseFieldLayout.js; write tests according to instructions above:</p><p><strong>1.First of all, create snapshot.</strong></p><p>This component will not be rendered without defaultProps:</p><ul><li>inputComponent</li><li>The props provided by redux-form: input and meta objects. Input with property name and meta with properties error and touched:</li></ul><pre>const defaultProps = {  <br>   meta: {<br>        touched: null,<br>        error: null<br>    },<br>    input: {<br>        name: &#39;field-name&#39;<br>    },<br>    inputComponent: () =&gt; { return &#39;test case&#39;; }<br>}</pre><p>To use defaultProps in each tested wrapper, do the following:</p><pre>import TestBaseFieldLayout from &#39;../BaseFieldLayout&#39;;</pre><pre>const BaseFieldLayout = (props) =&gt; &lt;TestBaseFieldLayout {...defaultProps} {...props} /&gt;;</pre><p>Now we are ready to create snapshot:</p><pre>it(&#39;render correctly BaseFieldLayout component&#39;, () =&gt; {  <br>    const BaseFieldLayoutComponent = renderer.create(&lt;BaseFieldLayout /&gt;).toJSON();<br>    expect(BaseFieldLayoutComponent).toMatchSnapshot();<br>});</pre><p><strong>2.Testing props:</strong></p><p>This component has many props. I will show examples of several ones; the rest are tested by analogy.</p><ul><li>Ensure icon prop is rendered correctly</li></ul><pre>it(&#39;render correctly icon prop&#39;, () =&gt; {  <br>    const props = {<br>            icon: &lt;span className=&quot;icon-exclamation&quot; /&gt;<br>        },<br>        BaseFieldLayoutComponent = mount(&lt;BaseFieldLayout {...props} /&gt;);<br>        expect(BaseFieldLayoutComponent.find(&#39;span&#39;).hasClass(&#39;icon-exclamation&#39;)).toBeTruthy();<br>});</pre><ul><li>Ensure tooltip content renders next to the label</li></ul><pre>const props = {  <br>        labelTooltipContent: &#39;tooltip for label&#39;<br>    },<br>    BaseFieldLayoutComponent = mount(&lt;BaseFieldLayout {...props} /&gt;);</pre><pre>it(&#39;check prop is rendered&#39;, () =&gt; {  <br>   expect(BaseFieldLayoutComponent.find(&#39;span&#39;).hasClass(&#39;tooltip-icon&#39;)).toBeTruthy();<br>});</pre><ul><li>Testing fieldLink prop</li><li>Ensure fieldLink is null by default</li></ul><pre>it(&#39;check prop is null by default&#39;, () =&gt; {  <br>    const BaseFieldLayoutComponent = shallow(&lt;BaseFieldLayout /&gt;);<br>    expect(BaseFieldLayoutComponent.props().fieldLink).toBe(null);<br>});</pre><ul><li>Ensure fieldLink renders correctly with custom value</li></ul><p><strong>3.Testing errors:</strong></p><pre>it(&#39;check if field has error&#39;, () =&gt; {  <br>    const props = {<br>            meta: {<br>                touched: true,<br>                error: &#39;This field is required&#39;<br>            }<br>        },<br>        BaseFieldLayoutComponent = mount(&lt;BaseFieldLayout {...props} /&gt;);<br>    expect(BaseFieldLayoutComponent.find(&#39;.error&#39;)).toHaveLength(1);<br>});</pre><p><strong>Full tests listing:</strong> <a href="https://github.com/ned-alyona/testing-jest-enzyme/blob/master/shared/forms/fields/__tests__/BaseFieldLayout.test.js">BaseFieldLayout.test.js</a></p><h3>Bottom Line</h3><p>Now you have full guidance on how to perform full coverage testing of components based on project structure. From my own experience, I tried to explain what is necessary to test, in which order, and what you can omit in test coverage. Also, I demonstrated examples of several testing components and spotted the sequence of codebase coverage. I hope that you will find this article useful and will share your response. Thank you for reading.</p><figure><a href="https://djangostars.com/services/web-development/#utm_source=medium&amp;utm_medium=blog.bitsrc.io&amp;utm_campaign=react%20components%20testing&amp;utm_content=banner_end"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uXvQcmeNupo-iVkclcxrSg.png" /></a></figure><blockquote>This article about <a href="https://djangostars.com/blog/what-and-how-to-test-with-enzyme-and-jest-full-instruction-on-react-component-testing/#utm_source=medium&amp;utm_medium=blog.bitsrc.io&amp;utm_campaign=react%20components%20testing&amp;utm_content=react%20components%20testing">react components testing</a> is originally published on <strong>Django Stars blog</strong>.</blockquote><blockquote><em>If you find this post useful, please tap 👏 button below :)</em></blockquote><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2F833939-2%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2F833939-2%2F&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/23806bfe1f184df6c93c60e10e7fdc04/href">https://medium.com/media/23806bfe1f184df6c93c60e10e7fdc04/href</a></iframe><h3>Learn more</h3><ul><li><a href="https://blog.bitsrc.io/how-to-easily-share-react-components-between-projects-3dd42149c09">How to Share React UI Components between Projects and Apps</a></li><li><a href="https://blog.bitsrc.io/11-react-component-libraries-you-should-know-178eb1dd6aa4">11 React UI Component Libraries you Should Know in 2019</a></li><li><a href="https://blog.bitsrc.io/5-tools-for-faster-development-in-react-676f134050f2">5 Tools for Faster Development in React</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=145fcd06b90" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bitsrc/how-to-test-react-components-with-jest-and-enzyme-in-depth-145fcd06b90">Testing React Components with Jest and Enzyme- In Depth</a> was originally published in <a href="https://medium.com/bitsrc">Bits and Pieces</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>