<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Jest - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Jest - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 29 May 2026 16:31:43 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/jest/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Upgrade from Node 16 and Jest 26 While Staying on React Scripts 4 ]]>
                </title>
                <description>
                    <![CDATA[ Recently, I was trying to upgrade some of my open source projects. They were made using create-react-app around 2019, and I wanted to upgrade to a newer version of NodeJS and Jest. This would let me take advantage of the security updates, bug fixes, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-upgrade-node-and-jest-while-on-react-scripts-v4/</link>
                <guid isPermaLink="false">66b9e801748589d7de3c86ab</guid>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Harsh Deep ]]>
                </dc:creator>
                <pubDate>Wed, 10 Jul 2024 19:35:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/image0.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Recently, I was trying to upgrade some of my open source <a target="_blank" href="https://github.com/classtranscribe/FrontEnd/">projects</a>. They were made using <a target="_blank" href="https://github.com/facebook/create-react-app">create-react-app</a> around 2019, and I wanted to upgrade to a newer version of NodeJS and Jest. This would let me take advantage of the security updates, bug fixes, speed improvements, and new features that the ecosystem has developed since then. </p>
<p>Unfortunately, it was not as simple as just running <code>$ nvm use 18</code> and sailing into the sunset. Luckily, if you follow all the proper steps, you'll get past many significant hurdles and upgrade successfully. In this guide, I will share all the knowledge I wish I had known going into the process. The goal is to get your React application using Node 18+ and Jest 29+ while not making the treacherous upgrade to React Scripts 5.</p>
<p>If you can upgrade to React Scripts 5 (which is impractical for most real-world applications), I highly recommend that path instead. This is because the newest version of CRA fixes many issues with older dependencies, like the <code>MD4 envelope</code> or Babel <code>process()</code> return shapes, that we'll manually tackle in this tutorial. If you can upgrade to v5, then Node versions 18+ should work out of the box.</p>
<p>Unfortunately, going up to React Scripts 5 introduces many breaking changes, mostly due to the upgrade to Webpack 5. While many small/tutorial-level applications can upgrade fairly easily, any real-world application faces a steep uphill journey to upgrade. </p>
<p>If the React Scripts 5 upgrade approach doesn't work for you, you can follow what I've written below on making the Node upgrade work while still staying on React Scripts 4. At the end of this page, I've written a small note about my journey trying the <code>v5</code> upgrade.</p>
<p>Everyone's upgrade journey will vary, especially considering the Jenga of <code>npm</code> dependencies and the relative lack of maintenance of Create React App's React Scripts in recent years.</p>
<p>These are the steps of the upgrade that I've tried with a few different React applications, but you may encounter issues I didn't encounter myself. Google is your best friend in these cases, and it will often lead you to Stackoverflow, GitHub issues, other tutorials, and maybe even source code. Don't be afraid; you'll be able to figure it out! </p>
<p>Note: In this tutorial, I'll refer to Create React App as CRA. React Scripts is the name of the installed package that abstracts all the configuration created by the Create React App command, and in most cases you'll see online resources use both interchangeably.</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-how-to-validate-every-step">How to Validate Every Step</a></li>
<li><a class="post-section-overview" href="#heading-how-to-bump-to-react-scripts-v403">How to Bump to React Scripts v4.0.3</a></li>
<li><a class="post-section-overview" href="#heading-how-to-bump-node-version-to-18">How to Bump Node Version to 18</a><br>– <a class="post-section-overview" href="#heading-understanding-the-md4-issue">Understanding the MD4 Issue</a></li>
<li><a class="post-section-overview" href="#heading-how-to-eject-out-of-react-scripts">How to Eject Out of React Scripts</a><br>– <a class="post-section-overview" href="#heading-how-to-add-linter-ignores-for-ejected-files">How to Add Linter Ignores For Ejected Files</a><br>– <a class="post-section-overview" href="#heading-how-to-update-your-dockerfile-and-other-build-processes-with-the-ejected-folders-1">How to update your Dockerfile and Other Build Processes with the ejected folders</a><br>– <a class="post-section-overview" href="#heading-how-to-fix-absolute-paths-for-jest">How to Fix Absolute Paths for Jest</a><br>– <a class="post-section-overview" href="#heading-how-to-update-your-dockerfile-and-other-build-processes-with-the-ejected-folders-1">How to update your Dockerfile and Other Build Processes with the ejected folders</a></li>
<li><a class="post-section-overview" href="#heading-how-to-override-webpack-md4-to-sha256">How to Override Webpack MD4 to SHA256</a></li>
<li><a class="post-section-overview" href="#heading-how-to-upgrade-to-the-latest-version-of-jest">How to Upgrade to the Latest Version of Jest</a><br>– <a class="post-section-overview" href="#heading-how-to-bump-to-jest-28">How to Bump to Jest 28</a><br>– <a class="post-section-overview" href="#heading-how-to-explicitly-set-jsdom-as-the-test-environment">How to explicitly set jsdom as the test environment</a><br>– <a class="post-section-overview" href="#heading-how-to-fix-transformer-return-type-for-process-and-processasync">How to Fix Transformer Return Type for process() and processAsync()</a><br>– <a class="post-section-overview" href="#heading-how-to-bump-jest-to-29">How to Bump Jest to 29</a></li>
<li><a class="post-section-overview" href="#heading-how-far-should-i-upgrade-nodejs">How Far Should I Upgrade NodeJS?</a></li>
<li><a class="post-section-overview" href="#heading-should-you-still-use-create-react-scripts-what-alternatives-are-there">Should You Still Use Create React Scripts? What Alternatives Are There?</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
<li><a class="post-section-overview" href="#heading-alternatively-how-to-upgrade-to-react-scripts-501">Alternatively: How to Upgrade to React Scripts 5.0.1</a></li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this guide, you should have a React application that is:</p>
<ul>
<li>created with <code>create-react-app</code> v4 or upgraded to use <code>react-scripts</code> v4. I've tested this tutorial on both scenarios.</li>
<li>running on Node 16</li>
</ul>
<p>If you're running NodeJS behind 16, I highly suggest upgrading to version 16. The upgrade path to 16 isn't too bad, but the jump from 16 to 18 creates breaking issues with CRA 4 defaults. </p>
<p>Our application also ran <code>jest</code> (v26), the most common test framework in React and shipped by default in CRA v4. If you aren't running Jest, then you can skip the steps relevant to it.</p>
<p>We were also using <code>yarn</code>, but the process should be identical with different syntax if you use any other runner/package manager like <code>npm</code>.</p>
<p>Ideally, you have some test case coverage to ensure things don't break between versions, so it's well worth taking some time to write some broad integration and unit tests before any upgrade.</p>
<p>I recommend using version control like <code>git</code> for each stage while working on a branch. I started over three different times using different upgrade strategies until I had something that worked. Here's a quick <a target="_blank" href="https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell">intro</a> to <code>git</code> branches if you're unfamiliar with them.</p>
<p>I also recommend using <a target="_blank" href="https://github.com/nvm-sh/nvm">nvm</a> (Node Version Manager) to to swap versions quickly. You don't have to use it, and there are many other alternatives out there to manage versions, but it makes quickly switching very easy with just <code>nvm use</code>. I'll use <code>nvm</code> syntax in this tutorial, but it should be pretty similar for your tool.</p>
<h2 id="heading-how-to-validate-every-step">How to Validate Every Step</h2>
<p>Throughout the tutorial, to ensure things still work, you'll run the following:</p>
<ul>
<li><code>$ yarn build</code> – End-to-end build to catch a lot of library-level issues</li>
<li><code>$ yarn test</code> – Regression tests to catch breaks in functionality</li>
<li><code>$ yarn start</code> – The starter scripts to catch many initialization bugs.</li>
</ul>
<p>If you have any more validation steps (CI builds, Docker, staging environments, smoke tests), make sure they're working already and use them throughout the process to validate the upgrade worked correctly. For the rest of the tutorial, I'll refer to these as validation commands.</p>
<p>Before you start the upgrade, make sure all validation steps are working on your current Node 16 and CRA 4. At the end of the tutorial, all these validation steps should be working too. Ultimately, make sure to actually use your React application extensively as the final test once all the upgrade process is done.</p>
<p>Occasionally, you may need to <code>$ rm -rf node_modules</code> and <code>$ rm package.lock.json</code> / <code>$ rm yarn.lock</code> because some library changes may not propagate correctly. Ideally you won't need to do this, but it's reasonably safe since it just downloads all packages again.</p>
<h2 id="heading-how-to-bump-to-react-scripts-v403">How to Bump to React Scripts v4.0.3</h2>
<p>Depending on when you started your project from CRA, you'll likely be at different versions along v4. First, we upgrade to the latest minor version to smooth over the rest of the upgrade process.</p>
<p>There shouldn't be any major breaking changes between the minor versions, but make sure to upgrade it incrementally in your <code>package.json</code> going from <code>4.0.0</code> -&gt; <code>4.0.1</code> -&gt; <code>4.0.2</code> -&gt; <code>4.0.3</code>. Going to <code>4.0.3</code> will streamline your upgrade process since these minor updates have a lot of useful bug, library, and dependency fixes while not creating new work for now. </p>
<p>I ran <code>$ yarn install</code> after each step and then checked my validation commands to ensure everything was still working.</p>
<pre><code class="lang-json">... 
<span class="hljs-string">"dependencies"</span>: { 
    <span class="hljs-attr">"react-scripts"</span>: <span class="hljs-string">"4.0.1"</span>, 
    ... 
}, 
...
</code></pre>
<p>In my projects, I didn't encounter any issues, but your mileage may vary. The official <a target="_blank" href="https://github.com/facebook/create-react-app/blob/main/CHANGELOG-4.x.md">CRA v4 changelog documentation</a> has a list of small changes and upgrade steps between the versions, which will narrow down the causes.</p>
<h2 id="heading-how-to-bump-node-version-to-18">How to Bump Node Version to 18</h2>
<p>After making sure your validation commands are working on your current Node 16, set your version to 18. Then we work on fixing all the validation commands until all of them work. Occasionally you may switch back to 16 to make sure things still work in the older version. </p>
<p>In your command line, run the following:</p>
<pre><code class="lang-sh">$ nvm install 18
$ nvm use 18
</code></pre>
<blockquote>
<p>Note: If you have a <code>.nvmrc</code> file, you can skip the version numbers in the <code>nvm install</code> and <code>nvm use</code> commands. Update the file as you change node versions.</p>
</blockquote>
<p>Unfortunately, if you try <code>$ yarn start</code> or <code>$ yarn build</code>, you'll immediately run into the cryptography error that comes from <code>openssl</code>, which blocks all encryption using MD4. This is the main error blocking the upgrade to Node 18 while on CRA 4.</p>
<pre><code><span class="hljs-built_in">Error</span>: error:<span class="hljs-number">0308010</span>C:digital envelope routines::unsupported
</code></pre><h3 id="heading-understanding-the-md4-issue">Understanding the MD4 Issue</h3>
<p>MD4 is an old encryption algorithm from the 1990s and has been considered very insecure since 1995 (<a target="_blank" href="https://en.wikipedia.org/wiki/MD4">Wikipedia</a>). OpenSSL from version 3 onward changed MD4 to not be supported by default, but it can be enabled with an allow unsafe legacy <a target="_blank" href="https://github.com/openssl/openssl/issues/21247">flag</a> on your system <code>openssl</code> or <code>--openssl-legacy-provider</code> if adding it to your node/CRA script (see the Node <a target="_blank" href="https://nodejs.org/api/cli.html#--openssl-legacy-provider">docs</a>). </p>
<p>It's a seemingly simple fix to the solution, but this is more of a last resort since allowing unsafe cryptography is generally a bad idea, and OpenSSL has disabled the algorithm entirely for a reason.</p>
<blockquote>
<p>Note: If you're curious, Webpack has a 1000+ response <a target="_blank" href="https://github.com/webpack/webpack/issues/14532">discussion</a> on this topic that might have something useful. Later versions of Webpack also eventually <a target="_blank" href="https://github.com/webpack/webpack/pull/14306">allowed</a> a better algorithm called <a target="_blank" href="https://github.com/Cyan4973/xxHash">xxHash</a>, added a built-in MD4 <code>wasm</code> <a target="_blank" href="https://github.com/webpack/webpack/pull/14584">implementation</a>, and added a new config option called <a target="_blank" href="https://webpack.js.org/configuration/optimization/#optimizationmoduleids">deterministic</a> that sidesteps the issue. </p>
</blockquote>
<p>I highly recommend reading this StackOverflow <a target="_blank" href="https://stackoverflow.com/questions/69692842/error-message-error0308010cdigital-envelope-routinesunsupported">answer</a> for a quick overview of the major options if we aren't patching it ourselves. Since upgrading dependencies isn't possible here, and we don't want to stay on an old Node version or allow insecure algorithms, we need to dive into the internals of CRA to fix it.  </p>
<h2 id="heading-how-to-eject-out-of-react-scripts">How to Eject Out of React Scripts</h2>
<p>CRA is designed for a zero-configuration experience for React Apps that lets you focus on just working on your business logic. </p>
<p>When you want to start changing configuration, CRA doesn't have a built-in method to override any option. Instead, it offers a command called <code>eject</code> that copies over all the internals of CRA to your project while leaving your yarn/npm commands intact and then removing React scripts from your project entirely. It's a one-way action, so make sure you save the previous version in <code>git</code>. </p>
<pre><code class="lang-shell">$ yarn eject
</code></pre>
<p>This is a huge command that will change lots of files in the <code>config/</code> and <code>scripts/</code> directories as well as your list of packages in <code>package.json</code>. Once you rerun <code>yarn install</code>, make sure to run all your validation commands to make sure everything still works on Node 16 since nothing should have changed in terms of functionality.</p>
<p>Alternatively, if you don't want to try <code>eject</code>, there are also workarounds like:</p>
<ul>
<li>CRACO uses a clever override mechanism to allow you to still use React Scripts while customizing. Read <a target="_blank" href="https://craco.js.org/docs/getting-started/">Getting Started</a> and <a target="_blank" href="https://medium.com/workleap/why-i-built-craco-33ff39f4fc94">Why I built CRACO</a>. Start off with version <code>6.4.5</code> for CRA v4.</li>
<li><a target="_blank" href="https://github.com/ds300/patch-package">patch-package</a> applies specific npm package changes for your project and then you share the patch with your team/project. For this guide, you will patch <code>react-scripts</code> with the modified webpack and config setups.</li>
<li>Forking CRA with your own modifications. This way you can still keep the zero config CRA with no hacks to patch in new functionality, but this might get complicated. Here's a guide I saw online: <a target="_blank" href="https://auth0.com/blog/how-to-configure-create-react-app/">Customizing create-react-app: How to Make Your Own Template</a>.</li>
</ul>
<p>There's also <a target="_blank" href="https://github.com/timarney/react-app-rewired">react-app-rewired</a> for a similar purpose, but it's mostly unmaintained right now and intended for older versions of CRA behind v4.</p>
<h3 id="heading-how-to-add-linter-ignores-for-ejected-files">How to Add Linter Ignores for Ejected Files</h3>
<p>A lot of the new files from the ejected configuration might not follow your existing project's linter rules. Until you're done with the upgrade, I recommend just adding new ignores on the top of the failing files like:</p>
<pre><code class="lang-js"><span class="hljs-comment">/* eslint-disable import/order */</span>

