<?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: Jordan Los</title>
    <description>The latest articles on DEV Community by Jordan Los (@jordanlos).</description>
    <link>https://dev.to/jordanlos</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%2F816250%2Fd33545b6-d736-4ce4-b55b-ad1ebb0fefdf.png</url>
      <title>DEV Community: Jordan Los</title>
      <link>https://dev.to/jordanlos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jordanlos"/>
    <language>en</language>
    <item>
      <title>Interpreted Languages: Reading Source Code</title>
      <dc:creator>Jordan Los</dc:creator>
      <pubDate>Thu, 07 Jul 2022 15:12:04 +0000</pubDate>
      <link>https://dev.to/jobber/interpreted-languages-reading-source-code-2b2o</link>
      <guid>https://dev.to/jobber/interpreted-languages-reading-source-code-2b2o</guid>
      <description>&lt;h3&gt;
  
  
  Types of Reading
&lt;/h3&gt;

&lt;p&gt;In my previous article, &lt;a href="https://dev.to/jobber/serious-jest-making-sense-of-hoisting-253i"&gt;Serious Jest: Making Sense of Hoisting&lt;/a&gt;, I noted the &lt;a href="https://jestjs.io/docs/manual-mocks#using-with-es-module-imports"&gt;Jest docs&lt;/a&gt; say they hoist their mocks. Hoisting means the Javascript engine assigns references in memory to some objects before executing code. But for Jest, hoisting is executing mock statements before import statements. So even if you define mocks after your imports, they will execute first. That Jest uses hoist to mean something different is not at all obvious and why I wrote the article.&lt;/p&gt;

&lt;p&gt;After posting, I was asked how I made the connection. The short answer is I spent a bunch of time stepping through Jest source code in my debugger. The longer answer is I followed a process I picked up in the humanities. Reading Plutarch's Parallel Lives may not seem like reading source code, but you have the same goal. You read to understand the intentions and ideas of another person.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How To Read a Book&lt;/em&gt; by Mortimer J. Adler and Charles Van Doren best describes the reading process. They describe four types of reading: elementary, inspectional, analytical, and syntoptical. Each type of reading played a crucial role in researching and writing the last article. I’ve structured this article around them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elementary Reading
&lt;/h3&gt;

&lt;p&gt;Elementary Reading is being able to understand the grammar and syntax of a language. This level of reading is the prerequisite to understanding another person's ideas. There's not much to discuss at this level of reading for our purposes.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Inspectional Reading
&lt;/h3&gt;

&lt;p&gt;Inspectional reading is strategic skimming. You want to grasp, as quickly as possible, the structure and meaning of a work. The sooner you learn the structure of a work, the sooner you can grasp its finer points. This means skimming the chapters, watching the movie first, or listening to a podcast.&lt;/p&gt;

&lt;p&gt;The same principles apply to code. Skim docs, look at function names, and read short articles. By the end, you should have familiarity with key concepts, files, and docs. I read blogs on hoisting, browsed the Jest source code on Github, and watched a few youtube videos. I identified two critical areas while inspectional reading: the ECMAScript spec and a few key files in the Jest repo. I also had notes on scopes, closures, and the Javascript Execution Context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analytical reading
&lt;/h3&gt;

&lt;p&gt;Analytical reading means reading for intent, structure, and relations. Different genres have different rules for these things as does code. Some parts of a file are "the main point" while others serve a supporting purpose. Since analytical reading is the most time-consuming and fruitful, prefer primary sources. Formal specs and source files are harder to read than summaries. But source docs give you unfiltered detail at a granular level. How do you know that blog post didn’t miss something relevant to your problem? If you haven’t read specs and source files, you’re trusting someone else’s interpretation.&lt;/p&gt;

&lt;p&gt;I started with the &lt;a href="https://tc39.es/ecma262/#sec-executable-code-and-execution-contexts"&gt;ECMAScript spec section 9&lt;/a&gt;. It didn't have any direct answers, but I had a better mental model of what was happening when my tests ran. The ECMAScript spec made sense of the &lt;code&gt;Closure&lt;/code&gt; section of the &lt;code&gt;Scope&lt;/code&gt; tab in Chrome DevTools. Monitoring the closures section during debugging helped answer several of my questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up the Debugger&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;node --inspect node_modules/.bin/jest --runInBand path/to/your/test&lt;/code&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open up Chrome and go to &lt;code&gt;chrome://inspect&lt;/code&gt;and click Open dedicated DevTools for Node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open up your test file in Sources tab and run your tests&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using the Sources Tab, I executed the test line-by-line. I did this for test files, the components under test, and some Jest source code. The key Jest file I looked at was &lt;code&gt;node-modules/jest-runtime/build/index.js&lt;/code&gt;. At each step, I monitored the Closure section and paid attention to the mocks. I monitored when the mocks received references and documented those changes. I then followed this line-by-line process for each of the four examples. Following code execution, while writing down my thoughts yielded the most results. I wrote out what I thought was happening, noted my questions, and made sure to answer every one of them.&lt;/p&gt;

