<?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: Maximilian</title>
    <description>The latest articles on DEV Community by Maximilian (@kaxmoglan).</description>
    <link>https://dev.to/kaxmoglan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F556761%2F9a60c833-c220-4175-b86b-11f886eba927.jpg</url>
      <title>DEV Community: Maximilian</title>
      <link>https://dev.to/kaxmoglan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kaxmoglan"/>
    <language>en</language>
    <item>
      <title>How to solve the 2 crystal balls problem in JS</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Wed, 13 Mar 2024 21:53:05 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/how-to-solve-the-2-crystal-balls-problem-in-js-9hm</link>
      <guid>https://dev.to/kaxmoglan/how-to-solve-the-2-crystal-balls-problem-in-js-9hm</guid>
      <description>&lt;p&gt;The 2 crystal balls (or the 2 balls, or the 2 glass balls, or the 2 eggs, or the 2 fragile things) problem is a maths challenge that goes like this:&lt;/p&gt;

&lt;p&gt;Given I have two crystal balls and a building with &lt;code&gt;n&lt;/code&gt; number of floors, find out the maximum height from which a ball can be dropped without breaking.&lt;/p&gt;

&lt;p&gt;In other words, find the first floor that a ball will smash if dropped from.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's define our assumptions and constraints
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The balls' integrity does not diminish when dropped&lt;/li&gt;
&lt;li&gt;Don't break both balls before you've found out which floor will break them&lt;/li&gt;
&lt;li&gt;The floors will be represented by a boolean array, where false represents a floor that won't smash our ball and true represents a floor that will smash our ball. E.g. &lt;code&gt;[false, false, false, false, true, true, true, true]&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Our plan
&lt;/h2&gt;

