<?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: Borislav Grigorov</title>
    <description>The latest articles on DEV Community by Borislav Grigorov (@brslv).</description>
    <link>https://dev.to/brslv</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%2F137963%2F3ec9f5de-2282-40c9-a8f1-3383fe0fd56e.jpg</url>
      <title>DEV Community: Borislav Grigorov</title>
      <link>https://dev.to/brslv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brslv"/>
    <language>en</language>
    <item>
      <title>Introduction to Testing React Components with Vite, Vitest and React Testing Library</title>
      <dc:creator>Borislav Grigorov</dc:creator>
      <pubDate>Thu, 11 Jan 2024 14:25:56 +0000</pubDate>
      <link>https://dev.to/brslv/introduction-to-testing-react-components-with-vite-vitest-and-react-testing-library-8cb</link>
      <guid>https://dev.to/brslv/introduction-to-testing-react-components-with-vite-vitest-and-react-testing-library-8cb</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on my blog: &lt;a href="https://bogr.dev/blog/react-testing-intro/" rel="noopener noreferrer"&gt;https://bogr.dev/blog/react-testing-intro/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article assumes a certain level of agreement between me and you that testing the code we write as developers, is important. And also, that the best way to ensure our code has no bugs, is to write tests and run them as often as possible during the development lifecycle. I'll leave the discussion about the pros and cons of writing tests (and the different approaches in that matter) for another article.&lt;/p&gt;

&lt;p&gt;In this article I want to walk you through the setup and writing of your very first test in React. Also, to provide some basic theory around the testing terminology and best practices. Meaning that this article is targeting mostly beginner JS/React developers, but could be a good starting point for any developer at any level of experience.&lt;/p&gt;

&lt;p&gt;I hate long intros, so why don't we just dive right in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you're going to learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to setup a React project with Vite, Vitest and React Testing Library&lt;/li&gt;
&lt;li&gt;How to implement a very basic quotes app, which shows a quote from an array and the user is able to navigate go to the next/previous quotes using previous and next buttons.&lt;/li&gt;
&lt;li&gt;What's the difference between &lt;strong&gt;Unit&lt;/strong&gt; and &lt;strong&gt;Integration&lt;/strong&gt; tests.&lt;/li&gt;
&lt;li&gt;What are some of the most common react-testing-library APIs (&lt;code&gt;render&lt;/code&gt;, &lt;code&gt;screen&lt;/code&gt;, &lt;code&gt;query functions&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;What's the difference between &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;query&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt; query functions&lt;/li&gt;
&lt;li&gt;The three &lt;code&gt;A&lt;/code&gt;s testing framework&lt;/li&gt;
&lt;li&gt;Some best practices for writing React tests&lt;/li&gt;
&lt;li&gt;I'll leave some of the tests for you to figure out by yourself. Remember - it's crucial apply the knowledge if you want it to stick.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/brslv/react-testing-intro" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with the code of our project. Feel free to clone it and experiment with it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Vite
&lt;/h3&gt;

&lt;p&gt;First things first, let's setup a react project using Vite.&lt;/p&gt;

&lt;p&gt;But what's vite, you may ask?&lt;/p&gt;

&lt;p&gt;From vite's website:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Vite (French word for "quick", pronounced /vit/, like "veet") is a build tool that aims to provide a faster and leaner development experience.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We'll use Vite's superpowers to run a simple dev server for our React app while developing. Also, we'll use it to bundle the application later when we're ready to deploy (won't be covered in this article).&lt;/p&gt;

&lt;h4&gt;
  
  
  Create a React project with Vite
&lt;/h4&gt;

&lt;p&gt;Let's start with creating a folder for the app. I'm naming my app &lt;code&gt;rtl-vite&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;rtl-vite &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;rtl-vite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now create the React app with Vite. Run this in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're going to be asked what project scaffold do you want for your new Vite app.&lt;/p&gt;

&lt;p&gt;For the sake of simplicity, I've picked the React with JavaScript template, but feel free to select the React with TypeScript one if you want to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing dependencies
&lt;/h3&gt;

&lt;p&gt;In order to test React apps, we need to bring in couple more libraries to our project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vitest and React Testing Library
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Vitest is a next generation testing framework powered by Vite.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; vitest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The React Testing Library is a very light-weight solution for testing React components. It provides light utility functions on top of react-dom and react-dom/test-utils, in a way that encourages better testing practices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The RTL is the primary tool we're going to use and interact with in this tutorial.&lt;/p&gt;

&lt;p&gt;All the other tools are in a way "the infrastructure" around the testing itself.&lt;/p&gt;

&lt;p&gt;So let's install that as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @testing-library/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: The &lt;code&gt;-D&lt;/code&gt; flag installs the deps as &lt;code&gt;dev dependencies&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the test globals and jsdom env
&lt;/h3&gt;

&lt;p&gt;In order to save us some import statements in our test files and tell vitest that we want to use &lt;code&gt;jsdom&lt;/code&gt;, update the exported config in your &lt;code&gt;vite.config.js&lt;/code&gt; to the following:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/vite.config.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// &amp;lt;--- Add this object&lt;/span&gt;
    &lt;span class="na"&gt;globals&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="na"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsdom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up a test script
&lt;/h3&gt;

&lt;p&gt;We have the needed libraries, but how do we run the tests?&lt;/p&gt;

&lt;p&gt;Let's add a &lt;code&gt;test&lt;/code&gt; command to our package.json's scripts section:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;package.json&lt;/em&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="nl"&gt;"scripts"&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;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;We're now ready to roll.&lt;/p&gt;

&lt;h2&gt;
  
  
  The app
&lt;/h2&gt;

&lt;p&gt;We need something to test, so let's create a very simple app.&lt;/p&gt;

&lt;p&gt;Here's what we're going to build now:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A minimalist quotes application featuring a streamlined interface with two primary controls: a 'Previous' button and a 'Next' button. The application's central feature is a designated display area where quotes are presented. Upon the user's interaction with the 'Next' button, the application will display a new quote. When the 'Previous' button is clicked, the application will revert to showing the immediately preceding quote.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's go.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;App&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;So, here's our &lt;code&gt;App&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/App.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&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="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Quote&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;./components/Quote&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;Previous&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;./components/Previous&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;Next&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;./components/Next&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;quotes&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;currentIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentIndex&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="mi"&gt;0&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;navigate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;direction&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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;nextIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;nextIndex&lt;/span&gt; &lt;span class="o"&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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="nx"&gt;nextIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;setCurrentIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App__quoteContainer"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Quote&lt;/span&gt; &lt;span class="na"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App__navigation"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Previous&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Next&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep things simple, our quotes data is going to be an array with a few items.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;App&lt;/code&gt; component expects a list of quotes to be passed through its &lt;code&gt;props&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Notice also that it keeps a reference to an internal state value called &lt;code&gt;currentIndex&lt;/code&gt;, which is initially &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;navigate&lt;/code&gt; function is the meat of our app's functionality. That function gets called when the user navigates back and forth between the quotes.&lt;/p&gt;

&lt;p&gt;In there we determine the next index, ensuring it's within the bounds of the quotes array.&lt;/p&gt;

&lt;p&gt;The UI consists of the core component (&lt;code&gt;&amp;lt;Quote /&amp;gt;&lt;/code&gt;), followed by the two controls, wrapped in a div that lays them out on the x axis.&lt;/p&gt;

&lt;h3&gt;
  
  
  The quotes list
&lt;/h3&gt;

&lt;p&gt;Ideally, our app would interact with some sort of an API to get a list of quotes.&lt;/p&gt;

