<?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: GrocStock</title>
    <description>The latest articles on DEV Community by GrocStock (@grocstock).</description>
    <link>https://dev.to/grocstock</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%2Forganization%2Fprofile_image%2F9059%2F236d6d63-523c-43d0-b027-9b76eafbf6b8.png</url>
      <title>DEV Community: GrocStock</title>
      <link>https://dev.to/grocstock</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/grocstock"/>
    <language>en</language>
    <item>
      <title>Introduction to React</title>
      <dc:creator>Rohith Poyyeri</dc:creator>
      <pubDate>Thu, 20 Jul 2023 23:32:42 +0000</pubDate>
      <link>https://dev.to/grocstock/introduction-to-react-2h1e</link>
      <guid>https://dev.to/grocstock/introduction-to-react-2h1e</guid>
      <description>&lt;p&gt;Are you new to React or in need of a refresher? Look no further! In this blog post, we will guide you through the process of building a ToDo application from scratch. React has gained immense popularity as a JavaScript library for building user interfaces, and by following this step-by-step guide, you'll embark on a journey to becoming a React developer. This app serves as the User Interface (UI) for the ToDo API, that we have built in my previous blog. Let's dive in and get started! &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we dive into the development process, let's make sure we have everything we need. Ensure that you have the following installed:&lt;br&gt;
Node.js and npm (Node Package Manager)&lt;br&gt;
npx&lt;/p&gt;
&lt;h2&gt;
  
  
  Order of execution
&lt;/h2&gt;

&lt;p&gt;In a React app that utilises TypeScript and functional components without relying on class components, the order of execution follows a specific sequence:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initialisation:&lt;/strong&gt; When the React app is loaded, the React library initialises by creating the virtual DOM (VDOM), which is a lightweight representation of the actual DOM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mounting:&lt;/strong&gt; The mounting phase begins by creating an instance of the root component specified in the ReactDOM.render() method. This component, written using TypeScript or pure JS/TS functions, is mounted onto the actual DOM, replacing the target HTML element.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component Rendering:&lt;/strong&gt; React traverses the component tree, starting from the root component. Each functional component's body is executed, returning a description of the component's user interface as React elements. This applies to both TypeScript and pure JS/TS functions used to define components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diffing and Reconciliation:&lt;/strong&gt; React performs a diffing algorithm to determine the differences between the previous and new versions of the virtual DOM. This process, applicable to both TypeScript and pure JS/TS functions-based components, is called reconciliation. It identifies the minimal set of changes needed to efficiently update the actual DOM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Updating:&lt;/strong&gt; Once the differences are identified, React applies the necessary updates to the actual DOM, ensuring it reflects the new state of the application. The update process, which includes inserting, updating, or removing elements, is performed for both TypeScript and pure JS/TS functions-based components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unmounting:&lt;/strong&gt; If a component is removed from the component tree, React cleans up any resources associated with that component. This is automatically handled by React when using functional components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event Handling:&lt;/strong&gt; React attaches event handlers, whether defined in TypeScript or pure JS/TS functions, to the appropriate elements in the actual DOM. When an event occurs, React triggers the corresponding event handler defined in the component, allowing us to respond to user interactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State and Props Updates:&lt;/strong&gt; When a component's state or props change, React re-invokes the body of the functional component, resulting in a re-rendering of that component and its child components. This applies to both TypeScript and pure JS/TS functions-based components.&lt;/p&gt;

&lt;p&gt;It's important to note that the execution order in React may vary depending on the specific circumstances of the application, the usage of TypeScript or pure JS/TS functions, and the hooks employed. However, the outlined sequence provides a general overview of the typical execution flow in a React app utilising TypeScript and functional components without relying on class components.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a new React project
&lt;/h2&gt;

&lt;p&gt;To create a new React app with TypeScript and SCSS (Sass), we can use the create-react-app tool and specify the necessary configurations.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx create-react-app todo-react-ui --template typescript&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Node version
&lt;/h2&gt;

&lt;p&gt;Lets start by creating a new .nvmrc file in the root of the project. This defines what version of node we are using. We are going to use the ‘lts/Gallium’ version. Add the following line to the file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lts/Gallium&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run the following command and might prompt us to install the version if it is missing.&lt;br&gt;
&lt;code&gt;nvm use&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Clean up and initial set-up
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;npm install node-sass&lt;/code&gt;&lt;br&gt;
&lt;code&gt;npm install @mui/icons-material @mui/material&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let us create a new App.scss file and import that in the App.tsx file. Now this acts as a global stylesheet and all the generic SCSS classes can go in here.&lt;/p&gt;

&lt;p&gt;Let's add FontAwesome and flexboxgrid in the public/index.html. Add the following in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v6.2.1/css/all.css" defer/&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&amp;lt;link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css" defer/&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;FontAwesome is a powerful icon library that provides a wide range of visually appealing icons that can enhance the visual appearance of our application. By utilising FontAwesome, we can easily incorporate these icons into various parts of our application, adding a touch of style and clarity.&lt;/p&gt;

&lt;p&gt;FlexBoxGrid, on the other hand, is a flexible grid system that leverages the power of the CSS flex display property. With FlexBoxGrid, we can easily create responsive and dynamic layouts for our application. It simplifies the process of arranging elements on the page, allowing us to achieve desired layouts with ease. By utilising the capabilities of FlexBoxGrid, we can ensure that our application's layout remains consistent across different screen sizes and devices.&lt;/p&gt;
&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;p&gt;In our project, we have introduced a configuration file named "config.json" located in the "public" folder. This file contains environment variables that are utilised throughout the application, excluding any sensitive information. To handle the retrieval of these variables, we will implement a ConfigContext that will read the "config.json" file and provide access to these variables within our components. However, in the production environment, we need to override this configuration by introducing a separate production config file. This allows us to customise the variables specifically for the production environment, ensuring proper configuration and security measures are in place. By adopting this approach, we can effectively manage and utilise environment variables across different environments in our application.&lt;/p&gt;

&lt;p&gt;To achieve a build-once, deploy-many scenario and ensure appropriate configuration for different environments such as staging, testing, and production, we can utilise multiple config.env.json files. Each environment can have its dedicated configuration file, allowing us to define specific settings and variables tailored to that particular environment.&lt;/p&gt;

&lt;p&gt;By maintaining separate configuration files, we can easily switch between environments during the build or deployment process. This ensures that the correct configuration is used for each environment, avoiding any potential conflicts or inconsistencies.&lt;/p&gt;

&lt;p&gt;Having separate config files for different environments simplifies the management of environment-specific settings, making it easier to maintain and update configurations without affecting other environments. This approach enhances the flexibility and scalability of our application, enabling smooth deployments and ensuring that the appropriate configurations are utilised based on the target environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Connecting to backend API
&lt;/h2&gt;

&lt;p&gt;Our React application has been configured to send API requests to a specific target URL, which in this case is the todo-api server running on port 3000. This setup enables smooth communication between the frontend and backend, facilitating the retrieval and manipulation of data from the todo-api server within our React application. To handle the API requests, we will utilise React hooks and the axios library. React hooks provide a convenient way to manage state and side effects, while the axios library simplifies the process of sending XMLHttpRequest (XHR) requests to the API.&lt;br&gt;
Component and its lifecycle&lt;br&gt;
In a pure JavaScript/TypeScript React component, also known as a functional component, the order of execution follows a specific sequence. Let's outline the order of execution for such components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function Body:&lt;/strong&gt; The function body contains the logic and JSX code that defines the component's UI and behaviour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initial Render:&lt;/strong&gt; When the component is first rendered, the function body is executed, and the JSX elements are returned. This initial render creates the initial representation of the component's UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Props Update:&lt;/strong&gt; If the component receives new props from its parent component, it triggers a re-render. The function body is executed again, and the JSX elements are updated based on the new props.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State Updates:&lt;/strong&gt; If the component's state is updated using hooks like useState, the function body is executed again, and the JSX elements are re-rendered based on the new state values.&lt;/p&gt;

&lt;p&gt;It's important to note that in functional components, there is no concept of lifecycle methods like componentDidMount or componentDidUpdate. Instead, React provides hooks like useEffect, useState, useContext, etc., to handle side effects, manage state, and access context.&lt;/p&gt;

&lt;p&gt;The useEffect hook allows us to perform side effects, such as fetching data from an API or subscribing to events, after the component has rendered or when specific dependencies change.&lt;/p&gt;

&lt;p&gt;The order of execution in a pure JavaScript/TypeScript React component involves the execution of the function body during the initial render and subsequent re-renders triggered by prop or state updates. By utilising hooks like useEffect and useState, we can control the component's behaviour and manage side effects effectively.&lt;/p&gt;
&lt;h2&gt;
  
  
  Shared Components
&lt;/h2&gt;

&lt;p&gt;Let us create a set of shared components that promote component reusability and maintain consistency throughout the application. These shared components reside in the 'src/components/' directory and are imported wherever required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Header&lt;/strong&gt; serves as the navigation bar of the application, providing users with easy access to different sections or pages of the app. It typically contains menus, links, or buttons for navigation purposes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Footer&lt;/strong&gt; is responsible for displaying a footer at the bottom of the application, providing additional information, copyright notices, or links to relevant pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heading&lt;/strong&gt; is a reusable component used to display a heading or title for each page. It helps to maintain consistent styling and structure across different pages of the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Empty&lt;/strong&gt; is designed to be displayed when a list or data set is empty. It provides a message or placeholder content to inform users that there is no data available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TextModal&lt;/strong&gt; is a dialog or modal component used to add or input data in the application. It typically includes form fields, buttons, and validation to gather user input and save it to the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TodoCard&lt;/strong&gt; is responsible for displaying individual ToDos as aesthetically pleasing card designs.&lt;/p&gt;

&lt;p&gt;The full code of these components is available in github.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pages
&lt;/h2&gt;

&lt;p&gt;Now let’s create the other pages that we are after. &lt;/p&gt;

&lt;p&gt;We should create a directory with the name of the page, along with its SCSS styles, and TypeScript code.&lt;/p&gt;

