<?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>Forem: Vladislav Zimnikov</title>
    <description>The latest articles on Forem by Vladislav Zimnikov (@mr0bread).</description>
    <link>https://forem.com/mr0bread</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%2F827878%2F5861bd56-a9ea-4c60-8008-5f38a34fbfa5.png</url>
      <title>Forem: Vladislav Zimnikov</title>
      <link>https://forem.com/mr0bread</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mr0bread"/>
    <language>en</language>
    <item>
      <title>Modern JavaScript: Promise</title>
      <dc:creator>Vladislav Zimnikov</dc:creator>
      <pubDate>Sat, 26 Mar 2022 10:24:45 +0000</pubDate>
      <link>https://forem.com/mr0bread/modern-javascript-promise-3h79</link>
      <guid>https://forem.com/mr0bread/modern-javascript-promise-3h79</guid>
      <description>&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Promise&lt;/li&gt;
&lt;li&gt;First Examples&lt;/li&gt;
&lt;li&gt;
Handling Promise

&lt;ol&gt;
&lt;li&gt;then()&lt;/li&gt;
&lt;li&gt;catch()&lt;/li&gt;
&lt;li&gt;finally()&lt;/li&gt;
&lt;li&gt;Chaining&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

Advanced Usage

&lt;ol&gt;
&lt;li&gt;Server Request&lt;/li&gt;
&lt;li&gt;Multiple Requests&lt;/li&gt;
&lt;li&gt;First to settle&lt;/li&gt;
&lt;li&gt;First to fulfill&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Outro&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When it comes to JavaScript it executes code one line after another so next line of code will not start it's execution up until previous one have finished&lt;/p&gt;

&lt;p&gt;But what if required operation takes too much time? Should we freeze whole application's execution waiting for result? Obviously, not&lt;/p&gt;

&lt;p&gt;Most common and easily understandable example is request to some server. You never know how much time exactly there is needed to receive response. It may take few dozens of milliseconds or few seconds&lt;/p&gt;

&lt;p&gt;And while waiting for response we still want our application to be responsive, usable and even let customer know about making server request like through showing some sort of loader animation&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%2F560jncweiq9mov0wshft.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%2F560jncweiq9mov0wshft.png" alt="small loader image that is used to let customer know that something is being loaded"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, once application receives response it should process it somehow so we also need a way to tell the program how it should treat data it is going to receive in future and we are not able to know when exactly&lt;/p&gt;

&lt;p&gt;Basically, we want to be able to tell our program such thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In &lt;strong&gt;background&lt;/strong&gt;, without blocking whole execution process, make this request, wait for the response and once received perform given set of commands&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But how can we achieve such kind of functionality if currently we are aware that JavaScript executes all of the code in strict sequence?&lt;/p&gt;

&lt;h2&gt;
  
  
  Promise
&lt;/h2&gt;

&lt;p&gt;In short, Promise allows performing operations asynchronously&lt;/p&gt;

&lt;p&gt;The concept of Promise is pretty straightforward:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give it piece of code you want to execute asynchronously and specify in what case Promise should fulfil successfully and vice versa&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand principle of Promise better before diving into examples few theory concepts have to be discussed&lt;/p&gt;

&lt;p&gt;First of all, when we create Promise with code to process asynchronously, we should pass this code in form of callback.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Callback&lt;/strong&gt; - function passed as an argument for another function that is going to be executed at some specific point of latter function execution&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Callback that is being passed to promise is called &lt;strong&gt;executor&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Executor&lt;/strong&gt; -  callback function, invoked by Promise with two arguments being passed: &lt;strong&gt;resolve&lt;/strong&gt; and &lt;strong&gt;reject&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;resolve&lt;/strong&gt; - callback function that should be called when operation inside of Promise finishes successfully. Usually, accepts one parameter - result of operation performed inside of &lt;strong&gt;executor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;reject&lt;/strong&gt; - callback function that should be called in case when error happens during &lt;strong&gt;executor's&lt;/strong&gt; code processing&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In terms of making server request we would call &lt;strong&gt;resolve&lt;/strong&gt; with response as an argument right after receiving it to proceed with it's further processing&lt;/p&gt;

&lt;h2&gt;
  
  
  First Examples
&lt;/h2&gt;

&lt;p&gt;When we need to create promise we have to use constructor of &lt;strong&gt;Promise&lt;/strong&gt; class with keyword new. Basically, we create instance of class &lt;strong&gt;Promise&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As it was mentioned earlier, to create promise we should pass &lt;strong&gt;executor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simplest example of how to create new Promise:&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;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Currently, our promise does nothing. To actually see, how promise executes code in async manner let me show you next example&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
new Promise((resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; {
        console.log('in promise');
    }, 1000)
})

console.log('after promise')

  &lt;/code&gt;
&lt;/div&gt;



&lt;p&gt;You can run this code right in browser or anywhere else to see what happens. First message to console we receive is 'after promise' and only after 1 second message 'in promise' is being printed out. &lt;/p&gt;

&lt;p&gt;Function &lt;code&gt;setTimeout&lt;/code&gt; allows to delay execution of code and I am going to use this feature to demonstrate more capabilities of promises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Promise
&lt;/h2&gt;