&lt;p&gt;But for the purposes of our exercise, we're going to keep things as simple as possible and define a simple array with a bunch of quotes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/quotes.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quotes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;`“What greater gift than the love of a cat.” — Charles Dickens`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`“One of the ways in which cats show happiness is by sleeping.” —Cleveland Amory`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`“A cat will be your friend, but never your slave.” —Theophile Gautier`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`“No home is complete without the pitter-patter of kitty feet.” —Unknown`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`“As every cat owner knows, nobody owns a cat.” —Ellen Perry Berkeley`&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;We're then passing the data to the &lt;code&gt;App&lt;/code&gt; component like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/main.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StrictMode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;React&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The &lt;code&gt;Quote&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;The Quote component is a pure functional component, which gets a quote and displays it. That's all.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/components/Quote.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Quote.css&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;Quote&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;quote&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;blockquote&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Quote"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;blockquote&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The navigation controls
&lt;/h3&gt;

&lt;p&gt;For the navigation controls, we also have two functional components.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/components/Previous.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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;Previous&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Previous
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;src/components/Next.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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;Next&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Next
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Since we already have a simple, yet functional app, let's see what we can do to ensure any further development of features in the app goes smoothly and doesn't break any of the existing functionalities.&lt;/p&gt;

&lt;p&gt;To do this, we're going to unit test the &lt;code&gt;Quote&lt;/code&gt;, &lt;code&gt;Previous&lt;/code&gt; and &lt;code&gt;Next&lt;/code&gt; components, and also integration test the &lt;code&gt;App&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;But before that, some theory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unit tests
&lt;/h3&gt;

&lt;p&gt;In programming, a unit test is a piece of code that is written to test a single application module of a software system.&lt;/p&gt;

&lt;p&gt;By module, we usually mean a tiny piece of functionality - a unit - that the program composes with other such pieces in order to do some task.&lt;/p&gt;

&lt;p&gt;Just like lego blocks, where each block is a unit/module.&lt;/p&gt;

&lt;p&gt;In the React world, you can think a React component as such a module. &lt;strong&gt;Thus, a unit test in React world is designed to test the behavior of a single React component&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Such components in our application are the &lt;code&gt;Quote&lt;/code&gt;, &lt;code&gt;Previous&lt;/code&gt; and &lt;code&gt;Next&lt;/code&gt;. They are a single-purpose, pure functional components.&lt;/p&gt;

&lt;p&gt;We're going to unit test them in a second, but before that, let's quickly remind ourselves what's integration testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration tests
&lt;/h3&gt;

&lt;p&gt;Integration tests, are designed to verify that the &lt;em&gt;interactions&lt;/em&gt; between two or more single-purpose modules in a software system run smoothly, without any bugs.&lt;/p&gt;

&lt;p&gt;In other words, &lt;strong&gt;we test whether a group of units &lt;em&gt;work together&lt;/em&gt; (interact) as expected&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In our application we have the &lt;code&gt;App&lt;/code&gt; component which composes the rest of the components and that's a perfect candidate for an integration test.&lt;/p&gt;

&lt;p&gt;Let's start with the simpler ones - the unit tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the &lt;code&gt;Quote&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;Our &lt;code&gt;Quote&lt;/code&gt; component is quite dumb and not much could break there. So it'd be enough to make sure it just renders properly as our first step.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;Quote.test.jsx&lt;/code&gt; file under &lt;code&gt;src/components/&lt;/code&gt; and paste that in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Quote&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;./Quote&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;Quote&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 render properly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Quote&lt;/span&gt; &lt;span class="na"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"What a nice day."&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what's actually going on here?&lt;/p&gt;

&lt;h4&gt;
  
  
  The &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; functions
&lt;/h4&gt;

&lt;p&gt;Vitest, our testing framework, exposes couple of useful functions which we use to build our tests.&lt;/p&gt;

&lt;p&gt;The first one is &lt;code&gt;describe&lt;/code&gt;. Think of it as a way to group couple of tests that are related in some way or another into a single &lt;code&gt;describe block&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since we're going to write couple of tests that are testing our &lt;code&gt;Quote&lt;/code&gt; component, I'm going to group them in a single describe block.&lt;/p&gt;

&lt;p&gt;You can have as many describe blocks as you wish. Also, you can nest them.&lt;/p&gt;

&lt;p&gt;My advice would be to keep things simple. Usually, a single describe block is more than enough.&lt;/p&gt;

&lt;p&gt;As you can see from the code above, we put our tests inside of &lt;code&gt;it&lt;/code&gt; functions. There's also a &lt;code&gt;test&lt;/code&gt; function, which is basically the same - they're interchangeable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;it&lt;/code&gt; functions is where you put the actual test code.&lt;/p&gt;

&lt;h5&gt;
  
  
  Are they global?
&lt;/h5&gt;

&lt;p&gt;Recall that in the beginning we added this to our &lt;code&gt;vite.config.js&lt;/code&gt; 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="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;globals&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="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsdom&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;What that does is to expose the &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; functions on the global object. That means that we can now use those (and couple of other functions) right away, without importing them.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;render&lt;/code&gt; is the first step
&lt;/h4&gt;

&lt;p&gt;Take a look at our test again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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 render properly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Quote&lt;/span&gt; &lt;span class="na"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"What a nice day."&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All it does is to render our component.&lt;/p&gt;

&lt;p&gt;But where does it render it?&lt;/p&gt;

&lt;p&gt;Well, the cool thing is it does it behind the scenes and you don't see it. Think of it as an invisible browser.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;render&lt;/code&gt; function call is the first step of a react test. You pass it the component you want to test, it does it's magic behind the scenes to generate the DOM for that component and after that you can interact with the rendered DOM, as if it was rendered in a browser.&lt;/p&gt;

&lt;p&gt;That's the magic of &lt;code&gt;react-testing-library&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Does it pass?
&lt;/h4&gt;

&lt;p&gt;A test in &lt;code&gt;Vitest&lt;/code&gt; passes if it doesn't throw an error.&lt;/p&gt;

&lt;p&gt;In our case, we never return from our test, so if everything works, it should pass successfully.&lt;/p&gt;

&lt;p&gt;Let's run it:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And yes, as expected, our first test is successful:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3revpj40b9crnkh9x6je.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3revpj40b9crnkh9x6je.png" alt="Quote tests are passing" width="308" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the &lt;code&gt;Previous&lt;/code&gt; and &lt;code&gt;Next&lt;/code&gt; components
&lt;/h3&gt;

&lt;p&gt;Now things get a bit more interesting.&lt;/p&gt;

&lt;p&gt;Our navigation components take a single &lt;code&gt;prop&lt;/code&gt;. A function (&lt;code&gt;onClick&lt;/code&gt;), which we run on button click.&lt;/p&gt;

&lt;p&gt;What a good test for those components would be?&lt;/p&gt;

&lt;p&gt;A good one would be to test whether or not the function gets called when a button is clicked, right?&lt;/p&gt;

&lt;p&gt;Let's do this.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/components/Previous.test.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&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;vi&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;vitest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="nx"&gt;fireEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Previous&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;./Previous&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&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;Previous&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="s1"&gt;should call "onClick" when a button is clicked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Previous&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;button&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;onClick&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;Lots of things are happening there. Let's go through each of them one step at a time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mocking the &lt;code&gt;onClick&lt;/code&gt; function
&lt;/h4&gt;