&lt;p&gt;This stage of analytical reading is when I figured out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Jest alters a test file's execution order. Mocks execute before imports. This is Jest hoisting. Javascript hoisting happens before execution. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jest collects &lt;code&gt;it&lt;/code&gt; and &lt;code&gt;describe&lt;/code&gt; blocks but then executes them later &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When Jest was actually evaluating function expressions defined within the test files&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When doing analytical reading across several works, you produce a lot of notes. Organizing those notes into something coherent is the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Syntoptical Reading
&lt;/h3&gt;

&lt;p&gt;Syntoptical reading is a term coined by Adler to mean reading across many authors.  If analytical reading is conversing with a single author answering their own question, then syntoptical reading is conversing with many authors to answer your own questions. You then take your answers and synthesize them into a cohesive line of thought.&lt;/p&gt;

&lt;p&gt;I wanted to know how Jest and Javascript handled different ways of creating mocks. Bringing notes from many sources together is a fuzzy process. I’d look at a note, get a question, and run through the debugger again. Or I'd peek at the ECMAScript spec. Or I'd go look at a couple of blogs to work out things like the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz"&gt;Temporal Dead Zone&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Reading your notes across many works is when you make novel connections. I realized here that Jest executing a mock meant something different than I assumed. If the mock is executing, then the Javascript engine is operating in the execution phase. And if Jest hoists during execution, then it's not the same type of hoisting as in Javascript. This only became clear, however, after all the previous exploration.&lt;/p&gt;

&lt;p&gt;A good sign the end is near is when you can create a rough outline from your notes. Here was one of my earlier outlines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sneaky Temporal Deadzone&lt;/li&gt;
&lt;li&gt;Test Step Through

&lt;ol&gt;
&lt;li&gt;Import parent module&lt;/li&gt;
&lt;li&gt;Jest function: &lt;code&gt;requireModuleOrMock&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Jest function: &lt;code&gt;requireMock&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Critical line of Jest code: &lt;code&gt;node-modules/jest-runtime/build/index.js&lt;/code&gt; Line 802: &lt;code&gt;const module = this._mockFactories.get(moduleID)()&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;ECMA Script Sepc&lt;/li&gt;
&lt;li&gt;Function Declaration vs Function Definition&lt;/li&gt;
&lt;li&gt;Jest Docs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This outline differs from the one I finally published. I still had questions and every time I answered one I saw a better way to organize my thoughts. The final iteration came after I had answered my questions on how the 4 examples were executed. When I put that final set of notes together, I could see there were 6 stages that each example went through. Those stages explained the differences in how the examples were executed. From that point, the rest of the article was filling in details from my exploration.&lt;/p&gt;

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

&lt;p&gt;Code describes machine instructions which distinguishes it from other textual works. Despite its mechanical nature, source code still embeds ideas in human-readable language. So reading to grasp ideas in code will use the four types of reading I've mentioned. By understanding each type of reading, you can focus your intent when doing your research. So dig into that source code and make sense of your problem. All the rest is commentary.&lt;/p&gt;

&lt;h3&gt;
  
  
  About Jobber
&lt;/h3&gt;

&lt;p&gt;Our awesome Jobber technology teams span across Payments, Infrastructure, AI/ML, Business Workflows &amp;amp; Communications. We work on cutting edge &amp;amp; modern tech stacks using React, React Native, Ruby on Rails, &amp;amp; GraphQL. &lt;br&gt;
If you want to be a part of a collaborative work culture, help small home service businesses scale and create a positive impact on our communities, then visit our &lt;a href="https://getjobber.com/about/careers?utm_source=linkedin&amp;amp;utm_medium=social&amp;amp;utm_campaign=eng_blog"&gt;careers&lt;/a&gt; site to learn more!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Debugger explanation: ↩&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;inspect&lt;/code&gt; allows you to access the test in your chrome dev tools&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;runInBand&lt;/code&gt; prevents Jest from running in parallel (not great for debugging)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;running Jest from the &lt;code&gt;node_modules&lt;/code&gt; directory was necessary in my environment to properly connect to the node debugger. This might vary depending on your environment.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>jobbertech</category>
      <category>lifeatjobber</category>
      <category>lifeatjobbertech</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Serious Jest: Making Sense of Hoisting</title>
      <dc:creator>Jordan Los</dc:creator>
      <pubDate>Tue, 24 May 2022 19:16:37 +0000</pubDate>
      <link>https://dev.to/jobber/serious-jest-making-sense-of-hoisting-253i</link>
      <guid>https://dev.to/jobber/serious-jest-making-sense-of-hoisting-253i</guid>
      <description>&lt;p&gt;&lt;strong&gt;“The ticket’s almost done, I just need to write a few tests”&lt;/strong&gt;&lt;br&gt;
