<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Dev Toolkit]]></title><description><![CDATA[Dev Toolkit]]></description><link>https://blog.dev-toolkit.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1716047657869/Ux-bV66fr.png</url><title>Dev Toolkit</title><link>https://blog.dev-toolkit.com</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 25 Apr 2026 04:52:05 GMT</lastBuildDate><atom:link href="https://blog.dev-toolkit.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Setting Up and Testing a React Application with Vitest]]></title><description><![CDATA[Welcome to the first part of our detailed series on setting up and testing a React app. Configuring and testing a React app can be daunting, especially when it comes to ensuring that your components, hooks, and utilities work as expected.
In this art...]]></description><link>https://blog.dev-toolkit.com/setting-up-and-testing-a-react-application-with-vitest</link><guid isPermaLink="true">https://blog.dev-toolkit.com/setting-up-and-testing-a-react-application-with-vitest</guid><category><![CDATA[React]]></category><category><![CDATA[react testing library]]></category><category><![CDATA[react testing]]></category><category><![CDATA[ReactHooks]]></category><category><![CDATA[Testing]]></category><category><![CDATA[test-automation]]></category><category><![CDATA[test driven development]]></category><dc:creator><![CDATA[Oluwafemi Sosanya]]></dc:creator><pubDate>Sat, 18 May 2024 16:49:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716051022707/db035f52-5438-40cb-af76-b7790496bfbd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the first part of <a target="_blank" href="https://dev-toolkit.com/series/testing-a-react-app">our detailed series</a> on setting up and testing a React app. Configuring and testing a React app can be daunting, especially when it comes to ensuring that your components, hooks, and utilities work as expected.</p>
<p>In this article, we will guide you through setting up Vitest, a modern and fast testing framework, along with React Testing Library to create a robust testing environment for your React application. This is the first part of a series where we will cover various aspects of testing in React, including component testing, hook testing, unit testing helpers, simulating timer events, and testing components and hooks under different routes.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You should have a React app running but if you'd like to follow through with this post you can initiate a new <a target="_blank" href="https://vitejs.dev/guide/#scaffolding-your-first-vite-project">VITE React Typescript App</a>.</p>
<ul>
<li><p><code>vitest</code> is the test runner itself</p>
</li>
<li><p><code>@testing-library/react</code> provides utilities for testing React components</p>
</li>
<li><p><code>@testing-library/jest-dom</code> adds custom Jest matchers for asserting on DOM nodes</p>
</li>
<li><p><code>jsdom</code> is a JavaScript implementation of the WHATWG DOM and HTML standards, used for simulating a browser environment</p>
</li>
</ul>
<pre><code class="lang-bash">yarn add -D @testing-library/dom @testing-library/jest-dom @testing-library/react jsdom vitest
</code></pre>
<h3 id="heading-configuring-vitest">Configuring Vitest</h3>
<p>Create a <code>setupTest.ts</code> file in the root of the app so that Vitest <code>expect</code> method can incorporate the matchers from this package <code>@testing-library/jest-dom</code>. This way Vitest key assertion methods will have access to assertion methods like <code>toHaveTextContent() | toHaveTextContent()</code> .</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> <span class="hljs-string">"@testing-library/jest-dom/vitest"</span>;
</code></pre>
<p>Next, create a <code>vitest.config.ts</code> file in the root of your application an update as below</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"vite"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
    test: {
        globals: <span class="hljs-literal">true</span>,
        environment: <span class="hljs-string">"jsdom"</span>,
        setupFiles: <span class="hljs-string">"./setupTest.ts"</span>,
        css: <span class="hljs-literal">true</span>,
        pool: <span class="hljs-string">"forks"</span>,
        include: [<span class="hljs-string">"**/__tests__/**/*.[jt]s?(x)"</span>, <span class="hljs-string">"**/?(*.)+(spec|test).[jt]s?(x)"</span>],
    },
});
</code></pre>
<h2 id="heading-writing-test">Writing Test</h2>
<p>With the setup complete, you can start writing tests for your React components, hooks and functions.</p>
<h3 id="heading-testing-a-react-component">Testing a React Component</h3>
<p>Create a component to test with. We'll be creating a simple <code>CounterButton.tsx</code> and <code>CounterButton.test.tsx</code> files inside a folder titled <code>CounterButton</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715533241070/80530f26-afc0-4cfb-aae9-760627b88c44.png" alt /></p>
<p>In <code>CounterButton.tsx</code>, we have a component with a simple functionality whenever the button is clicked, the count increases</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// CounterButton.tsx</span>
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> CounterButton = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

    <span class="hljs-keyword">return</span> (
        &lt;button data-testid=<span class="hljs-string">"counter-button-test-id"</span> onClick={<span class="hljs-function">() =&gt;</span> setCount(<span class="hljs-function">(<span class="hljs-params">count</span>) =&gt;</span> count + <span class="hljs-number">1</span>)}&gt;
            count is {count}
        &lt;/button&gt;
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> CounterButton;
</code></pre>
<p>In <code>CounterButton.test.tsx</code> , We are ensuring that the <code>&lt;CounterButton /&gt;</code> component renders correctly with the initial count value of 0, and the count increments when the button is clicked, including multiple times. It uses the React Testing Library's <code>render</code> function to render the component and <code>fireEvent</code> to simulate user interactions. The assertions are made using Jest's <code>expect</code> statements and the provided matchers from the React Testing Library, such as <code>toBeInTheDocument()</code> and <code>toHaveTextContent()</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// CounterButton.test.tsx</span>
<span class="hljs-keyword">import</span> { fireEvent, render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> CounterButton <span class="hljs-keyword">from</span> <span class="hljs-string">"./CounterButton"</span>;

describe(<span class="hljs-string">"CounterButton"</span>, <span class="hljs-function">() =&gt;</span> {
    test(<span class="hljs-string">"Renders conponent correctly with initial value."</span>, <span class="hljs-function">() =&gt;</span> {
        render(&lt;CounterButton /&gt;);

        <span class="hljs-keyword">const</span> counterBtnElement = screen.getByTestId(<span class="hljs-string">"counter-button-test-id"</span>);
        expect(counterBtnElement).toBeInTheDocument();
        expect(counterBtnElement).toHaveTextContent(<span class="hljs-string">"count is 0"</span>);
    });

    test(<span class="hljs-string">"increments count when button is clicked"</span>, <span class="hljs-function">() =&gt;</span> {
        render(&lt;CounterButton /&gt;);
        <span class="hljs-keyword">const</span> counterBtnElement = screen.getByTestId(<span class="hljs-string">"counter-button-test-id"</span>);
        fireEvent.click(counterBtnElement);
        expect(counterBtnElement).toHaveTextContent(<span class="hljs-string">"count is 1"</span>);
    });

    test(<span class="hljs-string">"increments count correctly multiple times"</span>, <span class="hljs-function">() =&gt;</span> {
        render(&lt;CounterButton /&gt;);
        <span class="hljs-keyword">const</span> counterBtnElement = screen.getByTestId(<span class="hljs-string">"counter-button-test-id"</span>);
        fireEvent.click(counterBtnElement);
        fireEvent.click(counterBtnElement);
        expect(counterBtnElement).toHaveTextContent(<span class="hljs-string">"count is 2"</span>);
    });
});
</code></pre>
<p>Run <code>yarn vitest</code> in your terminal and you should get a successful response like the image below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715534698393/4c287ef1-4fd8-4da1-8619-b9d118ed6fa0.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-testing-a-react-hook">Testing a React Hook</h3>
<p>Create a custom hook to test with. We'll be creating a simple <code>useCounter.tsx</code> and <code>useCounter.test.tsx</code> files inside a folder titled <code>useCounter</code>.</p>
<p><code>useCounter.tsx</code> provides a simple counter functionality. It manages a state variable <code>count</code> and exposes two functions, <code>increaseCountHandler</code> and <code>decreaseCountHandler</code>, to increment and decrement the count value, respectively.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// useCounter.tsx</span>
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> useCounter = <span class="hljs-function">(<span class="hljs-params">initialCount = <span class="hljs-number">0</span></span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> [count, setCount] = useState(initialCount);

    <span class="hljs-keyword">const</span> increaseCountHandler = <span class="hljs-function">() =&gt;</span> {
        setCount(<span class="hljs-function">(<span class="hljs-params">prevCount</span>) =&gt;</span> prevCount + <span class="hljs-number">1</span>);
    };

    <span class="hljs-keyword">const</span> decreaseCountHandler = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (count &gt; <span class="hljs-number">0</span>) {
            setCount(<span class="hljs-function">(<span class="hljs-params">prevCount</span>) =&gt;</span> prevCount - <span class="hljs-number">1</span>);
        }
    };

    <span class="hljs-keyword">return</span> { count, increaseCountHandler, decreaseCountHandler };
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useCounter;
</code></pre>
<p><code>useCounter.test.tsx</code> aims to ensure the correct behaviour of the <code>useCounter()</code> hook by testing the initialization of the count with different initial values, incrementing the count, and decrementing the count while handling edge cases like preventing the count from going below 0.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { renderHook } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> { act } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> useCounter <span class="hljs-keyword">from</span> <span class="hljs-string">"./useCounter"</span>;

describe(<span class="hljs-string">"useCounter"</span>, <span class="hljs-function">() =&gt;</span> {
    test(<span class="hljs-string">"should initialize count with the initial value"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useCounter(<span class="hljs-number">5</span>));
        expect(result.current.count).toBe(<span class="hljs-number">5</span>);
    });

    test(<span class="hljs-string">"should initialize count with default value of 0"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">(<span class="hljs-params">useCounter</span>) =&gt;</span> ());
        expect(result.current.count).toBe(<span class="hljs-number">0</span>);
    });

    test(<span class="hljs-string">"should increase count by 1"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> { result } = renderHook(<span class="hljs-function">() =&gt;</span> useCounter(<span class="hljs-number">5</span>));
        act(<span class="hljs-function">() =&gt;</span> {
            result.current.increaseCountHandler();
        });
        expect(result.current.count).toBe(<span class="hljs-number">6</span>);
    });

    test(<span class="hljs-string">"should decrease count by 1"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// Rest of the code...</span>
    });

    test(<span class="hljs-string">"should not decrease count below 0"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// Rest of the code...</span>
    });
});
</code></pre>
<p>And the result should be like the image below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716035923904/65a7e885-2a3a-41de-99a4-f8def08a3f00.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-unit-testing-helpers"><strong>Unit Testing Helpers</strong></h3>
<p>Create a helper function to test with. We'll be creating a simple <code>helpers.ts</code> and <code>helpers.test.ts</code> files inside a folder titled <code>helpers</code>.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// helper.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> formatDate = <span class="hljs-function">(<span class="hljs-params">date: <span class="hljs-built_in">Date</span></span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> year = date.getFullYear();
    <span class="hljs-keyword">const</span> month = (date.getMonth() + <span class="hljs-number">1</span>).toString().padStart(<span class="hljs-number">2</span>, <span class="hljs-string">"0"</span>);
    <span class="hljs-keyword">const</span> day = date.getDate().toString().padStart(<span class="hljs-number">2</span>, <span class="hljs-string">"0"</span>);

    <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${day}</span>/<span class="hljs-subst">${month}</span>/<span class="hljs-subst">${year}</span>`</span>;
};
</code></pre>
<p>write a unit test for <code>formartDate()</code> function expected to return any date passed in the parameter in DD/MM/YYYY format</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { formatDate } <span class="hljs-keyword">from</span> <span class="hljs-string">"."</span>;

describe(<span class="hljs-string">"Helper functions"</span>, <span class="hljs-function">() =&gt;</span> {
    test(<span class="hljs-string">"formatDate() to DD/MM/YYYY format"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-string">"2023-05-18T10:00:00Z"</span>);
        expect(formatDate(date)).toBe(<span class="hljs-string">"18/05/2023"</span>);
    });
});
</code></pre>
<p>You should have a result like the one below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716036988368/ffa398d4-7d0a-4330-81c6-95d1bcb0b143.png" alt class="image--center mx-auto" /></p>
<p>Congratulations! By following these examples, you can effectively test your React components, hooks, and utilities using Vitest, simulating various scenarios and ensuring your application works as expected.</p>
<p>Thank you for following along with this first part of our series on testing React applications. We hope you've found this guide informative and easy to follow.<br />Stay tuned for the next articles in this series, where we will dive deeper into advanced testing techniques and best practices to ensure your React application is thoroughly tested and maintainable.</p>
]]></content:encoded></item><item><title><![CDATA[Exploring the Essence of Learning: Is Learning Synonymous with Growth?]]></title><description><![CDATA[In our inaugural article, we embark on an exploration of the profound impact of learning on our lives, exploring its importance across three different contexts: the grand embroidery of life, as an individual, and as an employee. Learning is the corne...]]></description><link>https://blog.dev-toolkit.com/exploring-the-essence-of-learning-is-learning-synonymous-with-growth</link><guid isPermaLink="true">https://blog.dev-toolkit.com/exploring-the-essence-of-learning-is-learning-synonymous-with-growth</guid><category><![CDATA[learning]]></category><category><![CDATA[Learning Journey]]></category><category><![CDATA[#growth]]></category><category><![CDATA[growth mindset,]]></category><category><![CDATA[growth]]></category><category><![CDATA[development]]></category><category><![CDATA[development environments]]></category><dc:creator><![CDATA[Oluwafemi Sosanya]]></dc:creator><pubDate>Sat, 27 Apr 2024 11:28:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/aso6SYJZGps/upload/7039b093b2067ca89acc70be292659ae.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>In our inaugural article, we embark on an exploration of the profound impact of learning on our lives, exploring its importance across three different contexts: the grand embroidery of life, as an individual, and as an employee. Learning is the cornerstone of growth and development, touching on every aspect of our existence from childhood to adulthood. It's not just about acquiring knowledge, but about continuously evolving our perspectives, abilities, and understanding of the world</p>
</blockquote>
<h2 id="heading-part-1-in-the-general-context-of-life"><strong>Part 1: In the General Context of Life</strong></h2>
<p>Learning stands as a cornerstone of growth and development in the grand embroidery of life. From the moment we take our first steps, to the milestones we achieve as adults, learning permeates every aspect of our existence. It’s not merely the acquisition of knowledge, but the continuous evolution of our perspectives, abilities, and understanding of the world around us.</p>
<p>Throughout history, societies have thrived on the premise of learning. From the ancient philosophers of Greece to the modern innovators of Silicon Valley, the pursuit of knowledge has propelled civilizations forward. Learning empowers us to adapt to change, overcome challenges, and navigate the complexities of life with resilience and agility.</p>
<p>In essence, learning is synonymous with growth. It expands our horizons, broadens our minds, and enriches our lives in ways we may never have imagined. Whether it’s mastering a new skill, exploring a different culture, or delving into the depths of human creativity, each learning experience shapes who we are and who we aspire to become.</p>
<h2 id="heading-part-2-in-context-as-an-individual">Part 2: In Context as an Individual</h2>
<p>As individuals, learning serves as the catalyst for personal growth and self-discovery. It’s the journey of transformation that begins with curiosity and unfolds through exploration, experimentation, and reflection. From childhood to adulthood, we embark on a lifelong quest to expand our knowledge, hone our talents, and uncover our true potential.</p>
<p>Every lesson learned, whether from success or failure, contributes to our growth as individuals. It equips us with the tools to confront adversity, embrace uncertainty, and chart our own path in life. Through continuous learning, we not only discover new strengths and passions but also cultivate a deeper sense of fulfillment and purpose.</p>
<p>Moreover, learning fosters a sense of empowerment and autonomy. It empowers us to take control of our lives, make informed decisions, and shape our own destiny. By embracing a growth mindset, we embrace the belief that our abilities and intelligence can be developed through dedication and effort, rather than being fixed traits.</p>
<p>In the end, learning is not just about acquiring knowledge; it’s about embracing a mindset of lifelong growth and self-improvement. It’s about embracing the journey of becoming the best version of ourselves, one lesson at a time.</p>
<h2 id="heading-part-3-in-context-as-an-employee">Part 3: In Context as an Employee</h2>
<p>In the fast-paced world of work, learning is the cornerstone of professional development and career advancement. In today’s knowledge-driven economy, adapting, innovating, and learning new skills are essential for staying relevant and competitive in the job market.</p>
<p>As employees, learning enables us to stay ahead of the curve, seize new opportunities, and navigate the ever-changing nature of our industries. Whether it’s mastering the latest technology, acquiring industry-specific knowledge, or honing soft skills such as communication and leadership, continuous learning is key to staying agile and adaptable in today’s dynamic workplace.</p>
<p>Moreover, learning fosters a culture of innovation and creativity within organizations. It encourages employees to think outside the box, challenge the status quo, and explore <strong>new ways of solving problems.</strong> By investing in employee learning and development, companies not only empower their workforce but also drive innovation and growth from within.</p>
<p>Furthermore, learning enhances job satisfaction and employee engagement. It provides individuals with a sense of purpose and fulfillment, as they strive to expand their skills and contribute to the success of their organizations. By fostering a culture of learning and growth, companies can attract top talent, retain their best employees, and cultivate a workforce that is primed for success.</p>
<p><em>In conclusion, learning is not just a means to an end; it’s the cornerstone of personal and professional growth. Whether in the context of life, as an individual, or as an employee, the pursuit of knowledge empowers us to reach new heights, unlock new opportunities, and unleash our full potential. So let us embrace the journey of learning with open minds and eager hearts, for it is through learning that we truly grow.</em></p>
]]></content:encoded></item></channel></rss>