{"id":268,"date":"2024-06-11T17:50:00","date_gmt":"2024-06-11T17:50:00","guid":{"rendered":"https:\/\/andrearethy.com\/blog\/?p=268"},"modified":"2024-06-20T09:59:35","modified_gmt":"2024-06-20T09:59:35","slug":"how-to-set-up-your-first-typescript-project-with-tdd-and-ci-macos","status":"publish","type":"post","link":"https:\/\/andrearethy.com\/blog\/how-to-set-up-your-first-typescript-project-with-tdd-and-ci-macos\/","title":{"rendered":"How to set up your first TypeScript project with TDD and CI (MacOS)"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">Introduction<\/h3>\n\n\n\n<p>In last week&#8217;s article we looked into <a href=\"https:\/\/andrearethy.com\/blog\/how-to-design-and-build-a-portfolio-website-with-figma-html-css-and-javascript\/\" target=\"_blank\" rel=\"noopener\" title=\"\">how to create a basic portfolio website with HTML, CSS and JavaScript<\/a>. Unsurprisingly this portfolio website was a front-end project, with no real backend. Today we will dive into the beginning of backend development with TypeScript and Node.<\/p>\n\n\n\n<p>TypeScript, a superset of JavaScript, provides static type checking that helps catching errors early in the development process helping you to write clean, maintainable code. When combined with Test-Driven Development (TDD) and Continuous Integration (CI), you can ensure that your code is reliable, scalable, and easier to refactor.<\/p>\n\n\n\n<p>This guide will walk you through setting up your first TypeScript project using TDD with Jest and CI with GitHub Actions on a MacOS system with Apple Silicon. We&#8217;ll cover everything from initializing your project to running your tests in a CI pipeline.<\/p>\n\n\n\n<p>If you run into EACCES permission errors I recommend <a href=\"https:\/\/docs.npmjs.com\/resolving-eacces-permissions-errors-when-installing-packages-globally\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">reading this article about how to solve it<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Table of Contents<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"#setting-up-your-development-environment\">Setting Up Your Development Environment<\/a><\/li>\n\n\n\n<li><a href=\"#initializing-your-typescript-project\">Initializing Your TypeScript Project<\/a><\/li>\n\n\n\n<li><a href=\"#setting-up-tdd-with-jest\">Setting Up TDD with Jest<\/a><\/li>\n\n\n\n<li><a href=\"#writing-your-first-test\">Writing Your First Test<\/a><\/li>\n\n\n\n<li><a href=\"#setting-up-continuous-integration-with-github-actions\" title=\"\">Setting Up Continuous Integration with GitHub Actions<\/a><\/li>\n\n\n\n<li><a href=\"#running-your-ci-pipeline\">Running Your CI Pipeline<\/a><\/li>\n\n\n\n<li><a href=\"#conclusion\">Conclusion<\/a><\/li>\n\n\n\n<li><a href=\"#bonus\" title=\"\">Bonus: My Sample Project Setup<\/a><\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setting-up-your-development-environment\">Setting Up Your Development Environment<\/h3>\n\n\n\n<p>Before we start, make sure you have the following tools installed on your MacOS system:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Node.js and npm<\/li>\n\n\n\n<li>TypeScript<\/li>\n\n\n\n<li>Git<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Installing Node.js and npm<\/h4>\n\n\n\n<p>First, install <a href=\"https:\/\/nodejs.org\/en\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">Node.js<\/a>, which includes npm (<a href=\"https:\/\/docs.npmjs.com\/downloading-and-installing-node-js-and-npm\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">Node Package Manager<\/a>). We recommend using a version manager like&nbsp;<code>nvm<\/code> (Node Version Manager) to manage Node.js versions efficiently.<\/p>\n\n\n\n<p>Open your terminal and execute the following commands:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# If you don't have Homebrew installed start there\n\/bin\/bash -c &quot;$(curl -fsSL https:\/\/raw.githubusercontent.com\/Homebrew\/install\/HEAD\/install.sh)&quot;\n\n# Once brew is installed move on to nvm\nbrew install nvm\n\n# Add the following lines to your shell profile file (e.g., ~\/.bashrc, ~\/.zshrc, or ~\/.bash_profile):\nexport NVM_DIR=~\/.nvm\n[ -s &quot;$NVM_DIR\/nvm.sh&quot; ] &amp;&amp; \\. &quot;$NVM_DIR\/nvm.sh&quot;\n[ -s &quot;$NVM_DIR\/bash_completion&quot; ] &amp;&amp; \\. &quot;$NVM_DIR\/bash_completion&quot;\n\n# Restart your terminal and run this command\nsource ~\/.your_shell_profile\n\n# To install the latest version of node run this command\nnvm install --lts\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># If you don&#39;t have Homebrew installed start there<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">\/bin\/bash<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">-c<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&quot;$(<\/span><span style=\"color: #61AFEF\">curl<\/span><span style=\"color: #98C379\"> <\/span><span style=\"color: #D19A66\">-fsSL<\/span><span style=\"color: #98C379\"> https:\/\/raw.githubusercontent.com\/Homebrew\/install\/HEAD\/install.sh)&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Once brew is installed move on to nvm<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">brew<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">nvm<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Add the following lines to your shell profile file (e.g., ~\/.bashrc, ~\/.zshrc, or ~\/.bash_profile):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C678DD\">export<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #E06C75\">NVM_DIR<\/span><span style=\"color: #56B6C2\">=<\/span><span style=\"color: #98C379\">~\/.nvm<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">[ <\/span><span style=\"color: #56B6C2\">-s<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&quot;<\/span><span style=\"color: #E06C75\">$NVM_DIR<\/span><span style=\"color: #98C379\">\/nvm.sh&quot;<\/span><span style=\"color: #ABB2BF\"> ] &amp;&amp; <\/span><span style=\"color: #61AFEF\">\\.<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&quot;<\/span><span style=\"color: #E06C75\">$NVM_DIR<\/span><span style=\"color: #98C379\">\/nvm.sh&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">[ <\/span><span style=\"color: #56B6C2\">-s<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&quot;<\/span><span style=\"color: #E06C75\">$NVM_DIR<\/span><span style=\"color: #98C379\">\/bash_completion&quot;<\/span><span style=\"color: #ABB2BF\"> ] &amp;&amp; <\/span><span style=\"color: #61AFEF\">\\.<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&quot;<\/span><span style=\"color: #E06C75\">$NVM_DIR<\/span><span style=\"color: #98C379\">\/bash_completion&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Restart your terminal and run this command<\/span><\/span>\n<span class=\"line\"><span style=\"color: #56B6C2\">source<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">~\/.your_shell_profile<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># To install the latest version of node run this command<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">nvm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">--lts<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>If you receive an error for EACCES probably you have to use the &#8216;sudo&#8217; keyword (superuser do) before the command. This will prompt for you to enter your password. Type out your password and hit enter. It will look like you are not writing, just trust the process and hit enter at the end.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Installing TypeScript<\/h4>\n\n\n\n<p>Next, install <a href=\"https:\/\/www.typescriptlang.org\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">TypeScript<\/a> globally using npm.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# globally install to use typescript cli\nnpm install typescript -g\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># globally install to use typescript cli<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">typescript<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">-g<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Installing Git<\/h4>\n\n\n\n<p>If you haven&#8217;t already installed <a href=\"https:\/\/www.git-scm.com\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">Git<\/a>, you can do so using Homebrew:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Install Git\nbrew install git\n\n# Verify installation\ngit --version\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Install Git<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">brew<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">git<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Verify installation<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">--version<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"initializing-your-typescript-project\">Initializing Your TypeScript Project<\/h3>\n\n\n\n<p>Create a new directory for your TypeScript project and initialize it with npm. Open your terminal, navigate to the parent directory of where your project will live, and execute the following commands:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Create a new folder\nmkdir my-typescript-project\n\n# Change to that new folder\ncd my-typescript-project\n\n# Initialize node\nnpm init -y\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Create a new folder<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">mkdir<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">my-typescript-project<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Change to that new folder<\/span><\/span>\n<span class=\"line\"><span style=\"color: #56B6C2\">cd<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">my-typescript-project<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Initialize node<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">init<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">-y<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This will create a&nbsp;<code>package.json<\/code>&nbsp;file in your project directory. Next, install TypeScript and initialize a TypeScript configuration file. Remember to use the &#8216;sudo&#8217; keyword in front of your command if you run into EACCES errors.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Install TypeScript locally in your project\nnpm install typescript --save-dev\n\n# Initialize a TypeScript configuration file\nnpx tsc --init\n\n# Create source (for ts files) and distribution (for js files) folders\nmkdir src\nmkdir dist\n\n# Add script.ts\ntouch src\/script.ts\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Install TypeScript locally in your project<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">typescript<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">--save-dev<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Initialize a TypeScript configuration file<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">npx<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">tsc<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">--init<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Create source (for ts files) and distribution (for js files) folders<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">mkdir<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">src<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">mkdir<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">dist<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Add script.ts<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">touch<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">src\/script.ts<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The&nbsp;<code>tsc --init<\/code>&nbsp;command creates a&nbsp;<code>tsconfig.json<\/code>&nbsp;file with default settings. You can customize this file to suit your project&#8217;s needs.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Initialize git version control\ngit init\n\n# Add .gitignore\nnpx gitignore node\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Initialize git version control<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">init<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Add .gitignore<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">npx<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">gitignore<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">node<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setting-up-tdd-with-jest\">Setting Up TDD with Jest<\/h3>\n\n\n\n<p><a href=\"https:\/\/jestjs.io\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">Jest<\/a> is a popular testing framework for JavaScript and TypeScript projects. We&#8217;ll use it to write and run our tests following the <a href=\"https:\/\/testdriven.io\/test-driven-development\/\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">TDD methodology<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Installing Jest<\/h4>\n\n\n\n<p>First, install Jest and its TypeScript support packages. Using the &#8211;save-dev flag we indicate that these packages need to be installed as a development dependency.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"npm install --save-dev typescript jest ts-jest @types\/jest\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">--save-dev<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">typescript<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">jest<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">ts-jest<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">@types\/jest<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>If you get an error similar to this: ERESOLVE unable to resolve dependency tree:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/andrearethy.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-10-at-11.34.13.webp\" alt=\"\" class=\"wp-image-304\"\/><\/figure>\n\n\n\n<p>Then probably it is due to a dependency conflict between the versions of&nbsp;<code>jest<\/code>&nbsp;and&nbsp;<code>ts-jest<\/code>&nbsp;you&#8217;re trying to install. For example &#8216;<code>ts-jest@29.1.4<\/code>&#8216;&nbsp;expects&nbsp;&#8216;<code>jest@^29.0.0<\/code>&#8216;, but for some reason, it&#8217;s not able to find a compatible version. This is a common issue in the JavaScript ecosystem, especially when using the latest versions of packages or when the package maintainers haven&#8217;t yet synchronized their dependency versions.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# This flag tells npm to ignore peer dependency conflicts and install the packages anyway:\nnpm install --save-dev jest ts-jest @types\/jest --legacy-peer-deps\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># This flag tells npm to ignore peer dependency conflicts and install the packages anyway:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">--save-dev<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">jest<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">ts-jest<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">@types\/jest<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">--legacy-peer-deps<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Configuring Jest<\/h4>\n\n\n\n<p>Create a Jest configuration file to enable TypeScript support.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"npx ts-jest config:init\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #61AFEF\">npx<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">ts-jest<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">config:init<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Open your project in VS Code. <a href=\"https:\/\/code.visualstudio.com\/docs\/setup\/mac\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">If you need to set up VS Code or the code . command visit this link.<\/a><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Open your project in your code editor\ncode .\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Open your project in your code editor<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">code<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ In your jest.config.js file:\nmodule.exports = {\n  preset: 'ts-jest',\n  testEnvironment: 'node',\n};\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\">\/\/ In your jest.config.js file:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E5C07B\">module<\/span><span style=\"color: #ABB2BF\">.<\/span><span style=\"color: #E5C07B\">exports<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #56B6C2\">=<\/span><span style=\"color: #ABB2BF\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">preset<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&#39;ts-jest&#39;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">testEnvironment<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&#39;node&#39;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">};<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Adding Scripts to&nbsp;<code>package.json<\/code><\/h4>\n\n\n\n<p>Add scripts to your&nbsp;<code>package.json<\/code>&nbsp;file to run Jest easily.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"{\n  &quot;scripts&quot;: {\n    &quot;test&quot;: &quot;jest&quot;,\n    &quot;test:watch&quot;: &quot;jest --watch&quot;,\n    &quot;build&quot;: &quot;tsc&quot;\n  }\n}\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #ABB2BF\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">&quot;scripts&quot;<\/span><span style=\"color: #ABB2BF\">: {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;test&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;jest&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;test:watch&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;jest --watch&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;build&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;tsc&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Optional step: Update your tsconfig.json. As of writing this article my usual settings are as follow:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"{\n  &quot;compilerOptions&quot;: {\n    &quot;target&quot;: &quot;ES6&quot;,\n    &quot;module&quot;: &quot;commonjs&quot;,\n    &quot;outDir&quot;: &quot;.\/dist&quot;,\n    &quot;rootDir&quot;: &quot;.\/src&quot;,\n    &quot;strict&quot;: true,\n    &quot;esModuleInterop&quot;: true,\n    &quot;allowImportingTsExtensions&quot;: true,\n    &quot;noEmit&quot;: true,\n  },\n  &quot;include&quot;: [&quot;.\/src\/**\/*.ts&quot;],\n  &quot;exclude&quot;: [&quot;node_modules&quot;, &quot;dist&quot;]\n}\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #ABB2BF\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">&quot;compilerOptions&quot;<\/span><span style=\"color: #ABB2BF\">: {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;target&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;ES6&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;module&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;commonjs&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;outDir&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;.\/dist&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;rootDir&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;.\/src&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;strict&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #D19A66\">true<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;esModuleInterop&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #D19A66\">true<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;allowImportingTsExtensions&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #D19A66\">true<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;noEmit&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #D19A66\">true<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  },<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">&quot;include&quot;<\/span><span style=\"color: #ABB2BF\">: [<\/span><span style=\"color: #98C379\">&quot;.\/src\/**\/*.ts&quot;<\/span><span style=\"color: #ABB2BF\">],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">&quot;exclude&quot;<\/span><span style=\"color: #ABB2BF\">: [<\/span><span style=\"color: #98C379\">&quot;node_modules&quot;<\/span><span style=\"color: #ABB2BF\">, <\/span><span style=\"color: #98C379\">&quot;dist&quot;<\/span><span style=\"color: #ABB2BF\">]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"writing-your-first-test\">Writing Your First Test<\/h3>\n\n\n\n<p>With Jest configured, let&#8217;s write our first test using the TDD approach. Create a directory for your tests and add a sample test file.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# go back to the project directory first\nmkdir tests\ntouch tests\/script.test.ts\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># go back to the project directory first<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">mkdir<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">tests<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">touch<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">tests\/script.test.ts<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Open&nbsp;<code>tests\/sample.test.ts<\/code> in VS Code&nbsp;and add the following test:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ tests\/script.test.ts\ndescribe('Sample Test', () =&gt; {\n  it('should return true', () =&gt; {\n    expect(true).toBe(true);\n  });\n});\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\">\/\/ tests\/script.test.ts<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">describe<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #98C379\">&#39;Sample Test&#39;<\/span><span style=\"color: #ABB2BF\">, () <\/span><span style=\"color: #C678DD\">=&gt;<\/span><span style=\"color: #ABB2BF\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #61AFEF\">it<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #98C379\">&#39;should return true&#39;<\/span><span style=\"color: #ABB2BF\">, () <\/span><span style=\"color: #C678DD\">=&gt;<\/span><span style=\"color: #ABB2BF\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #61AFEF\">expect<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #D19A66\">true<\/span><span style=\"color: #ABB2BF\">).<\/span><span style=\"color: #61AFEF\">toBe<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #D19A66\">true<\/span><span style=\"color: #ABB2BF\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  });<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">});<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Run your test using the following command:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"npm test\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">test<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>You should see the test pass successfully. This simple test ensures that your Jest setup is working correctly.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/andrearethy.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-10-at-13.09.23.webp\" alt=\"\" class=\"wp-image-315\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setting-up-continuous-integration-with-github-actions\">Setting Up Continuous Integration with GitHub Actions<\/h3>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 26%\"><div class=\"wp-block-media-text__content\">\n<p class=\"has-text-align-left\"><a href=\"https:\/\/docs.github.com\/en\/actions\/automating-builds-and-tests\/about-continuous-integration\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">Continuous Integration (CI)<\/a> automates the process of running tests and other checks whenever you push code to your repository. GitHub Actions is a powerful CI tool that integrates seamlessly with GitHub.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/andrearethy.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-09-at-22.57.46.webp\" alt=\"\" class=\"wp-image-294 size-full\"\/><\/figure><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Creating a GitHub Repository<\/h4>\n\n\n\n<p>If you haven&#8217;t already, create a new repository on GitHub for your project. Choosing the repository settings: If your project is for learning purposes or to showcase your knowledge select public. If this is for your million dollar app, definitely choose private. Initialize it without a README file (you can add this later) and push your existing repository (the one we just created above).<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# First commit your existing changes to the local git repository\ngit add .\ngit commit -m &quot;Initial commit&quot;\n\n# You can copy the exact lines from GitHub\ngit remote add origin https:\/\/github.com\/your-username\/my-typescript-project.git # Replace with your GitHub username and repository name\ngit branch -M main\ngit push -u origin main\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># First commit your existing changes to the local git repository<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">add<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">commit<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">-m<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&quot;Initial commit&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># You can copy the exact lines from GitHub<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">remote<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">add<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">origin<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">https:\/\/github.com\/your-username\/my-typescript-project.git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #7F848E; font-style: italic\"># Replace with your GitHub username and repository name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">branch<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">-M<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">push<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">-u<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">origin<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">main<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Create a Personal Access Token with the&nbsp;<code>workflow<\/code>&nbsp;scope<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Go to&nbsp;<a href=\"https:\/\/github.com\/settings\/tokens\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">GitHub settings<\/a>.<\/li>\n\n\n\n<li>Click on&nbsp;<strong>Generate new token<\/strong>.<\/li>\n\n\n\n<li>Provide a&nbsp;<strong>note<\/strong>&nbsp;to remind you what the token is for.<\/li>\n\n\n\n<li>Select the&nbsp;<strong>expiration<\/strong>&nbsp;for the token.<\/li>\n\n\n\n<li>Under&nbsp;<strong>Select scopes<\/strong>, check the box for&nbsp;<code>workflow<\/code>&nbsp;and any other scopes you might need.<\/li>\n\n\n\n<li>Click on&nbsp;<strong>Generate token<\/strong>.<\/li>\n\n\n\n<li>Copy the token. Make sure to store it safely as you won&#8217;t be able to see it again.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Update your repository\u2019s remote URL to use the new token<\/strong>:<ul><li>Open your terminal.Navigate to your repository.Update the remote URL to use the new token<\/li><\/ul><\/li>\n\n\n\n<li><strong>Push your changes again<\/strong><\/li>\n<\/ol>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Replace\u00a0&lt;TOKEN&gt;,\u00a0&lt;USERNAME&gt;, and\u00a0&lt;REPOSITORY&gt;\u00a0with your actual token, GitHub username, and repository name respectively.\n# Example (obviously with fake token): git remote set-url origin https:\/\/dfh34209rggn0myfaketoken0vf82opi32fn@github.com\/AndreaRethy\/TypeScriptSetup.git\ngit remote set-url origin https:\/\/&lt;TOKEN&gt;@github.com\/&lt;USERNAME&gt;\/&lt;REPOSITORY&gt;.git\n\n# Push changes\ngit push origin main\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Replace\u00a0&lt;TOKEN&gt;,\u00a0&lt;USERNAME&gt;, and\u00a0&lt;REPOSITORY&gt;\u00a0with your actual token, GitHub username, and repository name respectively.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Example (obviously with fake token): git remote set-url origin https:\/\/dfh34209rggn0myfaketoken0vf82opi32fn@github.com\/AndreaRethy\/TypeScriptSetup.git<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">remote<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">set-url<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">origin<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">https:\/\/<\/span><span style=\"color: #ABB2BF\">&lt;<\/span><span style=\"color: #98C379\">TOKE<\/span><span style=\"color: #ABB2BF\">N&gt;<\/span><span style=\"color: #98C379\">@github.com\/<\/span><span style=\"color: #ABB2BF\">&lt;<\/span><span style=\"color: #98C379\">USERNAM<\/span><span style=\"color: #ABB2BF\">E&gt;<\/span><span style=\"color: #98C379\">\/<\/span><span style=\"color: #ABB2BF\">&lt;<\/span><span style=\"color: #98C379\">REPOSITOR<\/span><span style=\"color: #ABB2BF\">Y&gt;<\/span><span style=\"color: #98C379\">.git<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Push changes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">push<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">origin<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">main<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>If the above steps are followed correctly, you should be able to push your changes to GitHub without encountering the&nbsp;<code>refusing to allow a Personal Access Token to create or update workflow<\/code>&nbsp;error.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Adding a GitHub Actions Workflow<\/h4>\n\n\n\n<p>Create a directory for your GitHub Actions workflows.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"mkdir -p .github\/workflows\ntouch .github\/workflows\/main.yml\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #61AFEF\">mkdir<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">-p<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">.github\/workflows<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">touch<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">.github\/workflows\/main.yml<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Open&nbsp;<code>.github\/workflows\/main.yml<\/code>&nbsp;and add the following content:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"name: Test\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions\/checkout@v4\n    - name: Install dependencies\n      run: npm install\n    - name: Run tests\n      run: npm test\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #E06C75\">name<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">Test<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D19A66\">on<\/span><span style=\"color: #ABB2BF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">push<\/span><span style=\"color: #ABB2BF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">branches<\/span><span style=\"color: #ABB2BF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">      - <\/span><span style=\"color: #98C379\">main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">pull_request<\/span><span style=\"color: #ABB2BF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">branches<\/span><span style=\"color: #ABB2BF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">      - <\/span><span style=\"color: #98C379\">main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E06C75\">jobs<\/span><span style=\"color: #ABB2BF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">test<\/span><span style=\"color: #ABB2BF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">runs-on<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">ubuntu-latest<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">steps<\/span><span style=\"color: #ABB2BF\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    - <\/span><span style=\"color: #E06C75\">uses<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">actions\/checkout@v4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    - <\/span><span style=\"color: #E06C75\">name<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">Install dependencies<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">      <\/span><span style=\"color: #E06C75\">run<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">npm install<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    - <\/span><span style=\"color: #E06C75\">name<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">Run tests<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">      <\/span><span style=\"color: #E06C75\">run<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">npm test<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This configuration sets up a CI workflow that runs on every push and pull request to the&nbsp;<code>main<\/code>&nbsp;branch. It uses the latest Ubuntu runner, checks out your code, installs dependencies, and runs your tests.<\/p>\n\n\n\n<p>Warning: YAML is similar to JSON, but instead of curly brackets {} it uses spaces   and instead of brackets [] for arrays it uses dashes &#8211; If the indentation is not correct, it will throw errors.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Pushing Changes to GitHub<\/h4>\n\n\n\n<p>Commit your changes and push them to your GitHub repository.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"git add .\n# message for this specific commit\ngit commit -m &quot;Set up TypeScript project with TDD and CI&quot;\ngit push origin main\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">add<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># message for this specific commit<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">commit<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">-m<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&quot;Set up TypeScript project with TDD and CI&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">push<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">origin<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">main<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"running-your-ci-pipeline\">Running Your CI Pipeline<\/h3>\n\n\n\n<p>Once you&#8217;ve pushed your changes, navigate to the &#8220;Actions&#8221; tab of your GitHub repository. You should see your workflow running. If everything is set up correctly, the workflow should pass, indicating that your tests ran successfully in the CI environment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h3>\n\n\n\n<p>Setting up a TypeScript project with TDD and CI can significantly improve your development workflow, ensuring that your code is reliable and maintainable. By following this guide, you&#8217;ve learned how to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set up your development environment on MacOS with Apple Silicon<\/li>\n\n\n\n<li>Initialize a TypeScript project<\/li>\n\n\n\n<li>Configure Jest for TDD<\/li>\n\n\n\n<li>Write and run tests<\/li>\n\n\n\n<li>Set up a CI pipeline with GitHub Actions<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"bonus\">Bonus: My Sample Project Setup<\/h4>\n\n\n\n<p>I recommend following the above steps at least once, but for further projects here is an empty setup to speed up the kick off: <a href=\"https:\/\/github.com\/AndreaRethy\/TypeScriptSetup.git\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">Empty TypeScript Project<\/a>. You can copy this project to your library, rename the folder and run these three commands:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Install node packages from dev dependencies\nnpm install\n\n# Initialize a new git repository\ngit init\n\n# If you used git clone to copy the project:\ngit remote remove origin\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Install node packages from dev dependencies<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Initialize a new git repository<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">init<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># If you used git clone to copy the project:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">git<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">remote<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">remove<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">origin<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>After this you can continue with <a href=\"#setting-up-continuous-integration-with-github-actions\" title=\"\">Setting Up Continuous Integration with GitHub Actions<\/a>. YAML is already included in the example project so you can skip that step.<\/p>\n\n\n\n<p>With these tools in place, you&#8217;re well-equipped to develop high-quality TypeScript applications. Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This guide will walk you through setting up your first TypeScript project using TDD with Jest and CI with GitHub Actions on a MacOS system with Apple Silicon.<\/p>\n","protected":false},"author":1,"featured_media":316,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_siteseo_robots_primary_cat":"none","footnotes":""},"categories":[40],"tags":[45,48,29,53,49,28,52,43,56,50,44,47,55,46,54,22],"class_list":["post-268","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guide","tag-ci","tag-continuous-integration","tag-freelance-webdevelopment","tag-git","tag-github-actions","tag-guide","tag-jest","tag-node-js","tag-npm","tag-set-up-a-typescript-project","tag-tdd","tag-test-driven-development","tag-testing","tag-typescript","tag-version-control","tag-webdevelopment"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/posts\/268","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/comments?post=268"}],"version-history":[{"count":39,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/posts\/268\/revisions"}],"predecessor-version":[{"id":363,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/posts\/268\/revisions\/363"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/media\/316"}],"wp:attachment":[{"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/media?parent=268"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/categories?post=268"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/tags?post=268"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}