Later . . . &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%2Fyxj48xu4oibjolhm21we.gif" 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%2Fyxj48xu4oibjolhm21we.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hoisting Isn’t Always Hoisting
&lt;/h2&gt;

&lt;p&gt;Even if you’re using Jest, you may not have thought too much about how Jest actually replaces your module with a mock. At least until you’re mocks don’t work. &lt;/p&gt;

&lt;p&gt;Jest creates mocks through a process they refer to as hoisting. If you’ve used Javascript long enough you might assume you know what that means. But something I haven't seen elsewhere hoisting in Jest and hoisting in Javascript isn’t the same thing. In this article, I’ll explain both types of hoisting and walk through what happens each time your run a test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upcoming
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Four ways we might mock a component&lt;/li&gt;
&lt;li&gt;Jest Hoisting is Execution Order Manipulation&lt;/li&gt;
&lt;li&gt;Javascript Hoisting is Reference Assignment Manipulation&lt;/li&gt;
&lt;li&gt;Six Stages of Running a test&lt;/li&gt;
&lt;li&gt;Four ways to mock a component revisited&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Four Ways We Might Mock A Component
&lt;/h2&gt;

&lt;p&gt;For the sake of example, we’ll make a component called &lt;code&gt;MoviePoster&lt;/code&gt;. Take a look at it below:&lt;/p&gt;

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

&lt;span class="c1"&gt;// MoviePoster.jsx&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;useDolphLundgren&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;ThunderGunExpress&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;function&lt;/span&gt; &lt;span class="nf"&gt;MoviePoster&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;ThunderGun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDolphLundgren&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PosterContent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ThunderGun&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/PosterContent&lt;/span&gt;&lt;span class="err"&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;// MoviePoster.test.jsx&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;useDolphLundgren&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;ThunderGunExpress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HomePage&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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should not hesistate&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;// ... &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;code&gt;MoviePoster&lt;/code&gt; uses &lt;code&gt;ThunderGunExpress&lt;/code&gt; to make an API call through a hook called &lt;code&gt;useDolphLundgren&lt;/code&gt;. &lt;code&gt;useDolphLundgren&lt;/code&gt;, returns a component we can pass as a child to a &lt;code&gt;PosterContent&lt;/code&gt;. But our test suite can’t reproduce the output from the &lt;code&gt;useDolphLundgren&lt;/code&gt; hook so we'll need to mock it. Let’s look at some ways in which we might mock that hook.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jest Best Guess
&lt;/h3&gt;

&lt;p&gt;Let’s look at four examples of how we might mock out &lt;code&gt;useDolphLundgren&lt;/code&gt; using Jest’s factory mocks. Take a look at each example, guess whether it will work, and then guess why&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ex 1: Inline mock&lt;/strong&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;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&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;Ex 2: Passing a function declaration&lt;/strong&gt;&lt;/p&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MockHook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockHook&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;Ex 3: Passing a function expression&lt;/strong&gt;&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MockHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockHook&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;Ex 4: Calling a function expression within another function expression&lt;/strong&gt;&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MockHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&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="nc"&gt;MockHook&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;
  
  
  Jest Best Guess Addressed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Example 1 fails&lt;/strong&gt; with an error telling you that you can’t rely on that fragment you’ve imported to exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 2 works&lt;/strong&gt; because the function definition is hoisted and exists when the &lt;code&gt;useDolphLundgren&lt;/code&gt; mock gets created.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 3 fails&lt;/strong&gt; because the &lt;code&gt;MockHook&lt;/code&gt; variable is undefined when the mock function is created.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 4 works&lt;/strong&gt; because the function expression calling &lt;code&gt;MockHook()&lt;/code&gt; isn’t evaluated until it's invoked and at that time &lt;code&gt;MockHook&lt;/code&gt; has been initialized. &lt;/p&gt;

&lt;p&gt;And there you have it, Jest mocks demystified. Thanks for reading and remember to . . . oh, it's not clear why those work? Are you the type to get upset when you see a library as an answer to a StackOverflow question?&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%2Fvw9pvukarouz5xjygsje.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%2Fvw9pvukarouz5xjygsje.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before we can dig into what Jest is doing with these mocks we need to understand a bit about how Jest and Javascript actually run code.&lt;/p&gt;
&lt;h1&gt;
  
  
  Hoisting in Jest is Execution Order Manipulation
&lt;/h1&gt;