&lt;p&gt;Just to remind you, our &lt;code&gt;Previous&lt;/code&gt; and &lt;code&gt;Next&lt;/code&gt; components get a callback function called &lt;code&gt;onClick&lt;/code&gt; through their &lt;code&gt;props&lt;/code&gt;. The the button is clicked, the function is called.&lt;/p&gt;

&lt;p&gt;For the purposes of our test, we don't actually care what happens when the button is clicked. We care whether or not the function &lt;em&gt;gets called&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A common approach when you want to check if a function/object is being properly used by the system under test is to create a mock function/object and check that expected calls are made to the mock function/object.&lt;/p&gt;

&lt;p&gt;In vitest, you can mock a function, by creating a void one using &lt;code&gt;vi.fn()&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;em&gt;Arrange&lt;/em&gt; the stage
&lt;/h4&gt;

&lt;p&gt;The first line of our test should be already familiar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Previous&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We render the component and pass our mock &lt;code&gt;onClick&lt;/code&gt; function to it.&lt;/p&gt;

&lt;p&gt;But let's examine what happens on the next line:&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;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&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;It's pretty self-explanatory what that line does. But what's the deal with that &lt;code&gt;screen&lt;/code&gt; and what's &lt;code&gt;getByRole&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;screen&lt;/code&gt; object is a very important one. You're going to use it in most of your tests. It's always used in conjunction with &lt;code&gt;render&lt;/code&gt; and both of these objects come from the &lt;code&gt;react-testing-library&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Think of the &lt;code&gt;screen&lt;/code&gt; object as the "invisible browser", through which you can interact with the rendered DOM inside of the test. That object exposes a bunch of useful methods, which makes selecting elements on the DOM a trivial task.&lt;/p&gt;

&lt;p&gt;In our example, we call the &lt;code&gt;getByRole("button")&lt;/code&gt; to find the button in the rendered DOM.&lt;/p&gt;

&lt;p&gt;Here's a list of the most commonly used methods that the &lt;code&gt;screen&lt;/code&gt; exposes:&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="c1"&gt;// getBy*&lt;/span&gt;
&lt;span class="nx"&gt;getByRole&lt;/span&gt;
&lt;span class="nx"&gt;getByLabelText&lt;/span&gt;
&lt;span class="nx"&gt;getByTestId&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// getAllBy*&lt;/span&gt;
&lt;span class="nx"&gt;getAllByRole&lt;/span&gt;
&lt;span class="nx"&gt;getAllByLabelText&lt;/span&gt;
&lt;span class="nx"&gt;getAllByTestId&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// queryBy*&lt;/span&gt;
&lt;span class="nx"&gt;queryByRole&lt;/span&gt;
&lt;span class="nx"&gt;queryByLabelText&lt;/span&gt;
&lt;span class="nx"&gt;queryByTestId&lt;/span&gt;

&lt;span class="c1"&gt;// queryBy*&lt;/span&gt;
&lt;span class="nx"&gt;queryAllByRole&lt;/span&gt;
&lt;span class="nx"&gt;queryAllByLabelText&lt;/span&gt;
&lt;span class="nx"&gt;queryAllByTestId&lt;/span&gt;

&lt;span class="c1"&gt;// findBy*&lt;/span&gt;
&lt;span class="nx"&gt;findByRole&lt;/span&gt;
&lt;span class="nx"&gt;findByLabelText&lt;/span&gt;
&lt;span class="nx"&gt;findByTestId&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// findAllBy*&lt;/span&gt;
&lt;span class="nx"&gt;findAllByRole&lt;/span&gt;
&lt;span class="nx"&gt;findAllByLabelText&lt;/span&gt;
&lt;span class="nx"&gt;findAllByTestId&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  What's the difference between &lt;code&gt;getBy&lt;/code&gt;, &lt;code&gt;getAllBy&lt;/code&gt;, &lt;code&gt;queryBy&lt;/code&gt;, &lt;code&gt;queryAllBy&lt;/code&gt;, &lt;code&gt;findBy&lt;/code&gt; and &lt;code&gt;findAllBy&lt;/code&gt; in react-testing-library
&lt;/h5&gt;

&lt;p&gt;We can group all six of these so called &lt;em&gt;query functions&lt;/em&gt; in three groups: &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;query&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt; query functions.&lt;/p&gt;

&lt;p&gt;We use all of them to find elements on the rendered DOM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;getBy&lt;/code&gt;/&lt;code&gt;getAllBy&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;getBy&lt;/code&gt; and &lt;code&gt;getAllBy&lt;/code&gt; functions do a synchroneus query on the DOM and throw an error if no elements are found, thus failing the test right away. As the name implies, the &lt;code&gt;getBy&lt;/code&gt; is used to get a single element and the &lt;code&gt;getAllBy&lt;/code&gt; is used for selecting multiple elements that match the given query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;queryBy&lt;/code&gt;/&lt;code&gt;queryAllBy&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;queryBy&lt;/code&gt; and &lt;code&gt;queryAllBy&lt;/code&gt; do exactly the same, but they &lt;strong&gt;don't throw an error&lt;/strong&gt; if no elements are found. That's useful when you need to do some conditional logic inside of your tests, based on the presence of an element, and not fail the test immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;findBy&lt;/code&gt;/&lt;code&gt;findAllBy&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We use the &lt;code&gt;findBy&lt;/code&gt; and &lt;code&gt;findAllBy&lt;/code&gt; when dealing with some sort of asynchrony in the component we're testing.&lt;/p&gt;

&lt;p&gt;For example, when the component does a &lt;code&gt;fetch&lt;/code&gt; request to some API and waits for the result to come in order to render a DOM element.&lt;/p&gt;

&lt;p&gt;In that scenario, we can use &lt;code&gt;find&lt;/code&gt; functions to "tell" react-testing-library that the DOM element we're looking for is going to be rendered after some delay (caused by the &lt;code&gt;fetch&lt;/code&gt; in this case). So, the react-testing-library is going to wait for a certain amount of time for the element to appear and will throw after that time expires and no element is found.&lt;/p&gt;

&lt;p&gt;Keep in mind that you need to &lt;code&gt;await&lt;/code&gt; find operations, which makes the whole test &lt;code&gt;async&lt;/code&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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;some async test&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="c1"&gt;// &amp;lt;--- Notice the async&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SomeComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;findByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;--- Notice the await&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;Act&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;OK, that's the theory around react-testing-library's &lt;code&gt;query functions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Back to our test.&lt;/p&gt;

&lt;p&gt;After we have properly set the "stage" (rendered the component and got a reference to the button), we can proceed to doing the actual click.&lt;/p&gt;

&lt;p&gt;For that we're going to need another function from the &lt;code&gt;react-testing-library&lt;/code&gt; - &lt;code&gt;fireEvent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Again, as the name implies, that's how you trigger an event on a given DOM element.&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;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, right?&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;Assert&lt;/code&gt;ing that the button works as &lt;code&gt;expect&lt;/code&gt;ed
&lt;/h4&gt;

&lt;p&gt;Now to the meat of our test - making sure that what we've done in the first 4 lines actually worked.&lt;/p&gt;

&lt;p&gt;That's where the &lt;code&gt;expect&lt;/code&gt; function comes in handy.&lt;/p&gt;

&lt;p&gt;The expect function works like this:&lt;/p&gt;

&lt;p&gt;You pass it an object and it gives you back a wrapper around that object, exposing a bunch of useful functions, such as &lt;code&gt;toBe&lt;/code&gt; or &lt;code&gt;toEqual&lt;/code&gt; and so on.&lt;/p&gt;

