{"id":264,"date":"2019-01-15T09:54:28","date_gmt":"2019-01-15T09:54:28","guid":{"rendered":"https:\/\/www.visionmate.se\/en\/?p=264"},"modified":"2019-01-15T09:54:28","modified_gmt":"2019-01-15T09:54:28","slug":"testing-react-applications-with-jest-and-enzyme","status":"publish","type":"post","link":"https:\/\/www.visionmate.se\/en\/2019\/01\/15\/testing-react-applications-with-jest-and-enzyme\/","title":{"rendered":"Testing React applications with Jest and Enzyme"},"content":{"rendered":"<p>Testing is an essential part of software development, ensures maintainability of code. Writing automatic tests helps to locate new bugs, improve quality and perfectly complements manual testing.<\/p>\n<p>In this article we will go through the set up and some of most common ways to test React application developed with create-react-app (CRA) 2.1.3 version.<\/p>\n<p>To get started, let me introduce today&#8217;s heroes:<\/p>\n<ol>\n<li><a href=\"https:\/\/facebook.github.io\/jest\/docs\/en\/getting-started.html\" target=\"_blank\" rel=\"nofollow noopener\">Jest<\/a>\u00a0&#8211; a JavaScript testing framework by Facebook. We are using CRA where Jest is installed automatically. Its job is to take all test files in our project, run the tests and display results in terminal. Jest can be used with non-react applications.<\/li>\n<li><a href=\"http:\/\/airbnb.io\/enzyme\/\" target=\"_blank\" rel=\"nofollow noopener\">Enzyme<\/a><em>\u00a0<\/em>&#8211; is a testing tool developed and managed by Airbnb. Enzyme uses several of the utilities provided by React to build its API. Enzyme works only with React.<\/li>\n<\/ol>\n<h3>SET UP<\/h3>\n<ul>\n<li>Setting up React application with CRA<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">create-react-app testing\r\ncd testing\r\nnpm start<\/pre>\n<ul>\n<li>Setting up Enzyme<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">npm install --save enzyme enzyme-adapter-react-16<\/pre>\n<p>Put your attention to version of React which you are using. Here we have 16, but Enzyme has adapters for all versions. Here you will find details: <a href=\"http:\/\/airbnb.io\/enzyme\/#installation\" target=\"_blank\" rel=\"nofollow noopener\">Enzyme installation guide<\/a>.<\/p>\n<p>To finish configuration, we have to create a new file called <strong>setupTests.js <\/strong>under <strong>src <\/strong>directory, so we can use Enzyme in any of test files. Name is very important here.<\/p>\n<p>setupTests.js<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import Enzyme from 'enzyme';\r\nimport Adapter from 'enzyme-adapter-react-16';\r\n\r\nEnzyme.configure({adapter: new Adapter() });<\/pre>\n<p>This is it! Installation is behind us.<\/p>\n<h3>FUNCTIONS IN ENZYME<\/h3>\n<p>We will use the functions below. They will create instances of our components and return back objects which we can use to write tests<\/p>\n<ul>\n<li><strong>Static <\/strong>&#8211; renders the given component and returns plain HTML<\/li>\n<li><strong>Shallow<\/strong> &#8211; most basic version, it renders only given component without children. Perfect for unit tests<\/li>\n<li><strong>Full DOM<\/strong> which renders the components with all children, here we are able to interact with components<\/li>\n<\/ul>\n<h3>TEST STRUCTURE<img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-622 alignright\" src=\"https:\/\/www.visionmate.se\/wp-content\/uploads\/2019\/01\/0-246x300.png\" alt=\"\" width=\"246\" height=\"300\" \/><\/h3>\n<p>Our tests will be placed in a new directory <strong>__tests__<\/strong><\/p>\n<p>It is a good habit to organize tests in this way. Jest will run all files located inside.<\/p>\n<p>To make it easy to recognize which test pertain to which file, we are describing them in the same way as tested file: <strong>.test.js<\/strong> at the end.<\/p>\n<p>Our tests will always be in schema:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">it ('test description', function which contain logic of our test);<\/pre>\n<p>Function inside our test can contain few expectations, where we can describe the value which we expect to see.<\/p>\n<h3><strong>FINALLY TEST!<\/strong><\/h3>\n<p>Below is the content of two simple components:<\/p>\n<p>List.js<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import React, { Component } from 'react';\r\n\r\n\r\nclass List extends Component {\r\n    render() {\r\n        return (\r\n            &lt;form&gt;\r\n              &lt;h3&gt;Add new element&lt;\/h3&gt;\r\n              &lt;textarea \/&gt;\r\n              &lt;div&gt;\r\n                &lt;button&gt;Save&lt;\/button&gt;\r\n              &lt;\/div&gt;\r\n            &lt;\/form&gt;\r\n        );\r\n    }\r\n}\r\n\r\nexport default List;<\/pre>\n<p>App.js<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import React from 'react';\r\nimport List from '.\/List'\r\n\r\nexport default()=&gt;{\r\n    return (\r\n        &lt;div&gt;&lt;List \/&gt;&lt;\/div&gt;\r\n    );\r\n};<\/pre>\n<p>Let&#8217;s simply test rendering List.js component. We will use shallow function as we don&#8217;t need to render its children. If component is working correctly test will pass, otherwise it will fail.<\/p>\n<p>List.test.js<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import React from 'react';\r\nimport { shallow } from 'enzyme'; \r\nimport List from '..\/List';\r\n\r\nit('renders without crashing', () =&gt; {\r\n  shallow(&lt;List \/&gt;);\r\n});\r\n<\/pre>\n<p>Now check if the test will pass by typing in terminal<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">npm test<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-623\" src=\"https:\/\/www.visionmate.se\/wp-content\/uploads\/2019\/01\/1-300x98.png\" alt=\"\" width=\"300\" height=\"98\" \/><\/p>\n<p>Great! Our fist test works. To end testing mode just press ctrl+c.<\/p>\n<p>Now we will check the components instance.We want to check if List.js component is located in App.js.<\/p>\n<p>App.test.js<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import React from 'react';\r\nimport { shallow } from 'enzyme'; \r\nimport App from '..\/App';\r\nimport List from '..\/List';\r\n\r\nit('shows the list', () =&gt; {\r\n  const wrapped = shallow(&lt;App \/&gt;);\r\n  expect(wrapped.find(List).length).toEqual(1);\r\n});\r\n<\/pre>\n<p><strong>const wrapped<\/strong> means that the object which we will have from shallow(&lt;App \/&gt;) is a wrapped version of App component.<\/p>\n<p>And both tests passed!<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-624\" src=\"https:\/\/www.visionmate.se\/wp-content\/uploads\/2019\/01\/2-300x110.png\" alt=\"\" width=\"300\" height=\"110\" \/><\/p>\n<p>In similar way as above we can check if our component contains button and input area:<\/p>\n<p>List.test.js<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import React from 'react';\r\nimport { mount } from 'enzyme'; \r\nimport List from '..\/List';\r\n\r\nit('contains button and text area', () =&gt; {\r\n  const wrapped = mount(&lt;List \/&gt;);\r\n  expect(wrapped.find('textarea').length).toEqual(1);\r\n  expect(wrapped.find('button').length).toEqual(1);\r\n});<\/pre>\n<p><a href=\"https:\/\/airbnb.io\/enzyme\/docs\/api\/ReactWrapper\/find.html\" target=\"_blank\" rel=\"nofollow noopener\"><strong>Find<\/strong><\/a> is very powerful in tests. Thanks to it, we can detect every class, HTML element, attribute syntax, prop or object property selector and check if it meets our expectations.<\/p>\n<p>Now the question is, how to test&#8230;. a test?<\/p>\n<p>We can check it by changing expected value to an incorrect one. Let&#8217;s try to pretend that we don&#8217;t have a button in List.js, we put value <strong>0<\/strong> instead of <strong>1 <\/strong>in test file. Now test should fail<\/p>\n<p>List.test.js<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">it('shows button', () =&gt; {\r\n    const wrapped = shallow (&lt;List \/&gt;);\r\n    expect(wrapped.find('button').length).toEqual(0);\r\n});\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-625 alignnone\" src=\"https:\/\/www.visionmate.se\/wp-content\/uploads\/2019\/01\/3-300x164.png\" alt=\"\" width=\"300\" height=\"164\" \/><\/p>\n<p>Indeed it happened, Jest shows us exactly what goes wrong.<\/p>\n<h3>CONCLUSION<\/h3>\n<p>Jest and Enzyme are well integrated and provide flexible\u00a0testing abilities. Configuration is very easy what is a great advantage. We did not delve into the specific methods but now surely we are able to evaluate Jest&#8217;s and Enzyme&#8217;s efficiency.<\/p>\n<p>Origin: <a href=\"https:\/\/www.linkedin.com\/pulse\/testing-react-applications-jest-enzyme-monika-top%C3%B3r-m%C4%85dry\/\" target=\"_blank\" rel=\"noopener\">www.linkedin.com<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Testing is an essential part of software development, ensures maintainability of code. Writing automatic tests&#8230;<\/p>\n","protected":false},"author":1,"featured_media":265,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[18,19,4,20],"class_list":["post-264","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-enzyme","tag-jest","tag-react","tag-testing"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/posts\/264","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/comments?post=264"}],"version-history":[{"count":1,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/posts\/264\/revisions"}],"predecessor-version":[{"id":266,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/posts\/264\/revisions\/266"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/media\/265"}],"wp:attachment":[{"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/media?parent=264"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/categories?post=264"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.visionmate.se\/en\/wp-json\/wp\/v2\/tags?post=264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}