<span class="hljs-comment">// rest of file</span>
...
</code></pre>
<p>Once you're done with the entire tutorial, feel free to go back and try fixing some of the linter issues, but it might be okay to leave these files as-is since you'll rarely go in to change anything.</p>
<h3 id="heading-how-to-fix-absolute-paths-for-jest">How to Fix Absolute Paths for Jest</h3>
<p>In your <code>package.json</code>, the jest <code>"testRunner"</code> option might be encoded to the absolute path that only makes sense on your computer. So, you'll want to change it to a path based on your project's root directory. </p>
<p>While this might work fine for your local development, it will break for any collaborators or cloud computers.</p>
<pre><code class="lang-json">... 
<span class="hljs-string">"jest"</span>: { 
    ... 
    <span class="hljs-attr">"testRunner"</span>: <span class="hljs-string">"/my/computer/path/project_name/node_modules/jest-circus/runner.js"</span>, 
    ... 
}, 
...
</code></pre>
<p>We use the option <code>&lt;rootDir&gt;</code> that is provided by <a target="_blank" href="https://jestjs.io/docs/configuration#rootdir-string">Jest</a>:</p>
<pre><code class="lang-json">... 
<span class="hljs-string">"jest"</span>: { 
    ... 
    <span class="hljs-attr">"testRunner"</span>: <span class="hljs-string">"&lt;rootDir&gt;/node_modules/jest-circus/runner.js"</span>, 
    ... 
}, 
...
</code></pre>
<p>You might not have to do this on all projects, but <code>"modulePaths"</code> may need an update as well:</p>
<pre><code class="lang-json">...
<span class="hljs-string">"jest"</span>: { 
    ... 
    <span class="hljs-attr">"modulePaths"</span>: [ <span class="hljs-string">"/my/computer/path/project_name/src"</span> ] 
    ... 
}, 
...
</code></pre>
<p>Just remove the reference to your computer's absolute path:</p>
<pre><code class="lang-json">...
<span class="hljs-string">"jest"</span>: { 
    ... 
    <span class="hljs-attr">"modulePaths"</span>: [ <span class="hljs-string">"src"</span> ] 
    ... 
}, 
...
</code></pre>
<h3 id="heading-how-to-update-your-dockerfile-and-other-build-processes-with-the-ejected-folders">How to Update your Dockerfile and Other Build Processes with the Ejected Folders</h3>
<p>Make sure to include the new ejected folders, <code>scripts/</code> and  <code>config/</code>,  into your <code>Dockerfile</code> and other build processes you might be using that existed outside CRA. </p>
<p>For example, the Dockerfile will have the additions of new directories that CRA created that we also want to copy over.</p>
<pre><code class="lang-dockerfile">... 
<span class="hljs-keyword">COPY</span><span class="bash"> scripts scripts/</span>
<span class="hljs-keyword">COPY</span><span class="bash"> config config/ </span>
...
</code></pre>
<h2 id="heading-how-to-override-webpack-md4-to-sha256">How to Override Webpack MD4 to SHA256</h2>
<p>Based on this <a target="_blank" href="https://stackoverflow.com/a/78005686">StackOverflow answer</a>, we add to <code>webpack.config.js</code> right before we start defining <code>module.exports</code> to use the relatively more modern and secure SHA256 instead of MD4 that's also built into Webpack:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ... </span>
<span class="hljs-comment">// https://stackoverflow.com/a/78005686 </span>
<span class="hljs-keyword">const</span> crypto = <span class="hljs-built_in">require</span>(<span class="hljs-string">"crypto"</span>); 
<span class="hljs-keyword">const</span> crypto_orig_createHash = crypto.createHash; crypto.createHash = <span class="hljs-function"><span class="hljs-params">algorithm</span> =&gt;</span> crypto_orig_createHash(algorithm == <span class="hljs-string">"md4"</span> ? <span class="hljs-string">"sha256"</span> : algorithm); 
<span class="hljs-comment">// This is the production and development configuration. </span>
<span class="hljs-comment">// It is focused on developer experience, fast rebuilds, and a minimal bundle. </span>
<span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">webpackEnv</span>) 
// ...</span>
</code></pre>
<p>Once you've changed this, the envelope errors should disappear and your validation commands should now work for Node 18.</p>
<h2 id="heading-how-to-upgrade-to-the-latest-version-of-jest">How to Upgrade to the Latest Version of Jest</h2>
<p>The <code>eject</code> also exposes the Babel configuration used for making more recent versions of Jest work correctly. This works great for version 26 but moving the CRA config to the latest version (v29 at the time of writing) has a few more steps. </p>
<p>You should go through <code>v26</code> -&gt; <code>v28</code> -&gt; <code>v29</code> (skipping v27) for all the Jest dependencies. This part is optional if you're happy with CRA v4's Jest 26, but until you eject, you're blocked from upgrading to a recent version of Jest.</p>
<p>I'm skipping Jest 27 because it'll require a change in <code>config/jest/babelTransform.js</code> where you'll have to change <code>module.exports = babelJest.default.createTransformer({</code> to <code>module.exports = babelJest.createTransformer({</code>. This was a bug <a target="_blank" href="https://github.com/jestjs/jest/pull/12399">fixed</a> in version 28. Still, if you want to go through Jest 27 as well, you'll be able to follow the rest of the steps with this change and then optionally reverting it on Jest 28.</p>
<p>I also highly recommend reading the introduction articles for each of the Jest version upgrades:</p>
<ul>
<li><a target="_blank" href="https://jestjs.io/blog/2021/05/25/jest-27">Jest 27: New Defaults for Jest, 2021 edition ⏩</a></li>
<li><a target="_blank" href="https://jestjs.io/blog/2022/04/25/jest-28">Jest 28: Shedding weight and improving compatibility 🫶</a></li>
<li><a target="_blank" href="https://jestjs.io/blog/2022/08/25/jest-29">Jest 29: Snapshot format changes</a></li>
</ul>
<p>Most of the issues come from Jest 28 having many breaking changes, but the rest of the upgrade path is fairly straightforward.</p>
<h3 id="heading-how-to-bump-to-jest-28">How to Bump to Jest 28</h3>
<p>For each upgrade, I recommend doing a find and replace for all the many Jest-related packages in your <code>package.json</code> since the version numbers are all synced. Once you update the numbers, just run <code>$ yarn install</code>:</p>
<pre><code class="lang-json">... 
<span class="hljs-string">"devDependencies"</span>: { 
    ...
    <span class="hljs-attr">"babel-jest"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    ...
    <span class="hljs-attr">"jest"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    <span class="hljs-attr">"jest-circus"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    <span class="hljs-attr">"jest-resolve"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    ...
} 
...
</code></pre>
<h3 id="heading-how-to-explicitly-set-jsdom-as-the-test-environment">How to Explicitly Set <code>jsdom</code> as the Test Environment</h3>
<p>If you try running your tests out of the box with <code>$ yarn test</code>. It'll give you this error:</p>
<pre><code>● Validation <span class="hljs-built_in">Error</span>: 
Test environment jest-environment-jsdom cannot be found. 
Make sure the testEnvironment configuration option points to an existing node <span class="hljs-built_in">module</span>. 
Configuration Documentation: https:<span class="hljs-comment">//jestjs.io/docs/configuration </span>
As <span class="hljs-keyword">of</span> Jest <span class="hljs-number">28</span> <span class="hljs-string">"jest-environment-jsdom"</span> is no longer shipped by <span class="hljs-keyword">default</span>, make sure to install it separately.
</code></pre><p>In Jest 27, Jest <a target="_blank" href="https://jestjs.io/blog/2021/05/25/jest-27">changed the default test environment</a> to be meant for a more lightweight NodeJS backend environment. However, we have a frontend application, so we still want to test with a simulated browser environment that older Jest versions were based off called <a target="_blank" href="https://github.com/jsdom/jsdom">jsdom</a>. </p>
<p>To fix this, add <code>"jest-environment-jsdom"</code> to your dependencies and then run <code>$ yarn install</code>.</p>
<pre><code class="lang-json">... 
<span class="hljs-string">"devDependencies"</span>: { 
    ...
    <span class="hljs-attr">"babel-jest"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    ...
    <span class="hljs-attr">"jest"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    <span class="hljs-attr">"jest-circus"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    <span class="hljs-attr">"jest-resolve"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    <span class="hljs-attr">"jest-environment-jsdom"</span>: <span class="hljs-string">"^28.1.3"</span>, 
    ...
} 
...
</code></pre>
<h3 id="heading-how-to-fix-transformer-return-type-for-process-and-processasync">How to Fix Transformer Return Type for <code>process()</code> and <code>processAsync()</code></h3>
<p>‌‌Now, if you run <code>yarn test</code>, you'll get this:</p>
<pre><code>FAIL  src/App.test.js 
● Test suite failed to run 
● Invalid <span class="hljs-keyword">return</span> value: <span class="hljs-string">`process()`</span> or/and <span class="hljs-string">`processAsync()`</span> method <span class="hljs-keyword">of</span> code transformer found at <span class="hljs-string">"path/in/my/computer"</span> 
should <span class="hljs-keyword">return</span> an object or a <span class="hljs-built_in">Promise</span> resolving to an object. The object must have <span class="hljs-string">`code`</span> property <span class="hljs-keyword">with</span> a string <span class="hljs-keyword">of</span> processed code. 
This error may be caused by a breaking change <span class="hljs-keyword">in</span> Jest <span class="hljs-number">28</span>: https:<span class="hljs-comment">//jestjs.io/docs/upgrading-to-jest28#transformer Code Transformation Documentation: https://jestjs.io/docs/code-transformation</span>
</code></pre><p>This is because the <code>process()</code> functions that used to return a string now expect an object in the format of <code>{ code:</code>old_string_here<code>}</code>. </p>
<p>To fix this, we go into our ejected <code>config/jest</code> folder, and we change the output shape for all our files. For CSS, it's a single line change:</p>
<pre><code class="lang-js"><span class="hljs-comment">// This is a custom Jest transformer turning style imports into empty objects. </span>
<span class="hljs-comment">// http://facebook.github.io/jest/docs/en/webpack.html </span>

<span class="hljs-built_in">module</span>.exports = { 
    process() { 
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">code</span>: <span class="hljs-string">'module.exports = {};'</span> }; 
    }, 
    getCacheKey() { 
        <span class="hljs-comment">// The output is always the same. </span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">'cssTransform'</span>; 
    }, 
};
</code></pre>
<p>and for files, you have to change both branch return statements:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>); 
<span class="hljs-keyword">const</span> camelcase = <span class="hljs-built_in">require</span>(<span class="hljs-string">'camelcase'</span>); 

<span class="hljs-comment">// This is a custom Jest transformer turning file imports into filenames. // http://facebook.github.io/jest/docs/en/webpack.html </span>
<span class="hljs-built_in">module</span>.exports = { 
    process(src, filename) { 
        <span class="hljs-keyword">const</span> assetFilename = <span class="hljs-built_in">JSON</span>.stringify(path.basename(filename)); 
        <span class="hljs-keyword">if</span> (filename.match(<span class="hljs-regexp">/\.svg$/</span>)) { 
            <span class="hljs-comment">// Based on how SVGR generates a component name: </span>
            <span class="hljs-comment">// https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 </span>
            <span class="hljs-keyword">const</span> pascalCaseFilename = camelcase(path.parse(filename).name, { <span class="hljs-attr">pascalCase</span>: <span class="hljs-literal">true</span>, }); 
            <span class="hljs-keyword">const</span> componentName = <span class="hljs-string">`Svg<span class="hljs-subst">${pascalCaseFilename}</span>`</span>; 
            <span class="hljs-keyword">return</span> { <span class="hljs-attr">code</span>: <span class="hljs-string">`const React = require('react')...`</span> <span class="hljs-comment">// pretty long string }; </span>
        }

        <span class="hljs-keyword">return</span> {<span class="hljs-attr">code</span>: <span class="hljs-string">`module.exports = <span class="hljs-subst">${assetFilename}</span>;`</span> }; 
    }, 
};
</code></pre>
<p>Note: As of the time of writing, the error message link to the upgrade guide tutorial <a target="_blank" href="https://github.com/jestjs/jest/issues/15112#issuecomment-2160883936">doesn't work</a>, but you can find the correct link at <a target="_blank" href="https://jest-archive-august-2023.netlify.app/docs/28.x/upgrading-to-jest28/">https://jest-archive-august-2023.netlify.app/docs/28.x/upgrading-to-jest28/</a>. There's also an older <a target="_blank" href="https://web.archive.org/web/20230330085721/https://jestjs.io/docs/28.x/upgrading-to-jest28#transformer">archive link</a> if that doesn't work.</p>
<h3 id="heading-how-to-bump-jest-to-29">How to Bump Jest to 29</h3>
<p>Once all the validation steps are working with Jest 28, the upgrade to 29 should be smoother. Just update your <code>package.json</code> and run <code>$ yarn install</code>:</p>
<pre><code class="lang-json">... 
<span class="hljs-string">"devDependencies"</span>: { ... 
    <span class="hljs-attr">"babel-jest"</span>: <span class="hljs-string">"^29.7.0"</span>, 
    <span class="hljs-attr">"jest"</span>: <span class="hljs-string">"^29.7.0"</span>, 
    <span class="hljs-attr">"jest-circus"</span>: <span class="hljs-string">"^29.7.0"</span>, 
    <span class="hljs-attr">"jest-resolve"</span>: <span class="hljs-string">"^29.7.0"</span>, 
    <span class="hljs-attr">"jest-environment-jsdom"</span>: <span class="hljs-string">"^29.7.0"</span> ... 
} 
...
</code></pre>
<p>At this point, <code>$ yarn test</code> should work correctly with your existing test suite. </p>
<h2 id="heading-how-far-should-i-upgrade-nodejs">How Far Should I Upgrade NodeJS?</h2>
<p>Trying to decide how far ahead to upgrade Node versions can be a tricky question. Following the above steps, I was able to get all the Node versions up until the most recent Node 22 working. </p>
<p>At the time of writing, 18 is a pretty good stopping point in terms of current support and recent ECMAScript support. But if you're looking to decide, then the following three factors are the most important:</p>
<ol>
<li>Library support: Look at all your critical libraries and see if they have a strong preference for a certain version or have breaking issues for more recent versions. Later Node versions are usually better, but sometimes old libraries didn't get the right patches and might block your upgrade.</li>
<li>Support windows: Different Node versions have a window where the maintainers consider it under "Maintenance", "Active", "Current" or "Unsupported", and over time the older versions lose maintenance. The even versions are also designated LTS (Long Term Support), giving support for a long time and what works for most people. The website has a helpful chart for this: <a target="_blank" href="https://nodejs.org/en/about/previous-releases">https://nodejs.org/en/about/previous-releases</a>.</li>
<li>Language feature support: ECMAScript's specification is always evolving with every year, and getting to use the newer syntax with nicer constructs is always a big quality of life upgrade. I love <a target="_blank" href="https://node.green/">https://node.green/</a> which has a table of Node versions against ECMAScript syntax features with code examples for each feature.</li>
</ol>
<p>Due to technologies like <a target="_blank" href="https://babeljs.io/">Babel</a> (bundled with Create React App), you don't need to worry too much about the end users of your website, as newer Node features will just get transpiled to browser-compliant ones.</p>
<h2 id="heading-should-you-still-use-create-react-scripts-what-alternatives-are-there">Should You Still Use Create React Scripts? What Alternatives Are There?</h2>
<p>In this tutorial, I decided to eject out of CRA to access the Webpack and Babel configuration, and many CRA projects have eventually come to do this as well. Maintenance of CRA has nearly stopped while the ecosystem keeps evolving. </p>
<p>Personally, I recommend someone creating a React project today to try newer alternatives like <a target="_blank" href="https://vitejs.dev/guide/">Vite</a> or <a target="_blank" href="https://parceljs.org/recipes/react/">Parcel</a> which have a nice starter applications that are simple and easier to understand. Unfortunately, they might not have as many bells and whistles as what CRA gives, but it's good enough for almost all practical modern development. </p>
<p>In the context of education, my old tutorials used <code>create-react-app</code>, and it was such a major help, but my newer ones will use Vite.</p>
<p>Still, your application and development experience might be very different than mine. I recommend reading and learning from these resources to form your own perspective:</p>
<ul>
<li>GitHub <a target="_blank" href="https://github.com/reactjs/react.dev/pull/5487">issue</a> with 200+ responses and 1000s of reactions on if Create React App should be replaced with Vite on the official docs. It also has a <a target="_blank" href="https://github.com/reactjs/react.dev/pull/5487#issuecomment-1409720741">note</a> from the maintainer side of CRA explaining a lot of important context that is highly worth reading. Parcel's maintainer made a really good <a target="_blank" href="https://github.com/reactjs/react.dev/pull/5487#issuecomment-1399360209">comment</a> as well.</li>
<li>Some interesting comments (<a target="_blank" href="https://github.com/reactjs/react.dev/pull/5487#issuecomment-1423368130">one</a>, <a target="_blank" href="https://github.com/facebook/create-react-app/issues/13598">two</a>) on how CRA created a simple and easy to use React experience out of the box without worrying about setup hell and focusing on the actual application.</li>
<li><a target="_blank" href="https://medium.com/@vivekdwivedi/the-end-of-an-era-react-team-no-longer-recommends-create-react-app-f2fe6e842d13">News article</a> explaining that the React Team has chosen to stop recommending Create React App, along with some context behind this and future alternatives.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>At this point, you should be able to run all your validation scripts and have an application that works with Node 18+ and Jest 29+.</p>
<p>In an ideal world, you'd run into the same hurdles as I did, and everything would be working. Realistically, everyone's application is different, and the internet is full of numerous developers who have gone through this upgrade process with various issues. </p>
<p>I highly suggest making Google, StackOverflow, GitHub, and official library documentation your best friends in the process, and I wish you good luck!</p>
<h3 id="heading-alternatively-how-to-upgrade-to-react-scripts-501">Alternatively: How to Upgrade to React Scripts 5.0.1</h3>
<p>This is beyond the scope of this tutorial, so I'll be briefer here – but here's a little information to get you started. </p>
<p>I suggest starting with the official docs changelog for CRA v5 that includes all the major changes as well as some version upgrade instructions: <a target="_blank" href="https://github.com/facebook/create-react-app/blob/main/CHANGELOG.md">https://github.com/facebook/create-react-app/blob/main/CHANGELOG.md</a>.</p>
<p>Bumping the version is fairly easy, setting <code>react-scripts</code> to <code>5.0.1</code> in your <code>package.json</code>, but then the hard part is all the breaking changes.</p>
<p>The most complicated part of the upgrade is the upgrade to Webpack 5 from Webpack 4. Read Webpack's official guide <a target="_blank" href="https://webpack.js.org/migrate/5/">To v5 from v4</a> which has a nice overview, and look around the internet for guides for this upgrade. A few more hurdles that you might come across:</p>
<ul>
<li>For <code>@babel/helper-compilation-targets: 'opera_mobile' is not a valid target</code> you can add <code>"not op_mob &gt;= 1"</code> to the <code>browserslist</code> array as suggested by this <a target="_blank" href="https://github.com/babel/babel/issues/16171#issuecomment-2015227043">comment</a> on the babel issue tracker. The other comments may also be helpful.</li>
<li>You'll probably have to access the CRA internals for many steps using either React Scripts <code>eject</code> or something like <a target="_blank" href="https://craco.js.org/docs/getting-started/">CRACO version 7</a>.</li>
<li>Webpack 5 has a breaking change which removes support for a lot of browser specific APIs like <code>os</code>, <code>http</code>, <code>util</code> that worked in Webpack 4 that your application may have been using. You can either add all of them back using a package like <a target="_blank" href="https://github.com/Richienb/node-polyfill-webpack-plugin">node-polyfill-webpack-plugin</a> or add imports piecewise following this <a target="_blank" href="https://gist.github.com/ef4/d2cf5672a93cf241fd47c020b9b3066a">cheatsheet</a>.</li>
<li>For Babel eslint parser load errors like <code>Error: Failed to load parser 'babel-eslint' declared in '.eslintrc': Cannot find module 'babel-eslint'</code> , you might have to swap out <code>"parser": "babel-eslint"</code> with <code>"parser": "@babel/eslint-parser"</code> in your <code>.eslintrc</code> and install <code>"@babel/eslint-parser"</code> in your <code>package.json</code>. This might be caused by the move of <code>babel-eslint</code> to the <code>@babel</code> monorepo, see <a target="_blank" href="https://babeljs.io/blog/2020/07/13/the-state-of-babel-eslint">The State of babel-eslint</a> for more info.</li>
<li>Some filetype imports that used to work with Webpack 4 will start breaking with <code>Module build failed: UnhandledSchemeError</code> (the actual error took several screens in my Terminal). The solution here will be fixing the prefixes of the files you import, and for external files that were being included, see if you can find a npm package for it. For example, one of my projects stopped using <code>semantic-ui.min.css</code> downloaded from the internet, and instead I added <code>"semantic-ui-css": "^2.5.0"</code> to my <code>package.json</code>. Definitely read this <a target="_blank" href="https://github.com/webpack/webpack/issues/12792">issue</a> thread in the webpack repo for more information.</li>
</ul>
<p>After all of these I was able to get <code>yarn test</code> and <code>yarn build</code> to succeed, but <code>yarn start</code> still had too many issues and I pivoted to making CRA v4 work instead. Hopefully you might get further than I did.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Test Your Express.js and Mongoose Apps with Jest and SuperTest ]]>
                </title>
                <description>
                    <![CDATA[ By Rakesh Potnuru Testing is a vital part of software development. The sooner you start testing, the better.  In this article, I'll show you how to write tests for your NodeJs/ExpressJS and MongoDB/Mongoose applications with Jest and Supertest. Let's... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-test-in-express-and-mongoose-apps/</link>
                <guid isPermaLink="false">66d460c9787a2a3b05af43f6</guid>
                
                    <category>
                        <![CDATA[ Express JS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mongoose ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 27 Sep 2022 23:26:16 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/how-to-write-tests.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Rakesh Potnuru</p>
<p>Testing is a vital part of software development. The sooner you start testing, the better. </p>
<p>In this article, I'll show you how to write tests for your NodeJs/ExpressJS and MongoDB/Mongoose applications with <strong>Jest</strong> and <strong>Supertest</strong>.</p>
<h2 id="heading-lets-get-started">Let's get started</h2>
<p>First let's set up a demo Express.js app.</p>
<p>Let's say we are building a backend REST API for an eCommerce application.</p>
<p>This app should:</p>
<ul>
<li>Get all the products</li>
<li>Get a product by id</li>
<li>Add product(s) to the database</li>
<li>Delete product(s) from the database</li>
<li>Update product information</li>
</ul>
<h2 id="heading-expressjs-app-set-up">Express.js App Set Up</h2>
<h3 id="heading-step-1-project-set-up">Step 1: Project set up</h3>
<p>First, create a folder and start a blank application with <code>npm</code>.</p>
<pre><code class="lang-bash">npm init
</code></pre>
<p>Fill all the details it asks for.</p>
<p>Then, install <code>express</code>, <code>mongoose</code>, <code>axios</code> and <code>dotenv</code> with the following command:</p>
<pre><code class="lang-bash">npm i express mongoose axios dotenv
</code></pre>
<p>Here's a link to the <a target="_blank" href="https://github.com/itsrakeshhq/jest-tests-demo/blob/a1725cb3379f78a03cf8d3d4cfa22127469e8b50/package.json">package.json</a> on my GitHub.</p>
<h3 id="heading-step-2-create-the-boilerplate">Step 2: Create the boilerplate</h3>
<p>Let's create all the folders and files and then fill them with some boilerplate code.</p>
<p>This is how your folder hierarchy should look:</p>
<pre><code class="lang-bash">.
├── controllers
│   └── product.controller.js
├── models
│   └── product.model.js
├── routes
│   └── product.route.js
├── package-lock.json
├── package.json
├── .env
├── app.js
└── server.js
</code></pre>
<p>Use these files' code by copying and pasting. Analyze the code and flow as best you can.</p>
<ul>
<li><code>[product.controller.js](https://github.com/itsrakeshhq/jest-tests-demo/blob/main/controllers/product.controller.js)</code></li>
<li><code>[product.model.js](https://github.com/itsrakeshhq/jest-tests-demo/blob/main/models/product.model.js)</code></li>
<li><code>[product.route.js](https://github.com/itsrakeshhq/jest-tests-demo/blob/main/routes/product.route.js)</code></li>
<li><code>[app.js](https://github.com/itsrakeshhq/jest-tests-demo/blob/main/app.js)</code> </li>
<li><code>[server.js](https://github.com/itsrakeshhq/jest-tests-demo/blob/main/server.js)</code></li>
</ul>
<h3 id="heading-step-3-database-setup">Step 3: Database setup</h3>
<p>I advise using two databases for a project—one for testing, the other for development. But just one database will be sufficient for learning purposes.</p>
<p>First, create a <a target="_blank" href="https://mongodb.com">MongoDB</a> account or log in.</p>
<p>Then create a new project. Give it a name and press the <strong>Next</strong> button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Screenshot-2022-09-26-205148.png" alt="Naming the project" width="600" height="400" loading="lazy">
<em>Naming the project</em></p>
<p>Then click <strong>Create Project</strong> after that.</p>
<p>We must create a database in the following window by selecting a cloud provider, a location, and specs. So press <strong>Build a Database</strong> to get going.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Screenshot-2022-09-26-205911.png" alt="Build a database" width="600" height="400" loading="lazy">
<em>Build a database</em></p>
<p>Choose "Shared" because it is sufficient for learning purposes. And then click <strong>Create</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Screenshot-2022-09-26-211701.png" alt="Choose a deployment option" width="600" height="400" loading="lazy">
<em>Choose a deployment option</em></p>
<p>Next, select "aws" as your cloud provider and the region that is closest to you. Following your selection, click <strong>Create Cluster</strong>.</p>
<p>The cluster's formation will take some time. Create a user to access your database in the meanwhile.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Screenshot-2022-09-26-212537.png" alt="Create Superuser" width="600" height="400" loading="lazy">
<em>Create Superuser</em></p>
<p>Choose "My Local Environment" because we are developing our application. You can then add an IP addresses. To conclude, click <strong>Close</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Screenshot-2022-09-26-213347.png" alt="Add IP addresses" width="600" height="400" loading="lazy">
<em>Add IP addresses</em></p>
<p>You will receive a URI string after the database is set up, which we'll use to connect to the database. The string appears as follows:</p>
<pre><code class="lang-bash">mongodb+srv://&lt;YOUR_USERNAME&gt;:&lt;YOUR_PASSWORD&gt;@&lt;YOUR_CLUSTER_URL&gt;/&lt;DATABASE_NAME&gt;?retryWrites=<span class="hljs-literal">true</span>&amp;w=majority
</code></pre>
<p>Put this string in the <code>.env</code> file.</p>
<pre><code class="lang-bash">MONGODB_URI=your database string
</code></pre>
<p>Now we're ready to start testing our app.</p>
<h2 id="heading-how-to-write-tests-with-jest-and-supertest">How to Write Tests with Jest and SuperTest</h2>
<h3 id="heading-step-1-install-packages">Step 1: Install packages</h3>
<p>You need three npm packages to begin writing tests: <code>jest</code>, <code>supertest</code>, and <code>cross-env</code>. You can install them like this:</p>
<pre><code class="lang-bash">npm i jest supertest cross-env
</code></pre>
<ul>
<li><code>jest</code>: Jest is a framework for testing JavaScript code. Unit testing is the main usage of it.</li>
<li><code>supertest</code>: Using Supertest, we can test endpoints and routes on HTTP servers.</li>
<li><code>cross-env</code>: You can set environmental variables inline within a command using cross-env.</li>
</ul>
<h3 id="heading-step-2-add-test-script">Step 2: Add test script</h3>
<p>Open your <code>package.json</code> file and add the test script to the scripts.</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"cross-env NODE_ENV=test jest --testTimeout=5000"</span>,
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node server.js"</span>,
    <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"nodemon server.js"</span>
},
</code></pre>
<p>In this case, we're using <code>cross-env</code> to set environment variables, <code>jest</code> to execute test suites, and <code>testTimeout</code> is set to <code>5000</code> because certain requests might take a while to finish.</p>
<h3 id="heading-step-3-start-writing-tests">Step 3: Start writing tests</h3>
<p>First, create a folder called <code>tests</code> at the application's root, and then create a file there called <code>product.test.js</code>. Jest searches for the folder <code>tests</code> at the project's root when you do <code>npm run test</code>. As a result, you must place your test files in the <code>tests</code> folder.</p>
<p>Next, import the <code>supertest</code> and <code>mongoose</code> packages into the test file.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);
<span class="hljs-keyword">const</span> request = <span class="hljs-built_in">require</span>(<span class="hljs-string">"supertest"</span>);
</code></pre>
<p>Import <code>dotenv</code> to load environment variables, and import <code>app.js</code> as that is where our application starts.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);
<span class="hljs-keyword">const</span> request = <span class="hljs-built_in">require</span>(<span class="hljs-string">"supertest"</span>);
<span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../app"</span>);

<span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();
</code></pre>
<p>You'll need to connect and disconnect the database before and after each test (because we don't require the database once testing is complete).</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/* Connecting to the database before each test. */</span>
beforeEach(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> mongoose.connect(process.env.MONGODB_URI);
});

<span class="hljs-comment">/* Closing database connection after each test. */</span>
afterEach(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> mongoose.connection.close();
});
</code></pre>
<p>Now you can write your first unit test.</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">"GET /api/products"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should return all products"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).get(<span class="hljs-string">"/api/products"</span>);
    expect(res.statusCode).toBe(<span class="hljs-number">200</span>);
    expect(res.body.length).toBeGreaterThan(<span class="hljs-number">0</span>);
  });
});
</code></pre>
<p>In the above code, </p>
<ul>
<li>We use <code>describe</code> to describe the unit test. Even though it is not required, it will be useful to identify tests in test results.</li>
<li>In <code>it</code>, we write the actual test code. Tell what the test performs in the first argument, and then in the second argument, write a callback function that contains the test code.</li>
<li>In the callback function, the request is sent to the endpoint first, and the expected and actual responses are then compared. The test passes if both answers match, else, it fails. ✨ As simple as that ✨.</li>
</ul>
<p>You can write tests for all the endpoints in the same manner.</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">"GET /api/products/:id"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should return a product"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).get(
      <span class="hljs-string">"/api/products/6331abc9e9ececcc2d449e44"</span>
    );
    expect(res.statusCode).toBe(<span class="hljs-number">200</span>);
    expect(res.body.name).toBe(<span class="hljs-string">"Product 1"</span>);
  });
});

