<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bonnie Schulkin</title>
    <description>The latest articles on DEV Community by Bonnie Schulkin (@bonnie).</description>
    <link>https://dev.to/bonnie</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F855503%2Febb4a2ad-7e2a-4fc6-8dff-e6c158f8b841.png</url>
      <title>DEV Community: Bonnie Schulkin</title>
      <link>https://dev.to/bonnie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bonnie"/>
    <language>en</language>
    <item>
      <title>Why are functional tests so much longer than unit tests?</title>
      <dc:creator>Bonnie Schulkin</dc:creator>
      <pubDate>Thu, 02 Jun 2022 23:13:53 +0000</pubDate>
      <link>https://dev.to/bonnie/why-are-functional-tests-so-much-longer-than-unit-tests-4hgk</link>
      <guid>https://dev.to/bonnie/why-are-functional-tests-so-much-longer-than-unit-tests-4hgk</guid>
      <description>Photo by &lt;a href="https://unsplash.com/@nhphoto?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener"&gt;Nicolas Häns&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/sprint-vs-marathon?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener"&gt;Unsplash&lt;/a&gt;




&lt;p&gt;My unit testing background has trained me to write short tests, each covering one discrete piece of code. This makes unit tests simple to read and easy to diagnose. So why can’t this approach be applied to functional tests?&lt;/p&gt;




&lt;h2&gt;
  
  
  Functional Tests vs Unit tests
&lt;/h2&gt;

&lt;p&gt;Let’s back up a bit here to distinguish between unit and functional tests. Unit tests isolate one piece of code, often a function or React component. By definition, they are tightly associated with the code, which makes them easy to diagnose (they point right to the area in the code that’s causing the failure!) but sometimes farther away from the actual user experience (especially if the coder uses mocks to keep other parts of code from polluting the unit test).&lt;/p&gt;

&lt;p&gt;Functional tests on the other hand, test a user flow representing some functionality of your app. These emphasize interacting with the app the way a user would (clicking buttons and entering text) and de-emphasize any focus on specific code (you may have heard that it’s better not to test “internals” — or what’s going on in the code — because this makes your tests brittle and susceptible to breaking on refactors, even though there’s nothing wrong with your app).&lt;/p&gt;

&lt;p&gt;React testing is currently trending strongly toward functional tests and away from isolated unit tests. This is great for the reasons mentioned above and in my &lt;a href="https://bonniedotdev.medium.com/testing-react-a-converts-journey-from-enzyme-to-testing-library-70f85eebb674"&gt;Enzyme vs Testing Library&lt;/a&gt; post, but it can lead to tests that seem uncomfortably long and meandering to an old unit tester like me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of a long(ish) functional test
&lt;/h3&gt;

&lt;p&gt;Say you have an app that allows people to design and order an ice cream sundae. Before they submit the order, the terms and conditions warn their ice cream order isn’t ever gonna happen (via a popover):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kgP_UON1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rdwwx8xdi18zmlvju9gv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kgP_UON1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rdwwx8xdi18zmlvju9gv.png" alt="Mockup showing popover text on mouseover of “Terms and Conditions”" width="800" height="885"&gt;&lt;/a&gt;&lt;/p&gt;
You can’t say you weren’t warned



&lt;h3&gt;
  
  
  The test
&lt;/h3&gt;

&lt;p&gt;Here is the test for the popover, using &lt;a href="https://testing-library.com/docs/react-testing-library/intro"&gt;React Testing Library&lt;/a&gt; syntax. This test is short compared to a lot of my actual functional tests (hence the “ish” in the title of this section). Still I wanted something small and easy to follow for this article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;popover responds to hover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
          &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SummaryForm&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;  

          &lt;span class="c1"&gt;// assertion 1:   &lt;/span&gt;
          &lt;span class="c1"&gt;// popover starts out hidden  &lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nullPopover&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
            &lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;  
          &lt;span class="p"&gt;);&lt;/span&gt;  
          &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nullPopover&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

          &lt;span class="c1"&gt;// assertion 2:   &lt;/span&gt;
          &lt;span class="c1"&gt;// popover appears upon mouseover of checkbox label  &lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;termsAndConditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/terms and conditions/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
          &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;termsAndConditions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;popover&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
          &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;popover&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

          &lt;span class="c1"&gt;// assertion 3:  &lt;/span&gt;
          &lt;span class="c1"&gt;// popover disappears when we mouse out  &lt;/span&gt;
          &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unhover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;termsAndConditions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
          &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;waitForElementToBeRemoved&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  
            &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
          &lt;span class="p"&gt;);&lt;/span&gt;  
        &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test has three assertions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The popover is hidden when the component is first rendered&lt;/li&gt;
&lt;li&gt; The popover appears when the mouse hovers over “Terms and Conditions”&lt;/li&gt;
&lt;li&gt; The popover disappears when the mouse leaves “Terms and Conditions”&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Why not make three separate tests?
&lt;/h2&gt;

&lt;p&gt;This particular test could be broken into three tests, one for each of the assertions above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// test #1 //&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;popover starts out hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SummaryForm&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
     &lt;span class="c1"&gt;// assertion 1  &lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nullPopover&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
        &lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;  
      &lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nullPopover&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// test #2 //&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;popover appears after mouseover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SummaryForm&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;  

      &lt;span class="c1"&gt;// find and mouseover the Terms and Conditions text  &lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;termsAndConditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/terms and conditions/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;termsAndConditions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="c1"&gt;// assertion 2  &lt;/span&gt;
      &lt;span class="nx"&gt;popover&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;popover&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// test #3 //&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;popover disappears on mouseout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SummaryForm&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;  

      &lt;span class="c1"&gt;// find and mouseover the Terms and Conditions text  &lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;termsAndConditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/terms and conditions/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;termsAndConditions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

      &lt;span class="c1"&gt;// make sure the assertion appeared  &lt;/span&gt;
      &lt;span class="nx"&gt;popover&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;popover&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="c1"&gt;// assertion 3  &lt;/span&gt;
      &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unhover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;termsAndConditions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;waitForElementToBeRemoved&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  
        &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
      &lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this is not necessarily an improvement — especially when it comes to separating tests (2) and (3). In order to set up the third test (popover disappears), we’d have to go through all the same steps we went through in the second test (getting the popover to appear, since we don’t know whether the popover disappeared unless it was actually there at some point).&lt;/p&gt;

&lt;p&gt;Repeating the “appears” code in two separate tests feels repetitive and unnecessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about a beforeEach?
&lt;/h3&gt;

&lt;p&gt;Maybe we should put the “appears” code in a &lt;a href="https://jestjs.io/docs/en/api#beforeeachfn-timeout"&gt;beforeEach&lt;/a&gt; that runs, well, before each test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;popover appears and disappears&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SummaryForm&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;  

        &lt;span class="c1"&gt;// find and mouseover the Terms and Conditions text  &lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;termsAndConditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/terms and conditions/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
        &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;termsAndConditions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// test #1 //&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;popover starts out hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SummaryForm&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
     &lt;span class="c1"&gt;// assertion 1:   &lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nullPopover&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
        &lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;  
      &lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nullPopover&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// test #2 //&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;popover appears after mouseover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
       &lt;span class="c1"&gt;// assertion 2:   &lt;/span&gt;
       &lt;span class="nx"&gt;popover&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
       &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;popover&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
     &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// test #3 //&lt;/span&gt;
    &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;popover disappears on mouseout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
       &lt;span class="c1"&gt;// assertion 3  &lt;/span&gt;
       &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unhover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;termsAndConditions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
       &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;waitForElementToBeRemoved&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  
         &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/no ice cream will actually be delivered/i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
       &lt;span class="p"&gt;);&lt;/span&gt;  
     &lt;span class="p"&gt;});&lt;/span&gt;  
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’re writing one test that doesn’t do anything other than assert the popover is in the document. Then there's a second test that builds on the &lt;code&gt;beforeEach&lt;/code&gt; by running through the "disappears" code. That would work to break this particular test into three tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reasons NOT to use a beforeEach
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Any time you break up the test code by using &lt;code&gt;beforeEach&lt;/code&gt;, the code is less readable and requires more effort to determine what exactly happened when debugging failing tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This second reason is the stronger one for me.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For this fairly simple user flow test, one &lt;code&gt;beforeEach&lt;/code&gt; would cover the setup for both of the tests that aren't for initial conditions. However, imagine a more involved user flow, where a user:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  logs on to the site&lt;/li&gt;
&lt;li&gt;  selects some ice cream scoops and toppings&lt;/li&gt;
&lt;li&gt;  sees the order summary&lt;/li&gt;
&lt;li&gt;  agrees to the terms and conditions&lt;/li&gt;
&lt;li&gt;  sees a confirmation page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single &lt;code&gt;beforeEach&lt;/code&gt; will not be able to cover the setup for the half dozen or so actions we go through as part of the flow. If we wanted to isolate each action / assertion into its own test, it would require either&lt;/p&gt;

&lt;p&gt;a. repeating a lot of the setup of the previous tests, or&lt;/p&gt;

&lt;p&gt;b. mocking and/or setting the context value explicitly in order to set up the tests -- which is frowned upon in this type of functional, user-based testing because it's not what a user would actually do to get into that situation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The above is a verbose way of saying: most functional tests go through a series of steps, each step relying on the consequences of the previous step. The only way to run these tests without a huge amount of complexity or verbosity is to go through the whole flow in a single test, asserting along the way.&lt;/p&gt;