&lt;p&gt;Basically, promise can be fulfilled or rejected. If code inside of an executor processed well, callback &lt;strong&gt;resolve&lt;/strong&gt; is being invoked and promise starts fulfilling. In opposite case, callback &lt;strong&gt;reject&lt;/strong&gt; is called and rejection happens.&lt;/p&gt;

&lt;p&gt;Promise gives us, developers, possibility to control what has to be done in case of promise fulfilment and rejection.&lt;/p&gt;

&lt;p&gt;Object of Promise provides two methods for such thing: &lt;code&gt;then&lt;/code&gt; and &lt;code&gt;catch&lt;/code&gt;. Both accept callback&lt;/p&gt;

&lt;h3&gt;
  
  
  then()
&lt;/h3&gt;

&lt;p&gt;To understand better, let's firstly set up our playground. First of all, I will create promise and save it to constant. Inside of an executor I will utilize &lt;code&gt;setTimeout&lt;/code&gt; to postpone invocation of &lt;code&gt;resolve&lt;/code&gt; function up to 1 second. To &lt;code&gt;resolve&lt;/code&gt; I will pass string 'Hello Promise'&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ourPromise&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;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;setTimeout&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;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello Promise&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&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;Now, let's use &lt;code&gt;.then()&lt;/code&gt; for the first time. I know that promise will pass string to callback on fulfilling, so let's print received message&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;ourPromise&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;message&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="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const ourPromise = new Promise((resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; resolve('Hello Promise'), 1000);
});

ourPromise
    .then((message) =&amp;gt; console.log(message));

console.log('after promise');

  &lt;/code&gt;
&lt;/div&gt;



&lt;p&gt;If you run code above you can see that message 'after promise' is being printed first, just like last time. Only difference is that message 'Hello Promise' is being printed in callback passed to &lt;code&gt;.then()&lt;/code&gt; as an argument.&lt;/p&gt;

&lt;h3&gt;
  
  
  catch()
&lt;/h3&gt;

&lt;p&gt;In case if &lt;strong&gt;executor&lt;/strong&gt;'s code fails, Promise should be rejected by &lt;strong&gt;reject&lt;/strong&gt; invocation. To actually handle Promise's rejection, you should pass callback to &lt;code&gt;.catch()&lt;/code&gt; method of Promise instance. Usually, error being passed as an argument.&lt;/p&gt;

&lt;p&gt;Let's consider next code example:&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const ourPromise = new Promise((resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; reject('Rejecting Promise'), 1000);
});

ourPromise
    .catch((message) =&amp;gt; console.log(message));

console.log('after promise');

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;It's almost the same as previous one, but we call &lt;strong&gt;reject&lt;/strong&gt; instead of &lt;strong&gt;resolve&lt;/strong&gt; and replace &lt;strong&gt;.then()&lt;/strong&gt; with &lt;strong&gt;.catch()&lt;/strong&gt;. As a result we get the same output in console.&lt;/p&gt;

&lt;h3&gt;
  
  
  finally()
&lt;/h3&gt;

&lt;p&gt;It's pretty common occasion when you need to perform code on Promise's settlement despite the outcome. To avoid duplication of logic in &lt;code&gt;.then&lt;/code&gt; and &lt;code&gt;.catch&lt;/code&gt; methods there is &lt;code&gt;.finally&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Callback passed to method &lt;code&gt;.finally&lt;/code&gt; is going to be executed in any case: either Promise resolved successfully or was rejected&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const ourPromise = new Promise(
  (resolve, reject) =&amp;gt; {
    if (Math.random() &amp;gt; 0.5) {
      reject('Rejecting');
    }
resolve('Resolving');

}
);

ourPromise
  .then(msg =&amp;gt; console.log(msg))
  .catch(err =&amp;gt; console.log(err))
  .finally(() =&amp;gt; console.log('Final action'));

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;Important note&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;callback passed to &lt;code&gt;finally&lt;/code&gt; does not accept any arguments&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Chaining
&lt;/h3&gt;

&lt;p&gt;Methods &lt;code&gt;.then&lt;/code&gt;, &lt;code&gt;.catch&lt;/code&gt; and &lt;code&gt;.finally&lt;/code&gt; return promise itself, so they can be chained. That's what makes working with Promises neat and concise. Try to run below example multiple times and see how in different cases different callbacks are being invoked&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const ourPromise = new Promise(
  (resolve, reject) =&amp;gt; {
    if (Math.random() &amp;gt; 0.5) {
      reject('Rejecting');
    }
resolve('Resolving');

}
);

ourPromise
  .then(msg =&amp;gt; console.log(msg))
  .catch(err =&amp;gt; console.log(err))
  .finally(() =&amp;gt; console.log('final action'));

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;Another important thing is that you are not limited to one &lt;code&gt;.then&lt;/code&gt; invocation, for example. There can be occasions when you receive another promise while handling previous one and to process new promise we can just return it and use &lt;code&gt;.then&lt;/code&gt; again. Let me just show you&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const ourPromise = new Promise(
  (resolve, reject) =&amp;gt; {
    if (Math.random() &amp;gt; 0.5) {
      reject('Rejecting');
    }
resolve('Resolving');

}
);