describe(<span class="hljs-string">"POST /api/products"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should create a product"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).post(<span class="hljs-string">"/api/products"</span>).send({
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Product 2"</span>,
      <span class="hljs-attr">price</span>: <span class="hljs-number">1009</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"Description 2"</span>,
    });
    expect(res.statusCode).toBe(<span class="hljs-number">201</span>);
    expect(res.body.name).toBe(<span class="hljs-string">"Product 2"</span>);
  });
});

describe(<span class="hljs-string">"PUT /api/products/:id"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should update a product"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)
      .patch(<span class="hljs-string">"/api/products/6331abc9e9ececcc2d449e44"</span>)
      .send({
        <span class="hljs-attr">name</span>: <span class="hljs-string">"Product 4"</span>,
        <span class="hljs-attr">price</span>: <span class="hljs-number">104</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">"Description 4"</span>,
      });
    expect(res.statusCode).toBe(<span class="hljs-number">200</span>);
    expect(res.body.price).toBe(<span class="hljs-number">104</span>);
  });
});

describe(<span class="hljs-string">"DELETE /api/products/:id"</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">"should delete a product"</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).delete(
      <span class="hljs-string">"/api/products/6331abc9e9ececcc2d449e44"</span>
    );
    expect(res.statusCode).toBe(<span class="hljs-number">200</span>);
  });
});
</code></pre>
<p>Then run <code>npm run test</code> to run the test suites (suite - test file).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-428.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test results</em></p>
<p>And that's it! You now know how to test your Express/Mongoose apps with Jest and SuperTest.</p>
<p>Now go forth and create new tests for your apps. :)</p>
<p>If you have any questions, feel free to message me on <a target="_blank" href="https://twitter.com/rakesh_at_tweet">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to split the deployment of your front end and back end with the help of Consumer Driven Contract Testing ]]>
                </title>
                <description>
                    <![CDATA[ By Mario Fernandez Consumer driven contract testing is a great way to improve the reliability of interconnected systems. Integration testing becomes way easier and more self contained. It opens the door for independent deployments, and leads to faste... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/split-frontend-backend-deployment-with-cdcs/</link>
                <guid isPermaLink="false">66d460f27df3a1f32ee7f893</guid>
                
                    <category>
                        <![CDATA[ CircleCI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ continuous delivery ]]>
                    </category>
                
                    <category>
                        <![CDATA[ contract-testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ pact ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 12 Nov 2019 08:06:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/11/simple-cdc-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Mario Fernandez</p>
<p><a target="_blank" href="https://www.thoughtworks.com/de/radar/techniques/consumer-driven-contract-testing">Consumer driven contract testing</a> is a great way to improve the reliability of interconnected systems. Integration testing becomes way easier and more self contained. It opens the door for independent deployments, and leads to faster iterations and more granular feedback. Unlike your insurance, it doesn't have any fine print. This article is about setting it up in a delivery pipeline, in the context of doing <a target="_blank" href="https://continuousdelivery.com/">continuous delivery</a>.</p>
<p>I want to show how <em>Contract Tests</em> help split the deployment of the front end and the back end of a small application. I have a React client and a Spring Boot backend written in Kotlin.</p>
<h2 id="heading-what-is-a-contract-test">What is a Contract Test?</h2>
<p>I am not talking about <a target="_blank" href="https://en.wikipedia.org/wiki/Smart_contract">smart contracts</a>. There is no blockchain whatsoever in this article. Sorry for that (Contract Tests for Smart Contracts sounds like a conference talk that the world badly needs, though!).</p>
<p>In a nutshell, a Contract Test is a specification of the interactions between a consumer and a provider. In our case, the communication happens using REST. The consumer defines the actions sent to the provider and the responses that will be returned. In our case, the frontend is the consumer and the backend is the provider. A <em>contract</em> is generated. Both sides test against this contract.</p>
<p>It is not really about any particular technology. There are a bunch of different frameworks, but some simple scripts could do the trick.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/simple-cdc.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-why-have-it-as-part-of-the-delivery-pipeline">Why have it as part of the delivery pipeline?</h3>
<p>First of all, running these tests continuously ensures that they keep working at all times. The big benefit, however, is that we can separate the deployment of the front end and back end. If both sides are fulfilling the contract, it is likely that they work together correctly. Thus, we can consider avoiding expensive integrated tests. They tend to work pretty badly anyways.</p>
<h2 id="heading-setting-up-some-contracts">Setting up some contracts</h2>
<p>There are two sides to set up, consumer and provider. The tests will run in the pipelines that build the front end and the back end, respectively. We are going to use the <a target="_blank" href="https://docs.pact.io/">Pact framework</a> for our examples, which is the tool that I am most familiar with. Because of that, I tend to use pact and contract interchangeably. Our pipelines are written for <a target="_blank" href="https://circleci.com/">CircleCI</a>, but they should be fairly easy to port to other CI Tools.</p>
<h3 id="heading-the-consumer-side">The consumer side</h3>
<p>As mentioned, the consumer leads the creation of the contract. Having the client driving this might sound counterintuitive. Often, APIs are created before the clients that will use them. Flipping it around is a nice habit to get into. It forces you to really think in terms of what the client will actually do, instead of bikeshedding a super generic API that will never need most of its features. You should give it a try!</p>
<p>The pact is defined through interactions specified in unit tests. We specify what we expect to be sent to the back end, and then use the client code to trigger requests. Why? We can compare expectations against actual requests, and fail the tests if they don't match. </p>
<p>Let's have a look at an example. We are using <a target="_blank" href="https://jestjs.io/">Jest</a> to run the tests. We'll start with some initialization code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">'path'</span>
<span class="hljs-keyword">import</span> Pact <span class="hljs-keyword">from</span> <span class="hljs-string">'pact'</span>

<span class="hljs-keyword">const</span> provider = <span class="hljs-function">() =&gt;</span>
  Pact({
    port: <span class="hljs-number">8990</span>,
    log: path.resolve(process.cwd(), <span class="hljs-string">'logs'</span>, <span class="hljs-string">'pact.log'</span>),
    dir: path.resolve(process.cwd(), <span class="hljs-string">'pacts'</span>),
    spec: <span class="hljs-number">2</span>,
    consumer: <span class="hljs-string">'frontend'</span>,
    provider: <span class="hljs-string">'backend'</span>
  })

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> provider
</code></pre>
<p>Then we have the code for an actual test. The test consists of two parts. First we define the expected interaction. This is not very different from mocking an http library, with something like <a target="_blank" href="https://github.com/ctimmerm/axios-mock-adapter">axios</a>. It specifies the request that we will send (URL, headers, body and so forth), and the response that we will get.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> interaction: InteractionObject = {
  state: <span class="hljs-string">'i have a list of recipes'</span>,
  uponReceiving: <span class="hljs-string">'a request to get recipes'</span>,
  withRequest: {
    method: <span class="hljs-string">'GET'</span>,
    path: <span class="hljs-string">'/rest/recipes'</span>,
    headers: {
      Accept: <span class="hljs-string">'application/json'</span>,
      <span class="hljs-string">'X-Requested-With'</span>: <span class="hljs-string">'XMLHttpRequest'</span>
    }
  },
  willRespondWith: {
    status: <span class="hljs-number">200</span>,
    headers: { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json; charset=utf-8'</span> },
    body: [
      {
        id: <span class="hljs-number">1</span>,
        name: <span class="hljs-string">'pasta carbonara'</span>,
        servings: <span class="hljs-number">4</span>,
        duration: <span class="hljs-number">35</span>
      }
    ]
  }
}
</code></pre>
<p>Then we have the test itself, where we call the actual client code that will trigger the request. I like to encapsulate these requests in services that convert the raw response into the domain model that will be used by the rest of the app. Through some assertions, we make sure that the data that we are delivering from the service is exactly what we expect.</p>
<pre><code class="lang-typescript">it(<span class="hljs-string">'works'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> recipeList()

  expect(response.data.length).toBeGreaterThan(<span class="hljs-number">0</span>)
  expect(response.data[<span class="hljs-number">0</span>]).toEqual({
    id: <span class="hljs-number">1</span>,
    name: <span class="hljs-string">'pasta carbonara'</span>,
    servings: <span class="hljs-number">4</span>,
    duration: <span class="hljs-number">35</span>
  })
})
</code></pre>
<p>Note that even if <code>recipeList</code> is properly typed with <code>TypeScript</code>, that won't help us here. Types disappear at runtime, so if the method is returning an invalid <code>Recipe</code> we won't realize it, unless we explicitly test for it.</p>
<p>Finally we need to define some extra methods that will ensure that the interactions are verified. If there are interactions missing, or they don't look like they should, the test will fail here. After that, all that remains is writing the pact to disk.</p>
<pre><code class="lang-typescript">beforeAll(<span class="hljs-function">() =&gt;</span> provider.setup())
afterEach(<span class="hljs-function">() =&gt;</span> provider.verify())
afterAll(<span class="hljs-function">() =&gt;</span> provider.finalize())
</code></pre>
<p>In the end, the pact gets generated as a JSON file, reflecting all the interactions that we have defined throughout all our tests.</p>
<h4 id="heading-flexible-matching">Flexible matching</h4>
<p>Our pact thus far is specifying the exact values that it will get from the backend. That won't be maintainable in the long run. Certain things are inherently harder to pin down to exact values (for example, dates). </p>
<p>A pact that breaks constantly will lead to frustration. We are going through this whole process to make our life easier, not harder. We'll avoid that by using <a target="_blank" href="https://docs.pact.io/getting_started/matching">matchers</a>. We can be more flexible and define how things will look like, without having to provide exact values. Let's rewrite our previous body:</p>
<pre><code class="lang-typescript">willRespondWith: {
  status: <span class="hljs-number">200</span>,
  headers: { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json; charset=utf-8'</span> },
  body: Matchers.eachLike({
    id: Matchers.somethingLike(<span class="hljs-number">1</span>),
    name: Matchers.somethingLike(<span class="hljs-string">'pasta carbonara'</span>),
    servings: Matchers.somethingLike(<span class="hljs-number">4</span>),
    duration: Matchers.somethingLike(<span class="hljs-number">35</span>)
  })
}
</code></pre>
<p>You can be more specific. You can set the expected length of a list, use regexes and a bunch of other things.</p>
<h4 id="heading-integrating-it-in-the-pipeline">Integrating it in the pipeline</h4>
<p>The pact tests rely on an external process, and having multiple tests hitting it can lead to non deterministic behavior. One solution is to run all the tests sequentially:</p>
<pre><code class="lang-bash">npm <span class="hljs-built_in">test</span> --coverage --runInBand
</code></pre>
<p>If you want to run the pact tests independently, we can build our own task to run them separately:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-attr">"pact"</span>: <span class="hljs-string">"jest --transform '{\"^.+\\\\.ts$\": \"ts-jest\"}' --testRegex '.test.pact.ts$' --runInBand"</span>
}
</code></pre>
<p>Which will become an extra step in our pipeline:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">check:</span>
    <span class="hljs-attr">working_directory:</span> <span class="hljs-string">~/app</span>

    <span class="hljs-attr">docker:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">image:</span> <span class="hljs-string">circleci/node:12.4</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">checkout</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">linter:js</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">test</span> <span class="hljs-string">--coverage</span> <span class="hljs-string">--runInBand</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">pact</span>
</code></pre>
<h4 id="heading-storing-the-pact">Storing the pact</h4>
<p>Our pact is a json file that we are going to commit directly in the frontend repository, after running the tests locally. I've found that this tends to work well enough. Making the pipeline itself commit the pact to <code>git</code> does not seem to be necessary.<br>We'll get to extending the pact and in a second.</p>
<h3 id="heading-the-provider-side">The provider side</h3>
<p>At this point we have a working pact, that is being verified by the consumer. But that is only half of the equation. Without a verification from the provider side, we haven't accomplished anything. Maybe even less than that, because we might get a false sense of security!</p>
<p>To do this, we are going to start the back end as a development server and run the pact against it. There is a <code>gradle</code> provider that takes care of this. We need to configure it and provide a way of finding the pact (which is stored in the front end repository). You can fetch the pact from the internet, or from a local file, whichever is more convenient.</p>
<pre><code class="lang-groovy">buildscript {
    dependencies {
        classpath 'au.com.dius:pact-jvm-provider-gradle_2.12:3.6.14'
    }
}

apply plugin: 'au.com.dius.pact'

pact {
    serviceProviders {
        api {
            port = 4003

            hasPactWith('frontend') {
                pactSource = url('https://path-to-the-pact/frontend-backend.json')
                stateChangeUrl = url("http://localhost:$port/pact")
            }
        }
    }
}
</code></pre>
<p>What remains is starting the server and running the pact against it, which we do with a small script:</p>
<pre><code class="lang-bash">goal_test-<span class="hljs-function"><span class="hljs-title">pact</span></span>() {
  <span class="hljs-built_in">trap</span> <span class="hljs-string">"stop_server"</span> EXIT

  goal_build
  start_server

  ./gradlew pactVerify
}

<span class="hljs-function"><span class="hljs-title">start_server</span></span>() {
  artifact=app.jar
  port=4003

  <span class="hljs-keyword">if</span> lsof -i -P -n | grep LISTEN | grep :<span class="hljs-variable">$port</span> &gt; /dev/null ; <span class="hljs-keyword">then</span>
    <span class="hljs-built_in">echo</span> <span class="hljs-string">"Port[<span class="hljs-variable">${port}</span>] is busy. Server won't be able to start"</span>
    <span class="hljs-built_in">exit</span> 1
  <span class="hljs-keyword">fi</span>

  nohup java -Dspring.profiles.active=pact -jar ./build/libs/<span class="hljs-variable">${artifact}</span> &gt;/dev/null 2&gt;&amp;1 &amp;

  <span class="hljs-comment"># Wait for server to answer requests</span>
  until curl --output /dev/null --silent --fail http://localhost:<span class="hljs-variable">$port</span>/actuator/health; <span class="hljs-keyword">do</span>
    <span class="hljs-built_in">printf</span> <span class="hljs-string">'.'</span>
    sleep 3
  <span class="hljs-keyword">done</span>
}

<span class="hljs-function"><span class="hljs-title">stop_server</span></span>() {
  pkill -f <span class="hljs-string">'java -Dspring.profiles.active=pact -jar'</span>
}
</code></pre>
<h4 id="heading-fixtures">Fixtures</h4>
<p>If you are running your back end in development mode, it will have to deliver some data, so that the contract is fulfilled. Even if we are not using exact matching, we have to return something, otherwise it won't be possible to verify it.</p>
<p>You can use mocks, but I've found that avoiding them as much as possible leads to more trustworthy results. Your app is closer to what will happen in production. So what other options are there? Remember that when we were defining interactions, we had a <code>state</code>. That's the cue for the provider. One way of using it is the <code>stateChangeUrl</code>. We can provide a special controller to initialize our back end based on the <code>state</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> PATH = <span class="hljs-string">"/pact"</span>

<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Pact</span></span>(<span class="hljs-keyword">val</span> state: String)

<span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping(PATH, consumes = [MediaType.APPLICATION_JSON_VALUE])</span>
<span class="hljs-meta">@ConditionalOnExpression(<span class="hljs-meta-string">"\${pact.enabled:true}"</span>)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PactController</span></span>(<span class="hljs-keyword">val</span> repository: RecipeRepository) {
    <span class="hljs-meta">@PostMapping</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setup</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> body: <span class="hljs-type">Pact</span>)</span></span>: ResponseEntity&lt;Map&lt;String,String&gt;&gt; {
        <span class="hljs-keyword">when</span>(body.state) {
            <span class="hljs-string">"i have a list of recipes"</span> -&gt; initialRecipes()
            <span class="hljs-keyword">else</span> -&gt; doNothing()
        }

        <span class="hljs-keyword">return</span> ResponseEntity.ok(mapOf())
    }
}
</code></pre>
<p>Note that this controller is only active for a specific profile, and won't exist outside of it.</p>
<h4 id="heading-integrating-it-in-the-pipeline-1">Integrating it in the pipeline</h4>
<p>As with the provider, we will run the check as part of our pipeline</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-number">2</span>
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>

    <span class="hljs-attr">working_directory:</span> <span class="hljs-string">~/app</span>

    <span class="hljs-attr">docker:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">image:</span> <span class="hljs-string">circleci/openjdk:8-jdk</span>

    <span class="hljs-attr">steps:</span>

      <span class="hljs-bullet">-</span> <span class="hljs-string">checkout</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">./go</span> <span class="hljs-string">linter-kt</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">./go</span> <span class="hljs-string">test-unit</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">./go</span> <span class="hljs-string">test-pact</span>
</code></pre>
<p>There is a slight difference, though. Our contract gets generated by the consumer. That means that a change in the front end could lead to a pact that does not verify properly anymore, even though no code was changed in the back end. So ideally, a change in the pact should trigger the back end pipeline as well. I haven't found a way to represent this elegantly in <em>CircleCI</em>, unlike say <a target="_blank" href="https://concourse-ci.org/">ConcourseCI</a>.</p>
<h2 id="heading-how-the-contract-influences-the-relationship-between-front-end-and-back-end">How the contract influences the relationship between front end and back end</h2>
<p>It's nice that we got this set up. <a target="_blank" href="https://en.wiktionary.org/wiki/never_change_a_running_system">Never touch a running system</a>, right? Well, we might! After all, quick change is why we invest in all this tooling. How would you introduce a change that requires extending the API?</p>
<ol>
<li>We start with the client. We want to define what the client will get that is not there yet. As we learned, we do that through a test in the front end that defines the expectation for the new route, or the new fields. That will create a new version of the pact.</li>
<li>Note that at this point the back end <em>does not</em> fulfill the pact. A new deployment of the back end will fail. But also, the <em>existing</em> backend does not fulfill the pact either right now. The change you introduced has to be backwards compatible. The front end should not be relying on the changes, either.</li>
<li>Now it's time to fulfill the new pact from the back end side. If this takes a long time, you will block your deployment process, which is not good. Consider doing smaller increments in that case. Anyways, you've got to implement the new functionality. The pact test will verify that your change is what's actually expected.</li>
<li>Now that the back end is providing the new functionality, you can freely integrate it in your front end.</li>
</ol>
<p>This flow can get a bit awkward in the beginning. It is really important to work with the smallest quantum of functionality. You don't want to block your deployment process.</p>
<h2 id="heading-next-steps">Next steps</h2>
<p>For the integration between your own front end and back end I have found this setup to be sufficient in practice. However, as complexity grows, versioning will become important. You'll want to help multiple teams collaborate more easily. For that, we can use a <a target="_blank" href="https://docs.pact.io/pact_broker">broker</a>. This is a lot harder to implement, so you should ask yourself if you really need it. Don't fix problems that you don't have yet.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>To summarize, this is the setup we arrived at:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/pipelines-full.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Think about all the time you have spent writing tests to check that your back end is sending the right data. That is a lot more convenient to do with a contract. Moreover, releasing front end and back end independently means being faster, releasing smaller pieces of functionality. It might feel scary at first, but you will realize that you actually are much more aware of what's going out that way.</p>
<p>Once you have adopted this for one service, there is no reason not to do it for all of them. I really don't miss running costly end to end test suites just to verify that my back end is working. Here is the code that I used in the examples for the <a target="_blank" href="https://github.com/sirech/cookery2-frontend">front end</a> and the <a target="_blank" href="https://github.com/sirech/cookery2-backend">back end</a>. It is a full running (albeit small) application. Good luck with your contracts!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Test React Components: the Complete Guide ]]>
                </title>
                <description>
                    <![CDATA[ By Mohammad Iqbal When I first started learning to test my apps back in the day, I would get very frustrated with the different types, styles and technologies used for testing, along with the disbanded array of blog posts, tutorials and articles. I f... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/testing-react-hooks/</link>
                <guid isPermaLink="false">66d45f4547a8245f78752a6a</guid>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react testing library ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 11 Jul 2019 21:18:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/photo-1562679817-2aac4f5581ec.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Mohammad Iqbal</p>
<p>When I first started learning to test my apps back in the day, I would get very frustrated with the different types, styles and technologies used for testing, along with the disbanded array of blog posts, tutorials and articles. I found this to be true as well for React testing. </p>
<p>So I decided to just write a complete React testing guide in one article. </p>
<p>Complete Guide, huh, are you going to cover every possible testing scenario? Of course not. However, it will be a complete foundational guide to testing and will be enough to build off of for most other edge cases.</p>
<p>Also I have curated an extensive collection of blog posts, articles and tutorials in the further reading section at the end that should give you enough knowledge to be in the top 10% of developers in terms of testing.</p>
<p>You can find the completed project here:</p>
<p><a target="_blank" href="https://github.com/iqbal125/react-hooks-testing-complete">https://github.com/iqbal125/react-hooks-testing-complete</a>  </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<p>     <strong>Theory</strong></p>
<ul>
<li>What is Testing?   </li>
<li>Why Test? </li>
<li>What to Test? </li>
<li>What Not to Test? </li>
<li>How I test</li>
<li>Shallow vs Mount</li>
<li><p>unit vs integration vs e to e</p>
<p> <strong>Preliminary Info</strong></p>
</li>
<li><p>a few odds and ends</p>
<p>  <strong>Enzyme</strong></p>
</li>
<li><p>Enyme Setup</p>
</li>
<li>react-test-renderer</li>
<li>snapshot testing</li>
<li><p>testing implementation details</p>
<p>  <strong>React Testing Library</strong></p>
</li>
<li><p>useState and props </p>
</li>
<li>useReducer()</li>
<li>useContext()</li>
<li>Controlled component Forms</li>
<li><p>useEffect() and Axios API requests</p>
<p>  <strong>Cypress</strong> </p>
</li>
<li><p>A complete end to end test</p>
<p>  <strong>Continuous Integration</strong></p>
</li>
<li><p>Travis.yml</p>
</li>
<li>Code Coverage with coveralls </li>
</ul>
<h2 id="heading-theory">Theory</h2>
<h3 id="heading-what-is-testing">What is testing?</h3>
<p>Let's start at the beginning and discuss what testing is. Testing is a 3 step process that looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-12.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Arrange, your app is in a certain original state. Act, then something happens (click event, input, etc.). Then you assert, or make a hypothesis, of the new state of your app. The tests will pass if your hypothesis is correct and fail if it is wrong. </p>
<p>Unlike your react components, your tests are not executed in the browser. Jest is the test runner and testing framework used by React. Jest is the environment where all your tests are actually executed. This is why you do not need to import <code>expect</code> and <code>describe</code> into this file. These functions are already available globally in the jest environment. </p>
<p>Your tests syntax will look something like this:</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">'Testing sum'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">a, b</span>) </span>{
       <span class="hljs-keyword">return</span> a + b;
    }

    it(<span class="hljs-string">'should equal 4'</span>,<span class="hljs-function">()=&gt;</span>{
       expect(sum(<span class="hljs-number">2</span>,<span class="hljs-number">2</span>)).toBe(<span class="hljs-number">4</span>);
      })

    test(<span class="hljs-string">'also should equal 4'</span>, <span class="hljs-function">() =&gt;</span> {
        expect(sum(<span class="hljs-number">2</span>,<span class="hljs-number">2</span>)).toBe(<span class="hljs-number">4</span>);
      }) 
});
</code></pre>
<p><code>describe</code> wraps our <code>it</code> or <code>test</code> blocks, and is a way to group our tests. Both <code>it</code> and <code>test</code> are keywords and can be used interchangeably. The string will be something that should happen with your tests and will be printed to the console. <code>toBe()</code> is a matcher that works with expect to allow you to make assertions. There are many more matchers and global variables offered by jest, see the links below for a complete list. </p>
<p><a target="_blank" href="https://jestjs.io/docs/en/using-matchers">https://jestjs.io/docs/en/using-matchers</a></p>
<p><a target="_blank" href="https://jestjs.io/docs/en/api">https://jestjs.io/docs/en/api</a></p>
<h3 id="heading-ia"> </h3>
<p>Why test?</p>
<p>Testing is done to ensure that your app will work as intended for your end users. Having tests will make your app more robust and less error prone. It is a way to verify that the code is doing what the developers intended. </p>
<p>Potential Drawbacks:</p>
<ul>
<li>Writing tests is time consuming and difficult. </li>
<li>In certain scenarios executing tests in CI can cost actual money. </li>
<li>If done incorrectly, it can give you false positives. Your tests pass, but your app doesn’t function as intended. </li>
<li>Or false negatives. Your tests fail but your app is functioning as intended.</li>
</ul>
<h3 id="heading-what-to-test">What to test?</h3>
<p>To build upon the previous point, Your tests should test the functionality of the app, that mimic how it will be used by your end users. This will give you confidence that your app will function as intended in your production environment.  We will of course go into much more detail through out this article but this is the basic gist of it. </p>
<h3 id="heading-what-not-to-test">What not to test?</h3>
<p>I like to use Kent C dodds philosophy here that you shouldn’t test implementation details. </p>
<p>Implementation details meaning testing things that are not end user functionality. We will see an example of this in the Enzyme section below. </p>
<p>It seems that you are testing functionality there but you are actually not. You are testing the name of the function. Because you can change the name of the function and your tests will break but your app will still work giving you a false negative. </p>
<p>Constantly having to worry about function and variable names is a headache, and having to rewrite tests every time you change them is tedious, I will show you a better approach. </p>
<p><strong>Const variables:</strong> these are unchanging variables, no need to test them.    </p>
<p><strong>Third party libraries:</strong> It is not your job to test these libraries. It is up to the creators of these libraries to test it. If you are not sure if a library is tested you should not use it. Or you can read the source code to see if the author included tests. You can download the source code and run these tests yourself. You can also ask the author if their library is production ready or not.     </p>
<h3 id="heading-my-personal-philosophy-on-testing">My personal philosophy on testing</h3>
<p>A lot of my testing philosophy is based on Kent C dodds teachings so you will see a lot of his sentiments echoed here, but I some of my own thoughts as well.</p>
<p>Many integration tests. No snapshot tests. Few unit tests. Few e to e tests. </p>
<p>Unit testing is step above snapshot testing but its not ideal. It is however much easier to understand and maintain then snapshot testing. </p>
<p>Write mostly integration tests. Unit tests are good but they don't really resemble the way your end user interacts with your app. It is very easy to test implementation details with unit tests, especially with shallow render.  </p>
<p>Integration tests should mock as little as possible</p>
<p>Do not test implementation details such as names of functions and variables. </p>
<p>For example if we are testing a button and change the name of the function in the onClick method from increment() to handleClick() our tests would break but our component will still function. This is bad practice because we are basically just testing the name of the function which is an implementation detail, which our end user does not care about.</p>
<h3 id="heading-shallow-vs-mount">Shallow vs mount</h3>
<p>Mount actually executes the html, css and js code like a browser would, but does so in a simulated way. It is “headless” for example, meaning it doesn’t render or paint anything to a UI, but acts as a simulated web browser and executes the code in the background. </p>
<p>Not spending time painting anything to the UI makes your tests much faster. However mount tests are still much slower than shallow tests. </p>
<p>This is why you unmount or cleanup  the component after each test, because it’s almost a live app and one test will affect another test. </p>
<p>Mount/render is typically used for integration testing and shallow is used for unit testing.</p>
<p>shallow rendering only renders the single component we are testing. It does not render child components. This allows us to test our component in isolation. </p>
<p>For example consider this child and parent component.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
  )
}