&lt;p&gt;In our test, we pass it the &lt;code&gt;onClick&lt;/code&gt; mock function and &lt;code&gt;assert&lt;/code&gt; that it's being called once (&lt;code&gt;toBeCalledTimes(1)&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;onClick&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That completes our test.&lt;/p&gt;

&lt;p&gt;Now, try to write the test for the &lt;code&gt;Next&lt;/code&gt; component by yourself. I won't give you the code here, but it should be identical to the one we wrote for the &lt;code&gt;Previous&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;The best way to learn thins is to get your hands dirty, so go ahead and try.&lt;/p&gt;

&lt;h3&gt;
  
  
  The three &lt;code&gt;A&lt;/code&gt;s of testing
&lt;/h3&gt;

&lt;p&gt;When writing tests, a good framework to follow is the three &lt;code&gt;A&lt;/code&gt;s framework.&lt;/p&gt;

&lt;p&gt;That stands for &lt;strong&gt;Arrange, Act, Assert&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's take a look at our test for the &lt;code&gt;Previous&lt;/code&gt; component once again and notice the framework in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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;Previous&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="s1"&gt;should call "onClick" when a button is clicked&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;// Arrange (the stage)&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Previous&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Act&lt;/span&gt;
    &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Assert&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;onClick&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;Notice the comments. Those are the three main "blocks" in our test code.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Arrange&lt;/strong&gt; block is where you do the rendering and querying of elements. Basically, preparing the "stage" for action. Usually, you're going to see &lt;code&gt;render&lt;/code&gt;s and &lt;code&gt;screen&lt;/code&gt; operations in that block.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Act&lt;/strong&gt; block goes all the code that does something on the stage. Usually, you're going to see some &lt;code&gt;fireEvent&lt;/code&gt;s here.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Assert&lt;/strong&gt; is where we validate our assumptions. We do &lt;code&gt;expects&lt;/code&gt; here.&lt;/p&gt;

&lt;p&gt;Some tests may have only Arrange and Assert, some may have only Assert, and others may have all three of them.&lt;/p&gt;

&lt;p&gt;This is a universally applicable framework. You can think of your tests in three &lt;code&gt;A&lt;/code&gt;s regardless of the technology you're writing your tests on.&lt;/p&gt;

&lt;p&gt;Now, let's write an integration test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration testing the &lt;code&gt;App&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;It's time to make sure that the components that we compose inside of the &lt;code&gt;App&lt;/code&gt; component interact as expected.&lt;/p&gt;

&lt;p&gt;Here's our &lt;code&gt;App.test.jsx&lt;/code&gt; file. Try to understand what's going on by yourself. In the next few sections we're going to break down each of the three integration tests.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/App.test.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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;fireEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;quotes&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;./quotes&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;App&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;./App&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;App&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;shows first quote on app load&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstQuote&lt;/span&gt;&lt;span class="p"&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;shows next quote on `Next` button click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secondQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;next-button&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextButton&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;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secondQuote&lt;/span&gt;&lt;span class="p"&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;shows previous quote on `Previous` button click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;next-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;prev-button&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextButton&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="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevButton&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;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstQuote&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;h4&gt;
  
  
  Verify the &lt;code&gt;App&lt;/code&gt; renders the first quote
&lt;/h4&gt;

&lt;p&gt;The first test is going to verify that the &lt;code&gt;App&lt;/code&gt; component properly initializes the &lt;code&gt;Quote&lt;/code&gt; component with the first quote from the &lt;code&gt;quotes&lt;/code&gt; array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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;shows first quote on app load&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstQuote&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;As you can see, we don't have an &lt;strong&gt;Act&lt;/strong&gt; step here and that's totally fine. We just need to verify the text content of the &lt;code&gt;quote&lt;/code&gt; element is the proper one.&lt;/p&gt;

&lt;p&gt;Did you notice the &lt;code&gt;getByTestId&lt;/code&gt; call?&lt;/p&gt;

&lt;h5&gt;
  
  
  What is a &lt;code&gt;testId&lt;/code&gt;?
&lt;/h5&gt;

&lt;p&gt;A &lt;code&gt;testId&lt;/code&gt; is an easy way to get a handle of a given element in the DOM.&lt;/p&gt;

&lt;p&gt;Think of it as an &lt;code&gt;id&lt;/code&gt;, which you attach to the DOM element.&lt;/p&gt;

&lt;p&gt;To make things simple for me, I have just attached &lt;code&gt;data-testid="quote"&lt;/code&gt; test id to the Quote element, just like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/components/Quote.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;blockquote&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Quote&lt;/span&gt;&lt;span class="dl"&gt;"&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;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;blockquote&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also added test ids to the &lt;code&gt;Previous&lt;/code&gt; and &lt;code&gt;Next&lt;/code&gt; button components so that it's easier to query them in my tests:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;src/components/Previous.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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;Previous&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;data-testid&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"prev-button"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Previous
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;src/components/Next.jsx&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="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;Next&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;data-testid&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"next-button"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Next
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Verify the quote changes to the next one on &lt;code&gt;Next&lt;/code&gt; click
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="s2"&gt;shows next quote on `Next` button click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secondQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;next-button&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextButton&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;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secondQuote&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;What do we have here?&lt;/p&gt;

&lt;p&gt;In our &lt;em&gt;Arrange&lt;/em&gt; block, we get a reference to the &lt;code&gt;secondQuote&lt;/code&gt;, which we're going to use in our assert block.&lt;/p&gt;

&lt;p&gt;Then, we query the &lt;code&gt;quote&lt;/code&gt; and the &lt;code&gt;nextButton&lt;/code&gt; elements, again by using &lt;code&gt;getByTestId&lt;/code&gt; functions.&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;Act&lt;/em&gt; and &lt;em&gt;Assert&lt;/em&gt; blocks we trigger a click event on the &lt;code&gt;nextButton&lt;/code&gt; and then verify that the contents of the &lt;code&gt;quote&lt;/code&gt; is the same as the &lt;code&gt;secondQuote&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Easy peasy, lemon squeezy.&lt;/p&gt;

&lt;h4&gt;
  
  
  Verify the quote changes to the previous one on &lt;code&gt;Previous&lt;/code&gt; click
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="s2"&gt;shows previous quote on `Previous` button click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;quotes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;quotes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quotes&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;next-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;prev-button&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextButton&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="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevButton&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;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstQuote&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 time, in our &lt;em&gt;Act&lt;/em&gt; stage, we do a &lt;code&gt;next&lt;/code&gt; and then &lt;code&gt;previous&lt;/code&gt; click and verify that the quote is back to the original one.&lt;/p&gt;

&lt;p&gt;Pretty straight forward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactions are crucial
&lt;/h3&gt;

&lt;p&gt;Notice that in our integrations tests we test interactions between 2 or more components.&lt;/p&gt;

&lt;p&gt;That's what makes a test an integration one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now it's your turn
&lt;/h3&gt;

&lt;p&gt;I have intentionally left the tests for our array bounds logic. I'll leave that to you to figure out.&lt;/p&gt;

&lt;p&gt;The general idea is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Test that when the app shows the first quote and the user clicks the "Previous" button, the next quote that's being shown is the last one in the data array.
2. Test that when the app shows the last quote and the user clicks the "Next" button, the next quote that's being shown is the first one in the data array.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Got it? Now write the tests. :)&lt;/p&gt;

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

&lt;p&gt;I hope you had fun reading this article. It came out much longer than expected, but I think I've managed to show you the 80% of what testing a React application looks like.&lt;/p&gt;

&lt;p&gt;Of course, we never touched asynchrony, testing hooks and what not, but that was not the idea of this article.&lt;/p&gt;