&lt;p&gt;The Jest docs say Jest creates mocks through hoisting. But what Jest is doing is manipulating the code execution order. The Jest testing finds those &lt;code&gt;mock()&lt;/code&gt; calls in a file and execute them before any of the import statements. So it doesn’t matter where you put your mock in a test file, Jest will “hoist” it above the import statements. &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%2Fdqu3gvgdjg1do4kp1y63.gif" 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%2Fdqu3gvgdjg1do4kp1y63.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Hoisting in Javascript is Reference Assignment Manipulation
&lt;/h2&gt;

&lt;p&gt;So while Jest actually changes the order your code runs, Javascript doesn’t. Hoisting is what the Javascript engine does before executing any code at all. The Javascript engine first runs through your code to create what's called an Execution Context. The process of creating an execution context is beyond the scope of this article, but I’ll review the relevant parts. &lt;/p&gt;
&lt;h3&gt;
  
  
  Javascript Execution Context Summary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Javascript engine runs your code twice, creating an Execution Context from it and then executing it&lt;/li&gt;
&lt;li&gt;The Execution Context has an identifier for every variable, function, and class&lt;/li&gt;
&lt;li&gt;During the creation phase, the Javascript engine only assigns references in memory to function declarations and classes. It leaves everything else undefined&lt;/li&gt;
&lt;li&gt;Function expressions differ from function declarations because function expressions are (1) undefined until you initialize them and (2) evaluated only when you invoke them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, &lt;strong&gt;hoisting in Javascript means some variables get references to objects in memory before code execution happens.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Javascript Execution Context In-Depth
&lt;/h3&gt;