<span class="hljs-keyword">const</span> ChildComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Child components<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>If we used shallow rendering of <code>App.js</code> we would get something like this, notice none of the DOM nodes for the child component are present, hence the term shallow render. </p>
<pre><code>&lt;App&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> /&gt;</span> 
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/App&gt;
</code></pre><p>Now we can compare this to mounting the component: </p>
<pre><code>&lt;App&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Child components<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ChildComponent</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/App&gt;
</code></pre><p>What we have above is much closer to what our app will look like in the browser, hence the superiority of mount/render. </p>
<h3 id="heading-unit-vs-integration-vs-end-to-end">unit vs integration vs end to end</h3>
<p><strong>unit testing</strong>: testing an isolated part of your app, usually done in combination with shallow rendering. example: a component renders with the default props.</p>
<p><strong>integration testing:</strong> testing if different parts work or integrate with each other. Usually done with mounting or rendering a component. example: test if a child component can update context state in a parent. </p>
<p><strong>e to e testing</strong>: Stands for end to end. Usually a multi step test combining multiple unit and integration tests into one big test. Usually very little is mocked or stubbed. Tests are done in a simulated browser, there may or may not be a UI while the test is running. example: testing an entire authentication flow.</p>
<h2 id="heading-preliminary-info">Preliminary Info</h2>
<p><strong>react-testing-library:</strong> I personally like to use react-testing-library but the common way is to use Enzyme. I will show you one example of Enzyme because it is important to be aware of Enzyme at a basic level and the rest of the examples with react-testing-library. </p>
<p><strong>Examples Outline:</strong> Our examples will follow a pattern. I will first show you the React component and then the tests for it, with detailed explanations of each. You can also follow along with the repo linked at the beginning. </p>
<p><strong>Configuration:</strong> I will also assume you are using create-react-app with the default testing setup with jest so I will skip manual configurations.</p>
<p><strong>Sinon, mocha, chai:</strong> A lot of the functionality offered by sinon is available by default with jest so you dont need sinon. Mocha and chai are a replacement for jest. Jest comes pre configured out of the box to work with your app, so it doesnt make sense to use Mocha and chai.</p>
<p><strong>Components Naming scheme:</strong> My naming scheme for the components is <code>&lt;TestSomething /&gt;</code> but that does not mean they are fake components in any way. They are regular React components, this is just the naming scheme.</p>
<p><strong>npm test and jest watch mode</strong>: <code>yarn test</code>   worked for me. <code>npm test</code> did not work correctly with jest watch mode.</p>
<p><strong>testing a single file:</strong> <code>yarn test</code> name of file</p>
<p><strong>React Hooks vs Classes:</strong> I use React Hooks components for most of the examples but due to the power of react-testing-library all these tests will directly work with class components as well. </p>
<p>With the preliminary background info out of the way we can go over some code.</p>
<h2 id="heading-enzyme">Enzyme</h2>
<h3 id="heading-enzyme-setup">Enzyme Setup</h3>
<p>Our third party libraries</p>
<p><code>npm install enzyme enzyme-to-json  enzyme-adapter-react-16</code></p>
<p>Lets first start with our imports</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> Basic <span class="hljs-keyword">from</span> <span class="hljs-string">'../basic_test'</span>;