&lt;p&gt;I'll do my best to write such guide on the topics I couldn't cover here, so you can subscribe using the form bellow to get notified when I do.&lt;/p&gt;

&lt;p&gt;If you had any questions or comments, feel free to reach out. I'd be happy to discuss.&lt;/p&gt;

&lt;p&gt;Take care.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My programming principles</title>
      <dc:creator>Borislav Grigorov</dc:creator>
      <pubDate>Fri, 09 Apr 2021 15:42:52 +0000</pubDate>
      <link>https://dev.to/brslv/my-programming-principles-39oi</link>
      <guid>https://dev.to/brslv/my-programming-principles-39oi</guid>
      <description>&lt;p&gt;A principle is a "fundamental truth or proposition, that serves as the foundation for a system of belief or behavior".&lt;/p&gt;

&lt;p&gt;Simply put, it's the "why" behind our thoughts and actions.&lt;/p&gt;

&lt;p&gt;If you want to understand why principles are important, how to expand horizontally and what does it mean for a design to emerge continue reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should I care?
&lt;/h2&gt;

&lt;p&gt;Maybe you don't realize it, but you already operate on a set of internalized principles. It's one of these things that we let run in the background, without being conscious about it.&lt;/p&gt;

&lt;p&gt;It's a good thing because we don't have to map every single thought or action to a principle in our head. It happens automatically. We don't have to think about it.&lt;/p&gt;

&lt;p&gt;But on the other side, it's bad, because the mapping can go way off and map to some wrong conclusions about reality.&lt;/p&gt;

&lt;p&gt;Here's an example.&lt;/p&gt;

&lt;p&gt;We go to work or start a business, because we have to survive, but also because we know that a productive life is the most &lt;em&gt;efficient&lt;/em&gt; way to survive. So, our principle is: &lt;em&gt;do productive things to survive&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now, if we had the wrong principle internalized and we weren't mindful about it, we would simply robber a bank and think it's OK. We have internalized a principle, based on which in order to survive &lt;em&gt;we don't have to do anything productive&lt;/em&gt;. We're human beings and we &lt;em&gt;deserve&lt;/em&gt; to be alive and have an "easy" life, so the "rich" guys at the bank must pay their social duty and we're allowed to go and take what &lt;em&gt;belongs&lt;/em&gt; to us. Because we &lt;em&gt;deserve&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;Now, it's clear that the wrong principle in the second example leads to bad life decisions. What's fascinating is that there are people that &lt;em&gt;do&lt;/em&gt; think this way. People who internalized the wrong principle. And they don't even realize this.&lt;/p&gt;

&lt;p&gt;Having the wrong principles without realizing it is way worse than having them and doing something about it.&lt;/p&gt;

&lt;p&gt;That's why we should make it a routine to revise our framework. Not only in our professional field but in life, love, finance, etc. Our principles are the kernel of our operating system. They are the basis of the way we live, work and thrive. And if we're not mindful of the fundamentals, things can go really bad.&lt;/p&gt;

&lt;p&gt;It's mental work that has to be done beforehand, a volitional effort which we &lt;strong&gt;must&lt;/strong&gt; not skip!&lt;/p&gt;

&lt;p&gt;The current article is in a way such a reflection, narrowed down to the principles in my craft.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a programming principle
&lt;/h2&gt;

&lt;p&gt;It's a guiding set of truths for the way we structure our programs, devise solutions to problems, and approach common software tasks in the process of building a usable product.&lt;/p&gt;

&lt;p&gt;DRY (Don't Repeat Yourself) is such a principle you might have heard of.&lt;/p&gt;

&lt;p&gt;A (programming) principle should be general enough to serve as a useful heuristic in many seemingly unrelated scenarios. But it must not be too abstract, as it would be hard to apply to any concrete.&lt;/p&gt;

&lt;p&gt;Let's get started with my set of principles in no particular order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplicity is not a visual trait
&lt;/h2&gt;

&lt;p&gt;I see many developers fall into the trap of the so-called "simplicity". What's propagated as simple these days is not simple at all, but merely a way to make it &lt;em&gt;seem&lt;/em&gt; simple. It's an important observation.&lt;/p&gt;

&lt;p&gt;I know, because I've been there, too.&lt;/p&gt;

&lt;p&gt;Squeezing functions to no more than 3 lines of code. Refactoring if statements to a single line or, God forbid, polymorphism.&lt;/p&gt;

&lt;p&gt;I get the hype.&lt;/p&gt;

&lt;p&gt;But the way this hype is packaged and labeled as "simplicity" is merely wrong. It's false.&lt;/p&gt;

&lt;p&gt;Look, by making a function three lines of code, it doesn't get simpler. It just gets &lt;em&gt;faster&lt;/em&gt; to read. But not simpler.&lt;/p&gt;

&lt;p&gt;It's like the tip of an iceberg. You see just 1% of the thing and the rest is drawn deep below the waters. And for what reason? To hide the fact that the iceberg is big?&lt;/p&gt;

&lt;p&gt;Throughout the years I've seen so many icebergs, it's insane. And diving deep just to find out that it's so big, is a waste of energy.&lt;/p&gt;

&lt;p&gt;You might think, well, ok, then what do you suggest, to write behemoth functions and turn my code into spaghetti?&lt;/p&gt;

&lt;p&gt;Of course not.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I want you to be less concerned by the &lt;em&gt;visual&lt;/em&gt; simplicity and more about the technical one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a thing is a thing(), don't make it a t(h(i(n(g)))). Don't make small t, h, i, n, g functions but leave the thing() as is. Even if it's 4+ lines of code (scary!). Some thing()s must stay thing()s.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comments* on the way to prevent wrong abstractions
&lt;/h2&gt;

&lt;p&gt;Another trap for inexperienced developers. The common wisdom that comments are bad.&lt;/p&gt;

&lt;p&gt;I see where this comes from and I partially agree.&lt;/p&gt;

&lt;p&gt;But not using comments can be as harmful as overusing them.&lt;/p&gt;

&lt;p&gt;Let me explain.&lt;/p&gt;

&lt;p&gt;When I was still a more junior developer, I was extracting functions out of nothing. Just to make my code more "expressive".&lt;/p&gt;

&lt;p&gt;Extracting functions generally leads to the need to create new files and (probably) folders. It's like extracting the contents of your fridge into different fridges. One for eggs. One for ham. Another for the cheese and another one for the salads. You get the idea.&lt;/p&gt;

&lt;p&gt;At first, you might think that now your food is neatly organized, but if you try it for a week, you'll quickly realize that what you did was a big mistake.&lt;/p&gt;

&lt;p&gt;Now not only your fridges occupy more space at your home (whole fridge for 10 eggs, buddy!) but you have to keep a &lt;em&gt;mental map of what belongs where&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The same was happening to me constantly. I was always overthinking how a piece of 2 lines of code should be organized by file/folder. Later when I had to use it, I had to reconstruct a mental map out of those pieces to make them fit together. Doing this exercise hundreds of times each day is a mind-draining experience.&lt;/p&gt;

&lt;p&gt;Like trying to make dinner and having to open 20 fridges, one at a time, to see what's in there and come up with a recipe.&lt;/p&gt;

&lt;p&gt;Good luck.&lt;/p&gt;

&lt;p&gt;But why am I telling you this?&lt;/p&gt;

&lt;p&gt;Because what I do nowadays is exactly the opposite. I never introduce new files/folders in my projects just to make things more "expressive". Part of what helps me stay disciplined in this regard is comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My use of comments is a way to prevent unintended, unneeded or simply wrong abstractions emerge.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of extracting each line to make it more readable, I simply leave it as is, or if needed, write a one-line comment above it and call it a day.&lt;/p&gt;

&lt;p&gt;This way everything stays in the same function/file (fridge). And everything has its own block (shelf, if you keep up with the fridge analogy). I just put labels in there and the thing gets much more readable with the added benefit that it stays &lt;em&gt;compact&lt;/em&gt; at the same time.&lt;/p&gt;

&lt;p&gt;At this point, a lot of people are screaming behind the screens. The most triggered ones even closed the tab. That's good.&lt;/p&gt;

&lt;p&gt;I hear "and what about the fact that comments get outdated or even misleading, yadda, yadda"...&lt;/p&gt;

&lt;p&gt;What if you put your eggs on the shelf with the ham? And even stick a tiny label on the eggs box saying "HAM". Are the eggs now ham? If you still get the eggs out of the fridge thinking that it's a ham, the problem most probably is not the shelf nor the label, but the subject that got the object out of the fridge. :)&lt;/p&gt;

&lt;p&gt;I mean, the argument with the misleading comments sounds naive to me. We're not kids. You can stick a label to a car toy saying "SPACESHIP" and the kid would genuinely accept that it's exactly what it says. But a grownup would just fix the label and carry on (playing with the car toy :))).&lt;/p&gt;