&lt;p&gt;If we only had 1 ball, we would only have one option: we'd have to drop the ball from each floor until it smashed. Doing it any other way to improve our running time would mean the ball would smash before we could determine the exact floor that would smash it. Doing it in this way would be linear time, or &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because we have 2 balls (cough), we can get a much better running time. Our plan is to use the first ball to walk the array in chunks and if our ball smashes, then we use our 2nd ball to walk the array from the start of the previous chunk to our known breakage point. The 'chunk' unit we'll use (I'll explain why at the end) is the &lt;code&gt;sqrt(n)&lt;/code&gt; where &lt;code&gt;n&lt;/code&gt; is the length of our array.&lt;/p&gt;

&lt;p&gt;So, our plan is to walk the array with our first ball by &lt;code&gt;sqrt(n)&lt;/code&gt;, and if our ball breaks, we go back by &lt;code&gt;sqrt(n)&lt;/code&gt; and walk the array with our 2nd ball linearly until that one breaks.&lt;/p&gt;

&lt;p&gt;Let's explain with some pseudo code...&lt;/p&gt;

&lt;h2&gt;
  
  
  Some psuedo code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jumpAmount = square root of array length

i = jumpAmount

loop from i while i &amp;lt; array.length
    if array[i] = smash
        exit loop
    increment i by jumpAmount

decrement i by jumpAmount

loop from 0 to jumpAmount
    if (array[i]) = smash
        return i

return no smash

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// function takes in a boolean array and returns the&lt;/span&gt;
&lt;span class="c1"&gt;// index at which a ball will smash, or -1&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;twoCrystalBalls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// define our jump / chunk amount as the square root&lt;/span&gt;
    &lt;span class="c1"&gt;// of the array length&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jumpAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// loop through array starting with our jumpAmount&lt;/span&gt;
    &lt;span class="c1"&gt;// and increment by our jumpAmount&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jumpAmount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;floors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;jumpAmount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// if we find a floor where the ball smashes&lt;/span&gt;
        &lt;span class="c1"&gt;// break out the loop&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// decrement our iterator by our jumpAmount&lt;/span&gt;
    &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;jumpAmount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// walk the array linearly from i&lt;/span&gt;
    &lt;span class="c1"&gt;// a maximum of [jumpAmount] times&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;jumpAmount&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;floors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;floors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if we find the floor that breaks our ball&lt;/span&gt;
            &lt;span class="c1"&gt;// return the index&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// the ball didn't smash so return -1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Time complexity
&lt;/h2&gt;

&lt;p&gt;The biggest question I had with this algorithm was, 'why divide the array by its square root, why not divide in half, or by 10?'. WELL... it's because, if we divided by a fraction, for example 0.25, then our time complexity would be &lt;code&gt;O(1/2n)&lt;/code&gt;, in which case, we drop our constants so our running time would be &lt;code&gt;O(n)&lt;/code&gt; which takes us back to linear time. By dividing the array by its square root, our time complexity becomes &lt;code&gt;O(sqrt(n))&lt;/code&gt;. Neat huh? 🤓&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Quick Sort Algorithm</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Tue, 12 Mar 2024 22:47:39 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/the-quick-sort-algorithm-2anl</link>
      <guid>https://dev.to/kaxmoglan/the-quick-sort-algorithm-2anl</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I recently took a data structures and algorithms course as part of my pursuit to learn lower level programming and computer science concepts. As the saying goes, the best way of solidifying your knowledge in something is to teach it, and since I've already filled my quota for boring my partner with coding talk for the month (probably the year), I thought I'd write a series of posts with some of the things I've learned. This is one such post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Quick Sort Algorithm?
&lt;/h2&gt;

&lt;p&gt;The Quick Sort algorithm is another example of a 'divide and conquer' algorithm that takes an un-sorted array and, you guessed it, sorts it! It works by selecting a pivot (usually the last element in the array) and then adding the remaining elements in the array to 2 sub-arrays - 1 that will contain all the elements smaller than the pivot, and the other that will contain the elements greater than, or equal to, the pivot. We then recurse this step on the sub arrays until the entire array is sorted. This algorithm has an average time complexity of &lt;code&gt;O(nlogn)&lt;/code&gt; but its worst case is &lt;code&gt;O(n^2)&lt;/code&gt; when the array is already sorted but in reverse order.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work
&lt;/h2&gt;

&lt;p&gt;To explain how it works, here's some pseudo-code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pivot = arr.length -1
smallerItems = []
largerItems = []

for element in array to sort:
    if element &amp;lt; pivot
        add to smallerItems
    else
        add to largerItems

sort(smallerItems)
sort(largerItems)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How do we implement it
&lt;/h2&gt;

&lt;p&gt;Here's a heavily commented implementation in Typescript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// base case&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// select our pivot -- the last element in the array&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// create 2 sub-arrays&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leftArr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rightArr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="c1"&gt;// loop through the array&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// if the current item is less than the value of our pivot&lt;/span&gt;
        &lt;span class="c1"&gt;// add the item to our leftArr, otherwise, add it to our&lt;/span&gt;
        &lt;span class="c1"&gt;// rightArr&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;leftArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;rightArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// repeat/recurse this process for our sub arrays&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leftArr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rightArr&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  An alternative implementation
&lt;/h2&gt;

&lt;p&gt;Whilst the above implementation works, it would be pretty costly when it comes to memory as the input array scales. An alternative way of writing this function, is to split it up into 3 parts and sort our array inline without the need to create any additional arrays. Let's see what this looks like...&lt;/p&gt;

&lt;p&gt;First, let's define our interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll create a function that gets our pivot index and handles our recursion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pivotIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pivotIndex&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pivotIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we'll create our third function which manages 3 pointers - our pivot, our index (which starts at -1), and the item we're currently checking (current). Current walks through the array, and if the item is less than or equal to our pivot, we increment the index and swap the items located at index and current. At the end of our iteration, we increment our index and swap the items at our index and pivot, then we return the index. Here's what that function looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// set our pivot to the end of the array&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// set out index to the start of the array -1&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// loop through our array&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// if the item is less than or equal to the pivot&lt;/span&gt;
        &lt;span class="c1"&gt;// increment the index, then swap it with the item&lt;/span&gt;
        &lt;span class="c1"&gt;// at the index&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// after we've finished walking the array,&lt;/span&gt;
    &lt;span class="c1"&gt;// increment the index, then swap the item&lt;/span&gt;
    &lt;span class="c1"&gt;// at the pivot with the item at the index&lt;/span&gt;
    &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;

    &lt;span class="c1"&gt;// return the index&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, now let's put it all together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;pivot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pivotIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pivotIndex&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pivotIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;quickSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>typescript</category>
      <category>learning</category>
    </item>
    <item>
      <title>The Binary Search Algorithm</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Mon, 11 Mar 2024 22:11:20 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/the-binary-search-algorithm-51ao</link>
      <guid>https://dev.to/kaxmoglan/the-binary-search-algorithm-51ao</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I recently took a data structures and algorithms course as part of my pursuit to learn lower level programming and computer science concepts. As the saying goes, the best way of solidifying your knowledge in something is to teach it, and since I've already filled my quota for boring my partner with coding talk for the month (probably the year), I thought I'd write a series of posts with some of the things I've learned. This is one such post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Binary Search Algorithm
&lt;/h2&gt;

&lt;p&gt;The binary search algorithm is an efficient way of returning the index of a given value in a sorted array. It has a worst-case time complexity of &lt;code&gt;O(log n)&lt;/code&gt; where the element does not exist and a best-case time complexity of &lt;code&gt;O(1)&lt;/code&gt; where the value we're searching for happens to be the first one we check!&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work
&lt;/h2&gt;

&lt;p&gt;The idea behind the binary search algorithm is to divide and conquer. First, we check the mid point in the array. If the mid point is equal to the value we're looking for, we return the value. Otherwise, we divide the array in half and continue to look in the appropriate half and repeat the process. Remember, this only works on a sorted array.&lt;/p&gt;

&lt;p&gt;Let's write some pseudo-code where &lt;code&gt;v&lt;/code&gt; = the &lt;code&gt;value&lt;/code&gt; we're looking for to further this explanation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lo = 0
hi = arr.length
mid = (lo + hi) / 2

while lo &amp;lt; hi
    if mid = v
        we found it!

    if mid &amp;gt; v
        hi = mid

    if mid &amp;lt; v
        lo = mid

we didn't find it :(

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have 3 pointers; &lt;code&gt;lo&lt;/code&gt; (set to the 1st element of the array), &lt;code&gt;mid&lt;/code&gt; (set to the middle point of the array) and &lt;code&gt;hi&lt;/code&gt; (set to the length of the array). We check the value of &lt;code&gt;mid&lt;/code&gt;; if &lt;code&gt;mid&lt;/code&gt; is the value we're looking for, then we're done! If &lt;code&gt;mid&lt;/code&gt; is greater than our value, this means that the value we're looking for (if it exists) will be in the left half of our array. At this point, we move our &lt;code&gt;hi&lt;/code&gt; pointer down to where our &lt;code&gt;mid&lt;/code&gt; pointer is and we start the process again. If, however, &lt;code&gt;mid&lt;/code&gt; is &lt;strong&gt;less&lt;/strong&gt; than our value, then we move our &lt;code&gt;lo&lt;/code&gt; pointer &lt;strong&gt;up&lt;/strong&gt; to where our &lt;code&gt;mid&lt;/code&gt; pointer is, and we start the process again.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we implement it
&lt;/h2&gt;

&lt;p&gt;Here's some heavily commented Typescript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;binarySearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; 
  &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// we can exclude mid as we've already checked it&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation obviously uses a do-while loop, but you can get the job done with any kind of loop, really. Alternatively, this is a good place to use recursion. Here's what a recursive version might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;binarySearchRecursive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Base case&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// We found it!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// recurse - search in the right half&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;binarySearchRecursive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// recurse - search in the left half&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;binarySearchRecursive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  I think we're done here
&lt;/h3&gt;

&lt;p&gt;That's it for our binary search algorithm. I hope you found it useful or, at least, interesting!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>learning</category>
      <category>typescript</category>
    </item>
    <item>
      <title>The Bubble Sort Algorithm</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Tue, 05 Mar 2024 22:46:27 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/the-bubble-sort-algorithm-2f47</link>
      <guid>https://dev.to/kaxmoglan/the-bubble-sort-algorithm-2f47</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I recently took a data structures and algorithms course as part of my pursuit to learn lower level programming and computer science concepts. As the saying goes, the best way of solidifying your knowledge in something is to teach it, and since I've already filled my quota for boring my partner with coding talk for the month (probably the year), I thought I'd write a series of posts with some of the things I've learned. This is one such post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Bubble Sort Algorithm
&lt;/h2&gt;

&lt;p&gt;The Bubble Sort algorithm is typically applied where simplicity is favoured over efficiency. It has a time complexity of &lt;code&gt;O(n^2)&lt;/code&gt; which is less than ideal when dealing with larger lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work
&lt;/h2&gt;

&lt;p&gt;To explain how it works, here's some pseudo-code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for pointer1 in list
    for pointer2 in list
        if list[j] &amp;gt; list[j + 1]
            swap list[j] and list[j + 1]
        pointer2++

    pointer1++

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea of this algorithm is to 'bubble up' the larger items in the list to the end. We can think of this with 2 pointers, &lt;code&gt;pointer1&lt;/code&gt; and &lt;code&gt;pointer2&lt;/code&gt;. We start by setting both pointers to the first item in the list. We then go through the entire list with &lt;code&gt;pointer2&lt;/code&gt; and swap the item at &lt;code&gt;pointer2&lt;/code&gt;'s position if the item at position &lt;code&gt;pointer2 + 1&lt;/code&gt; is greater in value. We keep repeating this process until we reach the end of the list. We then move &lt;code&gt;pointer1&lt;/code&gt; up by 1 and we start the process again with &lt;code&gt;pointer2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You may have noticed that we need a way of avoiding checking items that we have already sorted. Seeing as the aim of each iteration is to move the larger items to the end of the list, we can do this by limiting the boundary of &lt;code&gt;pointer2&lt;/code&gt; by the value of &lt;code&gt;pointer1 + 1&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we implement it
&lt;/h2&gt;

&lt;p&gt;Here's a heavily commented implementation in Typescript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// pointer 1&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
       &lt;span class="c1"&gt;// pointer 2 + limit iterations by pointer1 + 1&lt;/span&gt;
        &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// check if current item is larger than the next item&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// temporarily store the current item so we don't lose it&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
                &lt;span class="c1"&gt;// swap the items in the array&lt;/span&gt;
                &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
                &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sorted
&lt;/h2&gt;

&lt;p&gt;This isn't a likely go-to algorithm in most cases, but I think it's a nice and easy one to get started. I hope you found it useful or, at least, a little bit interesting!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>How To Mock MongoDB's ObjectID</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Sat, 28 Oct 2023 01:58:37 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/how-to-mock-mongodbs-objectid-5fei</link>
      <guid>https://dev.to/kaxmoglan/how-to-mock-mongodbs-objectid-5fei</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR; the 2nd code block is how you do it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I updated a service method such that it created a Mongo ID before sending it to the DB instead of relying on the DB to do it for me. There are a few reasons why you might want to do this, in my case, it was because I was linking 2 things together, so instead of running 2 mutations (the 1st to create the linked item and get back the created ID, and the 2nd to add the new ID to the item I was linking from), I created the new IDs in my method, linked the 2 together and sent them off on their merry way in one happy mutation.&lt;/p&gt;

&lt;p&gt;I needed to write a unit test that ensured the created ID was correctly added as the ID on the linked item as well as the item it was linked from, but without mocking, we would have no way of knowing what ID would be created and so could not check that the correct ID existed in the right places. &lt;/p&gt;

&lt;p&gt;Simplified, here's the code we're testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LinkedItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;itemId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// MongoId&lt;/span&gt;
  &lt;span class="nl"&gt;newItemId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// temp ID used to identify new items that don't yet have an ID&lt;/span&gt;
  &lt;span class="nl"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Whatever&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;linkedItems&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LinkedItem&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;saveItemsToDb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create Mongo ID if one doesn't exist&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputsWithIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; 
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; 
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Update the linked items to include the new IDs&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputsWithUpdatedLinks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputsWithIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;linkedItems&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;linkedItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;updatedLinkedItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LinkedItem&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;linkedItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkedItemInput&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkedItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputsWithIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;inputWithId&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;inputWithId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;linkedItemInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;itemId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
          &lt;span class="nx"&gt;inputWithId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newItemId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;linkedItemInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;itemId&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkedItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkedItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;updatedLinkedItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;itemId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linkedItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the input with the updated links&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;linkedItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;updatedLinkedItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="c1"&gt;// Save the updated inputs to the DB&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputsWithUpdatedLinks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's a simplified section of the unit tests with the mocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;NEW_ID_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;NEW_ID_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;mockItemsToSave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;mockSavedItems&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./testData&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Item service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;jest&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toString&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mockReturnValueOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NEW_ID_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mockReturnValueOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NEW_ID_2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;restoreAllMocks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;links new items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;saveItemsToDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockItemsToSave&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockSavedItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using &lt;code&gt;jest.spyOn()&lt;/code&gt; we can watch for when &lt;code&gt;ObjectId().toString()&lt;/code&gt; gets called and override its return value so that we're able to test what happens with our data. By using a chain of &lt;code&gt;.mockReturnValueOnce()&lt;/code&gt; methods, we're also able to dictate what the method returns when it's called multiple times. For example, in the context of our code, if we're adding multiple new items that all link to each other, we can easily check that the right item links are being set across multiple new items. &lt;/p&gt;

&lt;p&gt;It's also important to note that we're calling &lt;code&gt;jest.spyOn()&lt;/code&gt; from within the &lt;code&gt;beforeEach&lt;/code&gt; callback and as such, we need to call &lt;code&gt;jest.restoreAllMocks()&lt;/code&gt; from our &lt;code&gt;afterEach&lt;/code&gt; callback function so that our mock return values (&lt;code&gt;NEW_ID_1&lt;/code&gt; and &lt;code&gt;NEW_ID_2&lt;/code&gt;) get reset each time we run a test. &lt;/p&gt;

&lt;p&gt;Hope that helps! I'm also leaving this here to help me when I inevitably forget how I did this in the future.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>testing</category>
    </item>
    <item>
      <title>Setting up your web development machine</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Tue, 28 Feb 2023 00:04:08 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/learn-to-code-for-free-part-1-set-up-1280</link>
      <guid>https://dev.to/kaxmoglan/learn-to-code-for-free-part-1-set-up-1280</guid>
      <description>&lt;p&gt;Learning how to code is easily the best thing I've done with my time as an adult, but navigating the quagmire of tutorials and courses is a big challenge. I was fortunate enough to figure out how to learn completely for free, at least well enough to land my first role, but it wasn't without its pitfalls. With the benefit of hindsight and work experience, I thought I'd collate some free resources that I've found helpful, starting with some web fundamentals and setting up your development machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  An overview
&lt;/h2&gt;

&lt;p&gt;Before we get started, I watched a video recently that I thought was great both for motivation and a reality check which I recommend watching.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/W1QdaeuOsx8"&gt;Mistakes That Prevent Self-taught Developers From Landing A Job&lt;/a&gt; by &lt;a href="https://www.youtube.com/@DonTheDeveloper"&gt;DonTheDeveloper&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the web works
&lt;/h3&gt;

&lt;p&gt;In order to learn how to code properly, you must first understand how the internet works, what programming languages are, the different programming languages that exist and why they exist.&lt;/p&gt;

&lt;p&gt;Throughout your coding journey, I recommend keeping the &lt;a href="https://developer.mozilla.org/en-US/"&gt;MDN documentation&lt;/a&gt; bookmarked and accessible at all times. This is one of the best resources for learning about all things web development and will prove extremely useful as a reference manual as you progress through your learning and career. Whilst one can learn how to code on this platform alone (the same goes for other resources I will reference later), the point of this guide is to cherry pick what I think are the best parts of all the available free tools and resources. I also recommend bookmarking &lt;a href="https://www.w3schools.com"&gt;W3 Schools&lt;/a&gt; for similar reasons!&lt;/p&gt;

&lt;p&gt;The first resource I’d like to recommend is the free online course provided by Harvard University called &lt;a href="https://www.edx.org/course/introduction-computer-science-harvardx-cs50x"&gt;CS50’s Introduction to Computer Science&lt;/a&gt;. If you would like to go through this entire course, it wouldn't be a waste of time, however, I only recommend watching the first lecture; &lt;a href="https://www.youtube.com/watch?v=IDDmrzzB14M"&gt;Lecture 0&lt;/a&gt; which passionately talks about what code actually is.&lt;/p&gt;

&lt;p&gt;The second resource is the following MDN articles: &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/How_does_the_Internet_work"&gt;How Does The Internet Work?&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/How_the_Web_works"&gt;How The Web Works&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you’ve completed Lecture 0 and read the 2 MDN articles, you’ll hopefully be excited to get into some coding and have some solid foundational knowledge to better prepare you for your learning journey.&lt;/p&gt;




&lt;h2&gt;
  
  
  Some Terminology
&lt;/h2&gt;

&lt;p&gt;There is no shortage of terms and acronyms in the world of software development and there are lots that you will need to learn - but don’t worry, they’re not as complicated as they sound. Here are a few definitions to hopefully make the set up process a bit easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Browser&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should already be familiar with web browsers, but they are one of the main tools for a web developer and are more capable than you may realise. Examples of web browsers include Google Chrome, Mozilla Firefox, Microsoft Edge and Apple's Safari.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Editor / Text Editor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whilst we can use any text editor to write code (yes, even Notepad or TextEdit), it makes life extremely difficult. A code editor is basically a text editor with extra features like language specific syntax and error highlighting, multi-line editing (where you type and edit multiple lines at once and feel like Neo), the ability to easily click through to other areas of your codebase and more. A code editor is the place where we write and edit all of our code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A terminal provides a Command Line Interface (CLI) to interact with your computer. Although it may seem archaic at first when compared to a GUI (Graphical User Interface), once you get used to it, you’ll realise how quick and powerful it can be. Using the terminal, we can run our code, browse, create, edit and delete files, run programs, install and manage applications and utilities and much, much more. Typically speaking, a software developer will live between their code editor and terminal. The code editor to write and edit code, and the terminal to execute commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bash&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bash is the CLI language that we use in a Unix terminal. It actually stands for ‘Bourne-Again-SHell’. You can find out more about it &lt;a href="https://en.wikipedia.org/wiki/Bash_(Unix_shell)"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zsh&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An alternative to Bash. This is now the default shell shipped with MacOS. You can read more about it &lt;a href="https://en.wikipedia.org/wiki/Z_shell"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IDE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An IDE (or Integrated Development Environment) is the software that developers use to build software. At its core, it will provide a platform which integrates a code editor with a terminal, but also provides and integrates other tools to make development easier. Arguably, the most widely used IDE is Microsoft’s VSCode but another popular suite of developer tools and IDEs comes from &lt;a href="https://www.jetbrains.com/"&gt;JetBrains&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NB: There is an argument about whether or not VSCode qualifies as an IDE, but my opinion is this: at its core, VSCode is a text editor with a built-in terminal panel but through the use of extensions, we can get an IDE-like experience without the need to learn and buy different tools when we use different languages. My advice would be to spend less time worrying about whether VSCode is an IDE, and more time learning and trying different tools until you find something you like!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Package Manager&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A package manager installs, updates, configures, and removes software packages. In the context of a package manager in the terminal, you can think of it like a CLI App Store where you can search for, download, install and uninstall open source apps (yes, even desktop ones with GUIs!). Popular package managers are &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; for the Mac and &lt;a href="https://chocolatey.org/"&gt;Chocolatey&lt;/a&gt; for Windows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up your development environment
&lt;/h2&gt;

&lt;p&gt;You don’t need a powerful or new computer and you can run MacOS, Windows or Linux, but if you want to develop for iOS or the Mac, you will need a Mac. If you’re worried about the age or spec of your computer, you should only run into hardware limitations once you start working on larger projects, or need to use virtual machines and emulators. Until then, most computers are up to the task.&lt;/p&gt;

&lt;p&gt;If you’re looking to buy a new machine and you want a hard and fast recommendation, I recommend any Apple Silicon Mac. In my experience, this will provide you with the most flexible and powerful platform for most development tasks, but do not let this be a barrier to entry as it’s by no means a requirement for learning and for working!&lt;/p&gt;

&lt;p&gt;Now let's get set up.&lt;/p&gt;

&lt;h3&gt;
  
  
  MacOS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Terminal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MacOS already ships with a built-in terminal, aptly named ‘Terminal’. You can launch it by searching in Spotlight, searching in Launchpad, opening the ‘Other’ folder in Launchpad, or by going to the ‘Utilities’ folder in your Applications folder. Whilst the built-in terminal on MacOS is more than sufficient, I recommend downloading and installing &lt;a href="https://iterm2.com/"&gt;iTerm 2&lt;/a&gt; which will give you really useful features that will make your life easier.&lt;/p&gt;

&lt;p&gt;Next, I recommend installing a package manager called &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt;, arguably the most popular package manager for the Mac. You should read the documentation and play around with it to get a feel for using the terminal and a package manager, however you will learn these things as we go. If you would like to learn more about using Homebrew, I think the first ~4minutes of &lt;a href="https://youtu.be/Ym2pxzWpTNw"&gt;this video&lt;/a&gt; is great.&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Terminal - WSL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Earlier I mentioned that we could configure Windows to use something called WSL (Windows Subsystem Linux). WSL allows you to install a Linux distribution, such as Ubuntu, Debian, or Kali, as an application in Windows. Once installed, you can open a Linux terminal and run commands, scripts, and tools as if you were running them on a native Linux system.&lt;/p&gt;

&lt;p&gt;In order to install WSL, follow the &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/install"&gt;official install guide&lt;/a&gt; and make sure it’s configured to WSL 2 and Ubuntu. Once installed, you will be able to open Ubuntu like an application which will open an Ubuntu terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal - PowerShell&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As an alternative to WSL, you can use Windows’ built in terminal, PowerShell which you can search for and launch from the Start menu. I recommend installing the package manager &lt;a href="https://chocolatey.org/"&gt;Chocolatey&lt;/a&gt;, reading the docs and having a play around to get a feel for using it.&lt;/p&gt;

&lt;p&gt;As to why you would choose the hassle of getting WSL set up; PowerShell doesn’t have Bash or Zsh, which the majority of the developer community uses due to nearly all servers running Linux and MacOS being ‘Unix-like’.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal - GitBash&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A great half way house (and my recommendation if you're not going to set up WSL) is &lt;a href="https://gitforwindows.org/"&gt;GitBash&lt;/a&gt;. GitBash brings bash-like commands to Windows, and is what I personally use on my Windows machine, as I find it a good compromise between performance and a Bash-like experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  MacOS &amp;amp; Windows
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;VSCode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I recommend using VSCode as your IDE as it’s currently amongst the most used, fully-featured and it's FREE! You’ll also find that a lot of online tutors will use VSCode which will make it easier to follow along. To install it, follow &lt;a href="https://code.visualstudio.com/"&gt;these instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’re using WSL, I recommend running VSCode inside WSL which you can do by following &lt;a href="https://code.visualstudio.com/docs/remote/wsl"&gt;these instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sublime Text&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alongside VSCode, I also recommend installing &lt;a href="https://www.sublimetext.com/"&gt;Sublime Text&lt;/a&gt;. Whilst there is an overlap in functionality between the two, I find that having a no nonsense code editor on hand can be beneficial as a scratch pad, or to quickly open files that you may want to access outside your current project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Browser&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I recommend &lt;a href=""&gt;Google Chrome&lt;/a&gt; for development, but it’s also important that you have multiple browsers installed to test web apps in browsers that your users are likely going to use, like Safari or Microsoft Edge. I personally use Firefox as my main browser and Chrome or Firefox Developer Edition for developing on as, in my opinion, they have certain superior features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mozilla.org/en-GB/firefox/new/"&gt;Click here to install Firefox&lt;/a&gt; or &lt;a href="https://www.mozilla.org/en-GB/firefox/developer/"&gt;here to install Firefox Developer Edition&lt;/a&gt; (or both if you’d like!).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Put simply, Node.js enables you to run JavaScript on your computer (or a server). It's a more advanced subject which we'll go through later, but for now, just know that you should install it! To install it, you can use your package manager, or &lt;a href="https://nodejs.org/en/"&gt;download the installer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Git is the standard version control system (VCS) for software developers. It’s an essential tool to learn and will be one of (if not the) most used tool in your arsenal. There are 2 ways to use Git - the first is via the terminal and the second is via a GUI. Learning how to use Git via the terminal is an essential skill, so you should get used to that first. However, GUI Git clients can be useful to visualise a repository, especially when you get stuck. It can also be handy whilst you’re learning so you can see what’s going on and what your commands are doing!&lt;/p&gt;

&lt;p&gt;To install Git, follow &lt;a href="https://www.atlassian.com/git/tutorials/install-git"&gt;this guide&lt;/a&gt; written by Atlassian. For MacOS users, I recommend installing Git via the &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; package manager. For Windows, I recommend installing &lt;a href="https://gitforwindows.org/"&gt;GitBash&lt;/a&gt; (if you haven’t already done so).&lt;/p&gt;

&lt;p&gt;For Git GUI tools, I recommend the VSCode plugin, &lt;a href="https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph"&gt;GitGraph&lt;/a&gt; which works conveniently within VSCode alongside the built in Git tools already available. Alternatively, 2 other popular choices are &lt;a href="https://www.sourcetreeapp.com/"&gt;SourceTree&lt;/a&gt; and, my personal favourite, &lt;a href="https://www.gitkraken.com/"&gt;GitKraken&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A scratch pad&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Throughout your learning (and beyond) you’ll probably want to try some things out to see how they work outside of your codebase. Rather than setting up a whole new project just to try a couple of quick things, there are some apps that allow you to do just that!&lt;/p&gt;

&lt;p&gt;For browser based apps, check out and bookmark &lt;a href="https://codesandbox.io/"&gt;Code Sandbox&lt;/a&gt; and &lt;a href="https://codepen.io/"&gt;Codepen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For desktop based apps, check out &lt;a href="https://runjs.app/"&gt;RunJS&lt;/a&gt; and the VSCode extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=WallabyJs.quokka-vscode"&gt;Quokka.js&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Customisation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Setting up VSCode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Out of the box, VSCode has a lot of features but we can extend and customise its functionality and appearance through the use of ‘extensions’ via the VSCode Marketplace. It’s a good idea to have a play around just to get a feel for it before continuing, but you will become extremely familiar with it as you learn. Check out &lt;a href="https://www.youtube.com/watch?v=ORrELERGIHs"&gt;this video&lt;/a&gt; by &lt;a href="https://www.youtube.com/@TechWithTim"&gt;Tech With Tim&lt;/a&gt; to give you a comprehensive beginner’s overview of some of VSCode’s core features and concepts.&lt;/p&gt;

&lt;p&gt;The extensions I recommend installing to get you going are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer"&gt;Live Server&lt;/a&gt; which lets you easily run your code in a browser with automatic refresh on save, which means you don’t have to refresh the browser every time you make a change to your code.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode"&gt;Prettier&lt;/a&gt; which lets you configure rules to set how your code is formatted, and automatically formats your code on save based on your formatting rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My favourite extensions for aesthetics that you may want to check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=vscode-icons-team.vscode-icons"&gt;VSCode Icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=GitHub.github-vscode-theme"&gt;GitHub Theme&lt;/a&gt; (I'm a long-term user of GitHub Dark Dimmed)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=dracula-theme.theme-dracula"&gt;Dracula Theme&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some utility extensions I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=Tyriar.sort-lines"&gt;Sort Lines&lt;/a&gt; which lets you sort lines of code in various formats&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree"&gt;Todo Tree&lt;/a&gt; which lets you add ‘to do’ comments to your code and view them all in one easy to access&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker"&gt;Spell Checker&lt;/a&gt; - if you only install one utility extension from this list, choose this one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course there are a seemingly limitless amount of extensions available (and more are being added every day), but you will figure out which ones you need as you go. VSCode also does a good job of recommending extensions when you open up different file types. For example, if you were to open a Python script (a .py file) you’d likely get a popup asking if you’d like to install some python specific extensions if you haven't got them installed already.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customising your terminal (WSL &amp;amp; MacOS)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can completely customise the look and feel of your terminal, as well as set up your own shortcuts (called aliases) or even your own scripts to get your common tasks completed more efficiently. You’ll get more into this side of things as you go, but if you like customising and tweaking things, I'd have a look at &lt;a href="https://ohmyz.sh/"&gt;Oh My Zsh&lt;/a&gt; and watch &lt;a href="https://youtu.be/SVh4osULjP4"&gt;this video&lt;/a&gt; on how to get it set up.&lt;/p&gt;




&lt;p&gt;Now go take over the world by writing your first app! &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>codenewbie</category>
      <category>career</category>
    </item>
    <item>
      <title>I switched to Windows</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Fri, 24 Feb 2023 16:22:46 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/i-switched-to-windows-2ckb</link>
      <guid>https://dev.to/kaxmoglan/i-switched-to-windows-2ckb</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I started out my computer life, as many do, on Windows, but I switched over to Mac in 2009 and never looked back. A recent project required me to use a Windows machine for development so, as someone who would probably read about this kind of thing, I thought I'd write about this kind of thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bit of background
&lt;/h2&gt;

&lt;p&gt;I used Windows for everything 'back in the day' but I couldn't get it to work for me for music and video production. I switched to Mac and it solved all the problems that I had (and then some). I then learned to code on a Mac and have used Macs exclusively ever since. I hadn't had any dealings with the Windows world for 14 years, even though it felt like 4, so I was looking forward to seeing what was on the other side again especially considering a lot of the tooling I use (VSCode, TypeScript, Github etc.) was made (or bought) by Microsoft and I had heard great things about WSL and that things were 'not like they used to be'. As with everything in life, I approached this change with optimism and enthusiasm (I can hear all those who know me laughing, but I did have an open mind.... honest!).&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardware
&lt;/h2&gt;

&lt;p&gt;Let's start with the hardware. I switched to a 15" Dell Precision laptop, some £2,300 worth, with a beefy i7, 32gb RAM, 512GB SSD and an nVidia GPU with 4GB VRAM. I will be comparing this with a similarly priced 16" M1 Pro MacBook Pro with 16GB RAM, 1TB SSD, and a 13" M1 MacBook Air, at about half the price, with 16GB RAM and a 512GB SSD.&lt;/p&gt;

&lt;h3&gt;
  
  
  A quick few points on hardware
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The weight of the Dell is really nice and sits between the MBA and MBP. The compromise is it feels a bit plasticy, but still very sturdy.&lt;/li&gt;
&lt;li&gt;The Dell's screen has a matte finish to it which helps with glare, but isn't very sharp especially when compared to the MacBooks so coding on it can cause a bit of eye strain.&lt;/li&gt;
&lt;li&gt;The Dell's webcam is rubbish but the little cover is nice. The MBP &amp;amp; MBA webcams are miles better.&lt;/li&gt;
&lt;li&gt;The Dell has a number pad which is cool for those who want it. I do not. Because of this, the trackpad and keyboard are off centre which makes typing feel weird. The keyboard is nice though.&lt;/li&gt;
&lt;li&gt;The ports on the Dell are great - HDMI, USB-A, USB-C, Ethernet etc. The MBP is nearly as good but with the absence of USB-A and ethernet. The MBP is better in as much as you can charge it from any USB-C port. The MBA falls miles short and I should also note that previous generations of MBPs fall miles short too!&lt;/li&gt;
&lt;li&gt;The Dell's charger is big, but surprisingly well thought out. I just wish the plug had a charging indicator instead of always being on when connected to mains even when unplugged from the laptop - this caught me out a few times when I thought the laptop was on charge when it wasn't.&lt;/li&gt;
&lt;li&gt;The Dell's trackpad is terrible. Not unusable, but very fiddly and awkward. I always connected a mouse to avoid tantrums.&lt;/li&gt;
&lt;li&gt;The Dell's speakers would have been better left out. They're that offensive, especially when compared to the speakers in either MacBook.&lt;/li&gt;
&lt;li&gt;The Dell's battery life is acceptable but about 5 times worse than either MacBook (and that's being generous under heavy load).&lt;/li&gt;
&lt;li&gt;You can't single handedly lift the lid of the Dell laptop without the rest of the laptop coming with it. A small annoying detail.&lt;/li&gt;
&lt;li&gt;The Dell gets hot - a problem all Intel/x86 machines suffer with, including (especially) previous generations of MacBooks. This isn't really a complaint, just a reminder of how big a leap Apple Silicon is in this department.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aesthetics are completely subjective so I won't belabour this point. Personally, I think the Dell looks like a sturdy, no nonsense, professional machine, but I'd take either MacBook over it. To my eyes, there are plenty of PC Laptops on the market that easily rival the MacBooks aesthetically if that's what you're looking for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dev environment
&lt;/h2&gt;

&lt;p&gt;I'm currently a full stack TypeScript and React developer. I use Docker containers with local DBs, VSCode running a load of extensions, a terminal used predominantly for Git and Chrome running the standard 2 million tabs with a bunch of dev tool add-ons.&lt;/p&gt;

&lt;p&gt;Given that I was coming from a Mac / Unix background and that I had heard so many good things about WSL, I decided to set up my Windows machine running WSL with Ubuntu LTS, with VSCode and Docker in WSL mode too. This worked a treat and although I was still stumbling over some keyboard shortcuts (Cmd = Ctrl and it's over to the left), it was simple enough to set up and I was more than happy working on my new Windows machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Favourite Windows features
&lt;/h2&gt;

&lt;p&gt;The built-in clipboard history that can be accessed with &lt;code&gt;Win + V&lt;/code&gt; is insanely useful. The Mac needs this feature. The window snapping feature is also great, but you can use Rectangle or Magnet to build this capability into the Mac. I also think that the minimise, maximise and close buttons are easier and clearer to use than Apple's which now includes &lt;code&gt;alt + click&lt;/code&gt; functionality which I personally find annoying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows gripes
&lt;/h2&gt;

&lt;p&gt;In my opinion, the Windows UI is garbage. I can't believe I'm still looking at windows from XP and earlier and the whole Settings / Control Panel situation is a mess. I think the whole task tray situation in the bottom right looks a state and it's fairly unclear what each thing does. Switching desktops whilst in Task View is very janky, separate displays can't have separate desktops and you can't re-order your desktops. It still seems like certain areas are designed for touch and others designed for a CRT screen. Files stored on the desktop with long filenames can stop you clicking on files that the filename obstructs, the lack of a proper preview feature (like the ability to hit the space bar on any file on MacOS) is very annoying when trying to find a file and, to top it all off, everything makes a sound. I must've heard that 3-note chime 100,000 times a day. Are you sure you want to delete this email? Da-da-ding! Do you want to empty the recycle bin? Da-da-ding! You need admin rights to modify this file. Da-da-ding! Are you sure you want to close Chrome? Da-da-ding! Unknown keyboard shortcut. Da-da-ding! You get the idea.&lt;/p&gt;

&lt;p&gt;I also had endless issues with every bluetooth peripheral including an intermittently stuttering and delayed mouse and keyboard that could only be solved by reinstalling the bluetooth driver (except once where turning the computer off for 10 minutes seemed to fix it). Bluetooth headphones of multiple makes all struggled to stay connected throughout the day so I had to join meetings at least 5 minutes early to ensure they'd connect properly, and even then, the sound quality on calls was abysmal. I also experienced wifi drop outs frequently. Oh, and I couldn't keep other wifi devices near the laptop, or the wifi dropped out completely. I tested this. Move a MacBook closer to the laptop - no internet - move a MacBook away from the laptop - internet!&lt;/p&gt;

&lt;p&gt;Lastly, just like my old PC from 14 years ago, a lot of the system audio (like shut down jingle etc.) was crackly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development problems
&lt;/h2&gt;

&lt;p&gt;After a couple of hours running my dev environment each day, my whole machine would start getting 'sticky'. Code would start taking much longer to compile, apps would start taking longer to load and UI animations would start glitching. I tried stopping my task runners, rebooting WSL and stopping the Docker container, I tried closing Chrome and Slack and Outlook but it would only get marginally better for a short amount of time before it would start up again. The only solution was to reboot, which I had to do up to 5 times a day. I don't think I need to stress what an interruption to work this can be. Equally, if I ever wanted to join a video call, I couldn't if I had my dev environment running as the machine seemingly couldn't cope, and I could forget about sharing my screen. The second I shared my screen, the whole thing ground to a halt -- not very conducive to a collaborative remote engineering team! I also found that the Windows version of various cross-platform apps that I relied upon day in day out were more buggy, like MongoDB Compass and Slack.&lt;/p&gt;

&lt;p&gt;After a few months of persevering, I decided to rebuild my dev environment without WSL as it was clear it was using a large amount of RAM and CPU. I rebuilt my dev environment and used GitBash as my terminal and I have to say, it solved a lot of my problems. GitBash, for the most part, was nice and familiar, albeit without the joys of oh-my-zsh but this wasn't a big deal. The system ran far more smoothly and consistently and I no longer had to reboot 5 times a day, but it still felt sluggish when it came to traversing the codebase, linting and autocomplete. It at least made it more possible to join calls while my environment was running, but sharing my screen was still reaching the limits of this £2,300 computer and it didn't solve my bluetooth or wifi issues.&lt;/p&gt;

&lt;p&gt;I have to compare this, I'm afraid, to a MacBook Air costing half as much...&lt;/p&gt;

&lt;p&gt;The project that I worked on with this Dell laptop was a React project. It's quite big, but it's still just React. The project I worked on with my MBA was using React Native running iOS and Android emulators simultaneously. I joined calls, shared my screen, connected headphones and to the internet with literally no problems. I had to reboot from time to time when an emulator got out of hand, but this was rare. The MBA also didn't even have a fan (let alone a loud one) and although it got warm, was still cooler than the Dell laptop with the fans screaming at me - something I realised is actually rather annoying to listen to all day!&lt;/p&gt;

&lt;h2&gt;
  
  
  I switched back to Mac
&lt;/h2&gt;

&lt;p&gt;Needless to say, I went back. I'm sorry to say that the difference, especially with Apple Silicon, is stark. Running the same project on a 14" M1 Pro MBP with 32GB RAM that costs around the same as the Dell is silent, glitch free and extremely responsive, and the bugs that I was putting up with across my everyday applications have disappeared. Virtual desktops are far easier to deal with and more intuitive and is a feature I heavily rely upon. I also found that after switching back to Mac, I realised I was putting up with numerous scaling issues on my external 4k screen. These issues were fairly app-specific so I can't fully blame Microsoft here, but from a user perspective, it does make the overall experience inferior.&lt;/p&gt;

&lt;p&gt;I really did give the switch a go with an open mind and I persevered for 9 months, but the fact remains: Windows seems to have the same problems it had for me 14 years ago. I was forever rebooting, rebuilding and tweaking instead of, well... working! In summary, whenever I've used Windows, I've used Windows. Whenever I've used a Mac, I've used my apps.&lt;/p&gt;

&lt;p&gt;I'd be interested to hear from any of you who are running Windows to see if you've had similar experiences. Whether you think the problems I had were hardware specific, or whether you've experienced the same or similar problems. I've spoken to other developers and, unfortunately, they've all echoed very similar issues - some of them were just used to it and hadn't really thought about it. It's amazing what you get used to and tolerate over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  A final note
&lt;/h2&gt;

&lt;p&gt;One thing that genuinely baffles me (and something that I can't believe isn't talked about more) is that if you have your Windows laptop unplugged, you don't get access to the laptop's full performance.&lt;/p&gt;

&lt;p&gt;You spend thousands of pounds for a high-performance, portable device, whose performance you can't make use of unless you're ported.&lt;/p&gt;

&lt;p&gt;You should get a refund.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>Why I always use backticks for strings</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Fri, 26 Aug 2022 22:53:48 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/why-i-always-use-backticks-for-strings-3fbj</link>
      <guid>https://dev.to/kaxmoglan/why-i-always-use-backticks-for-strings-3fbj</guid>
      <description>&lt;h2&gt;
  
  
  A quick one from me
&lt;/h2&gt;

&lt;p&gt;If you're using single quotes or double quotes for your strings and not backticks (template literals), then I'm afraid your sanity may be in question.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens when you DON'T use backticks
&lt;/h3&gt;

&lt;p&gt;If you're using single quotes (the worst offender) and your string requires an apostrophe, you're back to using double quotes. Now your code has inconsistent string syntax. The reverse is also true, albeit less common - if you're using double quotes and you need double quotes in your string, you're back to using single quotes. In both of these cases, if you ever need to pass in a variable, you're introducing template literals / backticks - a 3rd string syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens when you use backticks
&lt;/h3&gt;

&lt;p&gt;There are 2 main advantages:&lt;/p&gt;

&lt;p&gt;Firstly, your codebase's string syntax is consistent. You can pass in apostrophes / single quotes and double quotes without thinking -- a freedom you don't appreciate until it's taken away from you -- and secondly, you are free to pass in variables whenever you like without going back and changing those damned quotation marks!&lt;/p&gt;

&lt;p&gt;I wondered if people didn't do this because of some kind of performance advantage where template literals would be slower or more expensive, but I've found nothing that supports this theory, so it begs the question:&lt;/p&gt;

&lt;p&gt;Why would you use any other syntax?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>discuss</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to Offset a Server's Timezone to Store a UTC Datetime</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Sun, 10 Apr 2022 10:25:06 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/how-to-offset-a-servers-timezone-to-store-a-utc-datetime-18c7</link>
      <guid>https://dev.to/kaxmoglan/how-to-offset-a-servers-timezone-to-store-a-utc-datetime-18c7</guid>
      <description>&lt;p&gt;TLDR; the Javascript Date object is nasty. This is how I stored a UTC time in a Postgres database using the Javascript Date object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;As part of building a microservice responsible for handling bookings between 2 users, each of whom could be in any timezone, and also travel into any timezone between making the booking and fulfilling the booking, I stumbled across a little issue when it came to storing the UTC time.&lt;/p&gt;

&lt;p&gt;For this microservice, I'm using Typescript, Koa, Prisma and Postgres. It's out of the scope of this article to talk through the entire infrastructure or, indeed, how the whole microservice works, but here's what the relevant part of my Prisma schema looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model Booking {
  bookingId             String        @id @default(uuid())
  user1Id               String
  user2Id               String
  lengthMins            Int
  startDateTimeUTC      DateTime
  dateTimeCreated       DateTime      @default(now())
  dateTimeUpdated       DateTime?
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's how we could create a new row in our Booking table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;booking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;user1Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`user_1`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;user2Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`user_2`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lengthMins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;startDateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`2022-04-10T14:00:00`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All we're trying to do here is, using Prisma, store a new row in our Booking table that represents a booking between &lt;code&gt;user_1&lt;/code&gt; and &lt;code&gt;user_2&lt;/code&gt; at 14:00 on 10th April 2022, UTC. When running a function like this (albeit this would exist inside a &lt;code&gt;try/catch&lt;/code&gt; block in a re-usable function), I naively expected the time to be stored as... you know.... the time I passed into the Date constructor.&lt;/p&gt;

&lt;p&gt;Unfortunately, this didn't happen. What happens is the time gets converted into the server's local time. I was running this code locally in BST (UTC + 1), so, in this example, the time would have been stored as 15:00.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;My solution for the entire system was to store all datetime information in the database in UTC, then use the user's device location (with permission, of course) to convert the stored time into the user's local time.&lt;/p&gt;

&lt;p&gt;My solution for this specific issue (without the use of any 3rd party libraries, and without having to store extra information like the server's timezone) was to create a function that used Javascript's Date object to offset the server's timezone before we store it.&lt;/p&gt;

&lt;p&gt;This looked like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getUTCTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateTimeString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateTimeString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateTimeNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateTimeOffset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTimezoneOffset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateTimeUTC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;dateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateTimeNumber&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dateTimeOffset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we're doing here is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a new Date object (as we did in the first example) using a UTC datetime string that we can pass into the function.&lt;/li&gt;
&lt;li&gt;Getting the datetime in number format (or, the number of milliseconds from midnight on January 1, 1970 to the datetime we pass in).&lt;/li&gt;
&lt;li&gt;Using the &lt;code&gt;.getTimezoneOffset()&lt;/code&gt; method to get the difference, in minutes, between the date as evaluated in the UTC time zone, and the same date as evaluated in the local time zone. We multiply this value by 60,000 to convert this number into milliseconds to make it more useful to use later.&lt;/li&gt;
&lt;li&gt;Creating a new Date object (with &lt;code&gt;new Date()&lt;/code&gt;) which will be instantiated with the current datetime.&lt;/li&gt;
&lt;li&gt;Assigning the value of our new Date object to the datetime we passed into the function, minus our server's timezone offset (&lt;code&gt;datetimeNumber - dateTimeOffset&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Returning the Date object that we've now successfully set to the &lt;code&gt;dateTimeString&lt;/code&gt; we originally passed the function!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now when we add a row into our table, we can do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;booking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;user1Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`user_1`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;user2Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`user_2`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lengthMins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;startDateTimeUTC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getUTCTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`2022-04-10T14:00:00`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Peace Out
&lt;/h2&gt;

&lt;p&gt;There are libraries that cater for this kind of thing very well. The main one I use being &lt;code&gt;date-fns&lt;/code&gt;, but this is a fairly easy manual solution which solved my problem. This will work anywhere around the world too, as it just offsets the timezone of the server you're running the code on.&lt;/p&gt;

&lt;p&gt;As always, I hope this helped you in some way, or you at least found it an interesting read.&lt;/p&gt;

&lt;p&gt;I would love to hear any and all timezone puzzles you may have been a part of solving. I've found that timezones are one of those annoying rabbit holes that are really easy to make mistakes with. Fingers crossed, this isn't one of them!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>We trialled a 6-week project cycle and here's what happened</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Wed, 09 Mar 2022 09:31:02 +0000</pubDate>
      <link>https://dev.to/lettheinsideout/we-trialled-a-6-week-project-cycle-and-heres-what-happened-bfd</link>
      <guid>https://dev.to/lettheinsideout/we-trialled-a-6-week-project-cycle-and-heres-what-happened-bfd</guid>
      <description>&lt;p&gt;At InsideOut we've been managing our workload in a Scrum-based environment where we have 2-week long sprints and 4-sprint long iterations, but we recently switched to a project-based workflow and we've found several benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The old way: Scrum-diddly-umptious
&lt;/h2&gt;

&lt;p&gt;Each developer has a pre-set number of tickets that they aim to complete by the end of each sprint. Each ticket has a number of points that indicates its complexity, not time required to complete. The theory here being that if each ticket were scored by time taken, this would change per developer, whereas a complexity score is immutable. If a non-urgent issue or bug pops up, we add a ticket to the 'backlog' which will be picked up in a future sprint. Equally, tickets that contribute to a larger project (like a new app feature, or a new app entirely) will be written up and added to the backlog. These tickets may be prioritised if the project has a deadline.&lt;/p&gt;

&lt;p&gt;Sprint iterations are a collection of 4 sprints so we can assess our longer-term productivity, but also plan and work on longer-term projects. All sprints are managed via a Kanban board.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ok, so what's the problem?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There wasn't anything inherently &lt;em&gt;wrong&lt;/em&gt; with this approach. It worked for us in that we were getting a lot of work done, and the methodology was agile in as much as we were only ever a maximum of 2 weeks away from working on something new. For the wider business, this meant that if a non-critical bug was spotted, or if there was a small feature request that was provably important, we could work it into our next sprint.&lt;/p&gt;

&lt;p&gt;There were, however, 4 main problems with this approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Bigger projects took longer.&lt;/strong&gt;&lt;br&gt;
Our sprints always comprised of several types of tickets ranging from support, bug fixes and data reports, alongside tickets that contributed to larger projects. This inherently meant we were unable to focus on any single project and our time and attention was always split.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Requests came in thick and fast.&lt;/strong&gt;&lt;br&gt;
Because we were only ever a short amount of time away from new tickets, the wider business was more than happy to add to our workload regularly. For every request that came in, we would have to assess a solution and potentially add a ticket to our backlog, thus splitting our attention even further. Also, if you've ever written up tickets, you'll know that to do it properly requires some thought and time. Hence, we would often end up doing 'quick things' there and then which ended up being unaccounted for and distracted us further still.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Meetings.&lt;/strong&gt;&lt;br&gt;
On top of our daily stand-ups, we had sprint planning meetings every Friday. This involved going through our backlog of tickets and work out what needed to be prioritised in the next sprint. It also involved discussing and pointing each and every ticket. We tried to keep these meetings down to an hour, but they naturally always overran and sometimes even took up a whole morning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Under appreciation 🎻😭&lt;/strong&gt;&lt;br&gt;
As is often the case, the wider business doesn't see all the work we do. This is inevitable. But with this Scrum approach, our work felt even more obfuscated as the smaller, more technical things were being done but not necessarily understood, and the larger, more visible things appeared to take far longer than they 'should'.&lt;/p&gt;

&lt;h2&gt;
  
  
  The new way
&lt;/h2&gt;

&lt;p&gt;We have trialed, and intend to continue using an 8-week work cycle that's comprised of a 6-week project and a 2-week 'wash up' period.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project cycle&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A select few members (the best suited to the project) will be put on The Project Team. It is up to The Project Team to start and finish a project within 6 weeks. This means that by the Friday of Week 6, the project has been released to production and is in the customers' hands. The project can be anything from an internal product (the most recent being a new dashboard built in React) or a new feature for our mobile app that will be released as part of our regular app-store updates for our clients to use.&lt;/p&gt;

&lt;p&gt;The rest of the engineering team during this period will support the wider business with support requests and bug fixes etc - i.e. smaller tasks that do not belong to a larger project but still have to get done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wash Up cycle&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The 2 week Wash Up period is where we debrief the project and look for ways to improve the next project cycle. We can also use the time to add things that may have been missed in the project cycle, whether because they were out of scope or we ran out of time and they didn't affect the core functionality of the product. These 2 weeks are also used as Kaizen time, as well as planning the next project. It's important the projects are planned properly as the condition of any project is that it gets delivered in 6 weeks. This means that we need to properly assess ths scope of each project and ensure that the Project Team is not overstretched or, indeed, slacking ;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does a project get chosen?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the 2-week Wash Up period, any engineer can advocate for a new project. They don't necessarily have to take the lead on a project they advocate for, but it's often the case that they do. It means that the developers are actively encouraged to look for areas of the business that can be improved, but also advocate for things they may &lt;em&gt;want&lt;/em&gt; to work on. Projects also get put forward by other areas of the business where &lt;em&gt;they&lt;/em&gt; spot areas that need improvement in their department. Ultimately, the projects get given the green light by the CTO and CEO.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;p&gt;I'll get the downsides of this approach out of the way first, as I'm a big fan of this new approach and I'm honestly struggling to find many downsides.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Less agile.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It takes longer for requests and business support issues to get done as we are now dealing with an 8-week block of time, instead of 2. However, there are still engineers on hand to deal with these requests, so it's not like nothing can be done in these 8-weeks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Not everyone has a project!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is the case that developers not on a project, arguably, have less fulfilling work to complete as they're working through tickets just like before. Having said that, people might prefer grinding through tickets and might hate projects, so it's all swings and roundabouts!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Smaller things may get skipped... maybe.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I can foresee a situation where smaller issues do not get resolved if they're not important enough. The wider business might find this methodology more frustrating than the old way of working, however, it's actually good that developers aren't wasting their time on things that are not urgent. Smaller issues are likely to get resolved in a project cycle where an entirely new feature or product gets built that's better than any fix that could have been applied during a sprint thus, in the long run, the business is far better off even if it has to suffer minor niggles for slightly longer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Speed.&lt;/strong&gt; Big projects are completed and delivered quickly. Projects of the size we're able to complete within a 6-week project cycle used to take us at least 12.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Higher standards.&lt;/strong&gt; Developers are able to work on the project intensely and properly without distractions. This has resulted in better code quality and better infrastructure design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Planning.&lt;/strong&gt; The wider business knows that they will have a product in 6 weeks. This makes their scheduling and planning far easier and more efficient. It also means they don't have to continuously ask the engineering team about updated delivery times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visibility and appreciation.&lt;/strong&gt; The wider business can see the results of the developers' work. We deliver features and products that the wider business can see and use every 8 weeks, without fail. This has made the engineers feel more appreciated and look more accomplished.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer meetings.&lt;/strong&gt; We don't need to sprint plan every Friday. We don't need to micro-manage and change things around to suit the latest requests that come in during each sprint cycle. This means more time for development and actual work!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer requests.&lt;/strong&gt; Because the wider business knows what we're doing and how long it will take, we don't get inundated with requests. We are left to work on our project. This, of course, leads to less distraction and a better result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsibility.&lt;/strong&gt; Not everyone wants to be a manager or run a team, but if you do or you'd like to try it, being a lead on a project is a perfect way to get your feet wet. As a Project Owner, you will have the responsibility for ensuring the scope of the project is achievable and, more importantly, that the project gets delivered on time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No micro-management.&lt;/strong&gt; Because each project is run by a Project Owner, the project gets run in any way the Owner sees fit. This means you get exposed to different ways of working when you're not an owner, and you can trial and experiment with different ways of working when you are. On top of this, it also allows for each member of the team to work the way they like. The best way we've found so far, is for the overall 'to-do list' and timeline to be visible to the whole team, but a person's individual tasks to be managed in any way that person sees fit. This means you're not stuck working in a way that someone else's brain works, you can choose your own tooling and methodology - something that I find efficient, educational and rewarding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Education.&lt;/strong&gt; As a Project Owner, you could put yourself on areas you want to progress in. For example, if you're mainly a backend engineer but want to do more front end work, put yourself on the front end and elect another backend dev to work with you! So long as the project gets delivered and to a high standard, this is an excellent way of learning on the job and improving your abilities.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;To sum up, with this new way of working, the engineering team are getting through bigger projects more quickly, more efficiently and to a higher standard. Less time is being spent on the minutiae of day-to-day business and the wider team has a better understanding of what the developers are up to, and a better appreciation for what the developers do.&lt;/p&gt;

&lt;p&gt;This is a way of working that we certainly intend to continue with. We and the business are really happy with the results and, as a developer, it's more rewarding and more fun!&lt;/p&gt;

</description>
      <category>management</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Kaizen: Little and Often</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Tue, 08 Mar 2022 08:55:35 +0000</pubDate>
      <link>https://dev.to/lettheinsideout/kaizen-little-and-often-ec7</link>
      <guid>https://dev.to/lettheinsideout/kaizen-little-and-often-ec7</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I'm going to explain what Kaizen sessions are and how and why engineering teams have them. I'm then going to explain how and why the InsideOut Engineering Team incorporates Kaizen sessions and the Kaizen philosophy in a more unconventional manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Kaizen Sessions?
&lt;/h2&gt;

&lt;p&gt;Kaizen Sessions are an opportunity for members of the engineering team to use a portion of their working day for self improvement. You may have heard of these sessions also be referred to as 'self-learning', 'self-study', 'self-improvement', 'innovation-time' etc. but the reason we at InsideOut use the term 'Kaizen', is because of the philosophy behind it that we try to adopt.&lt;/p&gt;

&lt;p&gt;The term 'Kaizen' is a Japanese business term meaning 'change for the better', or 'continuous improvement'. There are a few different implementations of Kaizen, but for the sake of this blog post, I'd like to touch on the 5 core elements of the Kaizen approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Teamwork&lt;/li&gt;
&lt;li&gt;Personal Discipline&lt;/li&gt;
&lt;li&gt;Improved Morale&lt;/li&gt;
&lt;li&gt;Quality Circles (groups specifically brought together to identify potential improvements)&lt;/li&gt;
&lt;li&gt;Suggestions for Improvement&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By keeping these 5 principals at the heart of an engineering team, one creates a culture not only of self-development, but co-operative development. That is to say, everyone feels supported and motivated to better themselves and each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why have Kaizen sessions?
&lt;/h2&gt;

&lt;p&gt;We all know how quickly technology moves and having the time to keep up with the latest tech is a big challenge. As such, it's common practice for tech companies to afford a given amount of time to members of their engineering team for 'self-learning'. This is both beneficial for the employee as it keeps their skills sharp and their knowledge up to date, ultimately, making them more valuable in their own careers, but also to the employer who, in turn, will have sharper engineers at their disposal, as well as engineers who feel valued by the company.&lt;/p&gt;

&lt;h2&gt;
  
  
  InsideOut vs. The World
&lt;/h2&gt;

&lt;p&gt;The amount of time given to engineers for self-learning varies from company to company, but the most common schedules I've come across are one afternoon a month, one day a month, one day a quarter and one afternoon a quarter.&lt;/p&gt;

&lt;p&gt;At InsideOut, however, we've upped this to one afternoon a week and it makes everyone happier, more collaborative (somewhat more competitive) and, importantly, more productive.&lt;/p&gt;

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

&lt;p&gt;We tried once a quarter and we tried once a month and they were both fine. Everyone looked forward to tackling their own projects and felt grateful for having the time to learn.&lt;/p&gt;

&lt;p&gt;But...&lt;/p&gt;

&lt;p&gt;Sessions spread out this far apart presented some glaringly obvious problems which, I would argue, made them next to pointless! In no particular order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Frustration: We'd be left wanting to have learned more in the allotted time, and had to wait another month (or 3!) for our next learning opportunity.&lt;/li&gt;
&lt;li&gt;Fatigue: We tried to cram as much as possible into a relatively short amount of time, meaning energy and productivity levels were noticeably down for the following day (and sometimes for the rest of the week).&lt;/li&gt;
&lt;li&gt;Retention: It was difficult for us to retain what we'd learned due to the gap between learning sessions. It's far better to learn 'little and often'.&lt;/li&gt;
&lt;li&gt;A lack of desire to learn something directly associated with current company-work. After-all, we all have things we want to learn and projects we want to work on that aren't necessarily associated with work!&lt;/li&gt;
&lt;li&gt;An unfair 'urgent' work distribution. So, if something urgent came up that required an engineer, it's pretty unfair for that engineer to lose (potentially) a quarter of their yearly learning time to fix something.&lt;/li&gt;
&lt;li&gt;A lack of desire to teach someone else something. Even though we wanted to, we were conscious that knowledge-sharing took up a large chunk of our self-learning time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At InsideOut we feel like we've solved all of these problems and in doing so, found further benefits. In summary, we participate in weekly Kaizen sessions that start at 14:00 and span the rest of the day. At 14:00, the engineering team joins a video call and our aim is to spend about 60 minutes knowledge sharing where our target is for every person to bring something to the table - even if it's a question that they know another engineer has the expertise to answer and teach everyone. Afterwards, everyone goes away and progresses with their self-learning for the rest of the day.&lt;/p&gt;

&lt;p&gt;The benefits we've noticed to this approach, amongst others, are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates a culture of continuous learning and development (self-improvement).&lt;/li&gt;
&lt;li&gt;Creates a culture of teaching and progressing the people around you.&lt;/li&gt;
&lt;li&gt;Creates a culture of business improvements.&lt;/li&gt;
&lt;li&gt;Gives each engineer the time to pursue a proper educational path, with better knowledge retention due to a 'little and often' learning approach.&lt;/li&gt;
&lt;li&gt;Engineers are happy to jump on bits of work during Kaizen, should they need to.&lt;/li&gt;
&lt;li&gt;Engineers are happy to prioritise a deadline they may have over their self-learning.&lt;/li&gt;
&lt;li&gt;Engineers are much more likely to further their knowledge in areas directly beneficial to their work, with some choosing to alternate week-by-week between personal projects and work-related learning.&lt;/li&gt;
&lt;li&gt;Engineers are happier in general and feel more appreciated and cared for.&lt;/li&gt;
&lt;li&gt;Having one afternoon that's almost guaranteed to be slower-paced makes the team more productive and feel more rested for the rest of the week.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;p&gt;The InsideOut engineering team are happier, healthier, more productive and more collaborative!&lt;/p&gt;

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

&lt;p&gt;By having regular sessions like this, a culture of self-improvement, self-discipline and improving and helping others is almost guaranteed. We trialled it with a view to monitoring our output and seeing if our work got affected, and if so, by how much. The results were that our output measurably improved week-on-week, and moreover, everyone felt encouraged and supported to get better which made everyone happier and more achieved in their personal growth.&lt;/p&gt;

&lt;p&gt;I'd highly recommend this approach for all engineering teams, not least because I consider it a win for both parties in a professional capacity, but because it's a huge win in a personal one. On paper, of course, the engineering team gets 1 afternoon 'off' a week, but we all know that what's on paper can often be a far cry away from reality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maximilian Coghlan&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Full Stack Software Engineer at InsideOut&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>management</category>
      <category>startup</category>
    </item>
    <item>
      <title>Mocking Node-Fetch with Jest, Sinon and Typescript</title>
      <dc:creator>Maximilian</dc:creator>
      <pubDate>Tue, 09 Nov 2021 23:50:10 +0000</pubDate>
      <link>https://dev.to/kaxmoglan/mocking-node-fetch-with-jest-sinon-and-typescript-4dan</link>
      <guid>https://dev.to/kaxmoglan/mocking-node-fetch-with-jest-sinon-and-typescript-4dan</guid>
      <description>&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;If you don't care about the context of these tests and want to go straight to the &lt;code&gt;node-fetch&lt;/code&gt; mocks, skip to the &lt;strong&gt;here's my solution&lt;/strong&gt; section.&lt;/p&gt;

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

&lt;p&gt;I wrote a middleware library to be used by micro-services that decodes and verifies JWTs and works with Express and Koa. The requirement was for the library to make an API request to an external service in order to refresh tokens if the provided token had expired. I'm not writing this post to discuss the library itself, but to talk about how I wrote the unit tests for it as I found it a little tricky to implement a solution that catered for sending and receiving dynamic data to and from the external service, whilst keeping the tests isolated. Hopefully this will be helpful to someone trying to do a similar thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The middleware
&lt;/h2&gt;

&lt;p&gt;The controller function looks a little something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;checkToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;reqHeaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IncomingHttpHeaders&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ITokenData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get access token from auth header&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reqHeaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Decode token&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decodedToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;verifyAndDecodeToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Token is valid, return the decoded token&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decodedToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;decodedToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Store the data from the decoded token in a variable&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ITokenData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decodeToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Call the external API using the data decoded from the access token&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newAccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;refreshTokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Decode token returned from external API&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decodedNewToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;verifyAndDecodeToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newAccessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the decoded new token&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;checkNewToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;refreshTokens()&lt;/code&gt; function looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;refreshTokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ITokenData&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://refreshmytokensyouslag.com`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`post`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;tokenData&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`application/json`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resJson&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newAccessToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, just for the sake of context, the wrapper functions (or 'factories') for Koa and Express look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Middleware factory for Express
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;checkTokenExpress&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;checkTokenMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NextFunction&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decodedToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;checkToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decodedToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Middleware factory for Koa
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;checkTokenKoa&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;checkTokenMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Koa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Koa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Next&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decodedToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;checkToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decodedToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Code explanation
&lt;/h4&gt;

&lt;p&gt;We have our 2 'middleware factories'; one for Express and one for Koa. Both are exported, ready to be used in any other Express or Koa services as middleware. Both factories call the &lt;code&gt;checkToken()&lt;/code&gt; function, append a decoded token to the &lt;code&gt;req&lt;/code&gt; or &lt;code&gt;ctx&lt;/code&gt; objects respectively, then call &lt;code&gt;next()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our controller function, &lt;code&gt;checkToken()&lt;/code&gt;, verifies and decodes access tokens. If the token is valid and hasn't expired, it returns the decoded token object. If the token is invalid, it will throw an error, and if the token is valid but has expired, it calls the &lt;code&gt;refreshTokens()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;refreshTokens()&lt;/code&gt; function makes a request to an external API which handles the issuing of new access tokens if certain conditions are met. Our &lt;code&gt;checkToken()&lt;/code&gt; function will then decode and return this new token.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tests
&lt;/h2&gt;

&lt;p&gt;Testing for the token being valid was pretty simple as the code is already isolated. Here's what the code looks like for both the Koa and Express implementations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Express&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`middleware calls next if access token is valid`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a token to test&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testAccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`bar`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`1h`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Mock the request object&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testAccessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// Mock the response object&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockReq&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ExpressRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockRes&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ExpressResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Mock the next() function&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Invoke Express&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Our test expectation&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callCount&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Koa&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`middleware calls next if access token is valid`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a token to test&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testAccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`bar`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`1h`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Mock the ctx object&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockCtx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testAccessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockCtx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;KoaContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Mock the next() function&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Invoke Koa&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;koa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Our test expectation&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callCount&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Code explanation
&lt;/h4&gt;

&lt;p&gt;The tests for Express and Koa are nearly identical, we just have to cater for Express' &lt;code&gt;request&lt;/code&gt; object and Koa's &lt;code&gt;ctx&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;In both tests, we're creating a valid token &lt;code&gt;testAccessToken&lt;/code&gt; and mocking the &lt;code&gt;next()&lt;/code&gt; functions with Sinon. We're then mocking the &lt;code&gt;request&lt;/code&gt; and &lt;code&gt;response&lt;/code&gt; objects for Express, and the &lt;code&gt;ctx&lt;/code&gt; object for Koa. After that, we're invoking the middleware and telling Jest that we expect the &lt;code&gt;next()&lt;/code&gt; function to be called once, i.e. we're expecting the token to be valid and the middleware to allow us to progress to the next step in our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a test for a failure look like?
&lt;/h2&gt;

&lt;p&gt;From this point onwards, I'll only give code examples in Koa as there's slightly less code to read through, but you should have no problem adapting it for Express using the examples above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`middleware throws error if access token is invalid`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testAccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`abcd1234`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockCtx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testAccessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockCtx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;KoaContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;koa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;API_URI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;rejects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toThrowError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sr"&gt;/access token invalid/i&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Code explanation
&lt;/h4&gt;

&lt;p&gt;Here, we're creating a &lt;code&gt;testAccessToken&lt;/code&gt; that is just a random string, and giving it to our middleware. In this case, we're expecting the middleware to throw an error that matches the regular expression, &lt;code&gt;access token invalid&lt;/code&gt;. The rest of the logic in this test is the same as the last one, in that we're just mocking our &lt;code&gt;ctx&lt;/code&gt; object and &lt;code&gt;next&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tricky bit: testing dynamic calls to an external API
&lt;/h2&gt;

&lt;p&gt;We always need tests to run in isolation. There are several reasons for this, but the main one is that we're not interested in testing anything that's not a part of our code, and therefore outside of our control.&lt;/p&gt;

&lt;p&gt;So the question is, how can we dynamically test for different responses from an external API or service?&lt;/p&gt;

&lt;p&gt;First, we mock the &lt;code&gt;node-fetch&lt;/code&gt; library, which means that any code in the function we test that uses &lt;code&gt;node-fetch&lt;/code&gt; is mocked. Next, in order to make the responses dynamic, we create a variable that we can assign different values to depending on what we're testing. We then get our mocked &lt;code&gt;node-fetch&lt;/code&gt; function to return a function, which mocks the response object provided by Express and Koa.&lt;/p&gt;

&lt;p&gt;That's a bit of a mouth full. So let's look at some code...&lt;/p&gt;

&lt;h2&gt;
  
  
  Here's my solution
&lt;/h2&gt;

&lt;p&gt;At the top of my &lt;code&gt;.spec&lt;/code&gt; file, we have the following (in JS to make it easier to read):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The variable we can change for different tests&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mockTokenFromAPI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Mocking the 'node-fetch' library&lt;/span&gt;
&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`node-fetch`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The function we want 'node-fetch' to return&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generateResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Mocking the response object&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;newAccessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mockTokenFromAPI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Put it all together, Jest!&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;generateResponse&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We first get Jest to mock the &lt;code&gt;node-fetch&lt;/code&gt; library by returning a function. We then get the mocked library to return another function called &lt;code&gt;generateResponse()&lt;/code&gt;. The purpose of &lt;code&gt;generateResponse&lt;/code&gt; is to mock the response objects in Express and Koa, so it returns an object with the &lt;code&gt;json&lt;/code&gt; key. The value of &lt;code&gt;json&lt;/code&gt; is a function, thus mocking the &lt;code&gt;.json()&lt;/code&gt; method, which finally returns the data structure we're expecting from the API, using our &lt;code&gt;mockTokenFromApi&lt;/code&gt; variable. So now in order to make the whole thing dynamic, all we have to do in our tests is change the value of this variable!&lt;/p&gt;

&lt;h5&gt;
  
  
  Let's Typescript this up...
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IJsonResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;newAccessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;IJsonResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mockTokenFromAPI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`node-fetch`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generateResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;IResponse&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;IJsonResponse&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;newAccessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mockTokenFromAPI&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;generateResponse&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now here's how we can test our middleware with dynamic responses from an external API using the &lt;code&gt;node-fetch&lt;/code&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Middleware throws error if refresh token errors`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create an expired but valid access token to send&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testAccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`1234`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`0`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// DYNAMICALLY SET WHAT WE WANT THE EXTERNAL API / SERVICE TO RETURN&lt;/span&gt;
    &lt;span class="c1"&gt;// In this case, an invalid token&lt;/span&gt;
    &lt;span class="nx"&gt;mockTokenFromAPI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`abc123`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockCtx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testAccessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockCtx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;KoaContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;koa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;API_URI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;rejects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toThrowError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sr"&gt;/refresh token error/i&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Middleware calls next if refresh token exists and is valid`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create an expired but valid access token to send&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testAccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`1234`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`0`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// DYNAMICALLY SET WHAT WE WANT THE EXTERNAL API / SERVICE TO RETURN&lt;/span&gt;
    &lt;span class="c1"&gt;// In this case, a valid token&lt;/span&gt;
    &lt;span class="nx"&gt;mockTokenFromAPI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;tokenData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`1234`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`1h`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockCtx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;testAccessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockCtx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;KoaContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;koa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;API_URI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callCount&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;We now have the ability to get 100% isolated test coverage on our middleware, even though it relies on an external API.&lt;/p&gt;

&lt;p&gt;I hope this helped you in some way, and if it didn't, I hope you learned something or at least found it interesting!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