<span class="hljs-keyword">import</span> Enzyme, { shallow, render, mount } <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme'</span>;
<span class="hljs-keyword">import</span> toJson <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme-to-json'</span>;
<span class="hljs-keyword">import</span> Adapter <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme-adapter-react-16'</span>;

Enzyme.configure({ <span class="hljs-attr">adapter</span>: <span class="hljs-keyword">new</span> Adapter() })
</code></pre>
<p>We will start with our basic imports Our first 3 imports are for react and our component. </p>
<p>After this we import Enzyme. Then we import the toJson function from the 'enzyme-to-json' library. We will need this to convert our shallow rendered component into JSON which can be saved to the snapshot file. </p>
<p>Finally we import our Adapter to make enzyme work with react 16 and initialize it as shown above. </p>
<p>react-test-renderer</p>
<p>React actually comes with its own test renderer you can use instead of enzyme and the syntax will look like this. </p>
<pre><code class="lang-javascript"><span class="hljs-comment">// import TestRenderer from 'react-test-renderer';</span>
<span class="hljs-comment">// import ShallowRenderer from 'react-test-renderer/shallow';</span>


<span class="hljs-comment">// Basic Test with React-test-renderer</span>
<span class="hljs-comment">// it('renders correctly react-test-renderer', () =&gt; {</span>
<span class="hljs-comment">//   const renderer = new ShallowRenderer();</span>
<span class="hljs-comment">//   renderer.render(&lt;Basic /&gt;);</span>
<span class="hljs-comment">//   const result = renderer.getRenderOutput();</span>
<span class="hljs-comment">//</span>
<span class="hljs-comment">//   expect(result).toMatchSnapshot();</span>
<span class="hljs-comment">// });</span>
</code></pre>
<p>But even the react-test-render docs suggest using enzyme instead because it has a slightly nicer syntax and does the same thing. Just something to be aware of.   </p>
<h3 id="heading-snapshot-testing">SnapShot Testing</h3>
<p>Now our first test which is a snapshot test</p>
<pre><code class="lang-javascript">it(<span class="hljs-string">'renders correctly enzyme'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> wrapper = shallow(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Basic</span> /&gt;</span></span>)

  expect(toJson(wrapper)).toMatchSnapshot();
});
</code></pre>
<p>If you have not ran this command before, a <strong>snapshots</strong> folder and test.js.snap file will be created for you automatically. On every subsequent test the new snapshot will be compared to the existing snapshot file. The test will pass if the snapshot has not changed and fail if it has changed.</p>
<p>So essentially snapshot testing allows you to see how your component has changed since the last test, line for line. The lines of code that have changed is known as the diff.</p>
<p>Here is our basic component we are snapshot testing: </p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;


<span class="hljs-keyword">const</span> Basic = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Basic Test<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> This is a basic Test Component<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Basic;
</code></pre><p>Running the above test will generate a file that will look like this. This is essentially our tree of React DOM nodes. </p>
<pre><code><span class="hljs-comment">// Jest Snapshot v1, https://goo.gl/fbAQLP</span>

<span class="hljs-built_in">exports</span>[<span class="hljs-string">`renders correctly enzyme 1`</span>] = <span class="hljs-string">`
&lt;div&gt;
  &lt;h1&gt;
     Basic Test
  &lt;/h1&gt;
  &lt;p&gt;
     This is a basic Test Component
  &lt;/p&gt;
&lt;/div&gt;
`</span>;
</code></pre><p>And will produce a folder structure that will look like this: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Your terminal output will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-7.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>However what happens if we changed our basic component to this</p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;


<span class="hljs-keyword">const</span> Basic = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Basic Test<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Basic;
</code></pre><p>Our snapshots will now fail   </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-8.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And will also give us the diff</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-9.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Just like in git the " - " before each line means it was removed. </p>
<p>We just need to press "w" to activate watch mode then press "u" to update the snapshot. </p>
<p>our snap shot file will be automatically updated with the new snapshot and will pass our tests </p>
<pre><code><span class="hljs-comment">// Jest Snapshot v1, https://goo.gl/fbAQLP</span>

<span class="hljs-built_in">exports</span>[<span class="hljs-string">`renders correctly enzyme 1`</span>] = <span class="hljs-string">`
&lt;div&gt;
  &lt;h1&gt;
     Basic Test
  &lt;/h1&gt;
&lt;/div&gt;
`</span>;
</code></pre><p>This is it for snapshot testing but if you read my personal thoughts section you know I dont snapshot test. I included it here because like Enzyme it is very common and something you should be aware of, but below I'll try to explain why I dont use it.  </p>
<p>Let's go over again what snapshot testing is. It essentially allows you to see how your component has changed since the last test. What are the benefits of this. </p>
<ul>
<li>Its very quick and easy to implement and sometimes requires only a few lines of code. </li>
<li>You can see if our component is rendering correctly. You can see the DOM nodes clearly with the .debug() function.  </li>
</ul>
<p><strong>Cons, Arguments against snapshot testing:</strong></p>
<ul>
<li>The only thing a snapshot test does is tell you whether the syntax of your code has changed since the last test. </li>
<li>So what is it really testing? Some would argue not much.</li>
<li>Also basic rendering of the app correctly is React’s job so you're going a little into testing a third party library territory. </li>
<li>Also comparing diffs can be done with git version control. This should not be the job of snapshot testing.</li>
<li>A failed test doesn’t mean your app isn’t working as intended, only that your code has changed since the last time you ran the test. This can lead to a lot of false negatives and a lack of trust in the test. This can also lead to people just updating the test without looking too closely at it. </li>
<li>Snapshot testing also tells you if your JSX is syntactically correct, but again this can be easily done in the dev environment. Running a snapshot test just to check syntax errors doesnt make any sense. </li>
<li>It can become hard to understand what’s happening in a Snapshot test, since most people use snapshot testing with shallow rendering, which doesnt render child components so it doesnt give the developer any insights at all.    </li>
</ul>
<p>See the further reading section for more info</p>
<h3 id="heading-testing-implementation-details-with-enzyme">Testing Implementation details with Enzyme</h3>
<p>Here I will give an example on why not to test implementation details. Say we have simple counter component like so: </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props)

    <span class="hljs-built_in">this</span>.state = {
      <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>
    }
  }

  increment = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">this</span>.setState({<span class="hljs-attr">count</span>: <span class="hljs-built_in">this</span>.state.count + <span class="hljs-number">1</span>})
  }

  <span class="hljs-comment">//This incorrect code will still cause tests to pass</span>
  <span class="hljs-comment">// &lt;button onClick={this.incremen}&gt;</span>
  <span class="hljs-comment">//   Clicked: {this.state.count}</span>
  <span class="hljs-comment">// &lt;/button&gt;</span>

  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"counter-button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.incremen}</span>&gt;</span>
          Clicked: {this.state.count}
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )}
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Counter;
</code></pre>
<p>You will notice I have a comment suggesting that a non-working app will still cause the tests to pass, for example by misspelling the name of the function in the onClick event. </p>
<p>And let's see the tests which will make it clear why. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> Counter <span class="hljs-keyword">from</span> <span class="hljs-string">'../counter'</span>;

<span class="hljs-keyword">import</span> Enzyme, { shallow, render, mount } <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme'</span>;
<span class="hljs-keyword">import</span> toJson <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme-to-json'</span>;
<span class="hljs-keyword">import</span> Adapter <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme-adapter-react-16'</span>;

Enzyme.configure({ <span class="hljs-attr">adapter</span>: <span class="hljs-keyword">new</span> Adapter() })

<span class="hljs-comment">// incorrect function assignment in the onClick method</span>
<span class="hljs-comment">// will still pass the tests.</span>

test(<span class="hljs-string">'the increment method increments count'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> wrapper = mount(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> /&gt;</span></span>)

  expect(wrapper.instance().state.count).toBe(<span class="hljs-number">0</span>)

  <span class="hljs-comment">// wrapper.find('button.counter-button').simulate('click')</span>
  <span class="hljs-comment">// wrapper.setState({count: 1})</span>
  wrapper.instance().increment()
  expect(wrapper.instance().state.count).toBe(<span class="hljs-number">1</span>)
})
</code></pre>
<p>Running the above code will pass the tests. So will using <code>wrapper.setState()</code>. So we have passing tests with a non functional app. I dont know about you but this doesnt give me confidence that our app will function as intended for our end users. </p>
<p>Simulating click on the button will not pass the tests but it might give us the opposite problem, a false negative. Say we want to change the styling on the button by declaring a new CSS class for it, a very common situation. Our tests will now fail because we cant find our button anymore but our app will still be working, giving us a false negative. This is also true whenever we change the names of our functions or state variables.  </p>
<p>Every time we want to change our function and CSS class names we have to rewrite our tests, a very inefficient and tedious process. </p>
<p>So what can we do instead? </p>
<h2 id="heading-react-testing-library">React-testing-library</h2>
<h3 id="heading-usestate">useState</h3>
<p>From the react-testing-library docs we see that the main guiding principle is </p>
<blockquote>
<p>The more your tests resemble the way your software is used the more confidence they can give you. </p>
</blockquote>
<p>We will keep this guiding principle in mind as we explore further with our tests. </p>
<p>Let's start with a basic React Hooks component and test the state and props. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;


<span class="hljs-keyword">const</span> TestHook = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [state, setState] = useState(<span class="hljs-string">"Initial State"</span>)

  <span class="hljs-keyword">const</span> changeState = <span class="hljs-function">() =&gt;</span> {
    setState(<span class="hljs-string">"Initial State Changed"</span>)
  }

  <span class="hljs-keyword">const</span> changeNameToSteve = <span class="hljs-function">() =&gt;</span> {
    props.changeName()
  }

  <span class="hljs-keyword">return</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{changeState}</span>&gt;</span>
      State Change Button
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{state}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{changeNameToSteve}</span>&gt;</span>
       Change Name
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TestHook;
</code></pre>
<p>Our props are coming from the root parent component</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">const</span> [state, setState] = useState(<span class="hljs-string">"Some Text"</span>)
      <span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">"Moe"</span>)
  ...
      const changeName = <span class="hljs-function">() =&gt;</span> {
        setName(<span class="hljs-string">"Steve"</span>)
      }

      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">Basic</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Counter <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Basic Hook useState <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">TestHook</span> <span class="hljs-attr">name</span>=<span class="hljs-string">{name}</span> <span class="hljs-attr">changeName</span>=<span class="hljs-string">{changeName}/</span>&gt;</span>
    ...</span>
</code></pre>
<p>So keeping our guiding principle in mind, what will our tests look like? </p>
<p>The way our end user will use this app will be to: see some text on the UI, see the text in the button, then click on it, finally see some new text on UI. </p>
<p>This is how we will write our tests using the React testing library. </p>
<p>Use this command to install react testing library. </p>
<p><code>npm install @testing-library/react</code></p>
<p><strong>not</strong> </p>
<p><code>npm install react-testing-library</code></p>
<p>Now for our tests</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> TestHook <span class="hljs-keyword">from</span> <span class="hljs-string">'../test_hook.js'</span>;
<span class="hljs-keyword">import</span> {render, fireEvent, cleanup} <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'../../../App'</span>

afterEach(cleanup)

it(<span class="hljs-string">'Text in state is changed when button clicked'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestHook</span> /&gt;</span></span>);

    expect(getByText(<span class="hljs-regexp">/Initial/i</span>).textContent).toBe(<span class="hljs-string">"Initial State"</span>)

    fireEvent.click(getByText(<span class="hljs-string">"State Change Button"</span>))

    expect(getByText(<span class="hljs-regexp">/Initial/i</span>).textContent).toBe(<span class="hljs-string">"Initial State Changed"</span>)
 })


it(<span class="hljs-string">'button click changes props'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">TestHook</span> /&gt;</span>
                               <span class="hljs-tag">&lt;/<span class="hljs-name">App</span>&gt;</span></span>)

  expect(getByText(<span class="hljs-regexp">/Moe/i</span>).textContent).toBe(<span class="hljs-string">"Moe"</span>)

  fireEvent.click(getByText(<span class="hljs-string">"Change Name"</span>))

  expect(getByText(<span class="hljs-regexp">/Steve/i</span>).textContent).toBe(<span class="hljs-string">"Steve"</span>)
})
</code></pre>
<p>We first start with our usual imports.</p>
<p>Next we have the <code>afterEach(cleanup)</code> function. Since we are not using shallow render we have to unmount or cleanup after every test. And this is exactly what this function is doing. </p>
<p><code>getByText</code> is the query method we get by using object destructuring on the value of the render function. There are several more query methods but this is the one you will want to use most of the time.</p>
<p>To test our state notice we are not using any function names or the names of our state variables. We are keeping with our guiding principle and not testing implementation details. Since a user will see the text on the UI, this is how we will query the DOM nodes. We will also query the button this way and click it. Finally we will query the final state based on the text as well. </p>
<p><code>(/Initial/i)</code> is a regex expression that returns the first node that at least contains the text "Initial".  </p>
<p>We can do the same exact thing with props as well. Since the <strong>props</strong> are going to be changed in <code>App.js</code> we will need to render it along with our component. Like the previous example we are not using function and variable names. We are testing the same way a user would use our app and that is through the text they will see. </p>
<p>Hopefully this gives you a good idea of how to test with the <code>react-testing-library</code> and the guiding principle, you generally want to use <code>getByText</code> most of the time. There are a few exceptions we will see as we continue further. </p>
<h3 id="heading-usereducer">useReducer</h3>
<p>Now we can test a component with the useReducer hook. We will of course need actions and reducers to work with our component so let's set them up like so: </p>
<p>Our reducer</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> ACTIONS <span class="hljs-keyword">from</span> <span class="hljs-string">'./actions'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> initialState = {
    <span class="hljs-attr">stateprop1</span>: <span class="hljs-literal">false</span>,
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Reducer1 = <span class="hljs-function">(<span class="hljs-params">state = initialState, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span>(action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"SUCCESS"</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">stateprop1</span>: <span class="hljs-literal">true</span>,
      }
    <span class="hljs-keyword">case</span> <span class="hljs-string">"FAILURE"</span>:
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">stateprop1</span>: <span class="hljs-literal">false</span>,
      }
    <span class="hljs-attr">default</span>:
      <span class="hljs-keyword">return</span> state
  }
}
</code></pre>
<p>And the actions: </p>
<pre><code>


<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> SUCCESS = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'SUCCESS'</span>
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> FAILURE = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'FAILURE'</span>
}
</code></pre><p>we will keep things simple and use actions instead of action creators. </p>
<p>And finally the component that will use these actions and reducers: </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useReducer } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> ACTIONS <span class="hljs-keyword">from</span> <span class="hljs-string">'../store/actions'</span>
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> Reducer <span class="hljs-keyword">from</span> <span class="hljs-string">'../store/reducer'</span>


<span class="hljs-keyword">const</span> TestHookReducer = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [reducerState, dispatch] = useReducer(Reducer.Reducer1, Reducer.initialState)

  <span class="hljs-keyword">const</span> dispatchActionSuccess = <span class="hljs-function">() =&gt;</span> {
    dispatch(ACTIONS.SUCCESS)
  }

  <span class="hljs-keyword">const</span> dispatchActionFailure = <span class="hljs-function">() =&gt;</span> {
    dispatch(ACTIONS.FAILURE)
  }


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {reducerState.stateprop1
           ? <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>stateprop1 is true<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
           : <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>stateprop1 is false<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
       <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{dispatchActionSuccess}</span>&gt;</span>
         Dispatch Success
       <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TestHookReducer;
</code></pre>
<p>This is a simple component that will change <code>stateprop1</code> from false to true by dispatching a <code>SUCCESS</code> action.</p>
<p>And now for our test. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> TestHookReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'../test_hook_reducer.js'</span>;
<span class="hljs-keyword">import</span> {render, fireEvent, cleanup} <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> Reducer <span class="hljs-keyword">from</span> <span class="hljs-string">'../../store/reducer'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> ACTIONS <span class="hljs-keyword">from</span> <span class="hljs-string">'../../store/actions'</span>;


afterEach(cleanup)

describe(<span class="hljs-string">'test the reducer and actions'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'should return the initial state'</span>, <span class="hljs-function">() =&gt;</span> {
    expect(Reducer.initialState).toEqual({ <span class="hljs-attr">stateprop1</span>: <span class="hljs-literal">false</span> })
  })

  it(<span class="hljs-string">'should change stateprop1 from false to true'</span>, <span class="hljs-function">() =&gt;</span> {
    expect(Reducer.Reducer1(Reducer.initialState, ACTIONS.SUCCESS ))
      .toEqual({ <span class="hljs-attr">stateprop1</span>: <span class="hljs-literal">true</span>  })
  })
})

it(<span class="hljs-string">'Reducer changes stateprop1 from false to true'</span>, <span class="hljs-function">() =&gt;</span> {
   <span class="hljs-keyword">const</span> { container, getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestHookReducer</span> /&gt;</span></span>);

   expect(getByText(<span class="hljs-regexp">/stateprop1 is/i</span>).textContent).toBe(<span class="hljs-string">"stateprop1 is false"</span>)

   fireEvent.click(getByText(<span class="hljs-string">"Dispatch Success"</span>))

   expect(getByText(<span class="hljs-regexp">/stateprop1 is/i</span>).textContent).toBe(<span class="hljs-string">"stateprop1 is true"</span>)
})
</code></pre>
<p>We first start off by testing our reducer. And we can wrap the tests for the reducer in the <code>describe</code> block. These are fairly basic tests we are using to make sure the <strong>initial state</strong> is what we want and the actions produce the output we want. </p>
<p>You can make an argument that testing the reducer is testing implementation details, but I found in practice that testing actions and reducers is one unit test that is always necessary. </p>
<p>This is a simple example so it doesn't seem like its a big deal but in larger more complex apps not testing reducers and actions can prove disastrous. So actions and reducers would be one exception to the testing implementation details rule.</p>
<p>Next we have our tests for the actual component. Notice again here we are not testing implementation details. We use the same pattern from the previous useState example we are getting our DOM nodes by the text and also finding and clicking the button with the text as well. </p>
<h3 id="heading-usecontext">useContext</h3>
<p>Let's now move on and test if a child component can update the context state in a parent component. This may seem complex but it is rather simple and straight forward. </p>
<p>We will first need our context object that we can initialize in its own file. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> Context = React.createContext()

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Context
</code></pre>
<p>We also need our parent app component which will hold the Context provider. The value passed down to the <code>Provider</code> will be the state value and the <code>setState</code> function of the <code>App.js</code> component. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> TestHookContext <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/react-testing-lib/test_hook_context'</span>;