&lt;p&gt;Let's be honest here. Introducing new fridges is far more expensive than a misleading comment, which can just be deleted/fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design emerges
&lt;/h2&gt;

&lt;p&gt;Let's do a quick thought experiment.&lt;/p&gt;

&lt;p&gt;Imagine a completely blank world. Blank as a blank page. There's nothing, just ground.&lt;/p&gt;

&lt;p&gt;Imagine you are a being that has no conceptual knowledge. No words, no terms, no experience, no previous perceptual data. You are a blank being in a blank world.&lt;/p&gt;

&lt;p&gt;Now, could such a being come up with the term &lt;em&gt;coffee shop&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Of course not.&lt;/p&gt;

&lt;p&gt;To have the term coffee shop, you have to build on top of two other terms - coffee and shop. You have to construct their meanings. But to have the concept of coffee, you have to introduce the term plant and the term seed. To have the term shop, you have to introduce countless other concepts, such as building, cashier, money, trade, etc, etc.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It's obvious that having 0 reality, you're unable to construct higher concepts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yet, we still build software following exactly that same conviction.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We still build concepts, having close to zero understanding of the underlying reality.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In practice, this means that you cannot simply introduce a &lt;em&gt;concept&lt;/em&gt; (think function/class/module) without having any evidence of what does the "internals" of the concept mean to the world (technical and business-wise), what it's based on and if it's a single event or a recurring pattern.&lt;/p&gt;

&lt;p&gt;Going deeper into the details, having a loop that iterates a set of users, sends them emails, and assigns them a support team member, must not be immediately extracted to an &lt;code&gt;onboardUsers()&lt;/code&gt; function. You must let "reality" (your program/business logic context) evolve to the point where it's obvious that sending emails &lt;em&gt;and&lt;/em&gt; assigning the users a support guy is part of the onboarding process.&lt;/p&gt;

&lt;p&gt;In that sense, &lt;strong&gt;the design of your code must emerge, it must not be forced by your subjective whims&lt;/strong&gt;. Literally, a product development guy must write this spec down:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The onboarding process consists of &lt;em&gt;sending an email&lt;/em&gt; and &lt;em&gt;assigning a support buddy&lt;/em&gt;".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is reality, and having the concept of &lt;em&gt;onboarding&lt;/em&gt; there, you're safe to step on it and introduce it to your software context.&lt;/p&gt;

&lt;p&gt;Otherwise, let the loop be a loop and do its thing. Don't conceptualize it further. If it does many things, put a comment or two in there, but, please, don't introduce an "abstraction", a factory factory, a strategy, or whatever, where a comment would suffice. Concepts are easy to come up with but very hard to get disentangled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reuse consciously
&lt;/h2&gt;

&lt;p&gt;The most fundamental thing you're going to learn in an Economics 101 class is the theory of division of labor.&lt;/p&gt;

&lt;p&gt;This "invention" is one of the few tipping points in human history. It's the right way to leverage other's people potential. The same fundamental principle works in every possible field of human life.&lt;/p&gt;

&lt;p&gt;In software, too.&lt;/p&gt;

&lt;p&gt;We can take advantage of using other people's solutions to common problems in the form of frameworks and libraries. It's great to be able to step on a giant's shoulders and we must do it so that we're able to build meaningful products in time without going crazy.&lt;/p&gt;

&lt;p&gt;But I want to stress something that I see a lot of people do wrong here. And that's &lt;strong&gt;going to the extreme.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Having easy access to working software pieces and gluing them together is tempting, especially when we're in a rush or just don't want to engage in the process of coming up with solutions ourselves. And here is &lt;em&gt;the problem&lt;/em&gt;. We're so used to reusing other people's code, that this now serves as &lt;em&gt;an excuse not to think&lt;/em&gt;. Which is dangerous.&lt;/p&gt;

&lt;p&gt;See, solving problems involves thinking. It is inevitable. Yes, we can come up with something just by mindlessly gluing pieces together, but if we want to be good at it and if we want to design quality, resilient solutions, we must engage in a thinking process. We must get our hands dirty from time to time. Outsourcing critical thinking decisions to a framework or a library has its consequences, and we &lt;strong&gt;must&lt;/strong&gt; be aware of what they are.&lt;/p&gt;

&lt;p&gt;Reusing extraneous code is a choice. And as with every choice in our lives, it depends on the context.&lt;/p&gt;

&lt;p&gt;My principle here is: &lt;em&gt;Don't approach frameworks and libraries as defaults. Always consider reality, your context.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;The last one is a bit more abstract. I've left it last intentionally. If you were to take a single principle out of this article, let it be this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expand horizontally
&lt;/h2&gt;

&lt;p&gt;The way I would solve a given problem will most probably be different from the way you would do it. That's why programming is mostly a creative activity. Beyond the most simplistic problems, there are countless possibilities.&lt;/p&gt;

&lt;p&gt;But how does one &lt;em&gt;come&lt;/em&gt; to a solution? I have a theory.&lt;/p&gt;

&lt;p&gt;As with any other creative process out there, the result of coming up with a programming solution is a reflection of the creator's values, perceptions, fears, cravings, knowledge, etc. Our creative output is a mirror of ourselves.&lt;/p&gt;

&lt;p&gt;Hence, the following is a leading principle for creatives:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Being creators/problem-solvers we have the responsibility to expand ourselves not only vertically, but horizontally, so that our creative output gets more expressive and sophisticated in the process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's deconstruct the terms vertical and horizontal expansion.&lt;/p&gt;

&lt;p&gt;A Go developer "expands" vertically his knowledge by digging deeper into the Go ecosystem, learning advanced Go techniques, building a portfolio of projects in that field. It's what's mostly known as &lt;em&gt;specialization&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The same developer "expands" horizontally his knowledge by learning about economics, physics, reading fiction, studying philosophy, design, playing guitar, learning to brew beer, etc. Going a bit more narrow, learning Docker, Rust, and building iOS apps can also be considered horizontal expansion.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every activity that adds another &lt;em&gt;dimension&lt;/em&gt; to the knowledge base of a person can be considered widening horizontally. In other words, to get better at our craft, we must get better at any craft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;People that are good at this are commonly labeled &lt;em&gt;generalists&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Why is that so important for creatives?&lt;/p&gt;