&lt;p&gt;The HomePage serves as the welcome or homepage of our application, acting as the landing page that users first encounter when accessing our site. It provides an overview of our app's features, highlights, or any relevant information we want to showcase to users right from the start. This component is designed to provide a visually appealing and engaging user experience, making a positive first impression.&lt;/p&gt;

&lt;p&gt;On the other hand, the NotFoundPage plays a crucial role as a fallback page. Whenever users navigate to a route that doesn't exist or provide an incorrect route, they will be redirected to the NotFoundComponent. This component serves as an error page, informing users that the requested page or resource cannot be found. It helps to improve the user experience by gracefully handling such scenarios and providing a clear message to users about the issue encountered.&lt;/p&gt;
&lt;h2&gt;
  
  
  Elephant in the room, ToDo
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ToDo Modal
&lt;/h3&gt;

&lt;p&gt;Let us create a new modal, Todo.ts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface Todo {
 _id: string;
 description: string;
 is_active: boolean;
 updatedAt: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ToDo hook
&lt;/h3&gt;

&lt;p&gt;Let us create a React hook, src/hooks.todo.ts where we can define various functions to interact with the ToDo data. By utilising the power of React hooks, we can create a custom hook that encapsulates the logic for managing ToDo items. Within this hook, we can define functions such as getAllTodo, createTodo, updateTodo, and deleteTodo. The getAllTodo function retrieves all existing ToDo items, createTodo adds a new ToDo item to the list, updateTodo updates the details of a specific ToDo item, and deleteTodo removes a ToDo item from the list. By returning these functions as an object from the hook, we provide a convenient interface for other components to interact with the ToDo data. This approach promotes reusability and separation of concerns, allowing components to focus on rendering and user interactions while the hook handles the underlying ToDo data operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  ToDo Page
&lt;/h3&gt;

&lt;p&gt;Let's create a new ToDo Page with TodoPage.tsx inside the src/pages/TodoPage directory.&lt;br&gt;
Within the TodoPage, we define several state variables using the useState hook, including activeTodos, inactiveTodos, activeTab, and modalOpen. The useEffect hook is used to fetch Todo data using the getAllTodo function from the useTodo hook when the component mounts. The retrieved data is then filtered into active and inactive Todo items, which are stored in the activeTodos and inactiveTodos states, respectively.&lt;/p&gt;

&lt;p&gt;The component also includes various event handler functions that are responsible for handling tab changes, opening and closing the modal, submitting new Todo items, marking Todo items as active or inactive, deleting Todo items, and updating the Todo list.&lt;/p&gt;

&lt;p&gt;The return statement consists of JSX elements that render the TodoPage’s UI. It includes a heading, a button to open the modal, tabs to switch between active and inactive Todo lists, and conditional rendering of TodoCard components or an Empty component based on the selected tab and the existence of Todo items. Finally, it renders the TextModal component if modalOpen is true.&lt;/p&gt;
&lt;h3&gt;
  
  
  ToDo Style
&lt;/h3&gt;

&lt;p&gt;To make our ToDo app visually appealing, we can apply custom styles using SCSS. Modify the SCSS file (TodoPage.scss) in the same directory to match our desired design and import this to TodoPage.tsx.&lt;/p&gt;
&lt;h2&gt;
  
  
  Style
&lt;/h2&gt;

&lt;p&gt;Our application incorporates the powerful features of FontAwesome and FlexBoxGrid libraries, enhancing the visual aesthetics and layout capabilities. By integrating FontAwesome, we gain access to an extensive collection of icons that can be easily incorporated into our UI, allowing for visually appealing and intuitive designs. Additionally, the integration of FlexBoxGrid provides us with a responsive grid system, enabling us to create flexible and adaptive layouts that adapt to different screen sizes. Furthermore, we have seamlessly integrated Material UI and its associated material icons, enriching our application with pre-designed components and a vast library of visually pleasing icons. Together, these integrations enhance the user experience and provide us with a rich set of tools to create visually appealing and responsive interfaces.&lt;/p&gt;
&lt;h2&gt;
  
  
  Routing
&lt;/h2&gt;

&lt;p&gt;To enhance the navigation of our project, let's incorporate routes with the following configuration:&lt;br&gt;
Assign the empty routes to the Home page, providing users with a welcoming starting point.&lt;br&gt;
Direct the todo routes to the Todo page.&lt;br&gt;
Map the 404 routes to an Error Page, ensuring a user-friendly experience when encountering unexpected routes.&lt;br&gt;
For any other routes that don't match the defined paths, gracefully redirect users to the Error Page, maintaining a consistent flow throughout the app.&lt;/p&gt;

&lt;p&gt;Let us create a AppRoutes.tsx component and import this in the App.tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function AppRoutes() {
 return (
  &amp;lt;Routes&amp;gt;
   &amp;lt;Route path="/" element={&amp;lt;HomePage /&amp;gt;} /&amp;gt;
   &amp;lt;Route path="/todo" element={&amp;lt;TodoPage /&amp;gt;} /&amp;gt;
   &amp;lt;Route path="/404" element={&amp;lt;NotFoundPage /&amp;gt;} /&amp;gt;
   &amp;lt;Route path="*" element={&amp;lt;NotFoundPage /&amp;gt;} /&amp;gt;
  &amp;lt;/Routes&amp;gt;
 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the app
&lt;/h2&gt;

&lt;p&gt;Let’s us run the app and have a look at it spinning up at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn start&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  HomePage
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  ToDoPage
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  NotFoundPage
&lt;/h2&gt;

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

&lt;p&gt;It works!!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing and Debugging
&lt;/h2&gt;

&lt;p&gt;During the development phase of our React app, it is vital to thoroughly test and debug it to ensure proper functionality. React offers robust testing tools such as React Testing Library, Enzyme and Cypress, which empowers us to conduct comprehensive testing. Create unit tests for our components and services to validate their behaviour and identify any potential issues that may arise. By running these tests, we can ensure that our React app functions as intended and maintains the desired level of quality and reliability. The combination of Jest, React Testing Library, and Enzyme is often a popular choice for comprehensive testing in React applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building and Deploying the App
&lt;/h2&gt;

&lt;p&gt;Once we are ready with our ToDo app, it's time to proceed with the build and deployment process. React provides a seamless way to achieve this. Execute the following command in our terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run build&lt;/code&gt;&lt;br&gt;
This command initiates the build process and generates a production-ready build of our app. The resulting build files can then be deployed to a web server or hosting platform of our preference.&lt;/p&gt;

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

&lt;p&gt;Great job! We have accomplished the task of building and configuring our very own React ToDo app. Throughout the process, we gained valuable insights into creating a new React project, establishing components, integrating functionality, styling the app, and deploying it. This marks the start of our exciting journey with React, and there's a multitude of possibilities and knowledge awaiting us.&lt;/p&gt;

&lt;p&gt;Continue to practise and delve into React's extensive ecosystem, as well as leverage the official React documentation for further assistance. Embrace the joy of coding and relish in the convenience of using our newly created ToDo app.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/rohithart/todo-react-ui" rel="noopener noreferrer"&gt;https://github.com/rohithart/todo-react-ui&lt;/a&gt;&lt;br&gt;
API Code: &lt;a href="https://github.com/rohithart/nestjs-todo" rel="noopener noreferrer"&gt;https://github.com/rohithart/nestjs-todo&lt;/a&gt;&lt;br&gt;
React Documentation: &lt;a href="https://react.dev/learn" rel="noopener noreferrer"&gt;https://react.dev/learn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introduction to Angular</title>
      <dc:creator>Rohith Poyyeri</dc:creator>
      <pubDate>Sun, 02 Jul 2023 23:33:20 +0000</pubDate>
      <link>https://dev.to/grocstock/introduction-to-angular-25m6</link>
      <guid>https://dev.to/grocstock/introduction-to-angular-25m6</guid>
      <description>&lt;p&gt;In this blog post, we will walk you through the step-by-step process of building a ToDo application from scratch. Whether you are new to Angular or just looking for a refresher, this guide will help you get started on your journey to become an Angular developer. This app serves as the User Interface (UI) for the ToDo API, that we have built in my previous blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we dive into the development process, let's make sure we have everything we need. Ensure that we have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js and npm (Node Package Manager)&lt;/li&gt;
&lt;li&gt;Angular CLI (Command Line Interface)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Order of execution
&lt;/h2&gt;

&lt;p&gt;In Angular, understanding the order of execution is essential for developing robust and efficient applications. The following is a brief overview of the typical order of execution in an Angular application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bootstrap:&lt;/strong&gt; Angular starts by bootstrapping the root module of the application. This triggers the initialisation process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Module Loading:&lt;/strong&gt; Angular loads the required modules and their dependencies. It traverses the module tree, starting from the root module, and loads each module as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component Initialisation:&lt;/strong&gt; Once the modules are loaded, Angular initialises the components defined in the templates. It creates component instances, sets up bindings, and resolves dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Template Compilation:&lt;/strong&gt; Angular compiles the component templates to generate the corresponding views. During this process, it combines HTML templates with component logic, transforms directives and bindings, and creates the necessary data structures for rendering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Change Detection:&lt;/strong&gt; Angular performs change detection to detect and propagate changes throughout the application. It checks for changes in component properties, bindings, and other data sources, and updates the views accordingly. This ensures that the UI reflects the latest state of the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rendering:&lt;/strong&gt; After change detection, Angular renders the updated views based on the application state. It updates the DOM with the changes and applies any necessary styling or layout adjustments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event Handling and User Interaction:&lt;/strong&gt; Angular listens for user interactions and handles events triggered by user actions. It responds to user input, executes the corresponding logic, and updates the application state as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Destruction and Cleanup:&lt;/strong&gt; When a component is no longer needed or gets destroyed, Angular performs cleanup operations. It unsubscribes from event listeners, releases resources, and performs any necessary teardown tasks to prevent memory leaks and ensure efficient resource utilisation.&lt;/p&gt;

&lt;p&gt;Understanding the order of execution in Angular helps developers in optimising performance, identifying potential issues, and ensuring smooth application behaviour. It allows for better control over the application lifecycle and facilitates the implementation of complex application logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a new Angular project
&lt;/h2&gt;

&lt;p&gt;To kickstart our ToDo app, we'll begin by creating a new Angular project. Open our terminal or command prompt and run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng new todo-ui&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As we embark on setting up our ToDo app, a few important considerations come to mind. Firstly, we need to determine if routing is required for seamless navigation within our app (and the answer is a resounding "yes!"). Additionally, choosing the appropriate stylesheet format is crucial, and in this case, I recommend utilising SCSS for its flexibility and enhanced capabilities. To kickstart our project, navigate to the new directory called "todo-ui" which will serve as the foundation for our Angular project's basic structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Node version
&lt;/h2&gt;

&lt;p&gt;Lets start by creating a new .nvmrc file in the root of the project. This defines what version of node we are using. We are going to use the ‘lts/Gallium’ version. Add the following line to the file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lts/Gallium&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run the following command and might prompt us to install the version if it is missing.&lt;br&gt;
&lt;code&gt;nvm use&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Clean up and initial set-up
&lt;/h2&gt;

&lt;p&gt;Remove the static content of app.component.html and add the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;app-nav-bar&amp;gt;&amp;lt;/app-nav-bar&amp;gt;
&amp;lt;div class="app-container"&amp;gt;
&amp;lt;router-outlet&amp;gt;&amp;lt;/router-outlet&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;app-footer&amp;gt;&amp;lt;/app-footer&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, lets add Flex layout and Angular Material packages to the project.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng add @angular/material&lt;br&gt;
npm install @angular/flex-layout&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's add FontAwesome and flexboxgrid in the index.html. Add the following in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v6.2.1/css/all.css" defer/&amp;gt;
 &amp;lt;link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css" defer/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;p&gt;The environment.ts and environment.prod.ts files play a crucial role in managing environment-specific configuration settings. The environment.ts file contains configuration variables specific to the development environment, while the environment.prod.ts file contains configuration variables for the production environment.&lt;/p&gt;

&lt;p&gt;The environment.ts file is used during development and allows developers to define environment-specific settings such as API endpoints, debug flags, or other variables that are required during the development and testing phases. These variables can be easily accessed throughout the application using the Angular environment service.&lt;/p&gt;

&lt;p&gt;On the other hand, the environment.prod.ts file is used for the production build of the application. It contains configuration variables optimised for the production environment, such as production API endpoints, analytics keys, or any other settings that differ from the development environment. These variables are used when the application is built for deployment to ensure proper functionality and performance in the production environment.&lt;/p&gt;

&lt;p&gt;By maintaining separate environment files, developers can easily switch between different environments and ensure that the application behaves correctly in each environment. It allows for seamless deployment and configuration management, as the appropriate environment file is automatically selected based on the build target.&lt;/p&gt;

&lt;p&gt;Please do keep in mind not to add any secrets/passwords in these environment files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to backend API
&lt;/h2&gt;

&lt;p&gt;When connecting to the todo-api that we built earlier, which is running on port 3000, we can encounter Cross-Origin Resource Sharing (CORS) issues due to browser security restrictions. To overcome this, we can utilise a proxy configuration in our Angular project.&lt;/p&gt;

&lt;p&gt;The proxy configuration allows us to forward requests from our Angular application to the todo-api server, avoiding the CORS restrictions imposed by the browser. By configuring the proxy, we can send requests to the desired API endpoint without encountering any CORS-related errors.&lt;/p&gt;

&lt;p&gt;To set up the proxy, we need to create a file named "proxy.conf.json" in the src directory of our Angular project. Inside this file, we define the proxy configuration by specifying the target URL, which in our case is "&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "/api/*": {
  "target": "http://localhost:3000",
  "secure": false,
  "logLevel": "debug"
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the proxy configuration file is set up, we need to modify the "angular.json" file in our project's root directory. Under the "architect" section, we locate the "serve" options for our project, and inside that, we add the "proxyConfig" property, pointing to the "proxy.conf.json" file we created earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"serve": {
 "options": {
  "browserTarget": "todo-ui:build",
  "proxyConfig": "src/proxy.conf.json"
 },
 ...
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By configuring the proxy, our Angular application will send API requests to the specified target URL (todo-api running on port 3000) without encountering CORS issues. This enables seamless communication between our frontend and backend, allowing us to retrieve and manipulate data from the todo-api server within our Angular application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modules
&lt;/h2&gt;

&lt;p&gt;Modules in Angular play a crucial role in organising and structuring our application. They act as containers that group related components, services, directives, and other resources together. Modules provide a way to manage the complexity of larger applications by breaking them down into smaller, more manageable parts.&lt;/p&gt;

&lt;p&gt;Angular modules serve several purposes. They facilitate component encapsulation and provide a clear boundary for component dependencies. This promotes modularity, reusability, and maintainability. Modules also enable lazy loading, allowing us to load specific parts of our application only when needed, optimising performance.&lt;/p&gt;

&lt;p&gt;In addition to organising our code, modules define the context in which components and services are created and used. They handle dependency injection, allowing components to access the required services and dependencies.&lt;/p&gt;

&lt;p&gt;Angular provides different types of modules, including the root module (AppModule) and feature modules that focus on specific parts of our application. We can also create shared modules to encapsulate commonly used components, directives, and pipes, promoting code reuse across different parts of the application.&lt;/p&gt;

&lt;p&gt;By leveraging modules effectively, we can build scalable, maintainable Angular applications with clear separation of concerns, better code organisation, and improved developer productivity.&lt;/p&gt;

&lt;p&gt;In this project, we have followed some best practices to ensure modular abstraction and maintainability:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shared Modules:&lt;/strong&gt; We have created a Shared Module to gather all the shared components, directives, and pipes that are commonly used across different modules. This promotes reusability and reduces code duplication.&lt;br&gt;
&lt;strong&gt;Material Module:&lt;/strong&gt; To streamline the usage of Angular Material components, we have created a dedicated Material Module. Here, we import and configure all the necessary material modules to keep them isolated and easily manageable.&lt;br&gt;
&lt;strong&gt;Feature Modules:&lt;/strong&gt; Major components such as TodoModule have their own dedicated modules. This encapsulation ensures better separation of concerns and modularity. Each feature module contains the components, services, and other resources specific to that particular feature.&lt;br&gt;
&lt;strong&gt;AppModule:&lt;/strong&gt; Finally, in our AppModule, we import all the necessary modules, including the Shared Module, Material Module, and feature modules. This centralises the module imports and allows the components and services from different modules to interact seamlessly.&lt;/p&gt;

&lt;p&gt;By adhering to these norms, we promote code organisation, reusability, and maintainability, making our project more scalable and easier to maintain in the long run.&lt;/p&gt;
&lt;h2&gt;
  
  
  Component and its lifecycle
&lt;/h2&gt;

&lt;p&gt;In Angular components, the order of code execution follows a predefined sequence to ensure proper initialisation and functionality. Here is an overview of the typical order of execution within an Angular component:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constructor:&lt;/strong&gt; The component's constructor is the first code block that executes when an instance of the component is created. It is used for dependency injection and initialising local variables. However, it is important to note that the constructor should not be used for complex logic or data manipulation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ngOnChanges:&lt;/strong&gt; If the component has input properties bound to its template, the ngOnChanges lifecycle hook is triggered whenever the input values change. This hook allows us to respond to changes and perform actions based on the updated input values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ngOnInit:&lt;/strong&gt; The ngOnInit lifecycle hook is called after the constructor and ngOnChanges. It is commonly used for initialisation tasks that require the component to be fully set up. This is a good place to fetch data from a service, set default values, or perform other setup operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ngDoCheck:&lt;/strong&gt; The ngDoCheck lifecycle hook is invoked during every change detection cycle. It allows us to implement custom change detection logic and perform actions based on changes detected in the component's state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ngAfterContentInit:&lt;/strong&gt; This lifecycle hook is called after the component's content, such as projected content or child components, has been initialised. It is useful for accessing and manipulating the component's content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ngAfterViewInit:&lt;/strong&gt; The ngAfterViewInit hook is triggered after the component's view and child views have been initialised. It is commonly used for interacting with the DOM or performing operations that require the view to be fully rendered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ngOnDestroy:&lt;/strong&gt; The ngOnDestroy lifecycle hook is called just before a component is destroyed. It provides an opportunity to perform any necessary cleanup tasks, such as unsubscribing from observables, releasing resources, or cancelling timers.&lt;/p&gt;

&lt;p&gt;By following this order of execution, Angular ensures that components are properly initialised, their dependencies are resolved, and their lifecycle hooks are triggered at the appropriate times. Understanding this order allows developers to organise their code effectively and ensure that components function as intended throughout their lifecycle.&lt;/p&gt;
&lt;h2&gt;
  
  
  Shared Components
&lt;/h2&gt;

&lt;p&gt;Let us create a set of shared components that promote component reusability and maintain consistency throughout the application. These shared components reside in the 'src/app/shared/components' directory and are imported and exported from the SharedModule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NavBarComponent&lt;/strong&gt; serves as the navigation bar of the application, providing users with easy access to different sections or pages of the app. It typically contains menus, links, or buttons for navigation purposes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FooterComponent&lt;/strong&gt; is responsible for displaying a footer at the bottom of the application, providing additional information, copyright notices, or links to relevant pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HeadingComponent&lt;/strong&gt; is a reusable component used to display a heading or title for each page. It helps to maintain consistent styling and structure across different pages of the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EmptyComponent&lt;/strong&gt; is designed to be displayed when a list or data set is empty. It provides a message or placeholder content to inform users that there is no data available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LoadingComponent&lt;/strong&gt; is used to show a loading spinner or animation while the application is fetching data or performing asynchronous operations. It provides visual feedback to the users, indicating that the app is working in the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TextModalComponent&lt;/strong&gt; is a dialog or modal component used to add or input data in the application. It typically includes form fields, buttons, and validation to gather user input and save it to the system.&lt;/p&gt;

&lt;p&gt;By extracting and centralising these components in the SharedModule, we can easily import and use them in various other modules and components without duplicating code. Please do find the full code of these components in github.&lt;/p&gt;
&lt;h2&gt;
  
  
  Other Components
&lt;/h2&gt;

&lt;p&gt;Now let’s create the other components that we are after. We can make use of the Angular CLI commands for that, which is really handy.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng g c components/home&lt;br&gt;
ng g c components/not-found&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will generate the necessary files for our component, including the HTML template, SCSS styles, and TypeScript code. We need to add these components into the declaration section of AppModule.&lt;/p&gt;

&lt;p&gt;The HomeComponent serves as the welcome or homepage of our application, acting as the landing page that users first encounter when accessing our site. It provides an overview of our app's features, highlights, or any relevant information we want to showcase to users right from the start. This component is designed to provide a visually appealing and engaging user experience, making a positive first impression.&lt;/p&gt;

&lt;p&gt;On the other hand, the NotFoundComponent plays a crucial role as a fallback page. Whenever users navigate to a route that doesn't exist or provide an incorrect route, they will be redirected to the NotFoundComponent. This component serves as an error page, informing users that the requested page or resource cannot be found. It helps to improve the user experience by gracefully handling such scenarios and providing a clear message to users about the issue encountered.&lt;/p&gt;
&lt;h2&gt;
  
  
  Elephant in the room, ToDo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ToDo Modal&lt;/strong&gt;&lt;br&gt;
Let us create a new modal, Todo.ts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface Todo {
 _id: string;
 description: string;
 is_active: boolean;
 updatedAt: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ToDo Service&lt;/strong&gt;&lt;br&gt;
The TodoService is a crucial component in the ToDo application, responsible for handling the data management and communication with the backend API. It encapsulates the logic and functionality related to retrieving, updating, deleting, and adding new ToDo items.&lt;/p&gt;

&lt;p&gt;It includes the following functions: getAllToDos (retrieve all ToDo items), update (modify and update a ToDo item), delete (remove a ToDo item), and addNewTodo (create and add a new ToDo item). These functions handle the necessary HTTP requests.&lt;/p&gt;

&lt;p&gt;By utilising the TodoService and its functions, the application can interact with the backend server effectively, ensuring seamless data management and synchronisation between the client-side and server-side components.&lt;br&gt;
&lt;strong&gt;ToDo Component&lt;/strong&gt;&lt;br&gt;
Let's create a new ToDo component.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng g c components/todo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As mentioned previously, this will create all the associated components.&lt;/p&gt;

&lt;p&gt;Let us design this component so that this consists of two tabs: one for displaying active ToDos and another for inactive ToDos. The component utilises Angular Material's TabGroup component to handle the tab switching functionality.&lt;/p&gt;

&lt;p&gt;Within each tab, we incorporate a loading spinner using Angular Material's ProgressSpinner component. This spinner is displayed while the application is fetching data from the server, providing a visual indicator of the loading process.&lt;/p&gt;

&lt;p&gt;To handle the case when the ToDo list is empty, we employ the EmptyComponent. This component is shown within the corresponding tab when there are no ToDos to display. It provides a clear message to the user that the list is empty, enhancing the user experience.&lt;br&gt;
&lt;strong&gt;ToDo Card Component&lt;/strong&gt;&lt;br&gt;
In addition to the TodoComponent, we will create a TodoCardComponent to enhance the visual representation of each ToDo item. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng g c components/todo/todo-card&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The TodoCardComponent is responsible for displaying individual ToDos as aesthetically pleasing card designs.&lt;br&gt;
&lt;strong&gt;ToDo Module&lt;/strong&gt;&lt;br&gt;
To maintain a modular and organised structure for our ToDo components, it is advisable to create a dedicated ToDo module. The ToDo module will be responsible for declaring and encapsulating all the related ToDo components, providing a clear separation of concerns and promoting reusability.&lt;/p&gt;

&lt;p&gt;By creating a ToDo module, we can easily manage the dependencies and interactions between different ToDo components. This module acts as a container that groups together all the necessary components, services, and other related entities specific to ToDo functionality.&lt;/p&gt;

&lt;p&gt;The ToDo module also enables us to take advantage of Angular's dependency injection system. We can provide services and other dependencies within the module, allowing components to access and utilise them seamlessly.&lt;/p&gt;

&lt;p&gt;While it may seem like overkill in the initial stages of the application, adopting this modular approach early on lays the foundation for scalability and maintainability. As the application grows and more features are added, having a dedicated module for ToDo components ensures a clean and organised codebase, making it easier to manage and extend the application in the future.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NgModule } from '@angular/core';

import { SharedModule } from 'src/app/shared/modules/shared.module';
import { TodoComponent } from './todo.component';
import { TodoCardComponent } from './todo-card/todo-card.component';

@NgModule({
 declarations: [TodoComponent, TodoCardComponent],
 imports: [SharedModule],
 exports: [TodoComponent]
})
export class TodoModule {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ToDo Style&lt;/strong&gt;&lt;br&gt;
To make our ToDo app visually appealing, we can apply custom styles using CSS. Modify the generated CSS file (todo.component.scss and todo-card.component.scss) to match our desired design.&lt;/p&gt;
&lt;h2&gt;
  
  
  Style
&lt;/h2&gt;

&lt;p&gt;In our project, we've taken care of incorporating various essential dependencies and resources to enhance the overall design and functionality. FontAwesome and FlexBoxGrid have been integrated, providing access to a wide range of icons and a responsive grid system respectively. We've also seamlessly integrated Angular Material, empowering us to utilise the vast collection of Material design components to enhance the visual appeal and user experience. Additionally, we've implemented custom styles, colours, and functions to further refine the app's aesthetics and extend its capabilities. Feel free to explore the source code for a closer look at these enhancements.&lt;/p&gt;
&lt;h2&gt;
  
  
  Angular Material
&lt;/h2&gt;

&lt;p&gt;Angular Material is a valuable tool that saves us from reinventing the wheel by providing a comprehensive library of pre-built Material design components. To streamline the usage of these components, we have created a dedicated Material Module where all the necessary material modules are imported and configured. By injecting this Material Module into our AppModule, we ensure that the Material components are readily available throughout our application, simplifying the development process and maintaining consistency in the UI design. This approach allows us to harness the power of Angular Material and leverage its extensive range of components without the need for manual implementation from scratch.&lt;/p&gt;
&lt;h2&gt;
  
  
  Routing
&lt;/h2&gt;

&lt;p&gt;To enhance the navigation of our project, let's incorporate routes with the following configuration:&lt;br&gt;
Assign the empty routes to the Home page, providing users with a welcoming starting point.&lt;br&gt;
Direct the todo routes to the Todo page, enabling seamless task management and organisation.&lt;br&gt;
Map the 404 routes to an Error Page, ensuring a user-friendly experience when encountering unexpected routes.&lt;br&gt;
For any other routes that don't match the defined paths, gracefully redirect users to the Error Page, maintaining a consistent flow throughout the app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const routes: Routes = [
{ path: '', component: HomeComponent, pathMatch: 'full' },
{ path: AppConfig.routes.todo, component: TodoComponent, pathMatch: 'full' },
{ path: AppConfig.routes.error404, component: NotFoundComponent },
{ path: '**', redirectTo: '/' + AppConfig.routes.error404 }
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the app
&lt;/h2&gt;

&lt;p&gt;Let’s us run the app and have a look at it spinning up at &lt;a href="http://localhost:4200" rel="noopener noreferrer"&gt;http://localhost:4200&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HomePage&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;ToDoPage&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;NotFoundPage&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;It works!!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing and Debugging
&lt;/h2&gt;

&lt;p&gt;Throughout the development process, it's crucial to test and debug our app to ensure it functions as intended. Angular provides powerful testing tools like Karma and Jasmine. Write unit tests for our components and services to verify their behaviour and catch any potential issues.&lt;br&gt;
Building and Deploying the App&lt;br&gt;
Once we are satisfied with our ToDo app, it's time to build and deploy it. Angular CLI makes this process straightforward. Run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng build --prod&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will generate a production-ready build of our app, which can be deployed to a web server or hosting platform of our choice.&lt;/p&gt;

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

&lt;p&gt;Congratulations! We have successfully built and set up our own Angular ToDo app. We have learned how to create a new Angular project, set up components, implement functionality, style the app, and deploy it. This is just the beginning of our Angular journey, and there's much more to explore and learn.&lt;/p&gt;

&lt;p&gt;Remember to keep practising, exploring Angular's vast ecosystem, and referring to the official Angular documentation for additional guidance. Happy coding and enjoy using the new ToDo app!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/rohithart/todo-ui" rel="noopener noreferrer"&gt;https://github.com/rohithart/todo-ui&lt;/a&gt;&lt;br&gt;
API Code: &lt;a href="https://github.com/rohithart/nestjs-todo" rel="noopener noreferrer"&gt;https://github.com/rohithart/nestjs-todo&lt;/a&gt;&lt;br&gt;
Angular Documentation: &lt;a href="https://angular.io/docs" rel="noopener noreferrer"&gt;https://angular.io/docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>angular</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>NestJS – Data persistence with MongoDB</title>
      <dc:creator>Rohith Poyyeri</dc:creator>
      <pubDate>Wed, 21 Jun 2023 23:09:47 +0000</pubDate>
      <link>https://dev.to/grocstock/nestjs-data-persistence-with-mongodb-27i</link>
      <guid>https://dev.to/grocstock/nestjs-data-persistence-with-mongodb-27i</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;NestJS seamlessly integrates with MongoDB, a popular NoSQL database known for its flexibility and scalability. This combination empowers developers to efficiently store and retrieve data, ensuring robust and reliable data persistence for their applications.&lt;/p&gt;

&lt;p&gt;With NestJS and MongoDB, developers can leverage the benefits of a document-based database that allows for dynamic and schema-less data storage. MongoDB's flexible nature makes it well-suited for applications that handle unstructured or evolving data, offering the freedom to store and query data without the constraints of traditional relational databases. Leveraging the power of TypeScript, NestJS enables developers to define models, schemas, and repositories, providing a solid foundation for working with MongoDB collections.&lt;/p&gt;

&lt;p&gt;Whether you're building a simple REST API or a complex enterprise-grade application, NestJS and MongoDB make data persistence a breeze. You can effortlessly create, read, update, and delete documents, perform advanced queries, and apply various data manipulation operations using MongoDB's rich query language.&lt;/p&gt;

&lt;p&gt;In this blog post, we will delve into the fundamentals of data persistence with NestJS and MongoDB. Building upon the previous article on setting up a NestJS application, we will explore how to implement MongoDB and cover essential topics including establishing a MongoDB connection, defining models and schemas, executing CRUD operations, and querying data. By combining our knowledge of NestJS with MongoDB integration, we will unlock the power of data persistence in this API-driven environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;To configure the tests, let’s start by installing some dependencies.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install @nestjs/mongoose mongoose&lt;br&gt;
npm install @nestjs/config&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create an environment file. This is where environment variables can be placed locally. These values can then be injected into the pipeline for the production environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.env&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MONGO_DB_URL=mongodb://127.0.0.1:27017&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s update the app.module to include Mongoose and ConfigModule. ConfigModule is for us to access the environment variable. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app.module.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { TodoModule } from './modules/todo/todo.module';

@Module({
 imports: [
   ConfigModule.forRoot(),
   MongooseModule.forRoot(process.env.MONGO_DB_URL),
   TodoModule,
 ],
 controllers: [],
 providers: [],
})
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Model
&lt;/h2&gt;

&lt;p&gt;Let’s start by updating the existing ToDo model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

export type ToDoDocument = HydratedDocument&amp;lt;ToDo&amp;gt;;

@Schema({ timestamps: true })
export class ToDo {
 @Prop({ required: true })
 description: string;

 @Prop({ default: true })
 is_active: boolean;
}

export const ToDoSchema = SchemaFactory.createForClass(ToDo);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have removed a couple of fields here. id and created_at have been removed as the _id is added and updated automatically, and @Schema({ timestamps: true }) will create the timestamps for us out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Module
&lt;/h2&gt;

&lt;p&gt;Now, it's time to create a dedicated module for MongoDB. This module will serve as a centralised hub where we can inject and export all the features provided by MongooseModule, essentially representing our database tables. Once the MongoModule is set up, we can easily inject it into any other modules that require access to the Mongo tables. This modular approach ensures efficient organisation and seamless integration of MongoDB across our application. There might be scenarios where we might have multiple databases and this modular approach can help create a good level of abstraction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mongo.module.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';

import { ToDo, ToDoSchema } from 'src/models/ToDo';

@Module({
 imports: [
   MongooseModule.forFeature([{ name: ToDo.name, schema: ToDoSchema }]),
 ],
 exports: [
   MongooseModule.forFeature([{ name: ToDo.name, schema: ToDoSchema }]),
 ],
})
export class MongoModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s inject MongoModule in the ToDoModule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;todo.module.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Module } from '@nestjs/common';
import { MongoModule } from 'src/shared/mongo.module';
import { TodoController } from './todo.controller';
import { TodoService } from './todo.service';

@Module({
 imports: [MongoModule],
 controllers: [TodoController],
 providers: [TodoService],
})
export class TodoModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Service
&lt;/h2&gt;

&lt;p&gt;Firstly, we have to nuke the database.service.ts as we don’t need this anymore. We have to now update the todo.service.ts to replace DatabaseService with MongoModel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;todo.service.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';

import { ToDo, ToDoDocument } from 'src/models/ToDo';

@Injectable()
export class TodoService {
 constructor(@InjectModel(ToDo.name) private todoModel: Model&amp;lt;ToDoDocument&amp;gt;) {}

 getAll(): Promise&amp;lt;ToDo[]&amp;gt; {
   return this.todoModel.find().exec();
 }

 get(id: string): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoModel.findOne({ _id: id }).exec();
 }

 create(todo: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   const newToDo = new this.todoModel(todo);
   return newToDo.save();
 }

 update(id: string, body: unknown): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoModel
     .findOneAndUpdate({ _id: id }, body, { new: true })
     .exec();
 }

 delete(id: string): Promise&amp;lt;unknown&amp;gt; {
   return this.todoModel
     .findOneAndRemove({
       _id: id,
     })
     .exec();
 }

 // we can remove this and use the existing update function itself.
 markAsInActive(id: string): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoModel
     .findOneAndUpdate(
       { _id: id },
       { $set: { is_active: true } },
       { new: true },
     )
     .exec();
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Controller
&lt;/h2&gt;

&lt;p&gt;There are minor changes to the controller as well. Let’s update the controller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;todo.controller.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { ApiBody, ApiParam, ApiTags } from '@nestjs/swagger';

import { ToDo } from 'src/models/ToDo';
import { TodoService } from './todo.service';

@ApiTags('ToDo')
@Controller('todo')
export class TodoController {
 constructor(private readonly todoService: TodoService) {}

 @Get(':id')
 @ApiParam({ name: 'id', required: true })
 get(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.get(params.id);
 }

 @Get()
 getAll(): Promise&amp;lt;ToDo[]&amp;gt; {
   return this.todoService.getAll();
 }

 @Post()
 @ApiBody({})
 create(@Body() body: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.create(body);
 }

 @Put(':id')
 @ApiParam({ name: 'id', required: true })
 @ApiBody({})
 update(@Param() params: { id: string }, @Body() body: any): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.update(params.id, body);
 }

 @Put('inactive/:id')
 @ApiParam({ name: 'id', required: true })
 markAsInActive(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.markAsInActive(params.id);
 }

 @Delete(':id')
 @ApiParam({ name: 'id', required: true })
 delete(@Param() params: { id: string }): Promise&amp;lt;unknown&amp;gt; {
   return this.todoService.delete(params.id);
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let’s Swagger this
&lt;/h2&gt;

&lt;p&gt;Let’s start by running the application locally using yarn start.&lt;/p&gt;

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

&lt;p&gt;Now let us use the POST endpoint to create a new todo.&lt;/p&gt;

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

&lt;p&gt;We can see that the request came back with a HTTP 201 along with the data and let’s use the _id here to fetch the data.&lt;/p&gt;

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

&lt;p&gt;It worked!&lt;/p&gt;

&lt;h2&gt;
  
  
  MongoDB Account
&lt;/h2&gt;

&lt;p&gt;Now that we have successfully integrated MongoDB into our application, deploying it is a breeze. All you need to do is inject the MONGO_DB_URL into your production pipeline. By creating a free account on MongoDB, you can obtain the public URL required for deployment. With this in place, our API is ready to be deployed to production with ease.&lt;/p&gt;

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

&lt;p&gt;In conclusion, NestJS and MongoDB provide a powerful combination for data persistence in your NestJS applications. With NestJS's robust framework and MongoDB's flexible NoSQL database, you can store, retrieve, and manipulate data with ease.&lt;/p&gt;

&lt;p&gt;Throughout this blog, we have explored the essentials of integrating NestJS with MongoDB. We have learned how to establish a connection to the MongoDB database, define models and schemas, and perform various CRUD operations. We have also delved into querying data, handling relationships, and implementing data validation and business logic.&lt;/p&gt;

&lt;p&gt;Now that you have a solid understanding of NestJS - Data persistence with MongoDB, you can confidently embark on your journey to build scalable, efficient, and maintainable applications. &lt;/p&gt;

&lt;p&gt;MongoBD: &lt;a href="https://www.mongodb.com/" rel="noopener noreferrer"&gt;https://www.mongodb.com/&lt;/a&gt;&lt;br&gt;
Code: &lt;a href="https://github.com/rohithart/nestjs-todo" rel="noopener noreferrer"&gt;https://github.com/rohithart/nestjs-todo&lt;/a&gt;&lt;br&gt;
NestJS Documentation: &lt;a href="https://docs.nestjs.com/" rel="noopener noreferrer"&gt;https://docs.nestjs.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>mongodb</category>
      <category>database</category>
      <category>typescript</category>
    </item>
    <item>
      <title>NestJS - Unit and E2E testing</title>
      <dc:creator>Rohith Poyyeri</dc:creator>
      <pubDate>Wed, 08 Mar 2023 22:03:45 +0000</pubDate>
      <link>https://dev.to/grocstock/nestjs-unit-and-e2e-testing-7pb</link>
      <guid>https://dev.to/grocstock/nestjs-unit-and-e2e-testing-7pb</guid>
      <description>&lt;p&gt;Testing is a fundamental aspect of development that helps build trust in the code and ensures it can handle various scenarios. It also serves as an early warning system when changes are made to the code. If a test fails, it indicates that an unintended change has occurred, which either requires fixing the code or updating the test.&lt;/p&gt;

&lt;p&gt;In this post, we take a look at implementing testing in a NestJS application which was set up previously in this post - NestJS – Supercharging Node.js Applications. Now that we have a basic understanding of NestJS, this post will explore how to test the API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Types
&lt;/h2&gt;

&lt;p&gt;There are three main recommendations for testing:&lt;br&gt;
Unit testing&lt;br&gt;
End-to-end (E2E) testing&lt;br&gt;
SuperTest&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unit testing&lt;/strong&gt;&lt;br&gt;
It is best for a JavaScript function to be kept short, ideally with no more than three lines of code. However, this can be difficult to adhere to. Unit testing involves testing a function on its own, to ensure it is isolated and functioning properly. This allows for thorough testing of each part of the code, independently, and without interference from other functions or services. It is highly recommended to have as many tests as possible, as there is no such thing as too many tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E2E testing&lt;/strong&gt;&lt;br&gt;
As mentioned in my first blog, NestJS has a designated entry point module. In the example provided, the TodoModule was the entry point, responsible for setting up routes, injecting controllers, and services. End-to-end (E2E) testing can be used to verify the functionality of this module. The test bed injects the TodoModule and sets up routes, controllers, and services. By testing the module end-to-end, we can ensure that it works as intended throughout the entire process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supertest&lt;/strong&gt;&lt;br&gt;
We need a solution that can test the API regardless of the framework it is built on. The API can be built using NodeJS, NestJS, or any other framework. Supertest provides a framework-agnostic testing suite that allows for end-to-end testing of the API.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;To configure the tests, let us start by installing some dependencies.&lt;br&gt;
&lt;code&gt;$ yarn add supertest jest-sonar jest-junit @jest-performance-reporter/core  --save-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s set up an initial base configuration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jest.config.js&lt;/code&gt;&lt;br&gt;
This is the base configuration for all the tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
 testEnvironment: 'node',
 preset: 'ts-jest',
 rootDir: './',
 modulePaths: ['&amp;lt;rootDir&amp;gt;'],
 moduleNameMapper: {
   '^src$': '&amp;lt;rootDir&amp;gt;/src',
   '^src/(.+)$': '&amp;lt;rootDir&amp;gt;/src/$1',
 },
 modulePathIgnorePatterns: ['src/typings'],
 testPathIgnorePatterns: [
   '/node_modules./',
   '&amp;lt;rootDir&amp;gt;/(coverage|dist|lib|tmp)./',
 ],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;jest.unit.js&lt;/code&gt;&lt;br&gt;
This is the configuration for unit tests, which inherits the base configuration. The coverage has been set to low for the time being. Ideally, this has to be above 80.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sharedConfig = require('./jest.config');

module.exports = {
 ...sharedConfig,
 coverageDirectory: 'coverage',
 coverageReporters: ['text', 'lcov', 'cobertura'],
 collectCoverageFrom: [
   'src/**/*.ts',
   '!*/node_modules/**',
   '!&amp;lt;rootDir&amp;gt;/src/main.ts',
   '!&amp;lt;rootDir&amp;gt;/src/modules/database/database.service.ts',
 ],
 reporters: [
   'default',
   'jest-sonar',
   [
     'jest-junit',
     {
       outputDirectory: 'junit',
       outputName: 'test-results.xml',
     },
   ],
   [
     '@jest-performance-reporter/core',
     {
       errorAfterMs: 1000,
       warnAfterMs: 500,
       logLevel: 'warn',
       maxItems: 5,
       jsonReportPath: 'performance-report.json',
       csvReportPath: 'performance-report.csv',
     },
   ],
 ],
 coverageThreshold: {
   global: {
     branches: 10,
     functions: 10,
     lines: 10,
     statements: 10,
   },
 },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;jest.e2e.js&lt;/code&gt;&lt;br&gt;
This is the configuration for E2E tests, which inherits the base configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sharedConfig = require('./jest.config');

module.exports = {
 ...sharedConfig,
 moduleFileExtensions: ['js', 'json', 'ts'],
 testRegex: '.e2e-spec.ts$',
 transform: {
   '^.+\\.(t|j)s$': 'ts-jest',
 },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;jest.supertest.js&lt;/code&gt;&lt;br&gt;
This is the configuration for supertest tests, which inherits the base configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sharedConfig = require('./jest.config');

module.exports = {
 ...sharedConfig,
 moduleFileExtensions: ['js', 'json', 'ts'],
 testRegex: '.supertest-spec.ts$',
 transform: {
   '^.+\\.(t|j)s$': 'ts-jest',
 },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have all the configurations in place, we need to update our scripts in package.json. All/update the following scripts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   "test": "jest --config ./jest.unit.js",
   "test:cov": "yarn test --coverage",
   "test:e2e": "jest --config ./jest.e2e.js",
   "test:supertest": "jest --config ./jest.supertest.js"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Now let’s look at our previous sample code repo and get our hands dirty with some testing. Before we start, let us mock the database service. We will look into implementing MongoDB as a separate blog.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@nestjs/common';
import { ToDo } from 'src/models/ToDo';

@Injectable()
export class DataBaseService {
 data: ToDo[] = [
   {
     id: '1',
     description: 'Cook pasta',
     is_active: true,
     created_at: new Date(),
   },
   {
     id: '2',
     description: 'Do laundry',
     is_active: true,
     created_at: new Date(),
   },
   {
     id: '3',
     description: 'Clean kitchen',
     is_active: false,
     created_at: new Date(),
   },
 ];

 getAll(): Promise&amp;lt;ToDo[]&amp;gt; {
   return Promise.resolve(this.data);
 }

 get(id: string): Promise&amp;lt;ToDo&amp;gt; {
   return Promise.resolve(this.data.filter((t) =&amp;gt; t.id === id)[0]);
 }

 create(todo: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   this.data.push(todo);
   return Promise.resolve(todo);
 }

 update(todo: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   const dataIndex = this.data.findIndex((t) =&amp;gt; t.id === todo.id);
   this.data[dataIndex] = todo;
   return Promise.resolve(this.data[dataIndex]);
 }

 delete(id: string): Promise&amp;lt;boolean&amp;gt; {
   this.data = this.data.filter((t) =&amp;gt; t.id !== id);
   return Promise.resolve(true);
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Unit testing&lt;/strong&gt;&lt;br&gt;
Before we start, let us run the tests and coverage so we can compare the before and after results.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ yarn test:cov&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Let us start by adding unit tests to the controller, service and module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unit testing service&lt;/strong&gt;&lt;br&gt;
This is an example of what unit tests for a service may look like. Although it may appear extensive for a small service, it has several benefits. Each function is tested individually and, in the event of a failure, the test can pinpoint the specific point of failure. The use of "describe" blocks isolates each test, providing a level of abstraction and assurance they are not affected by other neighbouring tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Test, TestingModule } from '@nestjs/testing';
import { ToDo } from 'src/models/ToDo';
import { DataBaseService } from 'src/modules/database/database.service';
import { TodoModule } from './todo.module';
import { TodoService } from './todo.service';

describe('TodoService', () =&amp;gt; {
 let service: TodoService;

 const mockDataBaseService = {
   getAll: jest.fn(),
   get: jest.fn(),
   create: jest.fn(),
   update: jest.fn(),
   delete: jest.fn(),
 };

 beforeEach(async () =&amp;gt; {
   const module: TestingModule = await Test.createTestingModule({
     imports: [TodoModule],
   })
     .overrideProvider(DataBaseService)
     .useValue(mockDataBaseService)
     .compile();

   service = module.get&amp;lt;TodoService&amp;gt;(TodoService);
 });

 it('should have the service defined', () =&amp;gt; {
   expect(service).toBeDefined();
 });

 describe('#getAll', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockDataBaseService, 'getAll');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.getAll).toBeDefined();
   });

   it('should call the database', () =&amp;gt; {
     service.getAll();
     expect(mockDataBaseService.getAll).toBeCalledTimes(1);
   });
 });

 describe('#get', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockDataBaseService, 'get');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.get).toBeDefined();
   });

   it('should call the database', () =&amp;gt; {
     service.get('1');
     expect(mockDataBaseService.get).toBeCalledTimes(1);
   });
 });

 describe('#create', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockDataBaseService, 'create');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.create).toBeDefined();
   });

   it('should call the database', () =&amp;gt; {
     service.create({} as ToDo);
     expect(mockDataBaseService.create).toBeCalledTimes(1);
   });
 });

 describe('#update', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockDataBaseService, 'update');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.update).toBeDefined();
   });

   it('should call the database', () =&amp;gt; {
     service.update({} as ToDo);
     expect(mockDataBaseService.update).toBeCalledTimes(1);
   });
 });

 describe('#delete', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockDataBaseService, 'delete');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.delete).toBeDefined();
   });

   it('should call the database', () =&amp;gt; {
     service.delete('1');
     expect(mockDataBaseService.delete).toBeCalledTimes(1);
   });
 });

 describe('#markAsInActive', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockDataBaseService, 'get');
     jest.spyOn(mockDataBaseService, 'update');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.markAsInActive).toBeDefined();
   });

   describe('when inactive is called', () =&amp;gt; {
     it('should call the databaseService.get', () =&amp;gt; {
       expect(mockDataBaseService.get).toBeCalledTimes(1);
     });

     it('should call the databaseService.update', () =&amp;gt; {
       expect(mockDataBaseService.update).toBeCalledTimes(1);
     });
   });
 });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Unit testing controller&lt;/strong&gt;&lt;br&gt;