<span class="hljs-keyword">import</span> Context <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/store/context'</span>;


<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [state, setState] = useState(<span class="hljs-string">"Some Text"</span>)


  <span class="hljs-keyword">const</span> changeText = <span class="hljs-function">() =&gt;</span> {
    setState(<span class="hljs-string">"Some Other Text"</span>)
  }


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Basic Hook useContext<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">Context.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{changeTextProp:</span> <span class="hljs-attr">changeText</span>,
                               <span class="hljs-attr">stateProp:</span> <span class="hljs-attr">state</span>
                                 }} &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TestHookContext</span> /&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">Context.Provider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>And for our component</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> Context <span class="hljs-keyword">from</span> <span class="hljs-string">'../store/context'</span>;

<span class="hljs-keyword">const</span> TestHookContext = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> context = useContext(Context)

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{context.changeTextProp}</span>&gt;</span>
        Change Text
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{context.stateProp}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TestHookContext;
</code></pre>
<p>We have a simple component that displays the text we initialized in <code>App.js</code> and also we pass the <code>setState</code> function to the <code>onClick</code> method. </p>
<p><strong>Note:</strong> The state is changed, initialized and contained in our <code>App.js</code> component. We have simply passed down the state value and <code>setState</code> function to our child component through context, but ultimately the state is handled in the <code>App.js</code> component. This will be important to understanding our test. </p>
<p>And our test: </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> TestHookContext <span class="hljs-keyword">from</span> <span class="hljs-string">'../test_hook_context.js'</span>;
<span class="hljs-keyword">import</span> {act, render, fireEvent, cleanup} <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'../../../App'</span>

<span class="hljs-keyword">import</span> Context <span class="hljs-keyword">from</span> <span class="hljs-string">'../../store/context'</span>;

afterEach(cleanup)

it(<span class="hljs-string">'Context value is updated by child component'</span>, <span class="hljs-function">() =&gt;</span> {

   <span class="hljs-keyword">const</span> { container, getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span>&gt;</span>
                                            <span class="hljs-tag">&lt;<span class="hljs-name">Context.Provider</span>&gt;</span>
                                             <span class="hljs-tag">&lt;<span class="hljs-name">TestHookContext</span> /&gt;</span>
                                            <span class="hljs-tag">&lt;/<span class="hljs-name">Context.Provider</span>&gt;</span>
                                           <span class="hljs-tag">&lt;/<span class="hljs-name">App</span>&gt;</span></span>);

   expect(getByText(<span class="hljs-regexp">/Some/i</span>).textContent).toBe(<span class="hljs-string">"Some Text"</span>)

   fireEvent.click(getByText(<span class="hljs-string">"Change Text"</span>))

   expect(getByText(<span class="hljs-regexp">/Some/i</span>).textContent).toBe(<span class="hljs-string">"Some Other Text"</span>)
})
</code></pre>
<p>Even for context you can see we don't break our pattern of tests, we still find and simulate our events with the text. </p>
<p>I have included the <code>&lt;Context.Provider/&gt;</code> and <code>&lt;TestHookContext /&gt;</code>  components in the render function because it makes the code easier to read but we actually dont need either of them. Our test will still work if we passed only the <code>&lt;App /&gt;</code> component to the render function. </p>
<pre><code><span class="hljs-keyword">const</span> { container, getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span>/&gt;</span></span>)
</code></pre><p>Why is this the case? </p>
<p>Let's think back to what we know about context. All the context state is handled in <code>App.js</code>, for this reason this is the main component we are actually testing, even though it seems like we are testing the child component that uses the <strong>useContext</strong> Hook. This code also works because of <strong>mount/render</strong>. As we know in shallow render the child components are <strong>not rendered</strong>, but in mount/render they are. Since <code>&lt;Context.Provider /&gt;</code> and <code>&lt;TestHookContext /&gt;</code> are both child components of <code>&lt;App /&gt;</code> they are rendered automatically.  </p>
<h3 id="heading-controlled-component-forms">Controlled component Forms</h3>
<p>A controlled component form essentially means the form will work through the React state instead of the form maintaining its own state. Meaning the <code>onChange</code> handler will save the input text to the React state on every keystroke. </p>
<p>Testing the form will be a little bit different than what we have seen so far, but we will try to still keep our guiding principle in mind. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> HooksForm1 = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [valueChange, setValueChange] = useState(<span class="hljs-string">''</span>)
  <span class="hljs-keyword">const</span> [valueSubmit, setValueSubmit] = useState(<span class="hljs-string">''</span>)

  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> (
    setValueChange(event.target.value)
  );

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    event.preventDefault();
    setValueSubmit(event.target.text1.value)
  };

    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> React Hooks Form <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"form"</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"text1"</span>&gt;</span>Input Text:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"text1"</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>React State:<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Change: {valueChange}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Submit Value: {valueSubmit}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> HooksForm1;
</code></pre>
<p>This is a basic form we have here and we also display the value of the change and submit value in our JSX. We have the <code>data-testid="form"</code>  attribute which we will use in our test to the query for the form. </p>
<p>And our tests: </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> HooksForm1 <span class="hljs-keyword">from</span> <span class="hljs-string">'../test_hook_form.js'</span>;
<span class="hljs-keyword">import</span> {render, fireEvent, cleanup} <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;

afterEach(cleanup)

<span class="hljs-comment">//testing a controlled component form.</span>
it(<span class="hljs-string">'Inputing text updates the state'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> { getByText, getByLabelText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">HooksForm1</span> /&gt;</span></span>);

    expect(getByText(<span class="hljs-regexp">/Change/i</span>).textContent).toBe(<span class="hljs-string">"Change: "</span>)

    fireEvent.change(getByLabelText(<span class="hljs-string">"Input Text:"</span>), {<span class="hljs-attr">target</span>: {<span class="hljs-attr">value</span>: <span class="hljs-string">'Text'</span> } } )

    expect(getByText(<span class="hljs-regexp">/Change/i</span>).textContent).not.toBe(<span class="hljs-string">"Change: "</span>)
 })


 it(<span class="hljs-string">'submiting a form works correctly'</span>, <span class="hljs-function">() =&gt;</span> {
     <span class="hljs-keyword">const</span> { getByTestId, getByText } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">HooksForm1</span> /&gt;</span></span>);

     expect(getByText(<span class="hljs-regexp">/Submit Value/i</span>).textContent).toBe(<span class="hljs-string">"Submit Value: "</span>)

     fireEvent.submit(getByTestId(<span class="hljs-string">"form"</span>), {<span class="hljs-attr">target</span>: {<span class="hljs-attr">text1</span>: {<span class="hljs-attr">value</span>: <span class="hljs-string">'Text'</span> } } })

     expect(getByText(<span class="hljs-regexp">/Submit Value/i</span>).textContent).not.toBe(<span class="hljs-string">"Submit Value: "</span>)
  })
</code></pre>
<p>Since an empty input element does not have text, we will use a <code>getByLabelText()</code> function to get the input node. This will still be keeping with our guiding principle, since the label text is what the user will read before inputting text. </p>
<p>Notice we will fire the <code>.change()</code> event instead of the usual <code>.click()</code> event. We also pass in dummy data in the form of: </p>
<p><code>{ target: { value: "Text" } }</code> </p>
<p>Since the value from the form will be accessed in the form of <code>event.target.value</code>, this is what we pass to the simulated event. </p>
<p>Since we will generally not know what the text is the user will submit, we can just use a <code>.not</code> keyword to make sure the text has changed in our render method. </p>
<p>We can test the submitting of the form in a similar way.  The only difference is we use the <code>.submit()</code> event and pass in dummy data in this way: </p>
<p><code>{ target: { text1: { value: 'Text' } } }</code> </p>
<p>This is how to access form data from the synthetic event when a user submits a form. where <code>text1</code> is the id of our input element. We will have to break our pattern a little bit here, and use the <code>data-testid="form"</code>   attribute to query for the form since there is really no other way to get the form.  </p>
<p>And thats it for the form. It isnt that different from our other examples. If you think you got it, let's move onto something a little more complex. </p>
<p>### </p>
<h3 id="heading-useeffect-and-api-requests-with-axios">useEffect and API requests with axios</h3>
<p>Let's now see how we would test the <strong>useEffect hook</strong> and API requests. This will be fairly different than what we have seen so far. </p>
<p>Say we have a url passed down to a child component from the root parent. </p>
<pre><code class="lang-javascript">
...

     &lt;TestAxios url=<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts/1'</span> /&gt;

 ...
</code></pre>
<p>And the component itself. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;


<span class="hljs-keyword">const</span> TestAxios = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [state, setState] = useState()

  useEffect(<span class="hljs-function">() =&gt;</span> {
    axios.get(props.url)
      .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> setState(res.data))
  }, [])


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Axios Test <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        {state
          ? <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">data-testid</span>=<span class="hljs-string">"title"</span>&gt;</span>{state.title}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          : <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...Loading<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TestAxios;
</code></pre>
<p>We simply make an API request and save the results in the local state. We also use a ternary expression in our render method to wait until the request is complete to display the title data from json placeholder. </p>
<p>You will notice we will again out of necessity have to make use of the <code>data-testid</code> attribute, and again it is an implementation detail since a user will not see or interact with this attribute in any way, but this is more realistic, since we will generally not know the text from a API request beforehand. </p>
<p>We will also be using mocks in this test. </p>
<p>A <strong>mock</strong> is way to simulate behavior we dont actually want to do in our tests. For example we mock API requests because we dont want to make real requests in our tests. </p>
<p>We dont want to make real API requests in our tests for various reasons: it will make our tests much slower, might give us a false negative, the API request will cost us money, or we will mess up our database with test data. </p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> TestAxios <span class="hljs-keyword">from</span> <span class="hljs-string">'../test_axios.js'</span>;
<span class="hljs-keyword">import</span> {act, render, fireEvent, cleanup, waitForElement} <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;

<span class="hljs-keyword">import</span> axiosMock <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;
</code></pre><p>We have our usual imports but you will notice something peculiar. We are importing <code>axiosMock</code> from the <code>axios</code> library. We are not importing a mock axios object from the <code>axios</code> library. We are actually mocking the <code>axios</code> library <em>itself</em>. </p>
<p>How? </p>
<p>By using the mocking functionality offered by jest. </p>
<p>We first will make a <code>__mocks__</code> folder adjacent to our test folder, so something like this. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-13.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And inside the mocks folder we have an <code>axios.js</code> file and this is our fake <strong>axios</strong> library. And inside our fake <strong>axios</strong> library we have our <strong>jest mock function</strong>. </p>
<p>Mock functions allow us to use functions in our jest environment without having to implement the actual logic of the function. </p>
<p>So basically we are not going to implement the actual logic behind an axios get request. We will just use this mock function instead. </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">get</span>: jest.fn(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">Promise</span>.resolve({ <span class="hljs-attr">data</span>: {} }) )
};
</code></pre>
<p>Here we have our fake get function. It is a simple function that is actually a JS object. <code>get</code> is our key and the value is the <strong>mock function</strong>. Like an <strong>axios</strong> API request, we resolve a promise. We wont pass in any data here, we will do that in our testing setup. </p>
<p>Now our testing setup</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//imports</span>
...

afterEach(cleanup)

it(<span class="hljs-string">'Async axios request works'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  axiosMock.get.mockResolvedValue({<span class="hljs-attr">data</span>: { <span class="hljs-attr">title</span>: <span class="hljs-string">'some title'</span> } })

  <span class="hljs-keyword">const</span> url = <span class="hljs-string">'https://jsonplaceholder.typicode.com/posts/1'</span>
  <span class="hljs-keyword">const</span> { getByText, getByTestId, rerender } = render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TestAxios</span> <span class="hljs-attr">url</span>=<span class="hljs-string">{url}</span> /&gt;</span></span>);

  expect(getByText(<span class="hljs-regexp">/...Loading/i</span>).textContent).toBe(<span class="hljs-string">"...Loading"</span>)

  <span class="hljs-keyword">const</span> resolvedEl = <span class="hljs-keyword">await</span> waitForElement(<span class="hljs-function">() =&gt;</span> getByTestId(<span class="hljs-string">"title"</span>));

  expect((resolvedEl).textContent).toBe(<span class="hljs-string">"some title"</span>)

  expect(axiosMock.get).toHaveBeenCalledTimes(<span class="hljs-number">1</span>);
  expect(axiosMock.get).toHaveBeenCalledWith(url);
 })
</code></pre>
<p>The first thing we do in our test is call our fake <strong>axios get request</strong>, and mock the resolved value with ironically the <code>mockResolvedValue</code> function offered by jest. This function does exactly what its name says, it resolves a promise with the data we pass in, which simulates what axios does. </p>
<p>This function has to be called before our <code>render()</code> function otherwise the test wont work. Because remember we are mocking the <strong>axios library</strong> itself. When our component runs the <code>import axios from 'axios';</code> command it will be <strong>importing our fake axios library</strong> instead of the real one and this fake axios will be substituted in our component wherever we used axios. </p>
<p>Next we get our "...Loading" text node since this is what will be displayed before the promise resolves. After this we a function we havent seen before the <code>waitForElement()</code>  function, which will wait until the promise resolves before going to the next assertion. </p>
<p>Also notice the <strong>await</strong> and <strong>async</strong> keywords, these are used in the exact same way as they are used in a non testing environment. </p>
<p>Once resolved the DOM node will have the text of "some title" which is the data we passed to our fake mock axios library. </p>
<p>Next we make sure the request was only called once and with the right url. Even though we are testing the url we didnt make an API request with this url. </p>
<p>And this is it for API requests with axios. In the next section we will look at e to e tests with cypress. </p>
<h2 id="heading-cypress">Cypress</h2>
<p>Lets now go over cypress which I believe is the best framework to run e to e tests. We are now longer in jest land, we will now be working solely with cypress which has its own testing environment and syntax.</p>
<p>Cypress is pretty amazing and powerful. So amazing and powerful in fact that we can run every test we just went over in one test block and watch cypress run these tests in real time in a simulated browser. </p>
<p>Pretty cool, huh? </p>
<p>I think so. Anyway, before we can do that we need to setup cypress. Surprisingly Cypress can be installed as a regular npm module. </p>
<p><code>npm install cypress</code></p>
<p>To run cypress you will need to use this command. </p>
<p><code>node_modules/.bin/cypress open</code></p>
<p>If that seems cumbersome to write every time you want open cypress so you can add it to your package.json. </p>
<pre><code class="lang-javascript">...

  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"react-scripts start"</span>,
    <span class="hljs-string">"build"</span>: <span class="hljs-string">"react-scripts build"</span>,
    <span class="hljs-string">"test"</span>: <span class="hljs-string">"react-scripts test"</span>,
    <span class="hljs-string">"eject"</span>: <span class="hljs-string">"react-scripts eject"</span>,
    <span class="hljs-string">"cypress"</span>: <span class="hljs-string">"node_modules/.bin/cypress open"</span>, 

   ...
</code></pre>
<p>this will allow you to open up cypress with just the <code>npm run cypress</code> command. </p>
<p>Opening up cypress will give you a GUI that looks like this.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-14.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To actually run the cypress tests, your app will have to be running at the same time, which we will see in a second. </p>
<p>Running the <code>cypress open</code> command will give you a basic configuration of cypress and create some files and folders for your automatically. A cypress folder will be created in the project root. We will write our code in the integration folder. </p>
<p>We can begin by deleting the examples folder. Unlike jest, cypress files take a <code>.spec.js</code> extension.  Because this is a e to e test we will run it on our main <code>App.js</code> file. So you should have a directory structure that now looks like this. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-21.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can also set a Base url in the cypress.json file. Just like this: </p>
<p><code>{ "baseUrl": "[http://localhost:3000](http://localhost:3000)" }</code></p>
<p>Now for our large monolithic test </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

describe (<span class="hljs-string">'complete e to e test'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'e to e test'</span>, <span class="hljs-function">() =&gt;</span> {
    cy.visit(<span class="hljs-string">'/'</span>)
    <span class="hljs-comment">//counter test</span>
    cy.contains(<span class="hljs-string">"Clicked: 0"</span>)
      .click()
    cy.contains(<span class="hljs-string">"Clicked: 1"</span>)
    <span class="hljs-comment">// basic hooks test</span>
    cy.contains(<span class="hljs-string">"Initial State"</span>)
    cy.contains(<span class="hljs-string">"State Change Button"</span>)
      .click()
    cy.contains(<span class="hljs-string">"Initial State Changed"</span>)
    cy.contains(<span class="hljs-string">"Moe"</span>)
    cy.contains(<span class="hljs-string">"Change Name"</span>)
      .click()
    cy.contains(<span class="hljs-string">"Steve"</span>)
    <span class="hljs-comment">//useReducer test</span>
    cy.contains(<span class="hljs-string">'stateprop1 is false'</span>)
    cy.contains(<span class="hljs-string">'Dispatch Success'</span>)
      .click()
    cy.contains(<span class="hljs-string">'stateprop1 is true'</span>)
    <span class="hljs-comment">//useContext test</span>
    cy.contains(<span class="hljs-string">"Some Text"</span>)
    cy.contains(<span class="hljs-string">'Change Text'</span>)
      .click()
    cy.contains(<span class="hljs-string">"Some Other Text"</span>)
    <span class="hljs-comment">//form test</span>
    cy.get(<span class="hljs-string">'#text1'</span>)
      .type(<span class="hljs-string">'New Text {enter}'</span>)
    cy.contains(<span class="hljs-string">"Change: New Text"</span>)
    cy.contains(<span class="hljs-string">"Submit Value: New Text"</span>)
    <span class="hljs-comment">//axios test</span>
    cy.request(<span class="hljs-string">'https://jsonplaceholder.typicode.com/posts/1'</span>)
      .should(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
          expect(res.body).not.to.be.null
          cy.contains(res.body.title)
        })
  });
});
</code></pre>
<p>As mentioned we are running every single test we just went over in one test block. I have separated each section with a comment so it will easier to see. </p>
<p>Our test may look intimidating at first but most of the individual tests will follow a basic arrange-act-assert pattern.  </p>
<pre><code class="lang-javascript">
cy.contains(Some innerHTML text <span class="hljs-keyword">of</span> DOM node)

cy.contains (text <span class="hljs-keyword">of</span> button)
.click()