&lt;p&gt;The Execution Context is a stack frame that gets created every time you call a function. During the creation stage, the Javascript engine runs through your code, grabs all the variables, functions, and classes, puts their name at the top of the scope (we'll call these names &lt;em&gt;identifiers&lt;/em&gt;) and does things with them. What things the engine does depends on what it's looking at. &lt;/p&gt;

&lt;p&gt;If the engine finds a class or function declaration, it takes the definition, adds it to the heap, and then points the identifier to that definition in memory. I.e. each identifier gets a reference to the definition.&lt;/p&gt;

&lt;p&gt;If the engine finds a variable, it marks it undefined and moves on. It doesn’t matter if you defined the variable with var, const, or let because the Javascript engine still leaves them &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Function expressions are like variables with an extra step: the function body isn’t evaluated until you invoke the function expression. We’ll cover this in more detail later. &lt;/p&gt;

&lt;p&gt;After creating the execution context, the engine does a second pass on your code and evaluates it line by line. Look at the examples below to see how the Execution Context (EC) influences the output of our code:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Variable isn't declared, so doesn't exist at all in the EC&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needsDeclaration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Variable declared, but left undefined in the EC during creation phase&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needsInitialization&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;needsInitialization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Function defintion assigned during the creation phase, so you can call it before defining it&lt;/span&gt;
&lt;span class="nf"&gt;hoistedFoo&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;hoistedFoo&lt;/span&gt;&lt;span class="p"&gt;(){...}&lt;/span&gt;

&lt;span class="c1"&gt;// Function expressions are just like variables, they are undefined until initialized&lt;/span&gt;
&lt;span class="nf"&gt;unhoistedBar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;unhoistedBar&lt;/span&gt; &lt;span class="o"&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;// Const and let are the same as var, but will raise an error to avoid accessing an undefined variable&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alsoNeedsInitialization&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;alsoNeedsInitialization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;To recap, Jest hoists &lt;code&gt;mock()&lt;/code&gt; statements by manipulating the execution order, while Javascript hoists memory allocation by manipulating when it assigns references. The tricky part is that both of these ‘hoistings’ happen when you run a test: Javascript will manipulate your references during the creation phase, and then during the execution phase Jest will manipulate the order your code executes in. &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%2Fjuomqeextnvn1xb1u2pf.gif" 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%2Fjuomqeextnvn1xb1u2pf.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Six Stages of Running A Jest Test
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Stage 0:&lt;/strong&gt; Javascript creation phase runs and sets up the Execution Context&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 1:&lt;/strong&gt; Mocks are executed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jest finds the &lt;code&gt;jest.mock()&lt;/code&gt; calls and invokes those functions before the &lt;code&gt;import&lt;/code&gt; statements occur. &lt;/li&gt;
&lt;li&gt;Mocks are created during this stage, but the function expression’s passed to &lt;code&gt;mock()&lt;/code&gt; are not yet evaluated.&lt;/li&gt;
&lt;li&gt;This is happening during the Javascript engine’s execution phase, not its creation phase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stage 2: Import Calls are executed&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jest works down the component tree of each &lt;code&gt;import&lt;/code&gt; statement before moving on to the next.&lt;/li&gt;
&lt;li&gt;If Jest finds a mock, it will import that instead of the module.&lt;/li&gt;
&lt;li&gt;The factory expression you passed to &lt;code&gt;mock()&lt;/code&gt;gets evaluated here. &lt;em&gt;Whatever is in the Execution Context at this stage is what gets used for that factory expression.&lt;/em&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stage 3: Jest collects the blocks, but doesn't execute them&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jest runs through the &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; blocks in your test, but it doesn’t evaluate the function expressions you passed in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stage 4: Javascript executes the rest of the file&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whatever is defined below the &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; blocks gets evaluated. This means the Execution Context your tests run in can be updated after the tests are written&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stage 5: Jest runs the tests&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Revisiting the Examples
&lt;/h2&gt;

&lt;p&gt;Now that we've covered beginning to end what happens when we run a test file, let's revisit the original examples. I’ll include the code again to save you from going back up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ex 1: Inline mock&lt;/strong&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;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&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 code raises an error because the mock will run during Stage 1 but the fragment would be imported during Stage 2. So Jest raises an error to remind you that the fragment may not exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ex 2: Passing a function declaration&lt;/strong&gt;&lt;/p&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MockHook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockHook&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 works because the function definition for &lt;code&gt;MockHook&lt;/code&gt; gets added to memory and referenced to the &lt;code&gt;MockHook&lt;/code&gt; identifier during Stage 0. When the mock gets created in Stage 1, Jest replaces the module with the function definition referenced by &lt;code&gt;MockHook&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ex 3: Passing a function expression&lt;/strong&gt;&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MockHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockHook&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 fails because Jest is hoisting the call to mock and so &lt;code&gt;MockHook&lt;/code&gt; gets moved into the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz" rel="noopener noreferrer"&gt;Temporal Dead Zone&lt;/a&gt;. The code actually executes like this:&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;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockHook&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;MockHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&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;Ex 4: Calling the function expression mock within another function expression&lt;/strong&gt;&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MockHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;MockHook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;Line 5 looks like it should be identical to the same line in Example 3. But &lt;strong&gt;there’s a difference in when the variable&lt;/strong&gt; MockHook &lt;strong&gt;is accessed&lt;/strong&gt;. The timing for when a variable is accessed is subtle enough that it deserves some more attention.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Variable Access Timing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s take Jest out of the equation and dig a little deeper into how function expressions get evaluated.&lt;/p&gt;

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

&lt;span class="c1"&gt;// needsInitializing is in the Temporal Deadzone&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;needsInitializing&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;needsInitializing&lt;/span&gt; &lt;span class="o"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;initialized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The Javascript engine checks the value of &lt;code&gt;needsInitializing&lt;/code&gt; when attempting to assign it to bar during the creation phase. But that means &lt;code&gt;needsInitializing&lt;/code&gt; &lt;strong&gt;is accessed before it is defined&lt;/strong&gt;. Compare this to the example below:&lt;/p&gt;

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

&lt;span class="c1"&gt;// The expression at line 3 isn't evaluated until line 6&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;bar&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="nf"&gt;needsInitializing&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;needsInitializing&lt;/span&gt; &lt;span class="o"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;initialized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This time, the Javascript engine &lt;strong&gt;accesses&lt;/strong&gt; needsInitializing &lt;strong&gt;during the execution phase when&lt;/strong&gt; foo.bar() &lt;strong&gt;is invoked&lt;/strong&gt;. The difference is that during the creation phase Javascript engine doesn’t attempt to evaluate the function expression in line 2 and, so, never tries to access the needsInitializing variable.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Ex 4: One Last Time&lt;/strong&gt;
&lt;/h3&gt;

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

&lt;span class="c1"&gt;// The expression at line 6 isn't evaluated until `useDolphLundgren` is called&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MockHook&lt;/span&gt; &lt;span class="o"&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="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ThunderGunExpress&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="na"&gt;useDolphLundgren&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="nc"&gt;MockHook&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;Stage 0: Creation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MockHook&lt;/code&gt; is &lt;code&gt;undefined&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(props) =&amp;gt; MockHook(props)&lt;/code&gt; is unevaluated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MockHook&lt;/code&gt; is &lt;em&gt;not accessed&lt;/em&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stage 1&lt;/strong&gt;: &lt;strong&gt;Mocks executes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jest moves the execution order of &lt;code&gt;jest.mock()&lt;/code&gt; above the &lt;code&gt;const MockHook&lt;/code&gt; initialization to mock the &lt;code&gt;useDolphLundgren&lt;/code&gt; module.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stage 2&lt;/strong&gt;: &lt;strong&gt;Import calls executed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 3&lt;/strong&gt;: &lt;strong&gt;Blocks collected&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 4&lt;/strong&gt;: &lt;strong&gt;Rest of test file executed&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;MockHook&lt;/code&gt; is initialized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stage 5&lt;/strong&gt;: &lt;strong&gt;Tests Run&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MoviePoster&lt;/code&gt; invokes &lt;code&gt;useDolphLundgren()&lt;/code&gt; while rendering&lt;/li&gt;
&lt;li&gt;Jest gets the mock component from &lt;code&gt;useDolphLundgren&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;() =&amp;gt; MockHook()&lt;/code&gt; gets evaluated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MockHook&lt;/code&gt; was defined in Stage 4 so the mock gets added. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stage 6: Success&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use your Javascript skills to impress family and friends&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/QZn4Lj79ms8BWUWyzB/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/QZn4Lj79ms8BWUWyzB/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Oftentimes we hit difficulties coding because we make unspoken and inaccurate assumptions. Its easy to assume that Jest and Javascript mean the same thing when they talk about hoisting. Jest, however, uses hoisting to mean manipulating the code execution order and Javascript uses hoisting to mean manipulating when objects in memory get references. I haven't covered how I tested those assumptions though. My first draft did include the steps I used to tease out the information here, but the length grew out of hand. I'll include in a follow up article the process I used to figure out the information here. &lt;/p&gt;

&lt;h2&gt;
  
  
  About Jobber
&lt;/h2&gt;

&lt;p&gt;We're hiring for remote positions across Canada at all software engineering levels! &lt;/p&gt;

&lt;p&gt;Our awesome Jobber technology teams span across Payments, Infrastructure, AI/ML, Business Workflows &amp;amp; Communications. We work on cutting edge &amp;amp; modern tech stacks using React, React Native, Ruby on Rails, &amp;amp; GraphQL. &lt;/p&gt;

&lt;p&gt;If you want to be a part of a collaborative work culture, help small home service businesses scale and create a positive impact on our communities, then visit our &lt;a href="https://getjobber.com/about/careers?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=eng_blog" rel="noopener noreferrer"&gt;careers &lt;/a&gt;site to learn more!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Planning for Complexity</title>
      <dc:creator>Jordan Los</dc:creator>
      <pubDate>Thu, 17 Feb 2022 16:23:35 +0000</pubDate>
      <link>https://dev.to/jobber/planning-for-complexity-2jec</link>
      <guid>https://dev.to/jobber/planning-for-complexity-2jec</guid>
      <description>&lt;p&gt;My team recently had to put together a large component for uploading CSVs that had a lot of moving parts. S3 uploads, background workers, GraphQL polling, and real-time progress bars were all involved. The final result looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V1fyd0an--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7md30od9sybf9g6e4sv0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V1fyd0an--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7md30od9sybf9g6e4sv0.gif" alt="CSV Upload Gif" width="480" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main challenge was how to structure the component so that it was readable, testable, and easy to work with later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat Complexity like Heavy Industry and Zone It Off
&lt;/h2&gt;

&lt;p&gt;Building anything worthwhile will eventually produce some undesirable byproduct. If you want a bustling city of a million-plus people living in sanitary, climate-controlled homes with food, water, and electricity, then you’re going to need a certain amount of heavy industry. But heavy industry produces all sorts of things we don't want near our homes and businesses. Imagine a Sriracha plant going up next door or a waste management facility beside your office. How a city zones for industrial facilities has a significant impact on how you experience that city.&lt;/p&gt;

&lt;p&gt;Code may not produce noise and pollution but it does generate a lot of complexity. If we don’t implement some kind of zoning for complex parts of our code, our components may start to feel like a city without land-use regulations. Ultimately, we want strategies for dealing with complexity that keep our interactions with it to a minimum. &lt;/p&gt;

&lt;p&gt;Here are four strategies we can use to zone off complexity in larger components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Declarative State Transitions&lt;/li&gt;
&lt;li&gt;Side Effect Containment&lt;/li&gt;
&lt;li&gt;Keep Your Return Statement Above the Fold&lt;/li&gt;
&lt;li&gt;Descriptive Functions Instead of Comments&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Declarative State Enums
&lt;/h2&gt;

&lt;p&gt;Before telling you anything about the &lt;code&gt;ImportCard&lt;/code&gt; component from above, see how much you can figure out by just reading the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;UIStates&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Idle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Importing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Done&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="nx"&gt;ImportCard&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="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Idle&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ImportCardProps&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUIState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UIStates&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;initialState&lt;/span&gt;&lt;span class="p"&gt;);&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;workerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setWorkerId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;bannerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBannerState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialBannerState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Idle&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;IdlingCard&lt;/span&gt; &lt;span class="nx"&gt;handleImport&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleImport&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Importing&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;ImportingCard&lt;/span&gt; &lt;span class="nx"&gt;onTransition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleTransitionToDone&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;workerId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;workerId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Done&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;DoneCard&lt;/span&gt; &lt;span class="nx"&gt;showBanners&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bannerState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;assertUnreachable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// I'll show the mutation, handleImport, and handleTransitionToDone a little later in the article.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here are the tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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="s2"&gt;ImportCard&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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;initializes in the idling state&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;ImportCard&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;begin-import&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transitions to importing state when import is started&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;findByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;ImportCard&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;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;begin-import&lt;/span&gt;&lt;span class="dl"&gt;"&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;waitFor&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;expect&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;findByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;awaiting-import&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transitions to done state when import is completed&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;ImportCard&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;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Importing&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;awaiting-import&lt;/span&gt;&lt;span class="dl"&gt;"&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;waitFor&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&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;Despite not knowing anything about the underlying components or what kind of problems they might contain, the intent of the &lt;code&gt;ImportCard&lt;/code&gt; component is hopefully clear. In fact, if I hadn’t already told you about all the difficulties underneath you might not even know this was a very complicated component. That nice, quiet suburb may be powered by a turbine larger than your house, but that fact never even needs to cross your mind. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating Declarative Enums&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first strategy we used was &lt;strong&gt;declarative state enums&lt;/strong&gt;. Declarative state enums involve:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An enum specifying the possible states&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;useState&lt;/code&gt; hook that initialized with the state enum&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;switch&lt;/code&gt; statement to return the appropriate components&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Declarative enums go a long way in preventing someone from misunderstanding what can happen in your component. And while Typescript's enums aren’t as powerful as the ones in languages like Rust, we can include a little helper function to ensure our switch statement is exhaustive, requiring a case for every value in the enum. This helper function ensures if someone adds another value to the enum, the Typescript compiler will raise an error:&lt;/p&gt;

&lt;p&gt;The function definition is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;assertUnreachable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Default should be unreachable&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;and gets used in the switch statement like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle the cases. . .&lt;/span&gt;
  &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;assertUnreachable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uiState&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;Testing Declarative Enums&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since the &lt;code&gt;ImportCard&lt;/code&gt; just swaps between child components, this makes them easy to mock. The mocked components are just a button with a test id and a handler for the state transition function that gets passed down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ImportCard.test.tsx&lt;/span&gt;

&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path/to/IdlingCard&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;IdlingCardContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IdlingCardProps&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;mockImport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleImport&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;button&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;testid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;begin-import&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mockImport&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&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="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ll admit the mocked button with a &lt;code&gt;data-testid&lt;/code&gt; is a bit of a workaround. A better solution here would be to just have some way to call the &lt;code&gt;handleImport&lt;/code&gt; function without worrying about how the subcomponents actually accomplish that task. However, the React Testing Library intentionally doesn’t allow us the ability to directly access a component's props because it wants us to focus on testing visible UI. Normally, testing UI is an excellent strategy. But with high-level components like the &lt;code&gt;ImportCard&lt;/code&gt;, testing UI elements too tightly couples the parent component's behaviour with the child component's implementation. A mock button avoids those implementation details and lets us trigger the desired function prop directly.&lt;/p&gt;

&lt;p&gt;Another way our tests benefit from using declarative state enums is that we can specify the starting state of our &lt;code&gt;ImportCard&lt;/code&gt;. By making the &lt;code&gt;initialState&lt;/code&gt; a prop with a default value we can start in a different component state than the default initial state by just specifying it when rendering the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;ImportCard&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;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Importing&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Side Effect Containment
&lt;/h2&gt;

&lt;p&gt;S3 uploads, triggering Rails workers, and background polling for progress updates all involve a certain type of complexity called a side effect. If you’re not familiar with the concept of side effects, one way to think of them is this: a function is either returning a value or causing something to happen outside of the function itself. Functions that only return values are simple. Functions that trigger something outside of themselves are not; they are coupled with code you might not control.&lt;/p&gt;

&lt;p&gt;But we still want some side effects. What we don't want is for these side effects to be mingled with the rest of our code.&lt;/p&gt;

&lt;p&gt;Let's look at how we isolate and zone off the side effects in the &lt;code&gt;ImportingCard&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ImportingCard&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;workerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onTransition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ImportingCardProps&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CardContents&lt;/span&gt;
      &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="o"&gt;=&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;ImportProgressBar&lt;/span&gt; &lt;span class="nx"&gt;workerId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;workerid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;nextUIState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onTransition&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;nextStateButton&lt;/span&gt;&lt;span class="o"&gt;=&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;ImportPendingButton&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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="s2"&gt;ImportingCard&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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;call the nextUIState call when the import is complete&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockOnTransition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&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;getByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;ImportingCard&lt;/span&gt; &lt;span class="nx"&gt;onTransition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mockOnTransition&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;import-complete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;click&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;mockOnTransition&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalled&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;All polling and progress updates can be sealed and tested inside the &lt;code&gt;ImportProgressBar&lt;/code&gt; component. &lt;code&gt;CardContents&lt;/code&gt; isolates the shared HTML used in each state of the &lt;code&gt;ImportCard&lt;/code&gt;. And because &lt;code&gt;ImportProgressBar&lt;/code&gt; and the &lt;code&gt;CardContents&lt;/code&gt; components have now isolated their complexities from each other, we can mock the &lt;code&gt;ImportProgressBar&lt;/code&gt; without worrying about testing anything but the &lt;code&gt;ImportingCard&lt;/code&gt;'s behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep Your Return Statement Above the Fold
&lt;/h2&gt;

&lt;p&gt;So far we’ve shown how to zone off complexity &lt;em&gt;between components&lt;/em&gt; but that same strategy also works &lt;em&gt;within a component&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Print newspapers put the most critical headlines above the fold where interested passersby can see them. Likewise, we can place our most critical sections of code (usually the return statement) near the top of a component. Giving the return statement a place of prominence lets a reader get straight to the point and drill down for details only if they need them.&lt;/p&gt;

&lt;p&gt;Take a second look at the &lt;code&gt;ImportCard&lt;/code&gt; component below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;UIStates&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Idle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Importing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Done&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="nx"&gt;ImportCard&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="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Idle&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ImportCardProps&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUIState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UIStates&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;initialState&lt;/span&gt;&lt;span class="p"&gt;);&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;workerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setWorkerId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;bannerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBannerState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialBannerState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Idle&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;IdlingCard&lt;/span&gt; &lt;span class="nx"&gt;handleImport&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleImport&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Importing&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;ImportingCard&lt;/span&gt; &lt;span class="nx"&gt;onTransition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleTransitionToDone&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;workerId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;workerId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Done&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;DoneCard&lt;/span&gt; &lt;span class="nx"&gt;showBanners&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bannerState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;assertUnreachable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/* As promised */&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;importItems&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMutation&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ImportItemsMutation&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;IMPORT_MUTATION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;onCompleted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;importMutationPayload&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;setWorkerId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;importMutationPayload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;importItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workerId&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;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleTransitionToDone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalWorkerState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BackgroundWorker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setUIState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;updateBannerOnCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalWorkerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBannerState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleImport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uploadUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&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;importItems&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;uploadUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;uploadUrl&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;setUIState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UIStates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Importing&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;All the component’s logic gets moved “below the fold” into intent-describing functions. Since Javascript uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#function_declaration_hoisting"&gt;function declaration hoisting&lt;/a&gt; we can use the functions in the return statement before they are defined. This does not, however, apply to function expressions (i.e. arrow functions) &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function#function_expression_hoisting"&gt;which are not hoisted&lt;/a&gt;. Arrow functions are a great language feature, but we don't want to force readers to look at the complex parts of our component before seeing our intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Descriptive functions instead of comments
&lt;/h2&gt;

&lt;p&gt;Lastly, there are always some lines of code that are complicated, error-prone, and essential. They might involve tricky math, object properties with misleading names, an unintuitive but necessary design choice, or anything non-obvious that makes you feel you should write a comment. Isolate that comment-worthy code into a function describing the intent and move it somewhere else. Spare the readers of your code (including future you) from having to figure out what the code is trying to accomplish by telling them directly.&lt;/p&gt;

&lt;p&gt;There weren’t any examples of this in the &lt;code&gt;ImportCard&lt;/code&gt;, but comment-worthy code that can be zoned off in a function happens often enough I’ve included it anyway.&lt;/p&gt;

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

&lt;p&gt;Strategies like the ones above often become more valuable after you’ve got something working. Complexity in software, like industrial facilities in cities, occurs because we’re building something big and useful. If we let that complexity operate just anywhere, we expose the rest of our code to problems more often than we need to. But unlike cities, we can choose how to handle complexity after we’ve created it. &lt;/p&gt;

&lt;h2&gt;
  
  
  About Jobber
&lt;/h2&gt;

&lt;p&gt;We're hiring for remote positions across Canada at all software engineering levels!&lt;/p&gt;

&lt;p&gt;Our awesome Jobber technology teams span across Payments, Infrastructure, AI/ML, Business Workflows &amp;amp; Communications. We work on cutting edge &amp;amp; modern tech stacks using React, React Native, Ruby on Rails, &amp;amp; GraphQL.&lt;/p&gt;

&lt;p&gt;If you want to be a part of a collaborative work culture, help small home service businesses scale and create a positive impact on our communities, then visit our &lt;a href="https://getjobber.com/about/careers?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=eng_blog"&gt;careers&lt;/a&gt; site to learn more!&lt;/p&gt;

</description>
      <category>jobbertech</category>
      <category>lifeatjobber</category>
      <category>lifeatjobbertech</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