Unit tests for controllers are similar to a service. Let us have a closer look at the get function, specifically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.get(params.id);
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function is responsible for reading the id from params, and invoking and returning the get function from service. So in our unit test, we test exactly the same. We are making sure when this function in the controller is being invoked, the relevant function in service is being called once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Test, TestingModule } from '@nestjs/testing';
import { ToDo } from 'src/models/ToDo';
import { TodoController } from './todo.controller';
import { TodoService } from './todo.service';

describe('TodoController', () =&amp;gt; {
 let controller: TodoController;
 let service: TodoService;

 const mockTodoService = {
   getAll: jest.fn(),
   get: jest.fn(),
   create: jest.fn(),
   update: jest.fn(),
   delete: jest.fn(),
   markAsInActive: jest.fn(),
 };

 beforeEach(async () =&amp;gt; {
   const module: TestingModule = await Test.createTestingModule({
     providers: [TodoService],
     controllers: [TodoController],
   })
     .overrideProvider(TodoService)
     .useValue(mockTodoService)
     .compile();

   controller = module.get&amp;lt;TodoController&amp;gt;(TodoController);
   service = module.get&amp;lt;TodoService&amp;gt;(TodoService);
 });

 it('should be defined', () =&amp;gt; {
   expect(controller).toBeDefined();
 });

 describe('#getAll', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(service, 'getAll');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.getAll).toBeDefined();
   });

   it('should call service.getAll', () =&amp;gt; {
     controller.getAll();
     expect(service.getAll).toBeCalledTimes(1);
   });
 });

 describe('#get', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(service, 'get');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.get).toBeDefined();
   });

   it('should call service.get', () =&amp;gt; {
     controller.get({ id: '1' });
     expect(service.get).toBeCalledTimes(1);
   });
 });

 describe('#create', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(service, 'create');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.create).toBeDefined();
   });

   it('should call service.create', () =&amp;gt; {
     controller.create({} as ToDo);
     expect(service.create).toBeCalledTimes(1);
   });
 });

 describe('#update', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(service, 'update');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.update).toBeDefined();
   });

   it('should call service.update', () =&amp;gt; {
     controller.update({} as ToDo);
     expect(service.update).toBeCalledTimes(1);
   });
 });

 describe('#delete', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(service, 'delete');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.delete).toBeDefined();
   });

   it('should call service.delete', () =&amp;gt; {
     controller.delete({ id: '1' });
     expect(service.delete).toBeCalledTimes(1);
   });
 });

 describe('#markAsInActive', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(service, 'markAsInActive');
   });

   it('should be defined', () =&amp;gt; {
     expect(service.markAsInActive).toBeDefined();
   });

   it('should call service.markAsInActive', () =&amp;gt; {
     controller.markAsInActive({ id: '1' });
     expect(service.markAsInActive).toBeCalledTimes(1);
   });
 });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Unit testing module&lt;/strong&gt;&lt;br&gt;