ourPromise
  .then(msg =&amp;gt; msg + ' x2')
  .then(msg =&amp;gt; console.log(msg))
  .catch(err =&amp;gt; console.log(err))
  .finally(() =&amp;gt; console.log('final action'));

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;As you can see from first callback I returned original message plus some extra characters. Value, returned from previous callback is being passed to next one.&lt;/p&gt;

&lt;p&gt;Now let me show example with multiple Promises:&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const ourPromise = new Promise(
  (resolve, reject) =&amp;gt; {
    if (Math.random() &amp;gt; 0.5) {
      reject('Rejecting');
    }
resolve('Resolving');

}
);

ourPromise
  .then(
     msg =&amp;gt; new Promise((resolve) =&amp;gt; resolve('Another Promise'))
  )
  .then(msg =&amp;gt; console.log(msg))
  .catch(err =&amp;gt; console.log(err))
  .finally(() =&amp;gt; console.log('final action'));

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;If you run code above and first promise is going to be resolved then you will see that message we passed to &lt;strong&gt;resolve&lt;/strong&gt; function inside of our second Promise successfully got to callback we passed to our second &lt;code&gt;.then&lt;/code&gt;. This way we can handle multiple consecutive Promises in beautiful and convenient way&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Server Request
&lt;/h3&gt;

&lt;p&gt;Modern JS libraries and APIs for making and handling requests to server are built around Promise. Client side &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/fetch" rel="noopener noreferrer"&gt;Fetch API&lt;/a&gt; is built around Promise&lt;/p&gt;

&lt;p&gt;Let me show you one example using quite well-known library &lt;code&gt;axios&lt;/code&gt;&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const axios = require('axios');

axios.get('https://jsonplaceholder.typicode.com/users')
    .then(res =&amp;gt; console.log(res.data));

console.log('Something after request');

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;As you can see, we were able to perform request and process it response without blocking execution process&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple Requests
&lt;/h3&gt;

&lt;p&gt;Sometimes there is need to perform multiple requests simultaneously. Specifically for this reason one of the methods provided by Promise can be utilised.&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const axios = require('axios');

const requests = [
    axios.get('https://jsonplaceholder.typicode.com/users'),
    axios.get('https://jsonplaceholder.typicode.com/posts'),
    axios.get('https://jsonplaceholder.typicode.com/comments')
]

Promise.all(requests)
    .then(res =&amp;gt; console.log(res))

  &lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Promise.all()&lt;/code&gt; accepts iterable object like array, for instance, with promises we need to wait for. Once all Promises are resolved or at least one is rejected, then result of method &lt;code&gt;all&lt;/code&gt; which is Promise itself is resolved or rejected&lt;/p&gt;

&lt;h3&gt;
  
  
  First to settle
&lt;/h3&gt;

&lt;p&gt;If you are waiting on multiple promises and you need to perform some action once one of them resolves or rejects there is method for that: &lt;code&gt;Promise.race&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There is an example:&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const ourPromise = new Promise(
  (resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; {
        if (Math.random() &amp;gt; 0.5) {
      reject('Rejecting 1');
    }
resolve('Resolving 1');
}, Math.floor(Math.random() * 1000))

}
);

const ourPromise2 = new Promise(
  (resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; {
        if (Math.random() &amp;gt; 0.5) {
      reject('Rejecting 2');
    }
resolve('Resolving 2');
}, Math.floor(Math.random() * 1000))

}
);

Promise.race([ourPromise, ourPromise2])
    .then(res =&amp;gt; console.log(res))
    .catch(res =&amp;gt; console.log(res));

  &lt;/code&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  First to fulfill
&lt;/h3&gt;

&lt;p&gt;If you want to perform action once first among many promises fulfils there is solution for you as well: &lt;code&gt;Promise.any&lt;/code&gt;. Be aware that &lt;code&gt;Promise.any&lt;/code&gt; exists in Node since version 15 so you might need to change the version of runner below&lt;/p&gt;


&lt;div class="runkit-element"&gt;
  &lt;code&gt;
    
  &lt;/code&gt;
  &lt;code&gt;
    
const ourPromise = new Promise(
  (resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; {
        if (Math.random() &amp;gt; 0.5) {
      reject('Rejecting 1');
    }
resolve('Resolving 1');
}, Math.floor(Math.random() * 1000))

}
);

const ourPromise2 = new Promise(
  (resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; {
        if (Math.random() &amp;gt; 0.5) {
      reject('Rejecting 2');
    }
resolve('Resolving 2');
}, Math.floor(Math.random() * 1000))

}
);

Promise.any([ourPromise, ourPromise2])
    .then(res =&amp;gt; console.log(res))
    .catch(res =&amp;gt; console.log(res));

  &lt;/code&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;That's it for today. Hope you enjoyed this little article.&lt;/p&gt;

&lt;p&gt;Don't hesitate to leave a comment, I would appreciate it.&lt;/p&gt;