cy.contains(Updated innerHTML text <span class="hljs-keyword">of</span> DOM node)
</code></pre>
<p>Since this is a e to e test you will find no mocking at all. Our app will be running in its full development version in a simulated browser with a UI. This will be as close to testing our app in realistic way as we can get.   </p>
<p>Unlike unit and integration tests we do not need to explicitly assert some things. This is because some Cypress commands have built in default assertions. <strong>Default assertions</strong> are exactly what they sound like, they are asserted by default so no need to add a matcher.  </p>
<p> <a target="_blank" href="https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Default-Assertions">Cypress default assertions</a> </p>
<p>Commands are chained together so order is important and one command will wait until a previous command is completed before running. </p>
<p>Even when testing with cypress we will stick to our philosophy of not testing implementation details. In practice this is going to mean that we will not use html/css classes, ids or properties as selectors if we can help it. The only time we will need to use id is to get our form input element.  </p>
<p>We will make use of the <code>cy.contains()</code> command which will return a DOM node with matching text. Seeing and Interacting with text on the UI is what our end user will do, so testing this way will be in line with our guiding principle. </p>
<p>Since we are not stubbing or mocking anything you will notice our tests will look very simplistic. This is good since this is a live running app, our tests will not have any artificial values. </p>
<p>In our axios test we will make a real http request to our endpoint. Making a real http request in an e to e test is common. Then we will check to see if that value is not null. Then make sure that the data of the response appears in our UI. </p>
<p>If done correctly you should see that cypress successfully ran the tests in chromium.   </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-22.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-continuous-integration">Continuous Integration</h2>
<p>Keeping track and Running all these tests manually can become tedious. So we have Continuous Integration, A way to automatically run our tests continuously.</p>
<h3 id="heading-travis-ci">Travis CI</h3>
<p>To keep things simple we'll just use Travis CI for our Continuous integration. You should know though that there are much more complex CI setups using Docker and Jenkins.</p>
<p>You will need to sign up for a Travis and Github account, both of these are luckily free. </p>
<p>I would suggest just using the "Sign Up with Github" option on Travis CI. </p>
<p>Once there you can just go on your profile icon and click the slider button next to the repository you want CI on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-15.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So that Travis CI knows what to do we will need to configure a .travis.yml file in our project root. </p>
<pre><code class="lang-yaml"><span class="hljs-attr">language:</span> <span class="hljs-string">node_js</span>

<span class="hljs-attr">node_js:</span> 
  <span class="hljs-bullet">-</span> <span class="hljs-string">stable</span>


<span class="hljs-attr">install:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span>

<span class="hljs-attr">script:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">test</span>
  <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">coveralls</span>
</code></pre>
<p>This essentially tells Travis that we are using node_js, download the stable version, install the dependencies and run the npm run test and npm run coveralls command.  </p>
<p>And this is it. You can know go on the dashboard and start the build. Travis will run the tests automatically and give you an output like this.  If your tests pass you are good to go. If they fail, your build will fail and you will need to fix your code and restart the build. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-16.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-coveralls">Coveralls</h3>
<p>coverall gives us a coverage report that essentially tells us how much of our code is being tested. </p>
<p>You will need to sign up to coveralls and sync with your github account. Similar to Travis CI, just go to the add repos tab and turn on the repo that you also activated on Travis CI. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-17.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next go to your package.json file and add this line of code </p>
<pre><code>  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"react-scripts start"</span>,
    <span class="hljs-string">"build"</span>: <span class="hljs-string">"react-scripts build"</span>,
    <span class="hljs-string">"test"</span>: <span class="hljs-string">"react-scripts test --coverage"</span>,
    <span class="hljs-string">"eject"</span>: <span class="hljs-string">"react-scripts eject"</span>,
    <span class="hljs-string">"cypress"</span>: <span class="hljs-string">"node_modules/.bin/cypress open"</span>, 
    <span class="hljs-string">"coveralls"</span>: <span class="hljs-string">"cat ./coverage/lcov.info | node node_modules/.bin/coveralls"</span>
  },