Unit testing modules are comparatively easier. The responsibility of this test is to make sure that the relevant controllers and services are injected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Test, TestingModule } from '@nestjs/testing';

import { TodoController } from './Todo.controller';
import { TodoModule } from './Todo.module';
import { TodoService } from './Todo.service';

describe('TodoModule', () =&amp;gt; {
 let module: TestingModule;

 beforeAll(async () =&amp;gt; {
   module = await Test.createTestingModule({
     imports: [TodoModule],
   }).compile();
 });

 it('should compile the module', async () =&amp;gt; {
   expect(module).toBeDefined();
 });

 it('should have Todo components', async () =&amp;gt; {
   expect(module.get(TodoController)).toBeInstanceOf(TodoController);
   expect(module.get(TodoService)).toBeInstanceOf(TodoService);
 });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we are finished with unit testing, let us run the coverage and compare the results. We can see that the coverage for statements, branches, functions and lines have increased significantly. We can talk a bit more about the coverage and jest setting at the end.&lt;/p&gt;

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

&lt;p&gt;This coverage report shows us a clear picture of the coverage of tests on each file. The most important column is that labelled ‘Uncovered Lines’. You’ll see that, for example, todo.service.ts has uncovered lines of code from 32 to 34. We now have to write unit tests to make sure those lines are also covered. In certain scenarios, it might not be possible to get 100% coverage. The goal is to get maximum coverage, and 80% or higher is considered good. If we can achieve 90% or more, we have a very confident test suite. However, it’s worth noting that we should not achieve these results by excluding files in the config.&lt;/p&gt;

&lt;h2&gt;
  
  
  E2E testing
&lt;/h2&gt;

&lt;p&gt;NestJS E2E testing involves testing the application end-to-end, starting from main.ts all the way to service. This is an easy way to test whether all the components are wired up correctly. This ensures the modules and its injections are in order, all the dependency injections are correct in controller and service, and confirms the routing is done as expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E2E testing Todo Module&lt;/strong&gt;&lt;br&gt;
E2E tests are written for each module. We have to make sure that we hit all the controller endpoints, which are technically all the routes configured through a module. So, now we are going to test the Todo Module end-to-end. We will be mocking the DatabaseService for the time being. Similar to the NestJS functions, we don’t need to test the database, as it is implied it works as expected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { INestApplication } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import * as request from 'supertest';

import { TodoService } from 'src/modules/todo/todo.service';
import { AppModule } from 'src/app.module';

describe('TodoModule', () =&amp;gt; {
 let app: INestApplication;

 const mockTodoService = {
   getAll: jest.fn(),
   get: jest.fn(),
   create: jest.fn(),
   update: jest.fn(),
   delete: jest.fn(),
   markAsInActive: jest.fn(),
 };

 beforeEach(async () =&amp;gt; {
   const moduleFixture: TestingModule = await Test.createTestingModule({
     imports: [AppModule],
   })
     .overrideProvider(TodoService)
     .useValue(mockTodoService)
     .compile();

   app = moduleFixture.createNestApplication();
   await app.init();
 });

 afterEach(() =&amp;gt; {
   jest.clearAllMocks();
 });

 describe('GET: todo/:id', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockTodoService, 'get');
   });

   it('should return OK', async () =&amp;gt; {
     await request(app.getHttpServer()).get('/todo/1').expect(200, {});
   });
 });

 describe('GET: todo/all', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockTodoService, 'getAll');
   });

   it('should return OK', async () =&amp;gt; {
     await request(app.getHttpServer()).get('/todo/all').expect(200, {});
   });
 });

 describe('POST: todo', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockTodoService, 'create');
   });

   it('should return OK', async () =&amp;gt; {
     await request(app.getHttpServer()).post('/todo').expect(201, {});
   });
 });

 describe('PUT: todo', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockTodoService, 'update');
   });

   it('should return OK', async () =&amp;gt; {
     await request(app.getHttpServer()).put('/todo').expect(200, {});
   });
 });

 describe('PUT: todo/inactive/:id', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockTodoService, 'update');
   });

   it('should return OK', async () =&amp;gt; {
     await request(app.getHttpServer())
       .put('/todo/inactive/:id')
       .expect(200, {});
   });
 });

 describe('DELETE: todo/:id', () =&amp;gt; {
   beforeEach(() =&amp;gt; {
     jest.spyOn(mockTodoService, 'delete');
   });

   it('should return OK', async () =&amp;gt; {
     await request(app.getHttpServer()).delete('/todo/:id').expect(200, {});
   });
 });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can run the E2E tests.&lt;br&gt;