&lt;p&gt;Because, unlike solutions, problems are not so unique. You'll be surprised to see that most of our software problems are already solved in some other seemingly unrelated field. Like architecture, for example. Or economics. Or physics, design, philosophy. And by expanding horizontally your knowledge and &lt;em&gt;awareness&lt;/em&gt; of those problem/solution sets, you get smarter. You get more creative. You have &lt;em&gt;more data points&lt;/em&gt; to play around with, to connect. It's just easier to see patterns, to spot weaknesses, to design working abstractions.&lt;/p&gt;

&lt;p&gt;It's not a novel idea. But it's powerful enough to serve as a guiding fundamental principle in my life. Consider expanding horizontally and becoming better at other crafts!&lt;/p&gt;




&lt;p&gt;As this article became fart too long for my taste, I'd rather end it here.&lt;/p&gt;

&lt;p&gt;I certainly have a few more principles to share about programming (and to some degree about life in general), but I'm gonna leave it for another article.&lt;/p&gt;

&lt;p&gt;Thanks for reading. 🙏&lt;/p&gt;

</description>
      <category>programming</category>
      <category>principles</category>
    </item>
    <item>
      <title>Massaging types in typescript (part 1)</title>
      <dc:creator>Borislav Grigorov</dc:creator>
      <pubDate>Tue, 12 Jan 2021 07:25:43 +0000</pubDate>
      <link>https://dev.to/brslv/massaging-types-in-typescript-part-1-8m1</link>
      <guid>https://dev.to/brslv/massaging-types-in-typescript-part-1-8m1</guid>
      <description>&lt;p&gt;TLDR;&lt;/p&gt;

&lt;p&gt;In TypeScript, we can retrieve type information in many different ways. In &lt;em&gt;type context&lt;/em&gt; we can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;typeof&lt;/strong&gt; - refer to the type of a value or a property: &lt;code&gt;typeof "some string"&lt;/code&gt; is &lt;code&gt;string&lt;/code&gt;; &lt;code&gt;typeof 1&lt;/code&gt; is &lt;code&gt;number&lt;/code&gt; etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;keyof&lt;/strong&gt; - given an object, reduces it to an union of it's keys: &lt;code&gt;type keys = keyof { name: "Bobi", age: 29 }&lt;/code&gt; resolves to the following type: &lt;code&gt;type keys = "name" | "age"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;indexed access&lt;/strong&gt; - given &lt;code&gt;type Person = { name: "Bobi" }&lt;/code&gt; and &lt;code&gt;type PersonName = Person["name"]&lt;/code&gt;, the &lt;code&gt;PersonName&lt;/code&gt; resolves to &lt;code&gt;string&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;TypeScript is great when it comes to types reusability. Once defined, a type can be "massaged" in order to suit different business logic needs.&lt;/p&gt;

&lt;p&gt;Here's one simple example.&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;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bobi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;29&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;updateName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;updateName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: "John", age: 29 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;updateName&lt;/code&gt; function accepts a person (&lt;code&gt;Person&lt;/code&gt;) and a name, which is in the form of a &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's all great, but imagine we get new requirements, which say a user can have an empty (&lt;code&gt;null&lt;/code&gt;) name.&lt;/p&gt;

&lt;p&gt;We do:&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;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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 have to also update the type of the &lt;code&gt;name&lt;/code&gt; argument in &lt;code&gt;updateName&lt;/code&gt; 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&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;null&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;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&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 move can be skipped if we were using &lt;strong&gt;indexed types access&lt;/strong&gt; for the &lt;code&gt;name&lt;/code&gt; property of the &lt;code&gt;Person&lt;/code&gt; type. Let me show you.&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="nx"&gt;updateName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&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;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&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;Having this type definition, typescript is smart enough to resolve the type for the &lt;code&gt;name&lt;/code&gt; argument by itself, using the type of &lt;code&gt;Person.name&lt;/code&gt;. Which, of course, is &lt;code&gt;string | null&lt;/code&gt; after the update with our new imaginary requirements.&lt;/p&gt;

&lt;p&gt;That's the power of &lt;strong&gt;indexed types access&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;typeof&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Another handy keyword in TypeScript is &lt;code&gt;typeof&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;const&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&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="s2"&gt;Mary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emojify&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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="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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;processor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;emojify&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="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;processor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&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="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;emojify&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// ["John 🤘", "Mary 🤘"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention to the &lt;code&gt;process&lt;/code&gt; function. It's &lt;code&gt;items&lt;/code&gt; argument is &lt;em&gt;anything&lt;/em&gt; that has the same &lt;em&gt;type&lt;/em&gt; as names, which happens to be &lt;code&gt;string[]&lt;/code&gt;. And the &lt;code&gt;processor&lt;/code&gt; argument is &lt;em&gt;anything&lt;/em&gt; that has the same &lt;em&gt;type&lt;/em&gt; as &lt;code&gt;emojify&lt;/code&gt;, which in the example is &lt;code&gt;(string) =&amp;gt; string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;type x = typeof y&lt;/code&gt; when we want tell the compiler: "Hey, compiler, whatever the type of that variable (&lt;code&gt;y&lt;/code&gt;) is, use it as a type for this (&lt;code&gt;x&lt;/code&gt;) variable".&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;keyof&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The last tool we're going to cover in the first part is &lt;code&gt;keyof&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It's quite self explanatory. Let me show you.&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;type&lt;/span&gt; &lt;span class="nx"&gt;Subscriber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SubscriberProp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "number" | email" | "topic"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;SubscriptionDetail&lt;/code&gt; gets resolved to the keys of the &lt;code&gt;Subscriber&lt;/code&gt; type. So we get &lt;code&gt;type SubscriberDetail = "email" | "topic"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's handy when we need something in the following fashion:&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="nx"&gt;getProp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subscriber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SubscriberProp&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="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&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;Part two is in the oven and is coming soon.&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@oneshotespresso?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Hans Vivek&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/massage?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Using TypeScript Intersections to extend component's props in React</title>
      <dc:creator>Borislav Grigorov</dc:creator>
      <pubDate>Sat, 09 Jan 2021 16:40:38 +0000</pubDate>
      <link>https://dev.to/brslv/using-typescript-intersections-to-extend-component-s-props-in-react-2omg</link>
      <guid>https://dev.to/brslv/using-typescript-intersections-to-extend-component-s-props-in-react-2omg</guid>
      <description>&lt;h2&gt;
  
  
  Every app has buttons.
&lt;/h2&gt;

&lt;p&gt;So, let's create a Button component, which uses the button html element under the hood.&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;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;Button&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="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;btn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="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;/button&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;Easy peasy.&lt;/p&gt;

&lt;p&gt;But in terms of functionality, our button is very limited. For example, having this implementation, we cannot handle any events, cannot extend the &lt;code&gt;className&lt;/code&gt;, nor pass any &lt;code&gt;style&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt;, etc. props to it. It's basically a very dumb component.&lt;/p&gt;

&lt;p&gt;There are several possible approaches we can take in order to make it a useful one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Props "babysitting" or any type
&lt;/h2&gt;

&lt;p&gt;One way to do it is by "babysitting" every possible button property there is by ourselves. 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;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;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ... etc.&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;
  &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nl"&gt;style&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="na"&gt;key&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="kr"&gt;any&lt;/span&gt;
  &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
  &lt;span class="c1"&gt;// ... etc.&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;button&lt;/span&gt;
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;btn&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;onClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;We can list all of native &lt;code&gt;button&lt;/code&gt;'s properties in our &lt;code&gt;Button&lt;/code&gt;' s props, or some of them, but that's very tedious and far from scalable.&lt;/p&gt;