</code></pre><p>Be sure to add the <code>--coverage</code>  flag to the <code>react-scripts test</code> command. This is what will generate the coverage data that coveralls will use to generate a coverage report. </p>
<p>And you can actually see this coverage data on the Travis CI console after your tests have ran.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-18.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Since we are not dealing with a private repo or Travis CI pro, we dont need to worry about repo tokens. </p>
<p>Once your done you can add a badge to your repo README by copying the provided link on the dashboard. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-19.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>It will look like this. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/image-20.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Count yourself among the top 20% of developers in terms of React testing skill if you made it through the entire tutorial. </p>
<p>Thanks for reading. cheers. </p>
<blockquote>
<p>You can follow me on twitter for more tutorials in the future: <a target="_blank" href="https://twitter.com/iqbal125sf?lang=en">https://twitter.com/iqbal125sf?lang=en</a></p>
</blockquote>
<h3 id="heading-further-reading">Further Reading</h3>
<p><strong>Blog Posts:</strong></p>
<p><a target="_blank" 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">https://djangostars.com/blog/what-and-how-to-test-with-enzyme-and-jest-full-instruction-on-react-component-testing/</a></p>
<p><a target="_blank" href="https://engineering.ezcater.com/the-case-against-react-snapshot-testing">https://engineering.ezcater.com/the-case-against-react-snapshot-testing</a></p>
<p><a target="_blank" href="https://medium.com/@tomgold_48918/why-i-stopped-using-snapshot-testing-with-jest-3279fe41ffb2">https://medium.com/@tomgold_48918/why-i-stopped-using-snapshot-testing-with-jest-3279fe41ffb2</a></p>
<p><a target="_blank" href="https://circleci.com/blog/continuously-testing-react-applications-with-jest-and-enzyme/">https://circleci.com/blog/continuously-testing-react-applications-with-jest-and-enzyme/</a></p>
<p><a target="_blank" href="https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html">https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html</a></p>
<p><a target="_blank" href="https://willowtreeapps.com/ideas/best-practices-for-unit-testing-with-a-react-redux-approach">https://willowtreeapps.com/ideas/best-practices-for-unit-testing-with-a-react-redux-approach</a></p>
<p><a target="_blank" href="https://blog.pragmatists.com/genuine-guide-to-testing-react-redux-applications-6f3265c11f63">https://blog.pragmatists.com/genuine-guide-to-testing-react-redux-applications-6f3265c11f63</a></p>
<p><a target="_blank" href="https://hacks.mozilla.org/2018/04/testing-strategies-for-react-and-redux/">https://hacks.mozilla.org/2018/04/testing-strategies-for-react-and-redux/</a></p>
<p><a target="_blank" href="https://codeburst.io/deliberate-practice-what-i-learned-from-reading-redux-mock-store-8d2d79a4b24d">https://codeburst.io/deliberate-practice-what-i-learned-from-reading-redux-mock-store-8d2d79a4b24d</a></p>
<p><a target="_blank" href="https://www.robinwieruch.de/react-testing-tutorial/">https://www.robinwieruch.de/react-testing-tutorial/</a></p>
<p><a target="_blank" href="https://medium.com/@ryandrewjohnson/unit-testing-components-using-reacts-new-context-api-4a5219f4b3fe">https://medium.com/@ryandrewjohnson/unit-testing-components-using-reacts-new-context-api-4a5219f4b3fe</a>  </p>
<p><strong>Kent C dodds Posts on Testing</strong></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/introducing-the-react-testing-library">https://kentcdodds.com/blog/introducing-the-react-testing-library</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests">https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/why-i-never-use-shallow-rendering">https://kentcdodds.com/blog/why-i-never-use-shallow-rendering</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/demystifying-testing">https://kentcdodds.com/blog/demystifying-testing</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/effective-snapshot-testing">https://kentcdodds.com/blog/effective-snapshot-testing</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/testing-implementation-details">https://kentcdodds.com/blog/testing-implementation-details</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/common-testing-mistakes">https://kentcdodds.com/blog/common-testing-mistakes</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/ui-testing-myths">https://kentcdodds.com/blog/ui-testing-myths</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/why-youve-been-bad-about-testing">https://kentcdodds.com/blog/why-youve-been-bad-about-testing</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/the-merits-of-mocking">https://kentcdodds.com/blog/the-merits-of-mocking</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/how-to-know-what-to-test">https://kentcdodds.com/blog/how-to-know-what-to-test</a></p>
<p><a target="_blank" href="https://kentcdodds.com/blog/avoid-the-test-user">https://kentcdodds.com/blog/avoid-the-test-user</a>  </p>
<p><strong>Cheat Sheets / github threads</strong></p>
<p><a target="_blank" href="https://devhints.io/enzyme">https://devhints.io/enzyme</a></p>
<p><a target="_blank" href="https://devhints.io/enzyme">https://devhints.io</a>/jest </p>
<p><a target="_blank" href="https://github.com/ReactTraining/react-router/tree/master/packages/react-router/modules/__tests__">https://github.com/ReactTraining/react-router/tree/master/packages/react-router/modules/<strong>tests</strong></a></p>
<p><a target="_blank" href="https://github.com/airbnb/enzyme/issues/1938">https://github.com/airbnb/enzyme/issues/1938</a> </p>
<p><a target="_blank" href="https://gist.github.com/fokusferit/e4558d384e4e9cab95d04e5f35d4f913">https://gist.github.com/fokusferit/e4558d384e4e9cab95d04e5f35d4f913</a></p>
<p><a target="_blank" href="https://airbnb.io/enzyme/docs/api/selector.html">https://airbnb.io/enzyme/docs/api/selector.html</a>  </p>
<p><strong>Docs</strong></p>
<p><a target="_blank" href="https://docs.cypress.io/">https://docs.cypress.io</a></p>
<p><a target="_blank" href="https://airbnb.io/enzyme/">https://airbnb.io/enzyme/</a></p>
<p><a target="_blank" href="https://github.com/dmitry-zaets/redux-mock-store">https://github.com/dmitry-zaets/redux-mock-store</a></p>
<p><a target="_blank" href="https://jestjs.io/docs/en">https://jestjs.io/docs/en</a></p>
<p><a target="_blank" href="https://testing-library.com/docs/learning">https://testing-library.com/docs/learning</a></p>
<p><a target="_blank" href="https://sinonjs.org/releases/v7.3.2/">https://sinonjs.org/releases/v7.3.2/</a></p>
<p><a target="_blank" href="https://redux.js.org/recipes/writing-tests">https://redux.js.org/recipes/writing-tests</a></p>
<p><a target="_blank" href="https://jestjs.io/docs/en/using-matchers">https://jestjs.io/docs/en/using-matchers</a></p>
<p><a target="_blank" href="https://jestjs.io/docs/en/api">https://jestjs.io/docs/en/api</a>  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to set up Jest and Enzyme to test React Native apps ]]>
                </title>
                <description>
                    <![CDATA[ By Sam Ollason This short article shares my experiences setting up my testing environment to unit test React Native components with Jest and Enzyme. _Photo by [Unsplash](https://unsplash.com/photos/6wdRuK7bVTE?utm_source=unsplash&utm_medium=referral... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/setting-up-jest-enzyme-for-testing-react-native-40393ca04145/</link>
                <guid isPermaLink="false">66c35eaac7095d76345eaffd</guid>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ unit testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 20 May 2019 07:55:33 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*Ro5rChbmw1G4Cf5i2GAZJg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sam Ollason</p>
<p>This short article shares my experiences setting up my testing environment to unit test React Native components with Jest and Enzyme.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/nks4F4Jhip65XWA3f1i0GDn6a2TvXE0qhwfh" alt="Image" width="800" height="1200" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/photos/6wdRuK7bVTE?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="_blank" title=""&gt;Neil Soni on &lt;a href="https://unsplash.com/search/photos/mobile-app?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="<em>blank" title=")</em></p>
<h3 id="heading-testing-tools-and-environment">Testing tools and environment</h3>
<p>The first thing I learnt was the approach and infrastructure for writing unit tests for a React Native app are very similar to writing unit tests for a React app…perhaps unsurprisingly.</p>
<p>However, while the tooling and the use of the test suites are very similar, the <strong>testing environment and infrastructure have to be set up in a slightly different way</strong>. This is essentially because React apps are designed to work with the DOM inside a browser whereas mobile apps don’t target this data structure for rendering (they target actual ‘native’ modules that are on the mobile system instead).</p>
<h4 id="heading-using-jest">Using Jest</h4>
<p><a target="_blank" href="https://jestjs.io/">Jest</a> is a library used for testing JavaScript apps.</p>
<p>I wanted to use Jest for several reasons:</p>
<p>Firstly, it was created and is actively maintained by Facebook for their own React Native apps.</p>
<p>Secondly, it comes pre-packaged with the version of React Native I was working with (created using <a target="_blank" href="https://github.com/facebook/react-native">react-native</a>).</p>
<p>Thirdly, <strong>Jest is a ‘comprehensive’ testing framework</strong> and contains the whole suite of testing tools I needed. For example, Jest comes with a library to check assertions, a test runner to actually run tests and tools to check code coverage. With other solutions, one has to choose and assemble individual components of a testing suite.</p>
<h4 id="heading-using-jest-enzyme">Using Jest + Enzyme</h4>
<p>I wanted to combine Jest and Enzyme. There are lots of slightly confusing comments on the web that compare ‘Jest versus Enzyme’. This is a bit misleading. While Jest is a testing framework you can think of Enzyme as a library that makes it easier to select and query elements inside of an emulated DOM. So <strong>it is often used alongside Jest</strong> to make writing the logic of tests cleaner and easier to read.</p>
<p>Still confused? It’s similar to how jQuery introduced a concise and clear syntax for querying and selecting elements in the DOM, whereas the syntax using vanilla JavaScript was (at least back when jQuery was first introduced) not as clear and easy to use. And people don’t often compare ‘jQuery versus JavaScript’, unless they are comparing a particular way that the two approaches use to query and modify elements of the DOM.</p>
<p><em>Note:</em> you can use Jest without Enzyme (I believe Facebook does this) but Enzyme makes your tests a bit easier to create and read. From my perspective, combining Enzyme with Jest is about convenience.</p>
<h3 id="heading-setting-up-jest-enzyme">Setting up Jest + Enzyme</h3>
<p>I had to jump through some hoops to successfully setup Jest and Enzyme in my React Native environment.</p>
<p>Jest now comes included with React Native apps created using the ‘react-native’ tool. So I could use Jest out of the box. Wonderful!</p>
<p>But I ran into some problems trying to combine Enzyme with React Native using their <a target="_blank" href="https://airbnb.io/enzyme/docs/guides/react-native.html">documentation</a>. I never quite got to the bottom of what was the underlying problem, but I kept getting ‘modules not found’ errors like this one <a target="_blank" href="https://github.com/facebook/react-native/issues/23943">here</a>.</p>
<h4 id="heading-a-solution">A solution</h4>
<p>In the end I used a solution that essentially abstracts away some of the setup into a pre-packaged environment using the <a target="_blank" href="https://github.com/FormidableLabs/enzyme-matchers/tree/master/packages/jest-enzyme#readme">jest-enzyme</a> library and then made sure the jest ‘presets’ was set to ‘react-native’ in my package.json.</p>
<p>I followed the instructions to install these libraries:</p>
<pre><code>npm install jest-environment-enzyme jest-enzyme enzyme-adapter-react<span class="hljs-number">-16</span> --save-dev
</code></pre><p>Errors when I tried to run my tests also directed me to explicitly install these myself too:</p>
<pre><code>npm install --save-dev react-dom enzyme
</code></pre><p>Here is what I had to manually add to package.json:</p>
<pre><code><span class="hljs-comment">// package.json before with react-native init</span>

{
...
   <span class="hljs-string">"jest"</span>: {
       <span class="hljs-string">"presets"</span>: [<span class="hljs-string">"react-native"</span>],
     }
...
}

<span class="hljs-comment">// package.json after my manual changes:</span>
{
...

<span class="hljs-string">"jest"</span>: {
       <span class="hljs-string">"presets"</span>: [<span class="hljs-string">"react-native"</span>], <span class="hljs-comment">// not clear in documentation!</span>
       <span class="hljs-string">"setupTestFrameworkScriptFile"</span>: <span class="hljs-string">"jest-enzyme"</span>,
       <span class="hljs-string">"testEnvironment"</span>: <span class="hljs-string">"enzyme"</span>,
       <span class="hljs-string">"testEnvironmentOptions"</span>: {
           <span class="hljs-string">"enzymeAdapter"</span>: <span class="hljs-string">"react16"</span>
       }  
   }
...
}
</code></pre><p>You can see the repo <a target="_blank" href="https://github.com/SamOllason/jest-enzyme-config-for-react-native/blob/master/README.md">here</a>.</p>
<p>Using the jest-enzyme library in this way worked easily for me and it also meant that I had a slightly cleaner setup. This is because the other approach (that I couldn’t get to work, following the Enzyme documentation) would have meant I also had to set up and maintain a separate ‘jest config’ script.</p>
<h3 id="heading-summary">Summary</h3>
<p>Writing business logic inside of Jest+Enzyme tests for React Native seems to be exactly the same as writing tests for React using Jest+Enzyme. This means the examples and documentation online for React unit testing are easily transferrable, which is really useful. This is a great step towards the vision of web developers being able to easily transfer their skills to create cross-platform mobile apps.</p>
<p>However, for the ease-of-use in the ‘test writing’ phase, I paid the price when setting up the infrastructure and environment so that the various tools were compatible with my React Native ecosystem.</p>
<p>In addition, from coming across Github issues in this area, it seems like there are lots of small instabilities between React Native versions that makes it really hard to find out what is the underlying cause of an infrastructure problem like the ones I described above. But I suppose we can’t have flexibility in such a fast-moving space as this without some challenges.</p>
<p><a target="_blank" href="https://github.com/SamOllason/jest-enzyme-config-for-react-native/blob/master/README.md">Here</a> is the repo with my jest-enzyme setup with a few example tests.</p>
<p>I hope you found this interesting and useful! Please feel free to add any questions or comments below.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to get started: testing a Ruby-on-Rails / ReactJS app with RSpec, Jest and Enzyme ]]>
                </title>
                <description>
                    <![CDATA[ By Holly Atkinson I recently made a simple ideas board web app using ReactJS, Ruby-on-Rails and PostgreSQL. Below, I’ll walk you through the initial steps I took to set up basic unit tests for one of the features of my app, adding a new idea. _Photo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-get-started-testing-a-ruby-on-rails-reactjs-app-with-rspec-jest-and-enzyme-d058f415894e/</link>
                <guid isPermaLink="false">66d45f339208fb118cc6cfc1</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 03 May 2019 17:55:33 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*KnkP0HAL3iL6tyTQo7jVZw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Holly Atkinson</p>
<p>I recently made a simple ideas board web app using ReactJS, Ruby-on-Rails and PostgreSQL. Below, I’ll walk you through the initial steps I took to set up basic unit tests for one of the features of my app, adding a new idea.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/yToemQSqCMdhO5ADFrrEyf8WwRNFKWl2Zq69" alt="Image" width="800" height="571" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/photos/awU3XEzdU94?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="_blank" title=""&gt;Dan DeAlmeida on &lt;a href="https://unsplash.com/search/photos/ideas?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="<em>blank" title=")</em></p>
<p>Note: I’m not going to discuss the <em>scope</em> of tests in this post; rather, my focus is on understanding how to install some of the <em>dependencies</em> in order to be able to get started with writing the tests.</p>
<h3 id="heading-background-ideas-board-set-up">Background: ideas board set up</h3>
<p>I used Node package manager to manage my project’s dependencies. If you’d like to code along, you’ll need to make sure you have Node installed on your computer.</p>
<p><em>Project features</em></p>
<p><strong>In Rails</strong></p>
<p>Models: Idea</p>
<p>Relationships: none</p>
<p><strong>In React</strong></p>
<p>Components: Navbar, IdeasContainer, Idea</p>
<h3 id="heading-getting-started-with-rspec"><strong>Getting started with RSpec</strong></h3>
<p>I used RSpec to test the Rails part of my ideas board web app. To get started:</p>
<ol>
<li>I added the gem ‘rspec-rails’, ‘~&gt; 3.8’ to my gemfile.</li>
<li><p>I then ran <code>bundle</code> in my terminal window (making sure I was in the Rails directory).</p>
</li>
<li><p>Next, in my Rails directory, I created a new folder called <code>spec</code>. And then, another new folder inside that one called <code>requests</code>.</p>
</li>
<li><p>I created a new file called <code>ideas_spec.rb</code>. You can replace the name <code>ideas_spec</code> with the name of whichever model you want to test, making sure to include the <code>_spec</code> part to denote that it's a test file.</p>
</li>
<li><p>At the top of my ideas_spec.rb file, I added the following text:</p>
</li>
</ol>
<p><code>require ‘rails_helper’</code></p>
<ol start="6">
<li>Then, in the same file, I included code describing the first test I wanted to run:</li>
</ol>
<pre><code class="lang-ruby">describe “add an idea”, <span class="hljs-symbol">:type</span> =&gt; <span class="hljs-symbol">:request</span> dodescribe “add an idea”, <span class="hljs-symbol">:type</span> =&gt; <span class="hljs-symbol">:request</span> <span class="hljs-keyword">do</span>
before <span class="hljs-keyword">do</span>
 post ‘/api/v1/ideas’
<span class="hljs-keyword">end</span>
it ‘returns a created status’ <span class="hljs-keyword">do</span>
  expect(response).to have_http_status(<span class="hljs-number">201</span>)
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<ol start="7">
<li>To run my test, I typed <code>rspec</code> in my terminal window, making sure I was in my rails project directory.</li>
</ol>
<p>If you’ve been following along, RSpec should run at this point and your first test should pass!</p>
<h3 id="heading-getting-started-with-jest"><strong>Getting started with Jest</strong></h3>
<p>I was pleasantly surprised to find out that the testing framework Jest is included with create-react-app! However, I also wanted to use Enzyme, a testing utility, for which I needed to install some dependencies.</p>
<ol>
<li>To start off, I created a new folder called <code>_tests_</code> in my app’s <code>src</code> directory.</li>
<li>In my client-side directory, I ran the following commands:</li>
</ol>
<pre><code>npm i -D react-test-renderer
</code></pre><pre><code>npm install --save-dev jest-enzyme
</code></pre><pre><code>npm install --save-dev enzyme enzyme-adapter-react<span class="hljs-number">-16</span>
</code></pre><ol start="3">
<li>To configure Enzyme, I created a file in <code>src</code> called <code>setupTests.js</code> and included the following:</li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> Enzyme = <span class="hljs-built_in">require</span>(<span class="hljs-string">'enzyme'</span>);
<span class="hljs-keyword">const</span> EnzymeAdapter = <span class="hljs-built_in">require</span>(<span class="hljs-string">'enzyme-adapter-react-16'</span>);
Enzyme.configure({ <span class="hljs-attr">adapter</span>: <span class="hljs-keyword">new</span> EnzymeAdapter() });
</code></pre>
<ol start="4">
<li><p>Inside my <code>_tests_</code> folder, I created a new file, called <code>App.tests.js</code></p>
</li>
<li><p>I included the following text at the top of this file to import my components and all the testing functionality I wanted for <em>all</em> my tests:</p>
</li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'../App'</span>;
<span class="hljs-keyword">import</span> Idea <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/Idea'</span>;
<span class="hljs-keyword">import</span> IdeasContainer <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/IdeasContainer'</span>;
<span class="hljs-keyword">import</span> { create, update } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-test-renderer'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'../setupTests'</span>;
<span class="hljs-keyword">import</span> { shallow, mount, render } <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme'</span>;
<span class="hljs-keyword">import</span> { shallowToJson } <span class="hljs-keyword">from</span> <span class="hljs-string">'enzyme-to-json'</span>;
</code></pre>
<ol start="6">
<li>Underneath, I included my <em>first</em> unit test:</li>
</ol>
<pre><code class="lang-ruby">describe(<span class="hljs-string">'Idea'</span>, () =&gt; {
  it(<span class="hljs-string">'should render a new idea correctly'</span>, () =&gt; {
    const output = shallow(
      &lt;Idea
      key=<span class="hljs-string">"mockKey"</span>
      idea={<span class="hljs-string">"1"</span>, <span class="hljs-string">"Test"</span>, <span class="hljs-string">"Test"</span>}
      onClick={<span class="hljs-string">"mockFn"</span>}
      delete={<span class="hljs-string">"mockFn2"</span>}
      /&gt;
    );
    expect(shallowToJson(output)).toMatchSnapshot();
  });
});
</code></pre>
<ol start="7">
<li><p>I ran <code>rails s</code> in the server side directory and then <code>npm start</code> in the client side directory to start my ideas board on localhost:3001.</p>
</li>
<li><p>To run my first test, I typed the following into my terminal window (making sure I was in the client directory):</p>
</li>
</ol>
<pre><code>npm run test
</code></pre><p>If you’ve been following along, Jest should run at this point, your test should pass — and you’re in a great place now to write more tests!</p>
<p>For more information on the ideas board project, my repo can be found <a target="_blank" href="https://github.com/atkinsonholly/tracr">here</a>.</p>
<p>If you made it this far, thanks for reading! I hope my post helped you get started with setting up your tests.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to correctly mock Moment.js/dates in Jest ]]>
                </title>
                <description>
                    <![CDATA[ By Iain Nash Times and dates are infamously hard to correctly implement in code. This makes testing date and time code correctly important. Testing allows for reasoning around logic in code and also to allow catching edge cases or errors before they ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-correctly-mock-moment-js-dates-in-jest-25fa2528ca11/</link>
                <guid isPermaLink="false">66c350da4f1fc448a3679057</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 18 Mar 2019 21:50:35 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*W26Jdk8ZEo4QDC797b7smA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Iain Nash</p>
<p>Times and dates <a target="_blank" href="https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time">are infamously hard</a> to correctly implement in code. This makes testing date and time code correctly important. Testing allows for reasoning around logic in code and also to allow catching edge cases or errors before they impact users.</p>
<p>A common mistake when testing date and time code is to not set the current time to a static time. If code in the UI renders today’s date and is tested properly, that test that only works until the current time changes too much. Javascript exposes the built-in <code>Date</code> object which allows for retrieving the current time through construction with no arguments or a call to the <code>now()</code> property.</p>
<p><a target="_blank" href="https://momentjs.com/">Moment.js</a> is a popular front-end date manipulation library that is commonly used to manipulate, load, format, and shift time. It uses an empty constructor to get the current time. Jest is often used in conjunction with Moment and React applications. Additionally, Jest snapshot testing introduces new dependencies on date and time that are important to consider. Below is an example problematic component that renders the current day:</p>
<p>An initial test for the <code>TodayIntro</code> component could look like:</p>
<p>However, this test will fail on any day that is not Jan 23rd. A solution to this is to override Javascript’s date function to return a known date to work against when writing tests.</p>
<p>This code overrides the Date constructor to set a static “current” date:</p>
<p>An ineffective solution is to do the date math yourself against the current time the test is run. This is an ineffective test because you’re running the same code you’re testing to test the return value. For instance, if testing by comparing formatted dates through moment, one would not catch if the moment formatting code changes <code>MMM</code> to <code>JAN</code> instead of <code>Jan</code> .</p>
<h4 id="heading-ways-to-set-a-static-time-and-timezone-for-jestjs">Ways to set a static time and timezone for Jest/JS</h4>
<ol>
<li>Use a library to mock out Date object to return a static date and timezone (we’d recommend <a target="_blank" href="https://github.com/boblauer/MockDate">MockDate</a> for simple cases, but read on for a breakdown of the alternatives)</li>
<li>Mock <code>moment().format()</code> to return a static string</li>
<li>Mock the <code>Date</code> constructor and <code>now()</code> function to return a static time</li>
</ol>
<p>Using a library in this case is preferable because these libraries are well tested, do not introduce boilerplate code and handle transparently both cases dates can be created (<code>Date.now()</code> vs <code>new Date()</code> etc.). Additionally, using a library allows for easily following test code and setting a specific time per test which allows for better testing practices.</p>
<ul>
<li><code>[MockDate](https://github.com/boblauer/MockDate)</code> provides further functionality for time zones and is easy to use</li>
<li><code>[sinon](https://sinonjs.org/releases/v7.2.4/fake-timers/)</code> provides Date and timer (<code>setTimeout</code> etc.) mocks</li>
<li>Manually setting the mock can be useful in limited environments, however, can become rather complicated</li>
<li><code>[jasmine](https://jasmine.github.io/)</code> (not included in jest), comes with a <a target="_blank" href="https://jasmine.github.io/api/2.6/Clock.html">jasmine.clock()</a></li>
</ul>
<p>The examples below use <a target="_blank" href="https://github.com/boblauer/MockDate">MockDate</a>, which only focuses on mocking the Date object simply and handles testing time zone offsets as well for testing local time zone conversion.</p>
<p>A <a target="_blank" href="https://jestjs.io/docs/en/snapshot-testing">snapshot test</a>, as well, is simple to test with mocked dates:</p>
<p>Since <a target="_blank" href="https://airbnb.io/enzyme/">enzyme</a> is an awesome library, an enzyme shallow example:</p>
<h3 id="heading-how-to-better-test-date-logic">How to (better) test date logic</h3>
<p>Dates have a lot of edge cases and logic behind them. When testing dates, make sure to cover edge cases and not just set one specific date to test and move on. Dates can also vary according to locale and time zone.</p>
<p>Properly testing dates require reasoning around edge cases that could occur and writing tests to ensure those edge cases behave as expected and that future changes to code or libraries used in your application don’t break those assumptions. Additionally, adding code to set the current date and time to a static date and time across all test code may be easier, but prevents good reasoning around testing Dates and hides test assumptions in library code.</p>
<p>Here are a few incorrect and often implicit assumptions about dates:</p>
<ol>
<li>Clients all exist within one time zone and daylight saving time</li>
<li>All clients exist within the developer’s time zone</li>
<li>The length of a Month name is relatively similar</li>
<li>Server clocks are always correct</li>
<li>The server knows the client’s timezone/time settings</li>
</ol>
<p>This test assumes the server is always in the correct timezone and that timezone is set correctly. Instead, set the timezone and make sure the date matches the local timezone correctly.</p>
<p>It is important to ensure that when tests access the current time the “current time” is set to a static value. If the value is dynamic, either tests eventually break or a test is testing against dynamic values. Dynamic values are not effective at testing behavior since a bug will not be exposed by comparing the return value of two functions that are the same as compared to comparing to a static value that doesn’t change as the code is modified.</p>
<h3 id="heading-looking-ahead-date-time-storage-and-design">Looking ahead: Date time storage and design</h3>
<p>Having a requirement to add tests to a code base doesn’t necessarily provide any value unless those tests are reviewed, run, and reasoned about just as strictly as running code.</p>
<p>Date and time logic introduces a large set of possibilities in terms of behavior and output, making a strong incentive to test effectively for date and time. Beyond testing, acknowledging and keeping relevant data along with a strategy to synchronize and store date times consistently across systems early on both helps testing and makes for a better user experience.</p>
<p>These tips and approaches apply to more than just Javascript &amp; Jest testing for dates and times. They also work in a NodeJS context and in a general sense around key things to test for in systems that handle date and time in general. In many cases, storing time on the server in UTC (Universal coordinated time) then converting to the local time zone based on client / browser settings is ideal. If the client is inaccessible, storing both the UTC time and user’s actual timezone is an effective way to consistently treat dates and times.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A quick introduction to test driven development with Jest ]]>
                </title>
                <description>
                    <![CDATA[ By Nicolas Mitchell This article is a simple walkthrough of how to apply Test Driven Development (TDD) principles to a JavaScript exercise using Jest. Intro After a few years of experience developing on my own personal projects, I recently decided to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-quick-introduction-to-test-driven-development-with-jest-cac71cb94e50/</link>
                <guid isPermaLink="false">66c343154f7405e6476b0168</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 25 Jun 2018 21:18:39 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*0jCUKud4CkbbmNrFDzIQZw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Nicolas Mitchell</p>
<p>This article is a simple walkthrough of how to apply Test Driven Development (TDD) principles to a JavaScript exercise using Jest.</p>
<h3 id="heading-intro">Intro</h3>
<p>After a few years of experience developing on my own personal projects, I recently decided to become a Full-Stack developer.</p>
<p>This new situation encouraged me to start thinking about practices that I’ve neglected until now, such as testing my code.</p>
<p>That is why I wanted to start my journey through Test Driven Development. I’ve decided to share my first steps here with you.</p>
<h3 id="heading-the-exercise">The exercise</h3>
<p>I decided to start with the first Osherove TDD kata. You can access the full exercise <a target="_blank" href="http://osherove.com/tdd-kata-1/">here</a>.</p>
<p>The goal is to deliver a function that takes a string entry (<code>"1, 2, 3"</code> for instance) and returns the sum of all numbers.</p>
<p>Our project will have the following structure:</p>
<pre><code>js-kata-jest/
</code></pre><pre><code>├─ src/
</code></pre><pre><code>  └─ kata.js
</code></pre><pre><code>├─ test/
</code></pre><pre><code>  └─ kata.test.js
</code></pre><pre><code>└─ package.json
</code></pre><h3 id="heading-setting-up-the-test-environment">Setting up the test environment</h3>
<p>First we have to set up the test environment. As a React developer, I decided to go with <a target="_blank" href="https://facebook.github.io/jest/">Jest</a>. You may use any other testing library of your choice.</p>
<h4 id="heading-installing-jest-dev-dependency">Installing Jest dev dependency</h4>
<pre><code>yarn add --dev jest
</code></pre><p>or with <a target="_blank" href="https://www.npmjs.com/">npm</a>:</p>
<pre><code>npm install --save-dev jest
</code></pre><h4 id="heading-activating-jest-on-your-code-editor">Activating Jest on your code editor</h4>
<p>I am using Atom as a code editor, and installed the <a target="_blank" href="https://atom.io/packages/tester-jest">tester-jest</a> package. This allowed me to run my tests on save for any <code>*.test.js</code> file.</p>
<h3 id="heading-test-driven-development">Test Driven Development</h3>
<p>The theory behind TDD is quite simple, and revolves around 3 steps:</p>
<ol>
<li>Writing a test for a small part of a functionality and checking that this new test is failing (Red step)</li>
<li>Writing the code that makes the test pass, then checking that your previous test and the new one are successful (Green step)</li>
<li>Refactoring the code to make sure it is clear, understandable, and behaves well with the previous functionalities</li>
</ol>
<p>In the next part, we are going to go into detail for each of these steps.</p>
<h3 id="heading-solving-the-exercise">Solving the exercise</h3>
<h4 id="heading-first-loop">First loop</h4>
<p>First, we want to handle the case where our <code>add</code> function is given an empty string or one with a single element.</p>
<ol>
<li><p><strong>Writing the tests</strong></p>
</li>
<li><p>The first test checks that an empty string returns 0</p>
</li>
<li>The second checks that a single element string returns the provided element</li>
</ol>
<p><strong>2. Writing the code</strong></p>
<ul>
<li>First we return 0 by default</li>
<li>Then we provide an <code>if</code> statement that handles the parsing of a single provided element</li>
</ul>
<p>Here is the final code:</p>
<p><strong>3. Refactoring the code</strong></p>
<p>As it is our first functionality, we can skip this step for now — but we will soon return to it. ;)</p>
<h4 id="heading-second-loop">Second loop</h4>
<p>We will now handle the case where the string contains multiple elements:</p>
<ol>
<li><strong>Writing the tests</strong></li>
</ol>
<p>The new test makes sure that calculation of a multiple element string was done correctly:</p>
<p><strong>2. Writing the code</strong></p>
<ul>
<li>First we create a new <code>if</code> statement on purpose to be sure that our first two tests affect the new solution</li>
<li>Second we create a new array from the entry string, using the <code>,</code> as a separator</li>
<li>Finally, we parse each element of the newly created array to calculate the sum</li>
</ul>
<p>Here is the final code:</p>
<p><strong>3. Refactoring the code</strong></p>
<p>As we can see above, there are several problems within our code:</p>
<ul>
<li>the two if statement shouldn’t be decorrelated, as adding one or more to zero should behave the same.</li>
<li>the separator value is drowned in the code. This adds complexity if we want to change to a <code>;</code> separator, for instance.</li>
<li>a large part of our code is located in an <code>if</code> statement. We could reverse the logic to extract our main code from it.</li>
</ul>
<p>So we can add a new <code>separator</code> variable, which will decide on the separator type. We can also merge the two <code>if</code> statement into one, and then reverse the logic.</p>
<p>We can now run our test again before moving on to the next loop.</p>
<h4 id="heading-third-loop">Third loop</h4>
<p>We can now handle the declaration of new separators and avoid the entry of negative numbers.</p>
<ol>
<li><p><strong>Writing the tests</strong></p>
</li>
<li><p>The first new test focuses on a single separator within the default values.</p>
</li>
<li>The second will make sure that we can configure a new separator directly within the input.</li>
<li>The third one will check that an error is thrown when a negative value is passed as an entry.</li>
</ol>
<p><strong>2. Writing the code</strong></p>
<ul>
<li>First, we replace the <code>separator</code> string by a <code>separators</code> array, where we add the <code>\n</code> value.</li>
<li>Second, we introduce a new separator search through a regular expression. That will be added to the previous array.</li>
<li>We can now join the previous array elements to split the string with them.</li>
<li>We filter the resulting array to remove all non-number elements.</li>
<li>We add a new array, <code>negatives</code>, that will spot negative values within the entry.</li>
<li>If the <code>negatives</code> array isn’t empty, throw an error.</li>
</ul>
<p>Here is the final code:</p>
<p><strong>3. Refactoring the code</strong></p>
<p>We now have two new possible optimizations:</p>
<ul>
<li>We are using the regular expression twice, and are willing to change it easily. We can extract it within a new <code>const regexp</code>.</li>
<li>We calculate <code>parseInt(list[i])</code>several times, so we should store the value only once to speed up the <code>for</code> loop.</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We can now run our tests again to make sure that all our expected functionalities are still working.</p>
<p>You may now continue on your own as well. Check out the definitive version of the kata with all tests passing <a target="_blank" href="https://github.com/nclsmitchell/js-kata-jest">here</a>.</p>
<p>Feel free to reach me on Twitter if you have any questions or comments <a target="_blank" href="https://twitter.com/nclsmitchell">@nclsmitchell</a> or through Medium :)</p>
<p>Thanks for your reading, and please clap for me if you like this post.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