&lt;p&gt;Have a nice day :)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Testing modern ReactJS Application: Unit Testing(Part 2)</title>
      <dc:creator>Vladislav Zimnikov</dc:creator>
      <pubDate>Fri, 18 Mar 2022 22:24:58 +0000</pubDate>
      <link>https://forem.com/mr0bread/testing-modern-reactjs-application-unit-testingpart-2-25m7</link>
      <guid>https://forem.com/mr0bread/testing-modern-reactjs-application-unit-testingpart-2-25m7</guid>
      <description>&lt;p&gt;As I promised in previous post in this part I would like to tell about unit testing of components, difference between testing functional and class components and how to test react hooks&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="//#Class%20vs.%20Function"&gt;Class vs. Function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
Testing React Components

&lt;ol&gt;
&lt;li&gt;Experiment Subjects&lt;/li&gt;
&lt;li&gt;Rendering Result&lt;/li&gt;
&lt;li&gt;Asynchronous Rendering Result&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Hook testing&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Class vs. Function
&lt;/h2&gt;

&lt;p&gt;As you may know ReactJS offers two ways of writing components: class-based and function-based. Latter approach offered more concise way of writing components and in the meantime enabled usage of &lt;a href="https://reactjs.org/docs/hooks-intro.html" rel="noopener noreferrer"&gt;React Hooks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In terms of testing there is significant difference between classes and functions. Functions, defined inside of function components cannot be mocked. If for some reason you want to have possibility to mock any of methods used in your component consider using class-based approach&lt;/p&gt;

&lt;p&gt;In my opinion, this limitation is not limitation at all since React components represent some parts of User Interface and therefore should not be tested the same way we test backend code. You'll get what I mean a bit later&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing React Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Experiment Subjects
&lt;/h3&gt;

&lt;p&gt;Before writing any tests we need few components to test. In the beginning of each section I will provide content of component I'm going to test. You are free to use any other component for experimenting&lt;/p&gt;

&lt;h3&gt;
  
  
  Rendering Result
&lt;/h3&gt;

&lt;p&gt;Component to test:&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="nx"&gt;React&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&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;TestComponent&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="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;div&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;/div&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;p&gt;When it comes to testing rendering output we can't rely on snapshots since they meant for regression testing&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Regression testing is a software testing practice that ensures an application still functions as expected after any code changes, updates, or improvements&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When we need to ensure that component renders properly on given input(or without it) &lt;code&gt;@testing-library/react&lt;/code&gt; steps in&lt;/p&gt;

&lt;p&gt;Firstly, we will need to render component. For this to manage we need to import &lt;code&gt;render&lt;/code&gt; function from &lt;code&gt;@testing-library/react&lt;/code&gt;. Component will be rendered in artificial DOM. To easily find nodes in this DOM we will import &lt;code&gt;screen&lt;/code&gt; object&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="s1"&gt;@testing-library/react&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;Next we use this &lt;code&gt;render&lt;/code&gt; function to render component the way we need. Simply pass JSX as argument&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="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;TestComponent&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/TestComponent&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;Now we can use queries provided by &lt;code&gt;testing-library&lt;/code&gt; in &lt;code&gt;screen&lt;/code&gt; object. As React components are about building User Interface that is presented to end user those queries provide methods to find nodes the way users see them. It becomes more clear when you see it in action&lt;/p&gt;

&lt;p&gt;Now we expect to see node with text &lt;code&gt;Node&lt;/code&gt;. Let's literally try to find such element. We can do it following way&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;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Node&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;And to actually check that we found it, let's expect that resulted value is defined&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="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="s1"&gt;Node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we run script &lt;code&gt;test&lt;/code&gt; we should see successful output. In case you need to update snapshots don't forget to add &lt;code&gt;-u&lt;/code&gt; flag&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%2Fijwnn9aqv48ft2bvny3x.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%2Fijwnn9aqv48ft2bvny3x.png" alt="first yarn test result testing rendering result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But currently our new test suite is not self-descriptive and informative. Library &lt;code&gt;@testing-library/jest-dom&lt;/code&gt; provide many additional matchers for DOM nodes. Import it into test file&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/jest-dom&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;And now replace matcher &lt;code&gt;toBeDefined&lt;/code&gt; with the one called &lt;code&gt;toBeInTheDocument&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="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="s1"&gt;Node&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rerun script &lt;code&gt;test&lt;/code&gt; and check if testing passes&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%2Fjlqbkzt6rlg0xcx0r096.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%2Fjlqbkzt6rlg0xcx0r096.png" alt="script test result with matcher toBeInTheDocument"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Asynchronous Rendering Result
&lt;/h3&gt;

&lt;p&gt;It's very common when component performs request to API and waits for response before rendering final result. Firstly, adjust TestComponent to mock server request and append conditional rendering&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="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&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&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;TestComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;span class="nf"&gt;useEffect&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;setTimeout&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;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&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="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;div&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;/div&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;p&gt;I'll use &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; hooks combined with setTimeout to postpone state change&lt;/p&gt;

&lt;p&gt;Now since our component renders result not instantly, different query should be used. Queries provided by &lt;code&gt;testing-library&lt;/code&gt; that allow to work with asynchronous rendering start with &lt;code&gt;find&lt;/code&gt; prefix instead of &lt;code&gt;get&lt;/code&gt; we used previously for synchronously rendered content&lt;/p&gt;