&lt;p&gt;Is this isolated? No. Is this testing one specific area of the code? Also no. The point here is to test the &lt;em&gt;app&lt;/em&gt;, not the &lt;em&gt;code&lt;/em&gt; so that the tests more accurately reflect whether or not the app is working from a user’s perspective. The down side is that these tests are harder to debug since they’re more vague about which part of the code caused the error. This is part of the cost of functional testing. If you’re interested in how unit testing can mitigate this, take a look at my article on &lt;a href="https://dev.to/bonnie/when-to-unit-test-your-react-app-4659"&gt;When to Unit Test your React App&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>react</category>
    </item>
    <item>
      <title>When to unit-test your React app</title>
      <dc:creator>Bonnie Schulkin</dc:creator>
      <pubDate>Thu, 02 Jun 2022 23:03:49 +0000</pubDate>
      <link>https://dev.to/bonnie/when-to-unit-test-your-react-app-4659</link>
      <guid>https://dev.to/bonnie/when-to-unit-test-your-react-app-4659</guid>
      <description>Image by Bernd Hildebrandt from Pixabay




&lt;p&gt;React testing is trending toward &lt;strong&gt;functional&lt;/strong&gt; testing: test your app the way a user would use it. The tests go through user flows, and are decoupled from the code (testing behavior over implementation). This is fantastic when it comes time to refactor your code, or update the code without changing the behavior. Since the tests are tied only to the behavior, there’s no need to update the tests. Champagne all around! 🍾&lt;/p&gt;

&lt;p&gt;This leaves a question, though: is there any space left in React for unit testing (tests that isolate one unit of code, often a function or component)?&lt;/p&gt;




&lt;h2&gt;
  
  
  Unit tests can be functional tests
&lt;/h2&gt;

&lt;p&gt;Functional testing and unit testing aren’t mutually exclusive. Functional testing means testing a certain flow of your app, which could be contained in a single component.&lt;/p&gt;

&lt;p&gt;For example, say you have a component, Quote, that displays a pithy quote and links to the author’s website. Some authors might not have a web site, though (Abraham Lincoln was notoriously bad at keeping up with web technology). Your tests need to check that the quote renders correctly for both situations: authors who have a link, and those who don’t.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jy0ockf6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28jb0cy1006b6uhbkx62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jy0ockf6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28jb0cy1006b6uhbkx62.png" alt="Deepak Chopra quote with link to author, Abraham Lincoln quote without a link to author" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;
When will Abe get a web presence?



&lt;p&gt;These are functional tests for a user experience: they confirm the author’s name is either a link to the right destination, or plain text without a link for author data without a web site link. But they’re also unit tests for the Quote component. The test can render the Quote component with the quote and author data as props, and the tests are isolated to that one component. So here you’re writing unit tests simply because all the code for your functional test is contained within one unit.&lt;/p&gt;

&lt;p&gt;Okay, so this example seems to be “unit testing as a technicality.” You’re actually doing functional tests that just happen to be unit tests. Are there any reasons you might want to unit test &lt;strong&gt;deliberately&lt;/strong&gt;? Read on, my friends.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unit tests help diagnose other failing tests
&lt;/h2&gt;

&lt;p&gt;Functional testing is awesome when it comes to refactors (see comments about champagne above). But, when you test behavior and not implementation, your tests are &lt;em&gt;intentionally&lt;/em&gt; decoupled from your code — which makes it harder to diagnose failing tests.&lt;/p&gt;

&lt;p&gt;In a large, complicated project, there could be dozens or hundreds of lines of code responsible for a certain functional test, and narrowing down the cause of a failure could take a fair amount of time and effort. In some cases, you could potentially spend more time tracking down test failures than you would maintaining unit tests.&lt;/p&gt;

&lt;p&gt;If there is a likely potential point of failure for one or more functional tests, you might consider making a unit test to cover it. This way, you can easily zero in on what is causing the functional test to fail — or eliminate a potential reason the functional test is failing.&lt;/p&gt;

&lt;p&gt;As a simple example, imagine an app where someone can look up laws about backyard chicken coops for a particular city. The user selects a state from a drop-down menu, which populates a second drop-down menu with cities in that state that have such laws. Some states (I’m looking at you, California) have a lot of cities, so the city menu is broken into sub-menus by alphabet if there are more than 20 cities in the state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8yIVvTTc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/218gh7qu5keztaubzmf8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8yIVvTTc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/218gh7qu5keztaubzmf8.png" alt="Dropdown for state, with dropdown for cities with alphabetical sub-menus" width="664" height="358"&gt;&lt;/a&gt;&lt;/p&gt;
oof, Califorina



&lt;p&gt;You may write a functional test where a user navigates to the search page, selects a state and a city, and sees the correct legal information. The most complicated part of this test — and most likely point of failure — is the appearance and content of the second drop-down containing the city options.&lt;/p&gt;

&lt;p&gt;So here you might want to write unit tests to support your functional test. These tests could render only the form element and ensure that the second menu is not there when you load the page, that it contains the correct data for a state with 20 or fewer cities that have ordinances, and that the menu paginates properly for cities that have more than 20 cities.&lt;/p&gt;

&lt;p&gt;This type of unit test makes it easier to diagnose failing functional tests. If all of these unit tests pass and your functional test fails, you know that the problem lies elsewhere. But if you find a failing unit test, you know what you have to fix in order to get the functional test to pass.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unit tests confirm data sent to the server
&lt;/h2&gt;

&lt;p&gt;Your functional React tests generally don’t involve your server. It’s common to use a tool like &lt;a href="https://mswjs.io/"&gt;Mock Service Worker&lt;/a&gt; to simulate responses &lt;strong&gt;from&lt;/strong&gt; the server, but how do you know that your app is sending the correct data &lt;strong&gt;to&lt;/strong&gt; the server?&lt;/p&gt;

&lt;p&gt;For example, say you have a Redux action creator that processes form data and creates a &lt;a href="http://jsonpatch.com/"&gt;JSON patch&lt;/a&gt; to update an entity on the server. You may want to write unit tests for this action creator to make sure that the JSON patch includes all the necessary data (and none of the extraneous data) for particular sets of form inputs.&lt;/p&gt;

&lt;p&gt;This is testing implementation to be sure! The user neither knows nor cares about the exact data being passed to the server. However, functional tests usually don’t involve the actual server; that’s reserved for end-to-end tests. So this type of unit test will highlight where an end-to-end test is (or isn’t!) breaking down — or even better, prevent you from pushing code that breaks end-to-end tests in the first place.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unit tests for edge cases that don’t affect render
&lt;/h2&gt;

&lt;p&gt;It doesn’t always make sense to render the whole app (or even a particular component) to cover all the edge cases for a helper function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yOo5KZhO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lochb96isp838xapa41z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yOo5KZhO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lochb96isp838xapa41z.png" alt="input to guess a secret word, and table of previous guesses with count of letters that match the secret word for each guess" width="650" height="408"&gt;&lt;/a&gt;&lt;/p&gt;
spoiler alert: the secret word is “party”



&lt;p&gt;Imagine you have a word game app that needs to check how many letters a guess has in common with the “secret word.” You write a helper function for this, which can easily be unit-tested to make sure it does the right thing when (a) the guess has more than one of the same letter, (b) the secret word has more than one of the same letter, (c ) the word has all the same letters as the secret word, (d) the words have zero letters in common.&lt;/p&gt;

&lt;p&gt;The app does the same thing with the match count regardless of the above conditions, so it’s not necessary to render your JSX to test edge cases for this particular function. You will want to test this logic to make sure any added code doesn’t introduce errors, though. So here, unit tests of this function are the best way to go.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I have switched mostly to functional tests along with the prevailing best practices. However, I still use unit tests when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  my functional tests happen to test only one unit&lt;/li&gt;
&lt;li&gt;  there’s a likely point of failure in a longer functional test&lt;/li&gt;
&lt;li&gt;  I want to confirm that the correct data is sent to the server&lt;/li&gt;
&lt;li&gt;  I’m testing edge cases for a helper function that don’t affect rendering&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>react</category>
    </item>
    <item>
      <title>Testing React Apps that use React Router</title>
      <dc:creator>Bonnie Schulkin</dc:creator>
      <pubDate>Thu, 02 Jun 2022 22:52:22 +0000</pubDate>
      <link>https://dev.to/bonnie/testing-react-apps-that-use-react-router-2bmd</link>
      <guid>https://dev.to/bonnie/testing-react-apps-that-use-react-router-2bmd</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This post is about React Router 5, not React Router 6&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;So your React app, like a lot of modern apps, uses React Router to get users from one page to another. And you, like any thorough tester, want to account for React Router in your testing. This post will help you learn about the syntax to get you started testing React Router with your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our App
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;: you can find the&lt;/em&gt; &lt;a href="https://github.com/bonnie/react-router-testing" rel="noopener noreferrer"&gt;&lt;em&gt;code for this project on GitHub&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. It will not win any awards for design.&lt;/em&gt; 😝&lt;/p&gt;

&lt;p&gt;For the purposes of this post, we’ll imagine a restaurant website that looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Menus&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Menus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Locations&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Locations&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./About&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Our Restaurant&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/menus"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Menus&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/locations"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Locations&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* routing */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/menus"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Menus&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/locations/:id"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Locations&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;             
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/locations"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Locations&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;About&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note that the Router is not included in the App component.&lt;/strong&gt; I’ve included it in &lt;em&gt;src/index.js&lt;/em&gt; instead. By omitting it from the App component, we are able to use a test router in our tests which is more easily manipulated.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if using a test router feels too artificial?
&lt;/h3&gt;