&lt;p&gt;Another option is to use the &lt;code&gt;any&lt;/code&gt; type and tell TypeScript that our component doesn't care about what types are the props it receives. I'm not going into details here, because &lt;code&gt;any&lt;/code&gt; defeats the purpose of using TypeScript in the first place. And on top of that, using it is a strong sign for being lazy and we're not lazy. :)&lt;/p&gt;

&lt;p&gt;So, there's a smarter approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;...rest&lt;/code&gt; with TypeScript's intersections.
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&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;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentPropsWithoutRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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;button&lt;/span&gt;
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;btn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;Using the JavaScript's &lt;code&gt;...rest&lt;/code&gt; operator, we collect every possible property the user of the component passes to it in an array, called &lt;code&gt;rest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that we "spread" the array in the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, making our Button component act as a "proxy".&lt;/p&gt;

&lt;p&gt;One thing that's important to notice is the intersection type &lt;code&gt;{ ... } &amp;amp; React.ComponentPropsWithoutRef&amp;lt;'button'&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is how we tell TypeScript that our Button component may receive any of the native button's properties through the &lt;code&gt;...rest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sweet. We are happy. TypeScript is happy. 🎉&lt;/p&gt;

&lt;p&gt;But we're not constrained only to extending props using only native HTML elements. We can do it with custom ones, too.&lt;/p&gt;

&lt;p&gt;Here's an example, where we create an &lt;code&gt;IconButton&lt;/code&gt;, which composes our &lt;code&gt;Button&lt;/code&gt; component, but adds the ability to display an icon, next to the button's content. Notice that in this case we should use &lt;code&gt;typeof Component&lt;/code&gt; to indicate that we're using a custom one.&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;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;IconButton&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentPropsWithoutRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Button&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="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;Button&lt;/span&gt;
      &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;rest&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;&lt;/span&gt;&lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="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;/Button&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;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;React.ComponentPropsWithoutRef&amp;lt;type&amp;gt;&lt;/code&gt; with intersections to compose custom component types. Forget about &lt;code&gt;any&lt;/code&gt; and props "babysitting". Be smart and reuse whenever possible, whatever possible.&lt;/p&gt;

&lt;p&gt;Here's very simple demo: &lt;a href="https://codesandbox.io/s/morning-cache-3vzb4?file=/src/App.tsx" rel="noopener noreferrer"&gt;https://codesandbox.io/s/morning-cache-3vzb4?file=/src/App.tsx&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Programmer's first principles</title>
      <dc:creator>Borislav Grigorov</dc:creator>
      <pubDate>Mon, 29 Jun 2020 15:40:18 +0000</pubDate>
      <link>https://dev.to/brslv/programmer-s-first-principles-4nbg</link>
      <guid>https://dev.to/brslv/programmer-s-first-principles-4nbg</guid>
      <description>&lt;p&gt;&lt;a href="https://borislav.netlify.app/articles/pfp/" rel="noopener noreferrer"&gt;Original article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our job as developers is to &lt;strong&gt;solve problems&lt;/strong&gt;. It's the programmer's axiom.&lt;/p&gt;

&lt;p&gt;Thus everything we do that contributes to the realization of this goal is good (productive). Everything that contradicts and interferes with it - is bad (unproductive). At the end of the day we must ship solutions.&lt;/p&gt;

&lt;p&gt;A fair question that arises is: How do we do this?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By observing objective truths from the reality in regards of your specific case and then implementing as much of the productive things (for that specific case) in your process as possible.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And how do we know if something is productive or not? Based on reasoning. In order to reason about something, one should have a solid foundation on top of which to build up and take logical decisions.&lt;/p&gt;

&lt;p&gt;Here are some of the solid foundations that I use as a guiding light in my practice as a developer (and some of those to some extend as a human being in my life).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simplicity over complexity. Always.&lt;/li&gt;
&lt;li&gt;Automation over manual work - if machine can do it, it must do it.&lt;/li&gt;
&lt;li&gt;If writing code can be avoided, avoid it. Remember the programmer's axiom - solve problems. It's not "write code".&lt;/li&gt;
&lt;li&gt;Single point of failure is always preferable.&lt;/li&gt;
&lt;li&gt;Remove what's not needed. It rots.&lt;/li&gt;
&lt;li&gt;Duplicating code IS OK. Duplicating knowledge in separate modules IS NOT.&lt;/li&gt;
&lt;li&gt;If it can be reused, reuse it. (Note: keep in mind simplicity)&lt;/li&gt;
&lt;li&gt;Name things properly.&lt;/li&gt;
&lt;li&gt;Do not succumb to the falacy that "there's no right or wrong approach". NO! There is! There always is. This fallacy is just an excuse. You should be aware of this and not allow it to influence your decisions.&lt;/li&gt;
&lt;li&gt;No one knows better than you. Do not accept authorities telling you what's right and what's wrong. Figure it out yourself. Do not make the mistake to hand over your responsibility to some vague, anonymized authority. Make sure that the decisions you make (in your code and in life in general) are closed for the opportunity to blame others. You are the responsible one and you should be proud of it. That's what makes you a rational being.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Share some of the truths that guide YOU in your day-to-day problem-solving career.&lt;/p&gt;

</description>
      <category>firstprinciples</category>
      <category>foundations</category>
    </item>
    <item>
      <title>Strive to get things wrong as soon as possible</title>
      <dc:creator>Borislav Grigorov</dc:creator>
      <pubDate>Sat, 07 Sep 2019 18:56:47 +0000</pubDate>
      <link>https://dev.to/brslv/strive-to-get-things-wrong-as-soon-as-possible-4kkb</link>
      <guid>https://dev.to/brslv/strive-to-get-things-wrong-as-soon-as-possible-4kkb</guid>
      <description>&lt;p&gt;Quite often people get stuck on a particular development problem and just sit there, staring at the screen for hours, hoping for the right solution to pop and enlighten their day.&lt;/p&gt;

&lt;p&gt;And…it never does.&lt;/p&gt;

&lt;p&gt;It turns out that developing software is far more different than solving problems in school.&lt;/p&gt;

&lt;p&gt;In school you have a &lt;em&gt;correct&lt;/em&gt; answer. That’s how teachers grade students (which is flawed by nature). In programming (and in life in general), you always have &lt;em&gt;many&lt;/em&gt; right answers. That’s the beauty of it (and that’s why the school doesn’t work in practice).&lt;/p&gt;

&lt;p&gt;So, instead of just sitting there and thinking about the big problem in front of you, what you could easily do is &lt;strong&gt;start experimenting&lt;/strong&gt;. And more importantly – &lt;strong&gt;start failing as soon as possible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I know, it sounds counterintuitive, but think about it for a second. You know the saying that every time you fail to do “the thing,” you discover a new way how not to do “the thing”. Therefore, why are you afraid of breaking things? Why are you afraid of being wrong?&lt;/p&gt;

&lt;p&gt;In fact, being &lt;em&gt;wrong&lt;/em&gt; is the inevitable step of the process to becoming &lt;em&gt;right&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So, once again, what are you waiting for? You just waste precious time.&lt;/p&gt;

&lt;p&gt;Start building, start breaking, start being wrong and get comfortable failing. It’s the yin-yang of the creator. &lt;strong&gt;You must be wrong in order to become right&lt;/strong&gt;. So, please get things wrong. You’re not in school anymore.&lt;/p&gt;

</description>
      <category>failing</category>
    </item>
  </channel>
</rss>