&lt;p&gt;Important notice: &lt;code&gt;find&lt;/code&gt; queries waits up to 1000ms&lt;/p&gt;

&lt;p&gt;Make test suite's callback &lt;code&gt;async&lt;/code&gt;, replace query with &lt;code&gt;findByText&lt;/code&gt; and await on returned Promised. Looks like following&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="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="s1"&gt;should render properly&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="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;TestComponent&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/TestComponent&lt;/span&gt;&lt;span class="err"&gt;&amp;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="k"&gt;await&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;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Node&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;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;Script &lt;code&gt;test&lt;/code&gt; result:&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%2F6v2y6o729l6014anlket.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%2F6v2y6o729l6014anlket.png" alt="async rendering test result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's also make sure that &lt;code&gt;Loading&lt;/code&gt; node is rendered initially. Simply use query &lt;code&gt;getByText&lt;/code&gt; to look for node containing &lt;code&gt;Loading&lt;/code&gt; text before last &lt;code&gt;expect&lt;/code&gt; were we await until final result is rendered&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="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="s1"&gt;Loading&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;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="k"&gt;await&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;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Node&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;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Script &lt;code&gt;test&lt;/code&gt; result:&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%2F3no2hk54x3prq2mpindi.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%2F3no2hk54x3prq2mpindi.png" alt="second async rendering test result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://testing-library.com/docs/queries/about" rel="noopener noreferrer"&gt;More info on queries provided by &lt;code&gt;testing-library&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hook testing
&lt;/h2&gt;

&lt;p&gt;I'll write simple hook that mocks request to server the same way I did it previously using setTimeout to add artificial delay&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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useMockRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;delay&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;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;span class="nf"&gt;useEffect&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;setTimeout&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;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;delay&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="nx"&gt;isLoading&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;TestComponent file:&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="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&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&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;useMockRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;delay&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;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;span class="nf"&gt;useEffect&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;setTimeout&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;setIsLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;delay&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="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&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;TestComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMockRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&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="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;div&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;/div&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;p&gt;Firstly, let's add new &lt;code&gt;describe&lt;/code&gt; block to our test file and give it a title &lt;code&gt;useMockRequest&lt;/code&gt;. Create one test inside of new &lt;code&gt;describe&lt;/code&gt; for further usage. I will name it &lt;code&gt;should change state after given delay&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In real world application you would create new file for new test block but currently I want to keep it simple&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let's clarify what are React Hooks.&lt;/p&gt;

&lt;p&gt;React Hooks are functions that enable control on your component's behavior. When it comes to testing it can be a bit misleading since you cannot really use capabilities of React hooks outside of a component. Or can we?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;testing-library&lt;/code&gt; provides one more library exactly for such purpose allowing us to avoid headache and safe strength for actual testing. It is called &lt;a href="https://react-hooks-testing-library.com" rel="noopener noreferrer"&gt;&lt;code&gt;@testing-library/react-hooks&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add it as development dependency&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D @testing-library/react-hooks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D @testing-library/react-hooks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It provides a lot of tools for easy and comfortable hook testing but let's check them step-by-step&lt;/p&gt;

&lt;p&gt;First thing that needs to be done is hook rendering. Our new library will do all hard work itself. See how it looks like below&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;renderHook&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;@testing-library/react-hooks&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&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;useMockRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To render hook we need &lt;code&gt;renderHook&lt;/code&gt;. Pretty straightforward, isn't it?&lt;/p&gt;

&lt;p&gt;Then you call it and pass callback as argument inside of which you invoke your hook with or without arguments&lt;/p&gt;

&lt;p&gt;The result of invocation is an object that provides many fields and utility functions to proceed with rendered hook testing&lt;/p&gt;

&lt;p&gt;First thing we need to get is the actual result of hook invocation since we have to verify that initial state is equal to &lt;code&gt;true&lt;/code&gt;. Hook's return value can be accessed by &lt;code&gt;result&lt;/code&gt; field of an object returned by &lt;code&gt;renderHook&lt;/code&gt; function. I will utilise destructuring to keep code concise&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&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;useMockRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Object &lt;code&gt;result&lt;/code&gt; also contains multiple fields but we should be interested in &lt;code&gt;current&lt;/code&gt; as it is containing exactly what we need&lt;/p&gt;

&lt;p&gt;Since our hook returns array of two elements, &lt;code&gt;current&lt;/code&gt; property will be exactly this array. To validate that state, returned by hook initially is false, just access first element of &lt;code&gt;current&lt;/code&gt; property and add assertion on that&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First state is tested, next thing that should be checked is that state changes after some time and to achieve that we need to wait for hook to rerender. Exactly for this purpose &lt;code&gt;renderHook&lt;/code&gt; returns function called &lt;code&gt;waitForNextUpdate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To wait for next hook update we have to... &lt;code&gt;await&lt;/code&gt; a Promise this function returns&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;await&lt;/span&gt; &lt;span class="nf"&gt;waitForNextUpdate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Be aware that by default it waits up to 1000ms but it can be changed by passing additional argument&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once promise had been awaited, we can check absolutely the same value to be changed - the one inside of &lt;code&gt;result.current[0]&lt;/code&gt;. Now we expect it to be &lt;code&gt;false&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeFalsy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full test case looks like that&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitForNextUpdate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&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;useMockRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitForNextUpdate&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeFalsy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run script &lt;code&gt;test&lt;/code&gt; to invoke all tests&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%2Fbiim7fppy3rc772ujifz.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%2Fbiim7fppy3rc772ujifz.png" alt="result of yarn test after adding test for hook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was only top of the mountain in regards of testing hooks. I'll dive deeply into this topic in separate post or series of posts&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://github.com/Mr0Bread/react-testing-tutorial-app" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; with all my code in one place if you need&lt;/p&gt;