&lt;p&gt;If you have qualms about using a different Router in your tests vs. production, you’ll probably want to to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Include the &lt;code&gt;Router&lt;/code&gt; in your &lt;code&gt;App&lt;/code&gt; component;&lt;/li&gt;
&lt;li&gt;  Always render the &lt;code&gt;App&lt;/code&gt; component in your tests (never child components like &lt;code&gt;Locations&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;  Navigate to your pages in tests by finding and clicking links on the page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The positives of this approach: you don’t need to read the rest of this post 🙃 (and your test setup will be less complicated). The negatives: you can’t immediately load a routing history (the current page and previous pages) in test setup; you need to go through all the user interactions to build the history.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Locations Component
&lt;/h2&gt;

&lt;p&gt;If you’re still here, then you’re interested in learning about using a different router in your tests. In this post, we’ll focus on the general locations page with no URL parameter:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/locations"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Locations&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And the specific page for a particular location id:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/locations/:id"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Locations&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Locations component uses &lt;code&gt;useParams&lt;/code&gt; to get the &lt;code&gt;:id&lt;/code&gt; URL param. If the &lt;code&gt;id&lt;/code&gt; param is falsy, that means the route was &lt;code&gt;/locations&lt;/code&gt; with no param, and, the component displays a list of location links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufms46f0b7998kbcfcvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufms46f0b7998kbcfcvg.png" alt="list of restaurant locations (San Francisco, Berkeley, Oakland) displayed at the  raw `/locations` endraw  route"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;id&lt;/code&gt; param is truthy, then it will display information for that particular location:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56kq8eatw12sxd7ottr6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56kq8eatw12sxd7ottr6.png" alt="the  raw `/locations/berkeley` endraw  route displays information about the berkeley location"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example code for the Locations component
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Locations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// We can use the `useParams` hook here to access&lt;/span&gt;
&lt;span class="c1"&gt;// the dynamic pieces of the URL.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useParams&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="c1"&gt;// in a real app, this info would come from the server&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locationData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;san-francisco&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;San Francisco&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123 Main Street&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;berkeley&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Berkeley&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;456 First Street&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;oakland&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Oakland&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;789 Elm Street&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="c1"&gt;// no id? then just list links for all the locations&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Locations&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locationData&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/locations/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="c1"&gt;// if there's an id URL parameter, give information about this location&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locationData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Location: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Including Router Context when Testing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: We will use* &lt;a href="http://jestjs.io/" rel="noopener noreferrer"&gt;&lt;em&gt;Jest&lt;/em&gt;&lt;/a&gt; &lt;em&gt;as a test runner and&lt;/em&gt; &lt;a href="https://testing-library.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Testing Library&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for rendering React components in this blog post.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s make a simple test for our Locations component in &lt;em&gt;Locations.test.js&lt;/em&gt;. No big deal, just seeing that it renders without error:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Locations&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Locations&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;renders without error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Locations&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Uh oh
&lt;/h3&gt;

&lt;p&gt;When we run this test with Jest, we get this ugliness:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kvc5f9awzi2v5u3cqyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kvc5f9awzi2v5u3cqyj.png" alt="Jest output with error at useParams: “Cannot read property ‘match’ of undefined”"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem is, we’re trying to use &lt;code&gt;useParams&lt;/code&gt; outside of a Router provider. No wonder Jest is confused.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Solution
&lt;/h3&gt;

&lt;p&gt;As luck would have it, Testing Library makes it easy to adapt its &lt;code&gt;render&lt;/code&gt; function to wrap with whatever your UI elements might need — be it the React Router provider, or any other type of provider (see “Including the Router and other Providers” below for rendering with multiple providers).&lt;/p&gt;

&lt;p&gt;The Testing Library React docs describe how to create &lt;a href="https://testing-library.com/docs/react-testing-library/setup#custom-render" rel="noopener noreferrer"&gt;a custom render that includes a wrapper&lt;/a&gt;. In our case, we could create this &lt;em&gt;test-utils.jsx&lt;/em&gt; file in our &lt;em&gt;src&lt;/em&gt; directory:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MemoryRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// create a customRender that wraps the UI in a memory Router&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customRender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MemoryRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// re-export everything&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// override render method&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;customRender&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, if we import &lt;code&gt;render&lt;/code&gt; (and &lt;code&gt;screen&lt;/code&gt;, and any other Testing Library imports) from this file instead of from &lt;code&gt;@testing-library/react&lt;/code&gt; all of our rendered components will be wrapped in a &lt;code&gt;MemoryRouter&lt;/code&gt; before being rendered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;: The React Router docs recommend&lt;/em&gt; &lt;code&gt;*MemoryRouter*&lt;/code&gt; &lt;em&gt;for testing; you can see other options in the&lt;/em&gt; &lt;a href="https://v5.reactrouter.com/web/guides/testing" rel="noopener noreferrer"&gt;&lt;em&gt;React Router testing docs&lt;/em&gt;&lt;/a&gt;&lt;em&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For the new and improved &lt;em&gt;Locations.test.js&lt;/em&gt;, simply change the first line to import from the &lt;em&gt;test-utils&lt;/em&gt; module:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./test-utils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Re-run the tests, and voila!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pf3rexzme38pixprts2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pf3rexzme38pixprts2.png" alt="passing tests!"&gt;&lt;/a&gt;&lt;/p&gt;
aaah, much better



&lt;h3&gt;
  
  
  Testing Location URL params
&lt;/h3&gt;

&lt;p&gt;Ok, so the component renders without error. That’s one test, but I want to know that it renders the &lt;em&gt;right thing&lt;/em&gt; without error. How can I specify what the route is?&lt;/p&gt;

&lt;p&gt;We’ll need to update our &lt;code&gt;render&lt;/code&gt; in &lt;em&gt;test-utils.jsx&lt;/em&gt; to accept an initial route, which we can feed to the &lt;code&gt;MemoryRouter&lt;/code&gt;. The “Memory” part means it stores routes in memory, as opposed to using a browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: In this case, we only need one initial route; in other cases, you might want to pass a whole array of historical routes (for example, if you were testing authentication that returned the user to the referring route).*&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a function for the render wrapper
&lt;/h3&gt;

&lt;p&gt;When we didn’t care about specifying initial routes, it was fine to specify the render &lt;code&gt;wrapper&lt;/code&gt; as the &lt;code&gt;MemoryRouter&lt;/code&gt; function in &lt;em&gt;test-utils.jsx&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MemoryRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;However, now we want to add a prop to &lt;code&gt;MemoryRouter&lt;/code&gt;, and things are going to get more interesting. The prop we want to add is &lt;code&gt;initialEntries&lt;/code&gt; , as recommended in the &lt;a href="https://reactrouter.com/web/guides/testing/starting-at-specific-routes" rel="noopener noreferrer"&gt;“Starting at Specific Routes” docs for React Router Testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because of that prop, we are going to have to make a new function for the &lt;code&gt;wrapper&lt;/code&gt; value. The &lt;code&gt;wrapper&lt;/code&gt; value has always been a function (&lt;code&gt;MemoryRouter&lt;/code&gt; is simply a functional component after all), but now we need to dig in and get our hands a little dirty.&lt;/p&gt;

&lt;p&gt;The function for &lt;code&gt;wrapper&lt;/code&gt; takes, among other props, &lt;code&gt;children&lt;/code&gt;. The &lt;a href="https://testing-library.com/docs/react-testing-library/setup#custom-render" rel="noopener noreferrer"&gt;Testing Library React setup docs for Custom Render&lt;/a&gt; show how to use the &lt;code&gt;children&lt;/code&gt; prop in a &lt;code&gt;wrapper&lt;/code&gt; function arg. This code does the same thing our previous code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MemoryRouterWithInitialRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MemoryRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MemoryRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customRender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MemoryRouterWithInitialRoutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But now we have some more room to maneuver.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passing initial entries to the wrapper function
&lt;/h3&gt;

&lt;p&gt;We want to be able to pass the initial entries to the options for the &lt;code&gt;render&lt;/code&gt; function, something like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;initialRoutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/locations/berkeley&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then we need to get this to the &lt;code&gt;MemoryRouterWithInitialRoutes&lt;/code&gt; function we wrote above, as the &lt;code&gt;initialEntries&lt;/code&gt; prop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1. Define &lt;code&gt;initialRoutes&lt;/code&gt; in &lt;code&gt;customRender&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;It’s important to have a default &lt;code&gt;initialRoutes&lt;/code&gt; of &lt;code&gt;["/"]&lt;/code&gt;, since &lt;code&gt;MemoryRouter&lt;/code&gt; spews errors if the array is empty. We can take care of that default in &lt;code&gt;customRender&lt;/code&gt; (no matter what the options array may or may not contain) like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialRoutes&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialRoutes&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 2. Pass &lt;code&gt;initialRoutes&lt;/code&gt; to &lt;code&gt;MemoryRouterWithInitialRoutes&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;Then we can pass our newly-defined &lt;code&gt;initialRoutes&lt;/code&gt; to &lt;code&gt;MemoryRouterWithInitialRoutes&lt;/code&gt; (along with the default args, so the function can still access &lt;code&gt;children&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;MemoryRouterWithInitialRoutes&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;initialRoutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 3. Use &lt;code&gt;initialRoutes&lt;/code&gt; parameter in &lt;code&gt;MemoryRouterWithInitialRoutes&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;and finally, &lt;code&gt;MemoryRouterWithInitialRoutes&lt;/code&gt; can make use of &lt;code&gt;initialRoutes&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MemoryRouterWithInitialRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialRoutes&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MemoryRouter&lt;/span&gt; &lt;span class="na"&gt;initialEntries&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;initialRoutes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MemoryRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Initial Routes in Action
&lt;/h4&gt;

&lt;p&gt;Whew, that was a lot of setup. The good news is, it’s relatively simple to use a in a test file. Let’s use it to test that the route does the right thing when we navigate to &lt;code&gt;"/locations/berkeley"&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;renders berkeley page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;initialRoutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/locations/berkeley&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;berkeleyHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;heading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/berkeley/i&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;berkeleyHeader&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, we’re looking for that &lt;strong&gt;Berkeley&lt;/strong&gt; header that we should see at &lt;code&gt;"/locations/berkeley"&lt;/code&gt; — and finding it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56kq8eatw12sxd7ottr6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56kq8eatw12sxd7ottr6.png" alt="the  raw `/locations/berkeley` endraw  route displays information about the berkeley location"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why App and not Locations?
&lt;/h3&gt;

&lt;p&gt;You might be wondering: why do the above examples render the &lt;code&gt;App&lt;/code&gt; component and not the &lt;code&gt;Locations&lt;/code&gt; component? It turns out, when you remove components from the React Router &lt;code&gt;Switch&lt;/code&gt; component, you don’t have access to the &lt;code&gt;[match](https://reactrouter.com/web/api/match)&lt;/code&gt; object (which contains the URL params, along with other route information).&lt;/p&gt;

&lt;p&gt;You can fix this by using &lt;code&gt;useRouteMatch&lt;/code&gt; in &lt;em&gt;Locations.jsx&lt;/em&gt; instead of &lt;code&gt;useParams&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// useParams: will not work with rendering Locations component&lt;/span&gt;
&lt;span class="c1"&gt;// const { id } = useParams();&lt;/span&gt;

&lt;span class="c1"&gt;// useRouteMatch: will work with rendering Locations component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouteMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/locations/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I would &lt;strong&gt;not recommend&lt;/strong&gt; this, however, as it’s generally not a great practice to complicate your production code merely for the sake of tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Including the Router and other Providers
&lt;/h2&gt;

&lt;p&gt;Remember &lt;code&gt;MemoryRouterWithInitialRoutes&lt;/code&gt; ?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MemoryRouterWithInitialRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialRoutes&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MemoryRouter&lt;/span&gt; &lt;span class="na"&gt;initialEntries&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;initialRoutes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MemoryRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This can be updated to add as many providers as you’d like. For example, if you want to add a &lt;a href="https://react-redux.js.org/api/provider" rel="noopener noreferrer"&gt;Redux&lt;/a&gt; provider and a &lt;a href="https://react-query.tanstack.com/" rel="noopener noreferrer"&gt;React Query&lt;/a&gt; provider:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MemoryRouterWithInitialRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialRoutes&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MemoryRouter&lt;/span&gt; &lt;span class="na"&gt;initialEntries&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;initialRoutes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;QueryClientProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MemoryRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You will have to create the* &lt;code&gt;*store*&lt;/code&gt; &lt;em&gt;for Redux&lt;/em&gt; &lt;a href="https://redux.js.org/api/createstore/" rel="noopener noreferrer"&gt;&lt;em&gt;the same way you would for the actual Provider&lt;/em&gt;&lt;/a&gt; &lt;em&gt;(not included in the code above). The good news is, you can also use this temporary test&lt;/em&gt; &lt;code&gt;*store*&lt;/code&gt; &lt;em&gt;to set up initial state for your tests.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You might want to update the name of the function at this point from &lt;code&gt;MemoryRouterWithInitialRoutes&lt;/code&gt; to &lt;code&gt;Providers&lt;/code&gt;. 🙃&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this is enough to get you started with testing apps that use React Router. As you can see, the setup is not simple! Fortunately, once you have the &lt;code&gt;MemoryRouter&lt;/code&gt; wrapping your &lt;code&gt;render&lt;/code&gt;, it’s more straightforward to apply routes in the test functions.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>react</category>
      <category>reactrouter</category>
    </item>
    <item>
      <title>Testing React: A convert’s journey from Enzyme to Testing Library</title>
      <dc:creator>Bonnie Schulkin</dc:creator>
      <pubDate>Thu, 02 Jun 2022 22:34:53 +0000</pubDate>
      <link>https://dev.to/bonnie/testing-react-a-converts-journey-from-enzyme-to-testing-library-5ai0</link>
      <guid>https://dev.to/bonnie/testing-react-a-converts-journey-from-enzyme-to-testing-library-5ai0</guid>
      <description>Image by &lt;a href="https://pixabay.com/users/wallace769-5217358/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=2264698" rel="noopener"&gt;Shri ram&lt;/a&gt; from &lt;a href="https://pixabay.com/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=2264698" rel="noopener"&gt;Pixabay&lt;/a&gt;




&lt;p&gt;I’m a big tester. Testing has saved my bacon enough times that I feel uneasy coding without it, like rock climbing without a rope. Even if I’m in a gym and the floor is really springy, a rope (like testing) helps minimize the damage when things inevitably go wrong.&lt;/p&gt;

&lt;p&gt;When I started learning React several years ago, &lt;a href="https://enzymejs.github.io/enzyme/"&gt;Enzyme&lt;/a&gt; was all the rage for test rendering and DOM manipulation. I come from an old-school back-end testing background (meticulous unit testing and isolation). Enzyme seemed great! I could take the same testing approach with React, testing state and other implementation details to my heart’s content.&lt;/p&gt;

&lt;p&gt;Then I started hearing about Testing Library (specifically &lt;a href="https://www.npmjs.com/package/@testing-library/react"&gt;testing-library/react&lt;/a&gt;). At first I was resistant: an opinionated library which enforced someone else’s ideas of “best practices”? My detailed unit testing approach was under threat! I steered clear.&lt;/p&gt;

&lt;p&gt;As time went by, it became clear Testing Library was here to stay, so I thought I’d check it out. After trying it for one project (my &lt;a href="https://github.com/bonnie/bonniedotdev"&gt;personal website&lt;/a&gt;), I am a total convert. Read on for my reasons why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opinionated === Best Practices
&lt;/h2&gt;

&lt;p&gt;Testing Library encourages your tests to interact with your code the same way your users would. For example: Find an element and click it. Then, instead of checking to see whether the &lt;em&gt;state&lt;/em&gt; changed (sorry, not an easy option in Testing Library!), check to see whether the &lt;em&gt;page&lt;/em&gt; changed in the way you expect.&lt;/p&gt;

&lt;p&gt;This is known as testing &lt;em&gt;behavior&lt;/em&gt; (what’s on the page) vs. testing &lt;em&gt;implementation&lt;/em&gt; (internal state). After all, user experience determines whether your code is working according to spec — not what state happens to be.&lt;/p&gt;

&lt;p&gt;The downside: when tests fail, there’s less granularity pointing to where exactly the tests failed (is the state the problem? Or is it something else in the onClick callback?). The upside: less test refactoring when your code changes. It’s a trade-off, but in front-end testing, I’m coming around to the “fewer, more robust tests” philosophy. The time spent tracking down errors is less significant than the time spent maintaining tests.&lt;/p&gt;

&lt;p&gt;I’ve especially come to appreciate this in the past year or so as React has moved from class-based components to functional components with hooks. If the behavior doesn’t change from the user perspective, there should be little-to-no cause to update tests when updating the implementation. Trends in React will continue to evolve, and your app can evolve with them without requiring a major testing overhaul.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessible Code
&lt;/h2&gt;

&lt;p&gt;Another opinion from Testing Library: &lt;a href="https://testing-library.com/docs/guide-which-query/"&gt;how to find page elements&lt;/a&gt; in your tests. The recommended element specifier is &lt;strong&gt;role&lt;/strong&gt;, which relies on the &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Accessibility_tree"&gt;accessibility tree&lt;/a&gt; (aka how elements appear to screen readers and other accessibility tools). Using role to find page elements for tests makes sure you have accessibility at top-of-mind while creating your content.&lt;/p&gt;

&lt;p&gt;You can also use Enzyme to find elements by role, but it is not nearly as easy: 1. You have to use the generic &lt;a href="https://enzymejs.github.io/enzyme/docs/api/ShallowWrapper/find.html"&gt;find&lt;/a&gt; method to find role attributes&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You have to account for cases for all attributes that represent role (for example, aria-role and role)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have to account for inferred roles (like the “button” role for a  element).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Testing Library, you get all these role indicators for free with the &lt;em&gt;getByRole&lt;/em&gt; method.&lt;/p&gt;

&lt;h2&gt;
  
  
  jest-dom Assertions
&lt;/h2&gt;

&lt;p&gt;Jest is pretty generic when it comes to &lt;a href="https://jestjs.io/docs/en/expect"&gt;assertions&lt;/a&gt;: You can test things like “does this variable have the right value?”, or “does this object have the expected property?”, or “was an error thrown?”, but there’s nothing specific to the DOM.&lt;/p&gt;

&lt;p&gt;Testing Library’s &lt;a href="https://github.com/testing-library/jest-dom"&gt;jest-dom&lt;/a&gt; to the rescue! Let’s say you want to know whether an element is visible on the page. You could use Enzyme to see whether the element &lt;a href="https://enzymejs.github.io/enzyme/docs/api/ShallowWrapper/hasClass.html"&gt;has the proper class&lt;/a&gt;, and use Jest’s &lt;code&gt;toBe&lt;/code&gt;, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toHaveClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hiddenClass&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, you could use jest-dom’s &lt;code&gt;[toBeVisible](https://github.com/testing-library/jest-dom#tobevisible)&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myElement&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By testing what the user sees (whether the element is visible, rather than whether it has a certain class), you’re testing &lt;em&gt;behavior&lt;/em&gt;, you savvy tester, you.&lt;/p&gt;

&lt;p&gt;There are also lots of other useful DOM specific assertions, for example: &lt;code&gt;[toHaveFocus](https://github.com/testing-library/jest-dom#tohavefocus)&lt;/code&gt; and &lt;code&gt;[toBeChecked](https://github.com/testing-library/jest-dom#tobechecked)&lt;/code&gt; . This makes for robust, concise, and extremely readable test code.&lt;/p&gt;

&lt;p&gt;Since the jest-dom assertions do not work with Enzyme wrapper objects, they are not available to use in Enzyme (at least not in any way I could figure out). Another item in the “plus” column for Testing Library.&lt;/p&gt;

&lt;h2&gt;
  
  
  ESLint Plugins
&lt;/h2&gt;

&lt;p&gt;To go even further in encouraging best practices, both &lt;a href="https://github.com/testing-library/eslint-plugin-testing-library"&gt;testing-library&lt;/a&gt; and &lt;a href="https://github.com/testing-library/eslint-plugin-jest-dom"&gt;jest-dom&lt;/a&gt; have ESLint plugins to give feedback when you’ve gone astray.&lt;/p&gt;

&lt;p&gt;For example, say you want to test that a checkbox is checked by default. You think to yourself, &lt;code&gt;[toHaveAttribute](https://github.com/testing-library/jest-dom#tohaveattribute)&lt;/code&gt; is the way to go! So you type out your test:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qd0TVmgA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/akilw4rgc2nrmwy0s0p5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qd0TVmgA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/akilw4rgc2nrmwy0s0p5.png" alt="jest-dom eslint hint for toHaveAttribute(‘checked’)" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait a minute… what’s that angry red line under &lt;code&gt;toHaveAttribute&lt;/code&gt;? A mouseover reveals that &lt;code&gt;[toBeChecked](https://github.com/testing-library/jest-dom#tobechecked)&lt;/code&gt; is preferred here. Nice way to be reminded of best practices (and even possibly learn a new assertion).&lt;/p&gt;

&lt;h2&gt;
  
  
  Helpful Hints on Roles
&lt;/h2&gt;

&lt;p&gt;Sometimes it’s hard to know which role to specify when searching for elements. Never fear — if you search for an element by role and Testing Library can’t find it, the test output tries to steer you right. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kuws0kP7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70gz14qj7x9pn4shry1m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kuws0kP7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/70gz14qj7x9pn4shry1m.png" alt="Test output shows “link” role instead of “heading” role for $12.99 text" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ooh! So I guess that element has a role of ‘link’ and not a role of ‘heading.’ Thanks, Testing Library. 😁&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I tinkered with Testing Library on a small project, and I can see why it’s gained so much momentum. The opinionated library encourages best practices such as testing behavior over implementation, and writing accessible code. Its jest-dom assertion library provides simple, readable tests. Finally, the ESLint plugins and test output help with best practices and finding elements. I am a big fan!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HJ_yBLuy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pw2zfwvvoa32ofg94ozi.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HJ_yBLuy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pw2zfwvvoa32ofg94ozi.jpeg" alt="photo of large fan" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;
Photo by &lt;a href="https://www.pexels.com/@enriquezafra?utm_content=attributionCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=pexels" rel="noopener"&gt;&lt;strong&gt;Enrique Zafra&lt;/strong&gt;&lt;/a&gt; from &lt;a href="https://www.pexels.com/photo/white-desk-fan-on-white-table-3675622/?utm_content=attributionCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=pexels" rel="noopener"&gt;&lt;strong&gt;Pexels&lt;/strong&gt;&lt;/a&gt;



</description>
      <category>testing</category>
      <category>react</category>
    </item>
    <item>
      <title>Testing Functions within Functional React Components</title>
      <dc:creator>Bonnie Schulkin</dc:creator>
      <pubDate>Thu, 02 Jun 2022 22:29:44 +0000</pubDate>
      <link>https://dev.to/bonnie/testing-functions-within-functional-react-components-1mba</link>
      <guid>https://dev.to/bonnie/testing-functions-within-functional-react-components-1mba</guid>
      <description>&lt;p&gt;People are switching to functional components in React, and class-based components are quickly becoming a thing of the past. However, with class-based components out of the picture, it’s much harder to access a function &lt;em&gt;within&lt;/em&gt; your functional component for &lt;a href="https://dev.to/bonnie/when-to-unit-test-your-react-app-4659"&gt;unit testing&lt;/a&gt;. A common question I get these days:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do I test functions inside my functional component?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The short answer: &lt;em&gt;you can’t&lt;/em&gt;. There is no way to access functions defined within a functional component for testing. But… if you’re reading this post, you probably don’t like that answer. Read on to see what your options are. 😊&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: Don’t unit test the functions
&lt;/h2&gt;

&lt;p&gt;Do any or all of the functions &lt;strong&gt;need&lt;/strong&gt; to be unit tested? The trend in React testing these days is &lt;em&gt;functional&lt;/em&gt; or &lt;em&gt;behavioral&lt;/em&gt; testing, which means testing the interface between your app and your user. Unit testing functions means you’re testing internals (that is, testing your code, instead of testing your app). This is generally frowned upon because it makes your tests brittle and subject to rewriting upon refactor.&lt;/p&gt;

&lt;p&gt;However, there are some cases where unit testing functions can be beneficial (for complex functions, or functions with edge cases that don’t affect the display layer). You can see &lt;a href="https://bonniedotdev.medium.com/when-to-unit-test-your-react-app-f5b211eb41c9"&gt;this blog post&lt;/a&gt; for my recommendations on when to unit test within React apps. If these reasons fit your situation, take a look at the other options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Move Functions Outside the Component
&lt;/h2&gt;

&lt;p&gt;Relocating functions to a &lt;a href="https://reactjs.org/docs/hooks-custom.html"&gt;custom hook&lt;/a&gt; makes them accessible for testing (plus you’re keeping business logic separate from the UI, in accordance with best practices). There’s even a library to help with testing custom hooks: &lt;a href="https://github.com/testing-library/react-hooks-testing-library"&gt;react-hooks-testing-library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s &lt;a href="https://github.com/bonnie/bonniedotdev/blob/5513fd5ff3384e44e396b33b6d477ce4788d462e/client/src/Hooks/useFilterTags.ts"&gt;an example of a custom hook with several related functions&lt;/a&gt; in my &lt;a href="https://bonnie.dev"&gt;website&lt;/a&gt; code. Note that I don’t test this particular hook separately from the UI because it fits under this category in “&lt;a href="https://github.com/testing-library/react-hooks-testing-library#when-not-to-use-this-library"&gt;When not to use the react-hooks library&lt;/a&gt;” : &lt;em&gt;Your hook is easy to test by just testing the components using it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Still, it’s an example of removing functionality from the functional component, so the component can focus solely on display. And I &lt;strong&gt;could&lt;/strong&gt; access the functions within the hook for testing if they matched the &lt;a href="https://github.com/testing-library/react-hooks-testing-library#when-to-use-this-library"&gt;reasons to use the react-hooks library&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; You’re writing a library with one or more custom hooks that are not directly tied to a component&lt;/li&gt;
&lt;li&gt; You have a complex hook that is difficult to test through component interactions&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Option 3: Use Class-Based Components
&lt;/h2&gt;

&lt;p&gt;This one might give you the heebie-jeebies — after all, you made a functional component to get &lt;strong&gt;away&lt;/strong&gt; from the complexity of class-based components. However, you always have this option if the first two options don’t work for you. Class-based components served the React community well for many years, and they are still supported by React. And to the point of this blog post, you can easily access functions within a class-based component as a property of the component.&lt;/p&gt;




&lt;p&gt;So there you have it: three options for testing functions within a functional component (none of which actually test functions within a functional component, since that’s just not possible). &lt;/p&gt;

</description>
      <category>testing</category>
      <category>react</category>
    </item>
    <item>
      <title>Getting Started with Redux and Testing Library</title>
      <dc:creator>Bonnie Schulkin</dc:creator>
      <pubDate>Thu, 02 Jun 2022 22:26:11 +0000</pubDate>
      <link>https://dev.to/bonnie/getting-started-with-redux-and-testing-library-36ln</link>
      <guid>https://dev.to/bonnie/getting-started-with-redux-and-testing-library-36ln</guid>
      <description>Photo by &lt;a href="https://unsplash.com/@saltsup?utm_source=medium&amp;amp;utm_medium=referral" rel="photo-creator noopener noreferrer"&gt;Piret Ilver&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="photo-source noopener noreferrer"&gt;Unsplash&lt;/a&gt;




&lt;p&gt;If you’re reading this, I’m guessing you’re testing a &lt;a href="https://redux.js.org/" rel="noopener noreferrer"&gt;Redux&lt;/a&gt; app with &lt;a href="https://testing-library.com/" rel="noopener noreferrer"&gt;Testing Library&lt;/a&gt;. And you probably want some tests to start with the Redux store in a particular state as the initial testing conditions.&lt;/p&gt;

&lt;p&gt;As you probably know, Testing Library &lt;a href="https://testing-library.com/docs/guiding-principles" rel="noopener noreferrer"&gt;emphasizes “testing behavior”&lt;/a&gt; (tests that interact with your app the way users would). Behavioral testing purists would say: to set up a Redux store with certain values, start the test by running through user interactions that populate the state.&lt;/p&gt;

&lt;p&gt;However, that’s simply not practical to do for every test, especially if the desired state needs a lot of interactions (and possibly server values) for setup. This blog post details how to set up a &lt;strong&gt;store factory&lt;/strong&gt; to generate a test store (with initial values) for test setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Store Factory
&lt;/h2&gt;

&lt;p&gt;The idea here is, you have a “factory function” to create a new store. This function creates the store for both production &lt;strong&gt;and&lt;/strong&gt; tests  to make sure your tests are as close as possible to production code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Here’s an example of a store factory function using &lt;a href="https://redux-toolkit.js.org/" rel="noopener noreferrer"&gt;Redux Toolkit&lt;/a&gt; and &lt;a href="https://redux-saga.js.org/" rel="noopener noreferrer"&gt;Redux Saga&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;EnhancedStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ThunkAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;createSagaMiddleware&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redux-saga&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createStoreWithMiddlewares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;EnhancedStore&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sagaMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSagaMiddleware&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;YOUR&lt;/span&gt; &lt;span class="nx"&gt;REDUCERS&lt;/span&gt; &lt;span class="nx"&gt;HERE&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getDefaultMiddleware&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;getDefaultMiddleware&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;prepend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sagaMiddleware&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;YOUR&lt;/span&gt; &lt;span class="nx"&gt;MIDDLEWARES&lt;/span&gt; &lt;span class="nx"&gt;HERE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;preloadedState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;sagaMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;YOUR&lt;/span&gt; &lt;span class="nx"&gt;ROOT&lt;/span&gt; &lt;span class="nx"&gt;SAGA&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s another one using &lt;a href="https://redux.js.org/" rel="noopener noreferrer"&gt;Redux&lt;/a&gt; and &lt;a href="https://github.com/reduxjs/redux-thunk" rel="noopener noreferrer"&gt;Redux Thunk&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;applyMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReduxThunk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-thunk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ReduxThunk&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createStoreWithMiddlewares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}):&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;YOUR&lt;/span&gt; &lt;span class="nx"&gt;REDUCERS&lt;/span&gt; &lt;span class="nx"&gt;HERE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;applyMiddleware&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both of these store factories have a &lt;code&gt;createStoreWithMiddlewares&lt;/code&gt; function that takes an &lt;code&gt;initialState&lt;/code&gt; and can be used to create either the production store or a test store — with the same configuration. You can use these examples to write a &lt;code&gt;createStoreWithMiddlewares&lt;/code&gt; for your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the Store Factory: Production
&lt;/h3&gt;

&lt;p&gt;The production store can be created using &lt;code&gt;createStoreWithMiddlewares&lt;/code&gt; either in your &lt;em&gt;store/index.js&lt;/em&gt; file or &lt;em&gt;src/index.js&lt;/em&gt;, and added as the &lt;code&gt;store&lt;/code&gt; prop to the &lt;a href="https://redux.js.org/tutorials/fundamentals/part-5-ui-react#passing-the-store-with-provider" rel="noopener noreferrer"&gt;Redux Provider&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s &lt;strong&gt;very important&lt;/strong&gt; to add the Redux Provider in &lt;em&gt;src/index.js&lt;/em&gt; and &lt;strong&gt;not&lt;/strong&gt; in &lt;em&gt;App.js&lt;/em&gt;! If &lt;em&gt;App.js&lt;/em&gt; contains the Redux Provider with the production store, then you won’t be able to test the &lt;code&gt;App&lt;/code&gt; component with your test store, since the actual production store will be used when you render &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Store Factory: Tests
&lt;/h2&gt;

&lt;p&gt;Now that the production Redux Provider has been relegated to &lt;em&gt;index.js&lt;/em&gt;, we have total control over the store for our tests. Follow these steps and delight in the power!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Custom Render Function
&lt;/h3&gt;

&lt;p&gt;We can overwrite &lt;a href="https://testing-library.com/docs/react-testing-library/api#render" rel="noopener noreferrer"&gt;the Testing Library&lt;/a&gt; &lt;code&gt;[render](https://testing-library.com/docs/react-testing-library/api#render)&lt;/code&gt; &lt;a href="https://testing-library.com/docs/react-testing-library/api#render" rel="noopener noreferrer"&gt;function&lt;/a&gt; with &lt;a href="https://testing-library.com/docs/react-testing-library/setup#custom-render" rel="noopener noreferrer"&gt;a custom render&lt;/a&gt; that includes a Redux Provider with a private store just for that test. Write this code in, say, &lt;em&gt;src/test-utils/index.tsx&lt;/em&gt; (actual file location and name are not important. Also, if you’re not using Typescript, you’ll probably want to use &lt;em&gt;index.jsx&lt;/em&gt; instead of &lt;em&gt;index.tsx&lt;/em&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EnhancedStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// for redux-toolkit&lt;/span&gt;
&lt;span class="c1"&gt;// import { Store } from 'redux' // for non-toolkit&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;rtlRender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;RenderOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;RenderResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStoreWithMiddlewares&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RootState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ReduxRenderOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;preloadedState&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;RootState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;EnhancedStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// for redux-toolkit&lt;/span&gt;
  &lt;span class="c1"&gt;// store?: Store // for non-toolkit&lt;/span&gt;
  &lt;span class="nx"&gt;renderOptions&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RenderOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wrapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;preloadedState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStoreWithMiddlewares&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;preloadedState&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;renderOptions&lt;/span&gt;
  &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ReduxRenderOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RenderResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Provider&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;rtlRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;renderOptions&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// re-export everything&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// override render method&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(this code is adapted from the &lt;a href="https://redux.js.org/usage/writing-tests#components" rel="noopener noreferrer"&gt;Redux Testing Docs&lt;/a&gt;). Note that the Typescript is different for Redux-Toolkit than for plain Redux; use the lines that apply to your project (or no Typescript at all if that’s your jam).&lt;/p&gt;

&lt;p&gt;The idea with the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The custom render in this doc takes a &lt;code&gt;preloadedState&lt;/code&gt; and UI component.&lt;/li&gt;
&lt;li&gt;  The custom render wraps the UI component in a Redux Provider, with a store that contains the &lt;code&gt;preloadedState&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  The code exports everything from &lt;em&gt;@testing-library/react&lt;/em&gt; and then overrides the &lt;code&gt;render&lt;/code&gt; method, so this file can be used &lt;strong&gt;in place of&lt;/strong&gt; the actual &lt;em&gt;@testing-library/react&lt;/em&gt; module (as we’ll see when we use it).&lt;/li&gt;
&lt;li&gt;  When importing from this file instead of &lt;em&gt;@testing-library/react,&lt;/em&gt; all the methods except &lt;code&gt;render&lt;/code&gt; (such as &lt;code&gt;screen&lt;/code&gt; or &lt;code&gt;fireEvent&lt;/code&gt;) will come straight from &lt;em&gt;@testing-library/react&lt;/em&gt; — except &lt;code&gt;render&lt;/code&gt;, which has been replaced with our custom &lt;code&gt;render&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that you can create a store beforehand and pass it to the &lt;code&gt;render&lt;/code&gt; function, or you can use the default, which is creating a new store with your &lt;code&gt;preloadedState&lt;/code&gt;, using all of the configuration from the &lt;code&gt;configureStoreWithMiddlewares&lt;/code&gt; function that our production uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStoreWithMiddlewares&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;preloadedState&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do create a store and pass it as an argument, it’s &lt;strong&gt;very important that a new store is created for every test&lt;/strong&gt; (so that there’s no sharing of state between tests).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Using custom render in tests
&lt;/h3&gt;

&lt;p&gt;To use this custom render in a test, we’ll import from our &lt;em&gt;test-utils/index.tsx&lt;/em&gt; file instead of from &lt;em&gt;@testing-library/react&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Say you have a user profile page, that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1tdqswsl0sz537796pxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1tdqswsl0sz537796pxc.png" alt="user profile web page showing user name and email"&gt;&lt;/a&gt;&lt;/p&gt;
our web site has won numerous awards for our clean, spare style 😝



&lt;p&gt;The &lt;code&gt;UserProfile&lt;/code&gt; component might look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EnhancedStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// for redux-toolkit&lt;/span&gt;
&lt;span class="c1"&gt;// import { Store } from 'redux' // for non-toolkit&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;rtlRender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;RenderOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;RenderResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStoreWithMiddlewares&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RootState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ReduxRenderOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;preloadedState&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;RootState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;EnhancedStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// for redux-toolkit&lt;/span&gt;
  &lt;span class="c1"&gt;// store?: Store // for non-toolkit&lt;/span&gt;
  &lt;span class="nx"&gt;renderOptions&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RenderOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wrapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;preloadedState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStoreWithMiddlewares&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;preloadedState&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;renderOptions&lt;/span&gt;
  &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ReduxRenderOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RenderResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Provider&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;rtlRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;renderOptions&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// re-export everything&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// override render method&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that the &lt;code&gt;user&lt;/code&gt; piece of state has &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt; properties. To test that the user &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt; show on the profile page, you need to preload the state with a user object for the test.&lt;/p&gt;

&lt;p&gt;Here’s how the tests might look with our custom &lt;code&gt;render&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../test-utils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// adjust for relative path to *your* test-utils directory &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./UserProfile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fakeUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tess Q. User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tess-user@fake.domain.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User profile shows name and email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;preloadedState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fakeUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tess Q. User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tess-user@fake.domain.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the steps in the custom &lt;code&gt;render&lt;/code&gt; method that make this work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The custom &lt;code&gt;render&lt;/code&gt; method uses the &lt;code&gt;preloadedState&lt;/code&gt; option (and the &lt;code&gt;createStoreWithMiddlewares&lt;/code&gt; function used in production) to create a new store.&lt;/li&gt;
&lt;li&gt; The custom &lt;code&gt;render&lt;/code&gt; method then creates a wrapper with a Redux Provider, passing the store with the preloaded state as a prop.&lt;/li&gt;
&lt;li&gt; The custom &lt;code&gt;render&lt;/code&gt; method uses the &lt;em&gt;actual&lt;/em&gt; testing-library/react &lt;code&gt;render&lt;/code&gt; to render the &lt;code&gt;ui&lt;/code&gt; argument (in this case, &lt;code&gt;&amp;lt;UserProfile /&amp;gt;&lt;/code&gt;) wrapped in the newly-created Provider from step 2, and returns the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This result now has the store pre-populated with the specified user, the &lt;code&gt;useSelector&lt;/code&gt; call in the component returns the &lt;code&gt;fakeUser&lt;/code&gt;, and the tests pass.&lt;/p&gt;

</description>
      <category>redux</category>
      <category>testinglibrary</category>
      <category>testing</category>
      <category>react</category>
    </item>
    <item>
      <title>Udemy, Enzyme and React 18</title>
      <dc:creator>Bonnie Schulkin</dc:creator>
      <pubDate>Thu, 02 Jun 2022 22:14:42 +0000</pubDate>
      <link>https://dev.to/bonnie/udemy-enzyme-and-react-18-4obm</link>
      <guid>https://dev.to/bonnie/udemy-enzyme-and-react-18-4obm</guid>
      <description>Photo by &lt;a href="https://unsplash.com/@sigmund?utm_source=medium&amp;amp;utm_medium=referral" rel="photo-creator noopener"&gt;Sigmund&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral" rel="photo-source noopener"&gt;Unsplash&lt;/a&gt;




&lt;p&gt;I’ve gotten some questions about my &lt;a href="https://www.udemy.com/course/react-testing-with-jest-and-enzyme/?referralCode=3A42BF689E28CADB0587"&gt;Udemy course on Enzyme&lt;/a&gt; in light of the React 18 release, so I wanted to write an article with my thoughts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enzyme and React 18
&lt;/h2&gt;

&lt;p&gt;tl;dr: Enzyme is not compatible with React 18, and probably never will be. I recommend React Testing Library instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The History
&lt;/h2&gt;

&lt;p&gt;I started writing the Udemy course in March 2018, and it was published in May 2018. At that time, Enzyme was the primary option for testing React components with Jest. React Testing Library (Enzyme’s current prime competitor) had &lt;a href="https://github.com/testing-library/react-testing-library/compare/v0.0.0...v0.1.0"&gt;just been released in March 2018&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since that time, a few things have happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  In June 2020, Enzyme &lt;a href="https://medium.com/airbnb-engineering/phase-ii-enzyme-d9efa717e297"&gt;switched from being maintained by Airbnb to being maintained by an individual&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  In October 2020, &lt;a href="https://reactjs.org/blog/2020/10/20/react-v17.html"&gt;React 17 was released&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Also in October 2020, an &lt;a href="https://github.com/wojtekmaj/enzyme-adapter-react-17/releases/tag/v0.2.0"&gt;unofficial Enzyme adapter for React 17&lt;/a&gt; was released.&lt;/li&gt;
&lt;li&gt;  In December 2021, the author of the unofficial adapter for React 17 wrote &lt;a href="https://dev.to/wojtekmaj/enzyme-is-dead-now-what-ekl"&gt;an article entitled Enzyme is Dead&lt;/a&gt;, where he stated that he would not be writing an adapter for React 18.&lt;/li&gt;
&lt;li&gt;  In March 2022, &lt;a href="https://github.com/facebook/react/releases/tag/v18.0.0"&gt;React 18 was released&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  In April 2022, the Enzyme maintainer has stated that &lt;a href="https://github.com/enzymejs/enzyme/issues/2556#issuecomment-1086869881"&gt;he will work on a React 17 adapter before a React 18 adapter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  As of June 2022, &lt;a href="https://github.com/enzymejs/enzyme/issues/2429"&gt;the official adapter for React 17&lt;/a&gt; has not been released.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I currently recommend React Testing Library
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://testing-library.com/docs/react-testing-library/intro/"&gt;React Testing Library&lt;/a&gt; and Enzyme do the same job: rendering components so that they can be tested with Jest. I recommend React Testing Library over Enzyme for these reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Unlike Enzyme, &lt;a href="https://testing-library.com/docs/react-testing-library/intro/"&gt;React Testing Library&lt;/a&gt; does not rely on React internals. This means React Testing Library &lt;strong&gt;does not have an adapter&lt;/strong&gt; that needs to be updated with each release of React, and is far less likely to have issues with new React versions.&lt;/li&gt;
&lt;li&gt; I find React Testing Library to be &lt;a href="https://dev.to/bonnie/testing-react-a-converts-journey-from-enzyme-to-testing-library-5ai0"&gt;easier to use&lt;/a&gt; than Enzyme.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What all this means for the Udemy course
&lt;/h2&gt;

&lt;p&gt;Now that React 18 has come out and there’s no React 17 adapter in sight, I don’t believe there’s a future for Enzyme. I &lt;strong&gt;would not recommend this course&lt;/strong&gt; for people who are looking to learn how to test new React applications. Instead I would recommend you find a course on React Testing Library. (I have &lt;a href="https://www.udemy.com/course/react-testing-library/?referralCode=0B60E8FEB40F0D159E84"&gt;a recommendation&lt;/a&gt; 😂 — see my &lt;a href="https://bonnie.dev/courses"&gt;website&lt;/a&gt; for coupons)&lt;/p&gt;

&lt;p&gt;That said, there are still &lt;a href="https://www.npmjs.com/package/enzyme"&gt;around 2.1 million downloads of Enzyme&lt;/a&gt; a week (as of June 2022). Here are the circumstances under which I would recommend learning Enzyme:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; You are working on a legacy project that already has a large suite of Enzyme tests, and the project never intends to upgrade to React 18.&lt;/li&gt;
&lt;li&gt; You are working on a project with a large suite of existing Enzyme tests, and you wish to understand these tests before migrating to React Testing Library (RTL). However, Wojciech Maj, the author of the unoffiical Enzyme adapter for React 17, &lt;a href="https://dev.to/wojtekmaj/enzyme-is-dead-now-what-ekl"&gt;suggests&lt;/a&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;While &lt;a href="https://testing-library.com/docs/react-testing-library/migrate-from-enzyme"&gt;Migrate from Enzyme support article&lt;/a&gt; is available, I suggest you to just start fresh, forgetting that Enzyme has ever existed. &lt;strong&gt;RTL is by no means an Enzyme drop-in replacement&lt;/strong&gt;, so having a completely fresh mindset will help you getting the most of it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Enzyme was a great way to test React applications when this course came out; however, I can no longer recommend it. I encourage you to study React Testing Library instead.&lt;/p&gt;

</description>
      <category>enzyme</category>
      <category>testing</category>
      <category>udemy</category>
      <category>react</category>
    </item>
    <item>
      <title>ESLint, Prettier and VSCode Troubleshooting</title>
      <dc:creator>Bonnie Schulkin</dc:creator>
      <pubDate>Thu, 02 Jun 2022 21:54:48 +0000</pubDate>
      <link>https://dev.to/bonnie/eslint-prettier-and-vscode-troubleshooting-ljh</link>
      <guid>https://dev.to/bonnie/eslint-prettier-and-vscode-troubleshooting-ljh</guid>
      <description>&lt;p&gt;ESLint and Prettier can make coding so much easier with VSCode. I can’t tell you how many mistakes it catches in my code that are easily fixed in the moment — but would be difficult to track down as bugs later on.&lt;/p&gt;

&lt;p&gt;But what if your problem is getting ESLint / Prettier to work with VSCode? See below for some troubleshooting tips. I’ve sorted the tips into three general symptoms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Symptom 1&lt;/strong&gt;: VSCode does not highlight errors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Symptom 2&lt;/strong&gt;: VSCode does not format on save&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Symptom 3&lt;/strong&gt;: ESLint generates hundreds of “Delete &lt;code&gt;␍&lt;/code&gt; prettier/prettier error"s&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Symptom 1: VSCode does not highlight errors&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s say you’ve gotten ESLint and Prettier set up, but VSCode is not highlighting errors:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1f76gjg674tf584ydbe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1f76gjg674tf584ydbe.png" alt="No errors or warnings highlighted" width="695" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyohsg4c2khwsrec23vuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyohsg4c2khwsrec23vuh.png" alt="Errors and warnings highlighted" width="698" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some things to look into:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. ESLint and Prettier installation
&lt;/h3&gt;

&lt;p&gt;Make sure &lt;a href="https://eslint.org/docs/user-guide/getting-started#installation-and-usage" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; and &lt;a href="https://prettier.io/docs/en/install.html" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; are installed for your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. ESLint Plugin for VSCode
&lt;/h3&gt;

&lt;p&gt;Make sure the &lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;ESLint plugin for VSCode&lt;/a&gt; is installed and enabled.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfftwqieub2sekmvsrz7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfftwqieub2sekmvsrz7.png" alt="What the ESLint plugin looks like in VSCode when it’s installed and enabled" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. ESLint Configuration File
&lt;/h3&gt;

&lt;p&gt;Make sure you have an &lt;a href="https://eslint.org/docs/user-guide/configuring/configuration-files#configuration-file-formats" rel="noopener noreferrer"&gt;ESLint configuration file&lt;/a&gt; at the top level of your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. eslint-plugin-prettier
&lt;/h3&gt;

&lt;p&gt;I strongly prefer to use &lt;a href="https://github.com/prettier/eslint-plugin-prettier" rel="noopener noreferrer"&gt;eslint-plugin-prettier&lt;/a&gt; and configure Prettier within my ESLint configuration file (rather than maintain two configuration files).&lt;/p&gt;

&lt;h3&gt;
  
  
  5. VSCode Default Formatter Setting
&lt;/h3&gt;

&lt;p&gt;Make sure the default formatter in &lt;a href="https://code.visualstudio.com/docs/getstarted/settings" rel="noopener noreferrer"&gt;VSCode Settings&lt;/a&gt; is set to ESLint. Check both the User settings and the Workspace settings (Workspace takes precedence over User).&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmry5x7bol7jlsc6u817.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmry5x7bol7jlsc6u817.png" alt="Default Formatter in VSCode settings" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. VSCode “Workspace” Directory
&lt;/h3&gt;

&lt;p&gt;Make sure the directory you opened in VSCode (aka the &lt;a href="https://code.visualstudio.com/docs/editor/workspaces" rel="noopener noreferrer"&gt;workspace&lt;/a&gt;) is the top level of your project. For example, say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your project lives at &lt;code&gt;/usr/src/my-project&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;your ESLint configuration file is at &lt;code&gt;/usr/src/my-project/.eslintrc.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you open any directory &lt;strong&gt;other than&lt;/strong&gt; &lt;code&gt;/usr/src/my-project&lt;/code&gt; as the workspace in VSCode (for example &lt;code&gt;/usr/src&lt;/code&gt; or &lt;code&gt;/usr/src/my-project/client&lt;/code&gt;), then VSCode &lt;strong&gt;won’t recognize&lt;/strong&gt; the ESLint configuration file.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. ESLint Configuration Errors
&lt;/h3&gt;

&lt;p&gt;Check for ESLint configuration errors: open the &lt;a href="https://code.visualstudio.com/docs/editor/integrated-terminal" rel="noopener noreferrer"&gt;VSCode Terminal&lt;/a&gt;, go to the Output tab, and choose ESLint from the dropdown:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fteanxtkqbpur5k4dir55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fteanxtkqbpur5k4dir55.png" alt="the Output tab of the VSCode terminal, with ESLint selected" width="800" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  8. ESLint overrideConfigFile Configuration
&lt;/h3&gt;

&lt;p&gt;Check to see whether you have an ESLint &lt;code&gt;overrideConfigFile&lt;/code&gt; &lt;a href="https://eslint.org/docs/developer-guide/nodejs-api#-new-eslintoptions" rel="noopener noreferrer"&gt;option&lt;/a&gt; in &lt;a href="https://code.visualstudio.com/docs/getstarted/settings" rel="noopener noreferrer"&gt;VSCode settings&lt;/a&gt;. If this option exists, make sure there’s a configuration file in that location.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpa52y4z77oqx0qipuhnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpa52y4z77oqx0qipuhnl.png" alt="ESLint option settings in VSCode" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  9. ESLint Working Directories in VSCode
&lt;/h3&gt;

&lt;p&gt;Check to see if your file is excluded from the ESLint Working Directories in your &lt;a href="https://code.visualstudio.com/docs/getstarted/settings" rel="noopener noreferrer"&gt;VSCode User or Workspace settings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1e5n7mew1sv7dll5hea7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1e5n7mew1sv7dll5hea7.png" alt="Settings search for ESLint working directories" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Symptom 2: VSCode does not format on save&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. VSCode “Format on Save” settings
&lt;/h3&gt;

&lt;p&gt;Make sure your &lt;a href="https://code.visualstudio.com/docs/getstarted/settings" rel="noopener noreferrer"&gt;VSCode settings&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;have “Format on Save” enabled&lt;/li&gt;
&lt;li&gt;have “Format on Save Mode” set to “file”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3675vpkzfmcqwkcotfdf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3675vpkzfmcqwkcotfdf.png" alt="“Format on Save” settings in VSCode" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. VSCode “code actions on save” setting
&lt;/h3&gt;

&lt;p&gt;Make sure your &lt;a href="https://code.visualstudio.com/docs/getstarted/settings" rel="noopener noreferrer"&gt;VSCode settings&lt;/a&gt; include ESLint in the “code actions on save”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwtuwzgwtfn4vyg7jiud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwtuwzgwtfn4vyg7jiud.png" alt="VSCode " width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In settings.json, there should be an entry like this:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;"editor.codeActionsOnSave": &lt;br&gt;
  {&lt;br&gt;
    "source.fixAll.eslint": true&lt;br&gt;
  },&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  

&lt;ol&gt;
&lt;li&gt;Not all ESLint errors are “auto-fixable”
&lt;/li&gt;
&lt;/ol&gt;
&lt;/h3&gt;


&lt;p&gt;Note that some ESLint errors won’t be auto-fixed on save, because they are not auto-fixable. To use &lt;a href="https://github.com/testing-library/eslint-plugin-testing-library" rel="noopener noreferrer"&gt;eslint-plugin-testing-library&lt;/a&gt; as an example, this error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sstsoclsccy7ofs1re1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sstsoclsccy7ofs1re1.png" alt="highlighted error for using toHaveAttribute(" width="800" height="47"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;auto-fixes to this on save:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0k8tmyr1gp5hxy20ikjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0k8tmyr1gp5hxy20ikjz.png" alt="corrected syntax using toBeChecked" width="800" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But this linting error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0h8adyjwui4z6ikuaub5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0h8adyjwui4z6ikuaub5.png" alt="Linting highlight for using screen.debug()" width="364" height="70"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;is not auto-fixable, so doesn’t update on save.&lt;/p&gt;




&lt;h2&gt;
  
  
  Symptom 3: ESLint generates hundreds of “Delete &lt;code&gt;␍&lt;/code&gt; prettier/prettier error”&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This might occur if you are on a Windows computer, but the code was generated on a Mac or Linux computer. The error might also look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2boebsfdasjxjza07tw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2boebsfdasjxjza07tw.png" alt="Alternate representation of ␍ character" width="436" height="46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some things to try: &lt;/p&gt;

&lt;h3&gt;
  
  
  1. Run &lt;code&gt;prettier&lt;/code&gt; from the command line
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;prettier&lt;/code&gt; on all of the files in the project (reference: &lt;a href="https://create-react-app.dev/docs/setting-up-your-editor/#formatting-code-automatically" rel="noopener noreferrer"&gt;create-react-app docs&lt;/a&gt;):&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;./node_modules/.bin/prettier --write "src/*&lt;em&gt;/&lt;/em&gt;.{js,jsx,ts,tsx,json,css,scss,md}"&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  

&lt;ol&gt;
&lt;li&gt;Update the prettier/prettier “endOfLine” rule
&lt;/li&gt;
&lt;/ol&gt;
&lt;/h3&gt;


&lt;p&gt;Update the prettier/prettier rule in the &lt;a href="https://eslint.org/docs/user-guide/configuring/configuration-files#configuration-file-formats" rel="noopener noreferrer"&gt;ESLint configuration file&lt;/a&gt; (reference: &lt;a href="https://stackoverflow.com/questions/53516594/why-do-i-keep-getting-delete-cr-prettier-prettier/53769213#53769213" rel="noopener noreferrer"&gt;StackOverflow&lt;/a&gt;):&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;"prettier/prettier": [&lt;br&gt;
  "error",&lt;br&gt;
  {&lt;br&gt;
    "endOfLine": "auto"&lt;br&gt;
  }&lt;br&gt;
],&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  

&lt;ol&gt;
&lt;li&gt;Set line endings in VSCode settings
&lt;/li&gt;
&lt;/ol&gt;
&lt;/h3&gt;


&lt;p&gt;Set the line endings in &lt;a href="https://code.visualstudio.com/docs/getstarted/settings#_settingsjson" rel="noopener noreferrer"&gt;.vscode/settings.json&lt;/a&gt; (reference: &lt;a href="https://stackoverflow.com/questions/53516594/why-do-i-keep-getting-delete-cr-prettier-prettier/64712055#64712055" rel="noopener noreferrer"&gt;StackOverflow&lt;/a&gt;):&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;{&lt;br&gt;
    "files.eol": "\n",&lt;br&gt;
}&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  

&lt;ol&gt;
&lt;li&gt;Update your global git settings
&lt;/li&gt;
&lt;/ol&gt;
&lt;/h3&gt;


&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; this will update your &lt;a href="https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration" rel="noopener noreferrer"&gt;global git settings&lt;/a&gt; and &lt;strong&gt;will affect ALL of your git projects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;git config --global core.autocrlf true&lt;/code&gt; and pull the code from GitHub again (or possibly re-clone the repo). (Reference: &lt;a href="https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings#global-settings-for-line-endings" rel="noopener noreferrer"&gt;GitHub docs&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Consider using Windows Subsystem for Linux
&lt;/h3&gt;

&lt;p&gt;Anecdotally, I did not get this error on my Windows laptop when using &lt;a href="https://apps.microsoft.com/store/detail/ubuntu-20044-lts/9MTTCL66CPXJ?hl=en-us&amp;amp;gl=US" rel="noopener noreferrer"&gt;Ubuntu 20.04 on Windows Subsystem for Linux&lt;/a&gt; (even though other Windows users -- who were likely using PowerShell -- reported the error for the same GitHub repository).&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>eslint</category>
      <category>prettier</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