&lt;code&gt;$ yarn test:e2e&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;In the above E2E test set up, we can see that we are injecting the test bed with the modules. The E2E is not agnostic of NestJS and its components. We might have to override the components and services to make sure that the test can pass.&lt;/p&gt;

&lt;p&gt;Now we need a test set up that is agnostic of the language or framework we have used. So we will run the application and our test will run against the running application. These tests can also be used to run against different environments. Since this test is framework agnostic, it will come handy if we decide to change the framework, for instance from NestJS to C#. This can also help us avoid regressions as it can be run against multiple environments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as request from 'supertest';

const baseURL = 'http://localhost:3000/';

describe('Todo', () =&amp;gt; {
 const apiRequest = request(baseURL);

 describe('GET: todo/:id', () =&amp;gt; {
   it('should have the response', async () =&amp;gt; {
     const response = await apiRequest.get('todo/1');

     expect(response.status).toBe(200);
   });
 });

 describe('GET: todo/all', () =&amp;gt; {
   it('should have the response', async () =&amp;gt; {
     const response = await apiRequest.get('todo/all');

     expect(response.status).toBe(200);
   });
 });

 describe('POST: todo', () =&amp;gt; {
   it('should have the response', async () =&amp;gt; {
     const response = await apiRequest.post('todo').send({});

     expect(response.status).toBe(201);
   });
 });

 describe('PUT: todo', () =&amp;gt; {
   it('should have the response', async () =&amp;gt; {
     const response = await apiRequest.put('todo').send({});

     expect(response.status).toBe(200);
   });
 });

 describe('PUT: todo/inactive/:id', () =&amp;gt; {
   it('should have the response', async () =&amp;gt; {
     const response = await apiRequest.put('todo').send({});

     expect(response.status).toBe(200);
   });
 });

 describe('DELETE: todo/:id', () =&amp;gt; {
   it('should have the response', async () =&amp;gt; {
     const response = await apiRequest.delete('todo/1');

     expect(response.status).toBe(200);
   });
 });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we run the tests, we have to run the application. This is because this test will be hitting the actual endpoints of the application rather than the code itself. Note that in cases of authenticated endpoints, we might have to pass header or token so that the test can pass.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ yarn test:supertest&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;There are a few things to keep an eye on here. Firstly, we are only checking the status of the response, however we can and should also check the response in here, which increases the reliability of the test.&lt;/p&gt;

&lt;p&gt;You can also configure a helper which gives you a response to compare against while running on different environments. I have hardcoded the base URL here for the ease of the demo. Ideally, we need the base URL to be read from an environment config file.&lt;/p&gt;

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

&lt;p&gt;Now that we have three sets of tests, we have achieved a higher level of confidence in updating existing implementations and introducing more features. These tests will help us in multiple ways. Firstly, they act like a technical documentation of what the expected behaviour is. Secondly, this will help us in alerting any unwanted bugs or regression that we might have been accidentally introduced. These tests should be added to the CI/CD pipelines so they can run against every change. The supertests can be very handy if we set them to run against all environments, if possible. &lt;/p&gt;

&lt;p&gt;In upcoming blogs, we will explore how these tests can become even more helpful when we start to add new features to this existing code base.&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/rohithart/nestjs-todo/tree/9bd7580e3ac43417cb49184b20919889d3b45bbc" rel="noopener noreferrer"&gt;https://github.com/rohithart/nestjs-todo/tree/9bd7580e3ac43417cb49184b20919889d3b45bbc&lt;/a&gt;&lt;br&gt;
NestJS Documentation: &lt;a href="https://docs.nestjs.com/" rel="noopener noreferrer"&gt;https://docs.nestjs.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>api</category>
    </item>
    <item>
      <title>NestJS - Node.js Application on steroids</title>
      <dc:creator>Rohith Poyyeri</dc:creator>
      <pubDate>Tue, 31 Jan 2023 04:00:56 +0000</pubDate>
      <link>https://dev.to/grocstock/nestjs-nodejs-application-on-steroids-43g7</link>
      <guid>https://dev.to/grocstock/nestjs-nodejs-application-on-steroids-43g7</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;NestJS, a progressive Node.js framework, can be used to build an efficient, scalable, flexible, enterprise-ready NodeJS server-side application, which provides structure and releases APIs directly to the developer. The architecture is heavily inspired by the Angular framework, making it easy for any Angular developers to understand and learn. Behind the scenes, Nest makes use of the robust HTTP server framework, Express, by default. Nest also uses progressive JavaScript that fully supports TypeScript, enabling developers to code in pure JavaScript, and combines elements of object oriented programming (OOP), functional programming (FP), and functional reactive programming (FRP).&lt;/p&gt;

&lt;p&gt;In this post, we will explore the architecture of NestJS, and set up a basic API using Typescript including its components, and a landing page using Swagger to gain an overview of all exposed endpoints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLI&lt;/strong&gt;&lt;br&gt;
NestJS has one the most powerful CLI tools. The CLI can be used to create any part of the framework automatically, and develop applications with NestJS without much of the graphical user interface (GUI) interactions. CLI can be used to create modules, controllers and services using command line, and is also consistent with Angular CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Support&lt;/strong&gt;&lt;br&gt;
NestJS supports many popular tools under the hood like Swagger, TypeORM, Mongoose, GraphQL, Logging, Routing, Validation, Caching, WebSockets, and much more, with little to no configurations. The NestJS website provides very detailed documentation so there’s no need to reinvent the wheel.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;NestJS has three architecture tiers, which are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controller - Handles the routing.&lt;/li&gt;
&lt;li&gt;Service - Handles the business logic.&lt;/li&gt;
&lt;li&gt;Data access layer - Handles the access of data from the data source.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The order of execution gives developers access to more functionality and application control, allowing them to implement some complex logics such as authentication, error handling, logging and validation, without writing custom logic.&lt;/p&gt;

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

&lt;p&gt;This order of execution is an important consideration, as it will allow us to implement some solutions and business logic higher up the ladder, rather than in the service itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Middleware&lt;/strong&gt;&lt;br&gt;
A middleware is a function that is executed before the route handler, which has access to the request, the response, and the next function. It can be used to change a request and response object, and end a request response cycle. For instance, if we needed to validate the auth token in the request header, we can use a middleware to read and validate the token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Guard&lt;/strong&gt;&lt;br&gt;
Guards are a single responsibility class which, as the name suggests, is responsible for guarding the routes. The guards are responsible for confirming the request has the required permissions, role or ACL to access the route. Developers can use this alongside authentication in use cases such as role-based access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interceptor&lt;/strong&gt;&lt;br&gt;
Interceptors are functions that can bind extra functionality before and after execution. Interceptors are really powerful as they are capable of updating the result, providing an exception, or even completely overriding the execution of a function. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pipe&lt;/strong&gt;&lt;br&gt;
Pipes can be used to transform or validate any data member. In simpler terms, pipes can be used to transform a string to a number, or to validate if the member is not empty. By default, NestJS offers nine out-of-the-box pipes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt;&lt;br&gt;
The controller is the entry point of the request to the main application using dependency injection, and is in charge of invoking the relevant service to handle the business logic. It’s worth noting that the controller is not to be used to implement any business logic, however there might be times where we need to break this convention. If required, a controller can inject multiple services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service&lt;/strong&gt;&lt;br&gt;
Service is the main brain of the application, and is where the business logic will be implemented. The service invokes the data access layer to receive data from the data source, apply any relevant business logic or data transformations, modifications or filtrations, and returns the response back to the controller. A servicer can also inject other services using dependency injection.&lt;/p&gt;

&lt;p&gt;There is a fine line between what has to be used and where the concept should lie. Considerations should be made, such as doing justice to the implementation, while ensuring not to exploit any services. For instance, header validation can be done using both an interceptor and a middleware. Developers should be careful with what they use, depending on the use case.&lt;/p&gt;
&lt;h2&gt;
  
  
  Set Up
&lt;/h2&gt;

&lt;p&gt;That’s enough of the boring theory, now let’s look at some cool stuff. Yes, code.&lt;/p&gt;

&lt;p&gt;Let’s create a new to-do list app.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i -g @nestjs/cli&lt;/code&gt;&lt;br&gt;
&lt;code&gt;nest new  todo&lt;/code&gt;&lt;br&gt;
This creates the following scaffold files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;main.ts&lt;/code&gt; The main entry point of application. This has the main core bootstrap function that creates a single instance NestFactory for the NestJS application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.module.ts&lt;/code&gt; The root module of application. All global modules that will be used by the application have to be injected here.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.service.ts&lt;/code&gt; A basic injectable service with a single function.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.controller.ts&lt;/code&gt; A basic controller with a single function&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.controller.spec.ts&lt;/code&gt; Unit tests for app.controller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are a few useful commands:&lt;br&gt;
&lt;code&gt;npm run start&lt;/code&gt; // start the application in the default port&lt;br&gt;
&lt;code&gt;npm run start:dev&lt;/code&gt; // start the application in the default port with  hot reload&lt;br&gt;
Now, let’s create the basic modules and components.&lt;/p&gt;

&lt;p&gt;Let’s start with an interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// models/ToDo.ts
export interface TodoList {
 id: string;
 description: string;
 is_active: boolean;
 created_at: Date;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have to create new module, controller and service for ToDo.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nest generate module modules/todo&lt;/code&gt;&lt;br&gt;
&lt;code&gt;nest generate controller modules/todo&lt;/code&gt;&lt;br&gt;
&lt;code&gt;nest generate service modules/todo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will create the following files:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;src/modules/todo/todo.controller.spec.ts&lt;br&gt;
src/modules/todo/todo.controller.ts&lt;br&gt;
src/modules/todo/todo.module.ts&lt;br&gt;
src/modules/todo/todo.service.spec.ts&lt;br&gt;
src/modules/todo/todo.service.ts&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's clean up before we start. We can now remove app.controller.ts, app.controller.spec.ts and app.service.ts since we need to create a level of abstraction between all the modules. We need to remove their reference from app.module.ts as well. The app.module.ts would already be updated by injecting todo.module.ts into it. This ensures the module is available for consumption by the app and if we run the app, we can hit the todo controller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TodoService&lt;/strong&gt;&lt;br&gt;
This is a Singleton Injectable service that is responsible for all the business logic and getting the data from database or source systems. Here, we update the service to have basic CRUD operations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@nestjs/common';

import { ToDo } from 'src/models/ToDo';

@Injectable()
export class TodoService {
 private readonly database: any; // We have to inject this through constructor.
 // constructor(private readonly database: any) {}

 getAll(): Promise&amp;lt;ToDo[]&amp;gt; {
   return this.database.getAll();
 }

 get(id: string): Promise&amp;lt;ToDo&amp;gt; {
   return this.database.get(id);
 }

 create(todo: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   return this.database.new(todo);
 }

 update(todo: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   return this.database.update(todo);
 }

 delete(id: string): Promise&amp;lt;ToDo&amp;gt; {
   return this.database.delete(id);
 }

 // we can remove this and use the existing update function itself.
 markAsInActive(id: string): Promise&amp;lt;ToDo&amp;gt; {
   return this.get(id).then((todo: ToDo) =&amp;gt; {
     todo.is_active = false;
     return this.update(todo);
   });
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ToDoController&lt;/strong&gt;&lt;br&gt;
ToDoController is the controller function that will expose the endpoints in the app. This controller injects the relevant service and calls the necessary actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
 Body,
 Controller,
 Delete,
 Get,
 Param,
 Post,
 Put,
} from '@nestjs/common';
import { ToDo } from 'src/models/ToDo';
import { TodoService } from './todo.service';

@Controller('todo')
export class TodoController {
 constructor(private readonly todoService: TodoService) {}

 @Get(':id')
 get(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.get(params.id);
 }

 @Get('all')
 getAll(): Promise&amp;lt;ToDo[]&amp;gt; {
   return this.todoService.getAll();
 }

 @Post()
 create(@Body() body: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.create(body);
 }

 @Put()
 update(@Body() body: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.update(body);
 }

 @Put('inactive/:id')
 markAsInActive(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.markAsInActive(params.id);
 }

 @Delete()
 delete(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.delete(params.id);
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's start the application. This will start the application in port 3000.&lt;/p&gt;

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

&lt;p&gt;From here, the available endpoints are unknown. We can make use of another handy package, Swagger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Swagger
&lt;/h2&gt;

&lt;p&gt;Let’s start by adding the Swagger package.&lt;br&gt;
&lt;code&gt;npm install --save @nestjs/swagger&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can now modify the main.ts to include Swagger and point it to the main page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
 const app = await NestFactory.create(AppModule);

 const config = new DocumentBuilder()
   .setTitle('ToDo API')
   .setDescription('The REST API for ToDo application')
   .setVersion('1.0')
   .build();
 const document = SwaggerModule.createDocument(app, config);
 SwaggerModule.setup('/', app, document); // Pointing to the main page.

 await app.listen(3000);
 console.log(`ToDo API is running on: ${await app.getUrl()}`);
}
bootstrap();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can make a few more tweaks to clean up Swagger. The updated controller code will look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
 Body,
 Controller,
 Delete,
 Get,
 Param,
 Post,
 Put,
} from '@nestjs/common';
import { ApiBody, ApiParam, ApiTags } from '@nestjs/swagger';

import { ToDo } from 'src/models/ToDo';
import { TodoService } from './todo.service';

@ApiTags('ToDo')
@Controller('todo')
export class TodoController {
 constructor(private readonly todoService: TodoService) {}

 @Get(':id')
 @ApiParam({ name: 'id', required: true })
 get(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.get(params.id);
 }

 @Get('all')
 getAll(): Promise&amp;lt;ToDo[]&amp;gt; {
   return this.todoService.getAll();
 }

 @Post()
 @ApiBody({})
 create(@Body() body: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.create(body);
 }

 @Put()
 @ApiBody({})
 update(@Body() body: ToDo): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.update(body);
 }

 @Put('inactive/:id')
 @ApiParam({ name: 'id', required: true })
 markAsInActive(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.markAsInActive(params.id);
 }

 @Delete()
 @ApiParam({ name: 'id', required: true })
 delete(@Param() params: { id: string }): Promise&amp;lt;ToDo&amp;gt; {
   return this.todoService.delete(params.id);
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can run the app again.&lt;/p&gt;

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

&lt;p&gt;Now that we have a complete component with all the CRUD operations, we can continue creating more components in a similar fashion. The next stage would be to add authentication to protect the routes, add unit tests, validations, using middlewares and interceptors. There is much more that the Swagger is capable of, but all of that is for another day.&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/rohithart/nestjs-todo" rel="noopener noreferrer"&gt;https://github.com/rohithart/nestjs-todo&lt;/a&gt;&lt;br&gt;
NestJS Documentation: &lt;a href="https://docs.nestjs.com/" rel="noopener noreferrer"&gt;https://docs.nestjs.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>nestjs</category>
      <category>api</category>
    </item>
  </channel>
</rss>