&lt;p&gt;In addition, feel free to leave a comment about what did you like and what did you not&lt;/p&gt;

&lt;p&gt;In regards of this post this is it for today. See you next time!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>testing</category>
    </item>
    <item>
      <title>Testing modern ReactJS Application: Unit Testing(Part 1)</title>
      <dc:creator>Vladislav Zimnikov</dc:creator>
      <pubDate>Sun, 13 Mar 2022 12:59:37 +0000</pubDate>
      <link>https://forem.com/mr0bread/testing-modern-reactjs-application-unit-testingpart-1-2g4g</link>
      <guid>https://forem.com/mr0bread/testing-modern-reactjs-application-unit-testingpart-1-2g4g</guid>
      <description>&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;More libraries&lt;/li&gt;
&lt;li&gt;Experiment Subject&lt;/li&gt;
&lt;li&gt;Experiment Environment&lt;/li&gt;
&lt;li&gt;
Snapshot Testing

&lt;ol&gt;
&lt;li&gt;Little bit of terminology&lt;/li&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;li&gt;Running tests&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Useful Links&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  More libraries
&lt;/h2&gt;

&lt;p&gt;To append additional layer of abstraction and make our as developer life easier few extra libraries should be added to project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/test-renderer.html"&gt;&lt;code&gt;react-test-renderer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://testing-library.com/docs/react-testing-library/intro/"&gt;&lt;code&gt;@testing-library/react&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://testing-library.com/docs/ecosystem-jest-dom"&gt;&lt;code&gt;@testing-library/jest-dom&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://testing-library.com/docs/ecosystem-user-event"&gt;&lt;code&gt;@testing-library/user-event&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open root of project in your terminal and invoke following command&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D react-test-renderer @testing-li
brary/react @testing-library/jest-dom @testing-library/user-event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D react-test-renderer @testing-li
brary/react @testing-library/jest-dom @testing-library/user-event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Experiment Subject
&lt;/h2&gt;

&lt;p&gt;Before starting performing tests component is needed. To save time contents of mock component is provided below:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;component.jsx&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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&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="nx"&gt;TestComponent&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Test&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&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;h2&gt;
  
  
  Experiment Environment
&lt;/h2&gt;

&lt;p&gt;In the same folder create &lt;code&gt;component.test.jsx&lt;/code&gt;. This file will contain all tests written in this post&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="nx"&gt;React&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&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;TestComponent&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;./component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;TestComponent&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Snapshot Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Little bit of terminology
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://jestjs.io/docs/snapshot-testing"&gt;Jest Documentation on Snapshot testing&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The first time this test is run, Jest creates a snapshot file. On subsequent test runs, Jest will compare the rendered output with the previous snapshot. If they match, the test will pass. If they don't match, either the test runner found a bug in your code that should be fixed, or the implementation has changed and the snapshot needs to be updated&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;Exactly for purpose of snapshot testing &lt;code&gt;react-test-renderer&lt;/code&gt; was installed&lt;/p&gt;

&lt;p&gt;1 - Import function &lt;code&gt;create&lt;/code&gt; from &lt;code&gt;react-test-renderer&lt;/code&gt; into &lt;code&gt;component.test.jsx&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;create&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-test-renderer&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;2 - Create test suite&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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should match snapshot&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 - Populate test suite&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;create&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;TestComponent&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="nx"&gt;toJSON&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;toMatchSnapshot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happens in test suite we created:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rendering component using function &lt;code&gt;create&lt;/code&gt; and passing JSX component as argument&lt;/li&gt;
&lt;li&gt;On result of calling &lt;code&gt;create&lt;/code&gt; calling method &lt;code&gt;toJSON&lt;/code&gt; to serialise output&lt;/li&gt;
&lt;li&gt;Passing serialised value to &lt;code&gt;expect&lt;/code&gt; function and calling matcher &lt;code&gt;toMatchSnapshot&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Jest will process snapshot itself, no additional input from developer is needed&lt;/p&gt;

&lt;h3&gt;
  
  
  Running tests
&lt;/h3&gt;

&lt;p&gt;Now try to invoke script &lt;code&gt;test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8hwX7Mgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ijir8g0dkj1wp9jb4xwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8hwX7Mgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ijir8g0dkj1wp9jb4xwu.png" alt="result of yarn test after adding snapshot test" width="880" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you did everything correctly output should be nearly the same. In short, since snapshot didn't exist Jest saved it inside of &lt;code&gt;__snapshots__&lt;/code&gt; directory next to test file and passed test. Run test again to see difference&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y1-nQHCi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2qkc6dxwqhli8o18yeu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y1-nQHCi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2qkc6dxwqhli8o18yeu.png" alt="second result of yarn test" width="880" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jest used existing snapshot for comparison. Now make some changes in component, e.g. change text in it and run script &lt;code&gt;test&lt;/code&gt; again&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iUqD0Lq4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zv3aofquxgrja4zvxe94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iUqD0Lq4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zv3aofquxgrja4zvxe94.png" alt="result of yarn test after changing component" width="880" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since content that is being rendered has been changed snapshot test had failed. That is exactly the purpose of snapshot tests: track down changes/errors in render process/result&lt;/p&gt;

&lt;p&gt;Now, if we know that received change is correct, we need to update snapshot accordingly. To do that just call script &lt;code&gt;test&lt;/code&gt; with argument &lt;code&gt;-u&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run test -u
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn test -u
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the result&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tZNILJwN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56rl3nvmc4fs27a7nwnb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tZNILJwN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56rl3nvmc4fs27a7nwnb.png" alt="result of yarn test -u" width="880" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is everything you need to know to start with snapshot testing and apply it ещ your components&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jestjs.io/docs/snapshot-testing"&gt;Jest Documentation on Snapshot testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/test-renderer.html"&gt;React Test Renderer Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next time will share on how to perform more granular unit testing of components, difference between testing functional and class components and how to test react hooks&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>testing</category>
    </item>
    <item>
      <title>Testing modern ReactJS Application: Setting Up</title>
      <dc:creator>Vladislav Zimnikov</dc:creator>
      <pubDate>Sun, 13 Mar 2022 09:05:22 +0000</pubDate>
      <link>https://forem.com/mr0bread/testing-modern-reactjs-application-setting-up-23h3</link>
      <guid>https://forem.com/mr0bread/testing-modern-reactjs-application-setting-up-23h3</guid>
      <description>&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
Foreword

&lt;ol&gt;
&lt;li&gt;Do you have to read this&lt;/li&gt;
&lt;li&gt;Create React App&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Your way of ReactJS&lt;/li&gt;
&lt;li&gt;How to bootstrap ReactJS App&lt;/li&gt;
&lt;li&gt;Installing and configuring Jest&lt;/li&gt;
&lt;li&gt;Holy Babel&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Foreword
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do you have to read this
&lt;/h3&gt;

&lt;p&gt;If you have already Jest installed and configured you can skip this part of series&lt;/p&gt;

&lt;h3&gt;
  
  
  Create React App
&lt;/h3&gt;

&lt;p&gt;I am completely aware that &lt;code&gt;create-react-app&lt;/code&gt; provides Jest configuration out of the box, but this fact breaks the whole point of this series. I want to demonstrate how to install everything from scratch.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript
&lt;/h3&gt;

&lt;p&gt;Regarding TypeScript - I will cover all additional configuration needed, but firstly I want to focus on setting up essentials using JavaScript only&lt;/p&gt;

&lt;h2&gt;
  
  
  Your way of ReactJS
&lt;/h2&gt;

&lt;p&gt;If for some reason you don't want to use Vite for app bootstrapping or you are already having ReactJS app you can skip this part of series as it does not matter really what bundling tool you are using.&lt;/p&gt;

&lt;p&gt;In case you are going to scaffold application your way be aware you can face issues not covered in this tutorial series&lt;/p&gt;

&lt;h2&gt;
  
  
  How to bootstrap ReactJS App
&lt;/h2&gt;

&lt;p&gt;Our initial goal is to bootstrap ReactJS application quickly without any need to perform manual configurations ourselves.&lt;/p&gt;

&lt;p&gt;For this tutorial I am going to use starter based on such bundling tool as &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;. Basically, it will only matter only on this step since &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt;(testing framework) invokes all tests in it's own environment and does not care what bundling tool you are using for development&lt;/p&gt;

&lt;p&gt;Use following command to scaffold ReactJS application named &lt;code&gt;react-testing-app&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm create vite@latest react-testing-app -- --template react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn create vite react-testing-app --template react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you are done with this step follow given instructions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;cd react-testing-app/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yarn&lt;/code&gt;(just &lt;code&gt;yarn&lt;/code&gt; and it will start installation by default)/&lt;code&gt;npm install&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After all previous steps you can invoke script &lt;code&gt;dev&lt;/code&gt; to start up dev server:&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And make sure that application starts properly and running on port 3000&lt;/p&gt;

&lt;p&gt;If everything works properly you can stop dev server and proceed further with tutorial&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing and configuring Jest
&lt;/h2&gt;

&lt;p&gt;First thing we need is Jest. In short, Jest is testing framework. I won't go deep in details regarding Jest, this post is about bit different thing.&lt;/p&gt;

&lt;p&gt;Firstly, let's add Jest as development dependency to our project and install it&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D --save jest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D jest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once command is completed you can open your &lt;code&gt;package.json&lt;/code&gt; and make sure that Jest is now listed in your &lt;code&gt;devDependencies&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^27.5.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can initialize Jest. Basically, it will create &lt;code&gt;jest.config.js&lt;/code&gt; that we are going to use for Jest configuration&lt;/p&gt;

&lt;p&gt;Run following command to start Jest initialization:&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx jest --init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn jest --init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be prompted to answer few questions. Answers provided below&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UxL3EA1O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f34cr97h8ue44p7apnjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UxL3EA1O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f34cr97h8ue44p7apnjg.png" alt="List of questions and answers to them for Jest configuration" width="680" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you are done just create &lt;code&gt;App.test.js&lt;/code&gt; inside of &lt;code&gt;src&lt;/code&gt; directory with following contents&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;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;jest&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="s1"&gt;should work&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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="mi"&gt;2&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;And then execute script test to verify that Jest runs test properly&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Result will be as follows&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qH52ZwqC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7wqdicfg37qut5kxe24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qH52ZwqC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7wqdicfg37qut5kxe24.png" alt="Result of Jest invocation" width="719" height="300"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Holy Babel
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://babeljs.io/"&gt;&lt;code&gt;Babel&lt;/code&gt;&lt;/a&gt; will be responsible for turning JSX and other modern language features to such state it can be understood by runtime environment Jest using under the hood since currently if you try to import file with JSX into test file you will get an error&lt;/p&gt;

&lt;p&gt;Firstly, adding Babel itself and few additional packages as development dependencies to our project&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D babel-jest @babel/core @babel/preset-env @babel/preset-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D babel-jest @babel/core @babel/preset-env @babel/preset-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create file named &lt;code&gt;babel.jest.config.js&lt;/code&gt;. The reason behind such name is to avoid possible collision with default &lt;code&gt;babel.config.js&lt;/code&gt;. For example NextJS automatically starts using babel compiler if it sees &lt;code&gt;babel.config.js&lt;/code&gt; in root of project&lt;/p&gt;

&lt;p&gt;Set following content of &lt;code&gt;babel.jest.config.js&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;presets&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&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;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;current&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}}],&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;In short such we are telling Babel to use following presets while transpiling our JavaScript code&lt;/p&gt;

&lt;p&gt;Now we need explicitly tell Jest to use this babel configuration for transpiling JS code. To do that open &lt;code&gt;jest.config.js&lt;/code&gt;, find &lt;code&gt;transform&lt;/code&gt; key, uncomment and replace &lt;code&gt;undefined&lt;/code&gt; with following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"\\.(js|jsx)$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"babel-jest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"configFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./babel.jest.config.js"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a result you should have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;transform:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"\\.(js|jsx)$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"babel-jest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"configFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./babel.jest.config.js"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to test whether Jest is configured properly for parsing modern JS and JSX, create file &lt;code&gt;component.jsx&lt;/code&gt;, export some mock component from there, import into &lt;code&gt;App.test.js&lt;/code&gt; and invoke &lt;code&gt;test&lt;/code&gt; script. Here are contents of my &lt;code&gt;component.jsx&lt;/code&gt; and &lt;code&gt;App.test.js&lt;/code&gt; respectively:&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="nx"&gt;React&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&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="nx"&gt;TestComponent&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Test&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&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 javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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&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;TestComponent&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;./component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;jest&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="s1"&gt;should work&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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="mi"&gt;2&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;&lt;code&gt;npm run test&lt;/code&gt;/&lt;code&gt;yarn test&lt;/code&gt; result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cTdB-cZz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/623yxmor6ds1g5epjnrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cTdB-cZz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/623yxmor6ds1g5epjnrw.png" alt="yarn test result after setting up babel" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have similar successful output, congratulations, you have set up Jest and Babel properly for transpiling and understanding JSX. Now you are ready to start testing your application.&lt;/p&gt;

&lt;p&gt;Next time I'm going to cover unit testing of components using &lt;code&gt;react-test-renderer&lt;/code&gt;, &lt;code&gt;@testing-library/react&lt;/code&gt;, &lt;code&gt;@testing-library/jest-dom&lt;/code&gt; and &lt;code&gt;@testing-library/user-event&lt;/code&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>testing</category>
    </item>
    <item>
      <title>Testing modern ReactJS Application: Introduction</title>
      <dc:creator>Vladislav Zimnikov</dc:creator>
      <pubDate>Wed, 09 Mar 2022 09:48:15 +0000</pubDate>
      <link>https://forem.com/mr0bread/testing-modern-reactjs-application-introduction-3kpg</link>
      <guid>https://forem.com/mr0bread/testing-modern-reactjs-application-introduction-3kpg</guid>
      <description>&lt;p&gt;Hello everyone! In this series I'm going to share with you my experience and knowledge in testing ReactJS-based applications using modern libraries such as &lt;a href="https://jestjs.io/"&gt;&lt;code&gt;jest&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://testing-library.com/docs/react-testing-library/intro/"&gt;&lt;code&gt;@testing-library/react&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://testing-library.com/docs/ecosystem-user-event/"&gt;&lt;code&gt;@testing-library/user-event&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://reactjs.org/docs/test-renderer.html"&gt;&lt;code&gt;react-test-renderer&lt;/code&gt;&lt;/a&gt; using both JavaScript and &lt;a href="https://www.typescriptlang.org/"&gt;&lt;code&gt;TypeScript&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>testing</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
