<?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: How to dev</title>
    <description>The latest articles on DEV Community by How to dev (@how-to-dev).</description>
    <link>https://dev.to/how-to-dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F4981%2F32aa81e3-6577-4707-86b6-9785004b710d.jpg</url>
      <title>DEV Community: How to dev</title>
      <link>https://dev.to/how-to-dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/how-to-dev"/>
    <language>en</language>
    <item>
      <title>Advantages of unit testing—with examples in Jasmine</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Thu, 15 Feb 2024 21:50:48 +0000</pubDate>
      <link>https://dev.to/how-to-dev/advantages-of-unit-testing-with-examples-in-jasmine-2lio</link>
      <guid>https://dev.to/how-to-dev/advantages-of-unit-testing-with-examples-in-jasmine-2lio</guid>
      <description>&lt;p&gt;Writing unit tests takes time and effort. Nonetheless, many teams insist on writing them anyway—that’s because of the benefits they bring to a project. Those benefits are mainly the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fast feedback—unit tests speed up each iteration of tweaking the code, and those gains can offset at least some time spent on writing tests.&lt;/li&gt;
&lt;li&gt;Explicit expectations—clear communication of what is expected from the code. &lt;/li&gt;
&lt;li&gt;Attention to edge cases—good unit tests will provide examples for every edge case that developers can think of.&lt;/li&gt;
&lt;li&gt;Easy refactoring—an infrastructure to support code evolution in the long term.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see those benefits in more details:&lt;/p&gt;

&lt;h2&gt;
  
  
  Fast feedback
&lt;/h2&gt;

&lt;p&gt;Computers excel at well-defined, repetitive tasks. When you write unit tests, you write code that will verify whether your program does what it was meant to do. With automated verification in place, you can check your code very quickly. In my work, I have 3200+ that run just under14 seconds. With such performance, you can retest your whole codebase every time when you save your code. After I got more experience with writing unit tests, it started to feel that the time I saved with the quicker feedback loop returns the time I invested in writing tests.&lt;/p&gt;

&lt;p&gt;As an example, let’s see update unit tests for the &lt;code&gt;translate&lt;/code&gt; method introduced in my &lt;a href="https://how-to.dev/pure-functions-and-basic-tests-in-jasmine"&gt;last article&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;translate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should translate to supported languages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cześć!&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should default to english if language missing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should return the key if translation is missing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;farewell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;farewell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;farewell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;farewell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;farewell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;farewell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running those tests happens in the blink of an eye:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; testing-example@1.0.0 &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; jasmine

Randomized with seed 31262
Started
...


Ran 3 of 21 specs
3 specs, 0 failures
Finished &lt;span class="k"&gt;in &lt;/span&gt;0.003 seconds
Incomplete: fit&lt;span class="o"&gt;()&lt;/span&gt; or fdescribe&lt;span class="o"&gt;()&lt;/span&gt; was found
Randomized with seed 31262 &lt;span class="o"&gt;(&lt;/span&gt;jasmine &lt;span class="nt"&gt;--random&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;--seed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;31262
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explicit expectation
&lt;/h2&gt;

&lt;p&gt;Another big advantage of unit tests is stating the expectations explicitly in the code. For example, the data formatting function &lt;code&gt;shortDate&lt;/code&gt; could do one of the following things when provided with an argument that is not a date:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;throw an error,&lt;/li&gt;
&lt;li&gt;return undefined, or&lt;/li&gt;
&lt;li&gt;return empty string.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of those choices could be a good idea in some places, so it could happen that at some point the exact behavior will be changed. I like adding special cases like this to the test, so the future developer will be reminded that some code can depend on specific behavior when they start changing the API.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shortDate&lt;/code&gt; tests, updated to cover invalid inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shortDate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should correctly format date&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-11-02&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shortDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-11-02&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should fail gracefully for no-dates&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shortDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shortDate&lt;/span&gt;&lt;span class="p"&gt;({})).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shortDate&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="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shortDate&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Attention to edge cases
&lt;/h2&gt;

&lt;p&gt;When I write the implementation for a method, I think about the happy path—everything going as expected. When I write unit tests, I think about everything that can go wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;some arguments missing,&lt;/li&gt;
&lt;li&gt;wrong data type, or&lt;/li&gt;
&lt;li&gt;invalid combinations or arguments—such as dividing 0 by 0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Covering those edge cases makes the tests really helpful. A few examples form the demo repository:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;greet&lt;/code&gt; tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should greet by name and surname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ipsum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Lorem Ipsum!&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should fail gracefully for missing arguments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Lorem!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ipsum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Ipsum!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;applyDiscount&lt;/code&gt; tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;applyDiscount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should lower the price accordingly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should manage rounding error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.06&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should round results to 0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.83&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should return NaN for corrupt inputs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeNaN&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeNaN&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toBeNaN&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should throw errors on discount percentage outside 0-100 range&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;125&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toThrowError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toThrowError&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;&lt;code&gt;calculatePrice&lt;/code&gt; tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;calculatePrice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should find a price of many products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should manage rounding error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should round results to 0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.56&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should return NaN for corrupt inputs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeNaN&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeNaN&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toBeNaN&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;
  
  
  Easy refactoring
&lt;/h2&gt;

&lt;p&gt;Once I have all expectations for my code defined, it’s effortless to refactor it. We can safely reorganize the code, improving the quality while maintaining the behavior. Removing friction from code improvements is where we see plenty of long-term benefits from unit testing. When your team is enabled to improve code without the fear that they will break something, they are more likely to try improving things.&lt;/p&gt;

&lt;p&gt;On the flip side, code that nobody can change without causing some unexpected changes is code that is very difficult and risky to improve. Unit tests are often a barrier that prevents code from entering into a spiral of growing complexity and unmaintainability.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ellipsis&lt;/code&gt; tests are a good example of checking all the behavior we could possibly care about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ellipsis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should shorten long text at 50 chars&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a faucibus massa.&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="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing…&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should leave short text unchanged&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum sin dolor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum sin dolor&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should shorten to custom length&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum sin dolor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsu…&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should return unchanged non-string argument&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;lorem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ipsum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;lorem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ipsum&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should ignore second argument if not number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a faucibus massa.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing…&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The cost/benefit balance will depend a lot on the type of project and the team that works on it. For benefits to show, you need a certain quality of tests—and this can be difficult if nobody on your team has experience with building unit tests. The communication benefits are greater when you have a bigger team—so different people work on the code; or when the projects live a long time—so people need a reminder about their past decisions. Long-term benefits of enabled refactoring will appear only if the project exists long enough such that the need for refactoring has a chance to arise.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>testing</category>
    </item>
    <item>
      <title>Pure functions and basic tests in Jasmine</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Thu, 08 Feb 2024 08:49:07 +0000</pubDate>
      <link>https://dev.to/how-to-dev/pure-functions-and-basic-tests-in-jasmine-23ch</link>
      <guid>https://dev.to/how-to-dev/pure-functions-and-basic-tests-in-jasmine-23ch</guid>
      <description>&lt;p&gt;Pure functions are the perfect case for unit testing. For a given input, we always expect the same output—there is no internal state involved. Let’s take a look at a few examples and some simple tests that check if the methods work as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jasmine
&lt;/h2&gt;

&lt;p&gt;Jasmine is a unit test framework for JavaScript. It can run tests in both Node.js or on the browser. It’s used in the Angular framework, and it’s especially popular in projects based on Angular. It’s a solid choice for Vanilla JS projects, or projects based on other frameworks as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Happy path testing
&lt;/h2&gt;

&lt;p&gt;Happy path testing is when we test a method with inputs that it’s expected to work normally using. The arguments are valid and within reasonable ranges. Those tests check if the method does its job correctly—the test cases should be straightforward examples of how the method is explained in its documentation.&lt;/p&gt;

&lt;p&gt;Pseudocode examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;expect(add(2, 2)).toBe(4)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;expect(concatenate(“Lorem”, “Ipsum”)).toBe(“LoremIpsum”)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those tests are meant to automatically catch it anytime the method key behavior is broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods
&lt;/h2&gt;

&lt;p&gt;Let’s see a few simple methods: simple operations that we might need in some real-world application.&lt;/p&gt;

&lt;p&gt;All implementations are greatly simplified—all methods will break in an ugly way if only we provide them with parameters that differ slightly from what is expected. The code is far from being robust.&lt;/p&gt;

&lt;h3&gt;
  
  
  greet
&lt;/h3&gt;

&lt;p&gt;Method that greets the user with their name and surname:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;surname&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="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;surname&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  shortDate
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;shortDate&lt;/code&gt; is a formatting method that takes a date object and returns it formatted as a short string. The code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shortDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&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;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;substring&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="mi"&gt;10&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;
  
  
  ellipsis
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ellipsis&lt;/code&gt; takes a long text string and an optional length parameter and then trims the string to fit within the limit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&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;50&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;text&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;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;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&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;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;…&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;text&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;
  
  
  translate
&lt;/h3&gt;

&lt;p&gt;A method that provides translated string values for a &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;lang&lt;/code&gt; pair. It’s a simplified implementation of what could be replaced with more advanced translating libraries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&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="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cześć!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  applyDiscount
&lt;/h3&gt;

&lt;p&gt;Method to apply a percentage discount to a price. It can feel like overkill with this naive implementation, but later when we start investigating edge cases it will get much more interesting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discountPercentage&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;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;discountPercentage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&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;
  
  
  calculatePrice
&lt;/h3&gt;

&lt;p&gt;This one calculates the total price when buying multiple units at a given price. It will also get more complicated after adding interesting edge cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unitPrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quantity&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;unitPrice&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;quantity&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;
  
  
  Complete JS code
&lt;/h2&gt;

&lt;p&gt;The complete JS code, &lt;code&gt;src/main.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;surname&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="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;surname&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shortDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&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;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;substring&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&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;50&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;text&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;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;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&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;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;…&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&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="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cześć!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discountPercentage&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;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;discountPercentage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unitPrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quantity&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;unitPrice&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;quantity&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;
  
  
  Adding Jasmine tests
&lt;/h2&gt;

&lt;p&gt;To add Jasmine, let’s start by converting the folder into an npm package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm init -y
Wrote to …/package.json:
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can install the Jasmine package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; jasmine

added 42 packages, and audited 43 packages &lt;span class="k"&gt;in &lt;/span&gt;2s

13 packages are looking &lt;span class="k"&gt;for &lt;/span&gt;funding
  run &lt;span class="sb"&gt;`&lt;/span&gt;npm fund&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;details

found 0 vulnerabilities
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then we can generate folders and files used by Jasmine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx jasmine init
&lt;span class="o"&gt;(&lt;/span&gt;no output&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command generates the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;spec/&lt;/code&gt;—a folder where we can put &lt;code&gt;*.spec.js&lt;/code&gt; files with the test, and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spec/support/jasmine.json&lt;/code&gt;—a file with the Jasmine config.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Unit tests
&lt;/h2&gt;

&lt;p&gt;For the following unit tests, I’m focusing on the happy path only—I check if the result is as expected for reasonable inputs. The test should be self-explanatory, so let’s take a look at them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;shortDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../src/main.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;greet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should greet by name and surname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ipsum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Lorem Ipsum!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shortDate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should format correclty date&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-11-02&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shortDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-11-02&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shortDate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should shorten long text at 50 chars&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a faucibus massa.&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="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing…&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should leave short text unchanged&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum sin dolor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum sin dolor&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should shorten to custom length&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsum sin dolor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lorem ipsu…&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;translate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should translate to supported langauges&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cześć!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;applyDiscount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should lower the price accordingly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&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="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;calculatePrice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should find a price of many products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;4.5&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;p&gt;(file &lt;code&gt;spec/main.spec.js&lt;/code&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Running tests
&lt;/h2&gt;

&lt;p&gt;To run the tests, we can add the following script to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;..&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jasmine"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="w"&gt;   
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this in place, &lt;code&gt;npm run test&lt;/code&gt; runs our tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run test

&amp;gt; testing-example@1.0.0 test
&amp;gt; jasmine

Randomized with seed 76873
Started
........


8 specs, 0 failures
Finished in 0.004 seconds
Randomized with seed 76873 (jasmine --random=true --seed=76873)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this post, we took a look at a simple example of JS code and how it can be covered by unit tests. You can find the &lt;a href="https://github.com/how-to-js/testing-example/tree/jasmine-basic"&gt;complete code example on GitHub&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
      <category>jasmine</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to prepare for a job interview</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Thu, 01 Feb 2024 10:00:13 +0000</pubDate>
      <link>https://dev.to/how-to-dev/how-to-prepare-for-a-job-interview-1d51</link>
      <guid>https://dev.to/how-to-dev/how-to-prepare-for-a-job-interview-1d51</guid>
      <description>&lt;p&gt;Let’s say you have a job interview in a few days. How should you prepare for it so that you can make an informed decision about joining the company, as well as make sure that your interests are taken care of?&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare your questions
&lt;/h2&gt;

&lt;p&gt;An interview is a two-way street: it’s not only the company investigating you as a potential employee: in addition, you are investigating the company as a potential employer. Hopefully, you have some other options available—such as staying at your current place or trying out other companies interested in you. In the best case, you’ll have flexibility to decide whether you want to follow through with the company or not.&lt;/p&gt;

&lt;p&gt;To learn about the potential employer, you need to ask questions. The question will depend on what’s important for you at the current stage of your career. Some things I would like to know before deciding to join a new company are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is their development process? If they use some standardized methodology as Scrum, I would like to hear how they implement it. Especially whether they have Scrum Master and Product Owner roles covered—and whether those people are easily reachable. I would also ask if they do retrospectives meetings.&lt;/li&gt;
&lt;li&gt;How do they do quality automatization: things such as unit tests, e2e, CI &amp;amp; code-style enforcing? For things that they don't have, I would ask if they would like to see it in the project.&lt;/li&gt;
&lt;li&gt;I would ask about their product, and how they do product design/discovery.&lt;/li&gt;
&lt;li&gt;Life–work balance questions inspired by &lt;a href="https://www.youtube.com/watch?v=cNbWmjGNZD8&amp;amp;t=1213s"&gt;Healthy Software Developer’s video&lt;/a&gt;:
** how long do employees usually work?
** how do they deal with emergencies?
** how often is there a need to receive a call or respond to messages outside working hours?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Salary negotiation
&lt;/h2&gt;

&lt;p&gt;The point of going to the interview is to get to the salary negotiation. The result of the negotiation will have a great impact on your life for the whole time you spend at the company—it’s a smart move to prepare well. The earlier you start, the better—as you will have more time to investigate, ask questions, and plan your strategy. &lt;/p&gt;

&lt;p&gt;The best resource for preparing for an interview in IT is &lt;a href="https://fearlesssalarynegotiation.com/"&gt;Fearless Salary Negotiation&lt;/a&gt;. You can buy the complete e-book, read the chapters online, or get the key advice from the bite-size articles on the website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Research compensation
&lt;/h3&gt;

&lt;p&gt;Before you start negotiation, figure out the current situation at the market. A little bit of time spent on systematic investigation can give you a much more precise picture than anecdotes heard here or there. Check out this &lt;a href="https://fearlesssalarynegotiation.com/book/value/market-value-overview/"&gt;chapter on market value estimation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decide your minimum
&lt;/h3&gt;

&lt;p&gt;Great advice is to decide on the  minimum pay that you’ll accept &lt;em&gt;before&lt;/em&gt; you start speaking with the company. It could happen that during the various rounds of interviews, they will manage to &lt;em&gt;sell&lt;/em&gt; the company very well, or that the effort you have already invested into the company will make you more flexible than you should be. In those cases, having the minimum salary decided ahead of time can be very helpful. &lt;a href="https://fearlesssalarynegotiation.com/book/negotiate/what-is-your-minimum-acceptable-salary/"&gt;Relevant chapter from the book here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Think open about your options
&lt;/h3&gt;

&lt;p&gt;As you negotiate with the company, it’s good to be flexible about options you consider. If you are asking for more money than they have budget for, you can propose reduced hours with the same hourly rate that you are happy with. Similarly, commuting to the office can easily take 1–2 hours of your day, so a lower salary could be worth it if it comes with guaranteed remote work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practice interview
&lt;/h2&gt;

&lt;p&gt;Try role-playing an interview with someone. If you can handle it, you can ask them to be tough on you—stricter than what you would expect from a real interview. Ideally, you’ll have a tough, low-stakes interview that would make you relaxed during the real thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Investigate the company
&lt;/h2&gt;

&lt;p&gt;Learn about the company—all you can before the meeting, that is. Check their website, their LinkedIn page, and their key employees. Play around with their product if you can. In short, spend an hour or two trying to learn as much as you can about the company. It will help you ask important questions and make a good impression.&lt;/p&gt;

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

&lt;p&gt;A bit of preparation can go a long way. As developers, we often think about the technical part of the interview, but learning about the company and preparing for salary negotiation can help us even more. We can filter out companies we shouldn’t join, and we can make sure that we get as good a deal as possible.&lt;/p&gt;

</description>
      <category>interview</category>
    </item>
    <item>
      <title>How to build a demo project</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Thu, 25 Jan 2024 08:32:09 +0000</pubDate>
      <link>https://dev.to/how-to-dev/how-to-build-a-demo-project-4m4e</link>
      <guid>https://dev.to/how-to-dev/how-to-build-a-demo-project-4m4e</guid>
      <description>&lt;p&gt;Creating example projects is a common way of showing your skills to potential employers. Let’s take a look at what’s important to keep in mind when building personal projects with an eye toward impressing prospective employers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplicity
&lt;/h2&gt;

&lt;p&gt;Building applications takes a lot of time and effort. Most projects of any kind are greatly underestimated. There are always unpredictable difficulties that you  encounter only after you start working. Besides that, in the case of personal projects, the project will compete with all the other things that you could be spending your spare time on.&lt;/p&gt;

&lt;p&gt;The solution to that problem is to keep the feature set as simple as possible. Even the simplest project proves your ability to deliver and shows how you work and what code you can create. If you can make the application solve some problem, that’s great—but focus on finding the minimal feature scope to address the need.&lt;/p&gt;

&lt;p&gt;If you are looking for inspiration for an application to build, in my &lt;a href="https://how-to.dev/oh-my-bill-project-introduction"&gt;other article&lt;/a&gt; I  present a simple energy usage calculator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Covers many aspects
&lt;/h2&gt;

&lt;p&gt;Keeping your feature set small will leave you with time and energy for expanding in another direction—to cover many different aspects of application development. Of all the types of things you can create, it’s always the first of its kind that delivers the most value. For example, demonstrating one class with full unit test coverage shows that you can design testable code, write unit tests, and set up the environment to run them. Writing ten classes would prove your persistence and commitment to the project, but there is a diminishing return on your investment. &lt;/p&gt;

&lt;h3&gt;
  
  
  Idea
&lt;/h3&gt;

&lt;p&gt;First and foremost, you need an idea for your project. The scope constraints make it tricky to find something that is simultaneously interesting and simple. A common approach is to either make a simple clone of a known application or to follow somebody’s idea for a demo app.&lt;/p&gt;

&lt;p&gt;A more creative approach would be to find a small real-world problem and try to solve it with an application. To keep the scope under control, you should aim for making a &lt;a href="https://en.wikipedia.org/wiki/Minimum_viable_product"&gt;minimum viable product&lt;/a&gt; (MVP)—the simplest product that addresses the users’ needs.&lt;/p&gt;

&lt;p&gt;The nice way to describe your application idea is to write &lt;a href="https://en.wikipedia.org/wiki/User_story"&gt;user stories&lt;/a&gt;. You could start with a very high-level one:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As a gym user, I want an application to book training sessions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then you can move down to more precise ones:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As a gym user, I want to have a page that shows the gym schedule with available spots for each class. I want to be able to book classes that have spaces left.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Mockup
&lt;/h3&gt;

&lt;p&gt;Before you begin in your code editor, it makes sense to draw the interface that you plan to build. You can catch many potential issues by thinking about how exactly things will be presented and how users will transition from one place to another. Working with pen and paper is much faster than working with code, and you can easily make many iterations of your interface in an hour or two.&lt;/p&gt;

&lt;p&gt;You can use the mockups to communicate your ideas—as I wrote &lt;a href="https://how-to.dev/how-to-collect-inputs-for-your-project"&gt;before&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Code repository
&lt;/h3&gt;

&lt;p&gt;As you start working with code, it makes sense to start a new repository. Git is an important skill for all developers, and it’s worth showing that you are familiar with it and that you follow &lt;a href="https://how-to.dev/how-to-get-the-most-value-out-of-your-git-repository"&gt;good practices&lt;/a&gt;. At the same time, putting your project on GitHub makes it accessible for others as well—so you show your skills and publish your work at the same time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Communication
&lt;/h3&gt;

&lt;p&gt;Communication skills are as important for programmers as technical skills. Your work has no way of impacting others if they cannot understand what your project is supposed to do. Usually, you demonstrate your communication skills in action to the people who interact directly with you. A demo project presents an excellent opportunity to demonstrate your skill to the broader public: the README file.&lt;/p&gt;

&lt;p&gt;In the README file, your audience is clear: people interested in your project, most likely other programmers who have no idea about what it does and how it works. Providing this information efficiently will show that you can understand what users want to know and provide them just that. You can see more info about writing README files in a &lt;a href="https://how-to.dev/the-readme-file-how-to-help-others-understand-your-project"&gt;guest post on my blog&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Prototype
&lt;/h3&gt;

&lt;p&gt;The next step would be to build a clickable interface. Build the screens that you designed with mockups using the technologies you plan to use in your final application. Don’t worry about implementing any functionalities: use hard-coded data and buttons that set values without any logic behind the updates. The goal is to give an impression of a usable application before spending time on building the actual thing.&lt;/p&gt;

&lt;p&gt;The benefits of starting with a prototype are two-fold. You will be able to try out the interface or ask others to give it a shot. The feedback from this experience will inform your further work on the application—maybe you will tweak some screens, or you will realize you are missing something. Besides that, at this stage your project will be ready to share as a demo with others: there is not much code in there yet, but one will already be able to see enough of your work to evaluate your skills.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code quality
&lt;/h3&gt;

&lt;p&gt;With some code ready to go, I recommend you put some code quality checks in place. The most basic verification will be static analysis of your code—checking your code without executing it. A few things that you can set up for your code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;linters—Programs that check code for possible issues and recommend best practices. For frontend projects you can use things such as &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;, &lt;a href="https://stylelint.io/"&gt;Stylelint&lt;/a&gt;, &lt;a href="https://htmlhint.com/"&gt;HTMLHint&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;code style tools—Programs that enforce a specific formatting for your code. On the frontend, Prettier covers almost all file types you could expect. I already wrote about it &lt;a href="https://how-to.dev/how-to-make-your-code-prettier"&gt;on the blog&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vanilla JS
&lt;/h3&gt;

&lt;p&gt;The next step is to implement the features with Vanilla JS alone. You can skip this step if you already know a JS framework well enough to build an application with it. If you don't, Vanilla JS is the safest bet—it’s the foundation that other solutions are using. I have a &lt;a href="https://how-to.dev/how-to-implement-a-basic-javascript-application"&gt;simple guide&lt;/a&gt; on how to set up a simple JS project with Webpack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Continuous Integration
&lt;/h3&gt;

&lt;p&gt;At this stage, your project will already have scripts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;static analysis to ensure the quality and styling of the code, and&lt;/li&gt;
&lt;li&gt;a build script that prepares the code for deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each change set, you can expect the codebase to be able to pass both scripts without any errors. You can enforce this expectation by setting up continuous integration (CI). Git hosting providers such as GitHub and GitLab offer CI on even the free plans. You can read more about the benefits &lt;a href="https://how-to.dev/continuous-integration-ci-and-how-it-can-help-you"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;With CI in place, the very next step is to deploy your application somewhere. Deploying the application will make it easy for anybody to check out your application in action—after all, people are more likely to click on the link than to download and build code locally. The easiest places to deploy are GitHub Pages, or GitLab Pages—each of them is easy to set up from the repository hosting. For GitLab, I have a &lt;a href="%E2%80%8B%E2%80%8Bhttps://how-to.dev/how-to-deploy-an-application-to-gitlab-pages"&gt;guide on the blog&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Framework
&lt;/h3&gt;

&lt;p&gt;Finally, with all that in place, you can move your application to your framework of choice. There are many options available, and you should choose one that matches what you would like to learn and what’s needed in your job market.&lt;/p&gt;

&lt;p&gt;If your application is indeed small, rewriting it to a framework shouldn’t be a big project—changing a few files from JS+HTML to whatever your frameworks uses. If it’s much more than that, you can rethink the scope of the project and find a smaller set of features to build your MVP. And build the rest &lt;em&gt;after&lt;/em&gt; you move your project to the framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;Lastly, to show that you care about the quality of the code you produce, you can add tests to the application. On the front end, we usually consider two levels of testing: unit tests that check the individual parts of the application, and end-to-end tests that interact with the whole app through its user interface. For a professional project, I &lt;a href="https://how-to.dev/does-my-web-application-need-end-to-end-and-unit-tests"&gt;recommend using both&lt;/a&gt;. For demo projects, unit tests alone should be enough—they are easier to set up and faster to run. &lt;/p&gt;

&lt;p&gt;It makes sense to add unit tests &lt;em&gt;after&lt;/em&gt; moving to a framework because Vanilla JS code is often difficult to test. Frameworks such as React, Vue, or Angular come with their own unit testing tools and best practices, so you should follow framework-related advice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good examples
&lt;/h2&gt;

&lt;p&gt;In my work with &lt;a href="https://how-to.dev/free-mentoring"&gt;mentees&lt;/a&gt;, I’ve had a chance to see this idea applied in practice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laundry
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/gulfaniputra"&gt;Gulfani Putra&lt;/a&gt; is working on an application that is for laundry services to inform customers about the progress of their order. It’s a practical and simple example: the idea came from inefficiencies that he had seen in local business and that could be addressed with a simple application. If you go to the &lt;a href="https://github.com/gulfaniputra/laundry-app"&gt;project page at GitHub&lt;/a&gt;, you can see the power of a good README file. By reading it, you will get a pretty good overview of what, why, and how he is building.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hexter
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/wojcraft"&gt;Wojciech Peczyk&lt;/a&gt; is building an application that randomly generates a color code: &lt;a href="https://github.com/wojcraft/hexter/tree/main"&gt;Hexter&lt;/a&gt;. The use case is straightforward to implement, and it allows showcasing all aspects of the project. In the case of features, it’s always possible to add more later on: things such as a button to copy the color to the clipboard, storing previously found colors, etc.&lt;/p&gt;

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

&lt;p&gt;Writing a demo project is a great idea to showcase your ability to deliver useful applications. At the same time, it’s a lot of work: more than one expects before starting. That’s why it’s important to keep the feature set small, cover many aspects of the project in it, and make sure you can show it to others before you are completely done with it. If you manage to build a project that touches all aspects covered in this article, you will have a strong demo project to show anybody interested in your skills.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>demo</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>What is version control?</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Thu, 11 Jan 2024 15:29:44 +0000</pubDate>
      <link>https://dev.to/how-to-dev/what-is-version-control-ne1</link>
      <guid>https://dev.to/how-to-dev/what-is-version-control-ne1</guid>
      <description>&lt;p&gt;Version control is a basic but integral tool in software development. Many people don’t prioritize it while learning to program and, often, developers only start using it when they start their job. Let’s see what version control is and how it can help you even before you start working on professional projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;p&gt;When you program, you’ll have many interconnected files that have to be in a precise state for things to work. In the case of the simplest applications, you can manage files yourself. As the complexity of the application grows, however, the difficulty of tracking the changes grows even faster.&lt;/p&gt;

&lt;p&gt;Version control is a tool to manage the state of the codebase. It’s an additional level of control on top of the files stored on the disc. So, along with your files, you have a code repository that stores additional information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;previous versions of code,&lt;/li&gt;
&lt;li&gt;sets of changes that can be applied, or reverted, together, and&lt;/li&gt;
&lt;li&gt;descriptions and metadata for sets of changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With version control, you can store code snapshots. You can think of it as a sort of ‘save’ for development—a place that you can always return to if you mess up something. Same as in games, saving your progress regularly helps to avoid being forced to do the same task twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git
&lt;/h2&gt;

&lt;p&gt;Currently, Git is the de facto standard for version control in the industry. You can safely assume that it’s all you need as a beginner—with a solid grasp of Git, you will be able to pick any tool that your employee could require you to learn.&lt;/p&gt;

&lt;p&gt;Git is a distributed system—in a typical use case, everybody has a complete copy of the repository on their machines. The copies of the repository can be easily synchronized. Usually, you have a central, remote repository that is often called “origin,” and each developer synchronizes with this repository.&lt;/p&gt;

&lt;p&gt;The centralized repositories are often hosted by external providers, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub,&lt;/li&gt;
&lt;li&gt;GitLab,&lt;/li&gt;
&lt;li&gt;CodeSummit from AWS,&lt;/li&gt;
&lt;li&gt;or others.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Impact on productivity
&lt;/h2&gt;

&lt;p&gt;Let’s see how using version control can improve your productivity. &lt;/p&gt;

&lt;h3&gt;
  
  
  Revert local changes
&lt;/h3&gt;

&lt;p&gt;The first impact is in having a quick way to revert any changes you’ve made locally. Sometimes you need to change the code in many places to make one change. Without version control, getting back to what was already working could be difficult: imagine having to revert changes to five different files in your code editor. You can be as careful as you want, but occasionally, you will struggle to get back in time—unless you create snapshots of your working application with version control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrate changes from many sources
&lt;/h3&gt;

&lt;p&gt;When you have changes coming from many sources, it can be challenging to get them integrated. Even without changes to the same file, it can be difficult to find what was changed in what files when different developers build different features. Changes to the same file are almost impossible to integrate manually—you would have to check the files line-by-line.&lt;/p&gt;

&lt;p&gt;Git tracks all changes separately, and it has a powerful feature of three-way merges: comparing two versions of the file that are being merged and the original state before they diverged. Thanks to this capability, Git can often integrate changes without developer intervention—and I have never seen those automated merges produce invalid code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restore past versions
&lt;/h3&gt;

&lt;p&gt;Sometimes, you want to get your code to where it was in the past—Git has you covered. You have many options to achieve this reversion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git checkout &amp;lt;version&amp;gt;&lt;/code&gt; at some version in the past—so you can see how the code worked at a given point&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git reset --hard &amp;lt;version&amp;gt;&lt;/code&gt;—move your branch to the specific version, dropping changes that have been made since that point&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git checkout &amp;lt;version&amp;gt; -- &amp;lt;file&amp;gt;&lt;/code&gt;—restore a given file to its state in some other version&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you’re working on a codebase, those features really come in handy.&lt;/p&gt;

&lt;h3&gt;
  
  
  History
&lt;/h3&gt;

&lt;p&gt;The longer a project lives and the more changes that occur throughout its life, the more value can be found in its history. Well-maintained history, with well-described, atomic commits can provide insight into why things are the way that they are right now in the codebase. This information can help future developers make informed decisions about code changes. In another article, I wrote about &lt;a href="https://how-to.dev/how-to-get-the-most-value-out-of-your-git-repository" rel="noopener noreferrer"&gt;creating a useful Git history&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Reverting some specific update
&lt;/h3&gt;

&lt;p&gt;Git allows you to revert very specific sets of changes with &lt;code&gt;git revert &amp;lt;version&amp;gt;&lt;/code&gt;. This command attempts to bring all affected files to the state before the change. It often requires manual conflict resolution, and it adds a new commit to revert the changes. This is another reason why you want your commits to be small, and contain closely related changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What goes into the repository?
&lt;/h2&gt;

&lt;p&gt;Once we have a code repository, we can start using it. Let’s see what things are typically managed with version control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source code
&lt;/h3&gt;

&lt;p&gt;The source code of our application is the most obvious example. In the case of a website, we will put all the related HTML, JS, CSS, etc. files into the repo. &lt;/p&gt;

&lt;p&gt;Code that you maintain is the perfect case for version control. Take the following cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you need to store the precise state of the files—even an extra comma or a whitespace in one of the files could break the application&lt;/li&gt;
&lt;li&gt;the files are text-based, so it’s easy to compare different versions&lt;/li&gt;
&lt;li&gt;you manage all the changes—it’s possible to ensure that there is a logical connection between all changes bundled together&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Description of dependencies
&lt;/h3&gt;

&lt;p&gt;For the code that you use but don’t maintain, you’ll usually store only information about dependencies. In the case of JavaScript applications, those are &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;package-lock.json&lt;/code&gt; files. The dependencies can be downloaded with a package manager in places where we want to run the code. Then it’s the package manager’s job to make sure the correct versions are installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Binary files
&lt;/h3&gt;

&lt;p&gt;There are some binary files that you can expect to appear in your codebase. You can expect media files that are used across the application interface: logos or other images, files with sound effects, etc.&lt;/p&gt;

&lt;p&gt;Git can manage binary files, but it's primarily focused on text files. When we store binary files, we cannot enjoy many Git features—such as help with conflict resolution or easy comparison between versions with &lt;code&gt;git diff&lt;/code&gt;. Git repositories will store each version of a binary file in an uncompressed way. If you add big files, and will continue changing them often, your repository will grow quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stays out of the repository
&lt;/h2&gt;

&lt;p&gt;Git is a powerful tool for managing files for your projects, but it’s not the right tool for all your needs. There are specific use cases that are better managed outside of a Git repository. &lt;/p&gt;

&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;p&gt;Many systems require a database to function. In those cases, it could be tempting to keep a database alongside the code inside the repository, but it’s rarely a good idea for various reasons.&lt;/p&gt;

&lt;p&gt;The life cycles of data and code changes are very different. With code, you create locally, test on a staging server, and finally deploy to production. With data, you want a different database for each environment, with some changes occasionally traveling across all of them in one direction or another. &lt;/p&gt;

&lt;p&gt;Databases are likely to compress the data and store it as binary files—and as we discussed before, those are problematic in Git. The only thing you need for running the application locally is a demo database. You could get this with a special container filled up with the example data, or with a database initialization script that you store in the codebase. Both approaches are more suitable than keeping a database in the repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built code
&lt;/h3&gt;

&lt;p&gt;There is no reason to keep your build code in the repository. It’s a binary file, it will take a lot of space, and its value is limited. You can always rebuild it directly from code. For storing build results, you need some other solution as an artifact repository: package registry is one you can get from NPM for node modules and a container repository for things that are deployed with container images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependencies
&lt;/h3&gt;

&lt;p&gt;Adding your dependencies to repo (committing &lt;code&gt;node_modules&lt;/code&gt;) has a few big downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your repo grows considerably, with code that you mostly leave unchanged,&lt;/li&gt;
&lt;li&gt;your commits will become less intelligible—for 100 lines of your own changes, you can get tens of thousands of lines in some 3rd-party libraries, and&lt;/li&gt;
&lt;li&gt;some 3rd-party dependencies are installed differently depending on the operating system. It will become harder to share code between OSes with significant differences between them—for example, between Windows and macOS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  User uploads
&lt;/h3&gt;

&lt;p&gt;In the case of websites, the user upload can end up inside the directory tree of your application. This is what I often saw when I was working on PHP websites. Nonetheless, those files don’t belong to your code repository—you need to find another way to manage them, and besides that, make sure you don’t remove them while deploying a new version of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repository in action
&lt;/h2&gt;

&lt;p&gt;Let’s see some examples of a Git repository. You can explore the repositories with your local Git client or on hosting platforms such as GitHub. Let’s take a look at a &lt;a href="https://lodash.com/" rel="noopener noreferrer"&gt;lodash&lt;/a&gt; repository at GitHub.&lt;/p&gt;

&lt;h3&gt;
  
  
  Codebase
&lt;/h3&gt;

&lt;p&gt;Git provides you a view of any version. The current state the &lt;a href="https://github.com/lodash/lodash/tree/main" rel="noopener noreferrer"&gt;repo&lt;/a&gt;:&lt;/p&gt;

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

&lt;p&gt;or &lt;a href="https://github.com/lodash/lodash/tree/1.0.0" rel="noopener noreferrer"&gt;version 1.0.0&lt;/a&gt; 12 years ago:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Tree
&lt;/h3&gt;

&lt;p&gt;One of my favorite views—all changes displayed on the commit tree. From &lt;a href="https://github.com/lodash/lodash/commits/main/" rel="noopener noreferrer"&gt;main branch&lt;/a&gt;:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Commit diff
&lt;/h3&gt;

&lt;p&gt;You can see the changes that were made in a &lt;a href="https://github.com/lodash/lodash/commit/aa18212085c52fc106d075319637b8729e0f179f" rel="noopener noreferrer"&gt;specific commit&lt;/a&gt; as a diff to all the files in the project:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Attribution
&lt;/h3&gt;

&lt;p&gt;If you want to know the author of the last change to a line, you can use the neatly named &lt;code&gt;git blame&lt;/code&gt; command, or you can see the &lt;a href="https://github.com/lodash/lodash/blame/1.0.0/package.json" rel="noopener noreferrer"&gt;file in blame mode at GitHub&lt;/a&gt;:&lt;/p&gt;

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

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

&lt;p&gt;Version control is a crucial tool in any developer’s toolbox. Not using it guarantees that, eventually, you will waste some time. Learning how to use Git takes effort, but it’s an investment that will pay off hugely when you program—even during your studies or work on personal projects.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why IT projects are never done</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Fri, 29 Sep 2023 05:47:07 +0000</pubDate>
      <link>https://dev.to/how-to-dev/why-it-projects-are-never-done-2b88</link>
      <guid>https://dev.to/how-to-dev/why-it-projects-are-never-done-2b88</guid>
      <description>&lt;p&gt;Many projects I have worked on seemed simple at first glance. Nonetheless, there is always something to be done, and there is no end in sight. Usually, it’s not a problem—as long as there is money to finance the development. Let’s take a look at why IT projects are never done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complexity
&lt;/h2&gt;

&lt;p&gt;Things are always more complicated than they seem at first. Often we have unexpected complexity in two places—the problem we want to solve and the solution itself. As we try to solve the problem, we learn about new aspects that make it more complicated than it looked at first. And the solution that we create often becomes more complicated than necessary. This leads to way slower progress, to the point when the requirements change at the similar rate as the code itself. &lt;/p&gt;

&lt;h2&gt;
  
  
  Technical surroundings
&lt;/h2&gt;

&lt;p&gt;No project is an island. Any functional piece of code depends on countless things over which we have no control. If you look with perspective long enough—5, 10, or 20 years—anything can change: operating systems, programming languages, or ways the IT economy is running. From a business perspective, plenty of efforts take many years to become profitable.&lt;/p&gt;

&lt;p&gt;I started my career in 2008, and over the 15 years since I’ve seen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;iOS (2007) and Android (2008) becoming important operating systems,&lt;/li&gt;
&lt;li&gt;the appearance of Node.js (2009) and its rise to popularity,&lt;/li&gt;
&lt;li&gt;Web platforms overtaking desktop applications,&lt;/li&gt;
&lt;li&gt;the growing popularity of JavaScript, and&lt;/li&gt;
&lt;li&gt;the disappearance of Flash and Java applets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With changes of this scope, there is no way to create &lt;em&gt;a future-proof&lt;/em&gt; project—at some point, you (or your successors) could be forced to rewrite everything on a new stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Third-party APIs
&lt;/h3&gt;

&lt;p&gt;On a less dramatic scale, your application is likely to use some external providers: for managing payments, sending emails, or any other services. Given enough time, some of those providers will go out of business or rebuild their API and deprecate the version that you are using. Usually, there is some transition period, but it will likely be a few months rather than a few years. In a project with many competing priorities, this can feel like short notice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Legal requirements
&lt;/h3&gt;

&lt;p&gt;Similarly, the legal requirements can change from one year to another. In the EU, we had a big change with VAT and online sales in 2021. For many online companies, that meant plenty of changes in the code. They were forced to start dealing with VAT in every EU country that they were selling to.&lt;/p&gt;

&lt;p&gt;The company where I work deals with brick and mortar businesses—we were not affected by online trade regulations. Nonetheless, we had an assumption in the code that there are only 3 levels of VAT—for example 0%, 7%, and 21%. This worked fine for us for a long time. It turned out to be a problem, however, when one of our customers expanded to a new country. Over there, not only were the percentages different, but there were also simply more levels. When you have to change a fundamental assumption like this, you are likely to get an avalanche of changes in your codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code dependencies
&lt;/h3&gt;

&lt;p&gt;A mature JavaScript project has many essential dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the framework it uses&lt;/li&gt;
&lt;li&gt;unit test library&lt;/li&gt;
&lt;li&gt;end-to-end solution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Creators of those tools try to smoothen the upgrade path as much as possible, but they have a trade-off between the ease of upgrade for you and how much they can change. And when the tool is discontinued, moving to a replacement is guaranteed to be a lot of work.&lt;/p&gt;

&lt;p&gt;When I started working with AngularJS, Protractor was an impressive end-to-end tool—the best tool available for doing integration testing of angular applications, and probably for any frontend application. Now, 8–9 years later, it’s been a few years since it got an update, and in August 2023, it reached its end-of-life. There are better tools available now, but moving four hundred tests I have on Protractor would be a huge project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Product discovery
&lt;/h2&gt;

&lt;p&gt;Product discovery is a nice term that covers the fact that it takes time to find the right combination, where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your customers have a problem,&lt;/li&gt;
&lt;li&gt;you can address this problem at scale with an application,&lt;/li&gt;
&lt;li&gt;they are willing to pay for using your solution, and&lt;/li&gt;
&lt;li&gt;what they pay covers your costs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can expect this process to take time and many iterations. Some of the iterations will require implementing a feature and then seeing if it's useful to customers, and whether it makes money for the company. As long as the product is used, there will be some ideas worth checking.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to manage it
&lt;/h2&gt;

&lt;p&gt;So we know that the IT projects are unlikely to be done—that there will always be some changes that require updates to the code. What can we do about it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Plan long term
&lt;/h3&gt;

&lt;p&gt;There are always dead-lines to be met, but make sure that quarterly goals will not ruin the long-term future. Think about it as a marathon, not a sprint. One thing worth investing time in is code quality. Some compromise and flexibility will be needed, but think about overall architecture, consistency, and best practices of the stack you use. Rushing too much can lead to making a code so difficult to maintain that it will become impossible to make the simplest changes.&lt;/p&gt;

&lt;p&gt;Document what you are writing. For a start, maintain a README file with instructions on how to start the project. Write documentation for classes and methods, preferably in a way that makes it easy to extract the documentation—for example, JSDoc.&lt;/p&gt;

&lt;p&gt;Write automated tests. Unit tests slow down development when you are learning to test at the same time as you write code. Once you are proficient with testing, developing tests along with your code can be faster than the code alone. When you write code and tests together, you have a quick way to recheck all the edge cases you want to cover.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep the team around
&lt;/h3&gt;

&lt;p&gt;Even with the best effort at documentation, there is a lot of knowledge that is stored only in the minds of your team members. What decisions were made 4 years ago and why; how similar bugs were fixed the last time; what code is responsible for what. Every time a team loses someone, part of this knowledge is irreversibly lost. It’s a shame the industry got to the point where changing jobs often is the best advice for developers. If you can influence that, it would make sense to make sure the devs are happy with the job and the conditions and stay as long as possible.&lt;/p&gt;

</description>
      <category>management</category>
    </item>
    <item>
      <title>Why is it difficult to get onboarded on an existing project?</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Wed, 20 Sep 2023 04:34:09 +0000</pubDate>
      <link>https://dev.to/how-to-dev/why-is-it-difficult-to-get-onboarded-on-an-existing-project-1pbg</link>
      <guid>https://dev.to/how-to-dev/why-is-it-difficult-to-get-onboarded-on-an-existing-project-1pbg</guid>
      <description>&lt;p&gt;Often, when you start working on a project, you will find yourself struggling with the most basic task: getting it up and running on your machine. This can be a frustrating process, so let’s see what causes those problems and how you can handle it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Developer experience
&lt;/h2&gt;

&lt;p&gt;User experience (UX) focuses on how the user interacts with the system and makes their journey as smooth as possible. Similarly, we could consider developer experience with the system. Usually, in small projects, the priority of improvements that benefit developers is low enough to never be done.&lt;/p&gt;

&lt;p&gt;The examples of good developer experience come from large projects and products targeting developers specifically—for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cypress for end-to-end testing,&lt;/li&gt;
&lt;li&gt;popular frameworks, such as Angular or React, or&lt;/li&gt;
&lt;li&gt;GitHub, CircleCI, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small companies, or one-person open-source projects, often lack the resources needed to make your journey pleasant. Simply, if you have to onboard a new developer once a year, it can be cheaper to have them struggle for a bit then to make the installation smooth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ever-growing complexity
&lt;/h2&gt;

&lt;p&gt;Projects tend to grow in complexity with time. All the time, things are being added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;new features&lt;/li&gt;
&lt;li&gt;refactorings that take forever to be applied on the whole codebase&lt;/li&gt;
&lt;li&gt;dependencies that become outdated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have a project that lasts for a few years, it will definitely be more complicated than something that would be written now. &lt;/p&gt;

&lt;p&gt;The accumulated complexity often spills into troubles with starting up the project: you might find a mismatch of technologies, and they can interact in an unexpected way when you start the project on a new machine. &lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation challenge
&lt;/h2&gt;

&lt;p&gt;Explaining things in writing can be difficult, but this doesn’t often  receive enough attention. Even if the team you join tries to keep docs of a decent quality, there is always one challenge left: they have to assume some level of knowledge in the reader. There is always a trade-off involved with that—when you explain too much, it will be more work to write and maintain the docs. Moreover, you could flood the reader with too much text. If you explain too little, the documentation will lack crucial information for some people.&lt;/p&gt;

&lt;p&gt;Some common examples of things you could struggle with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plenty of programming (C++, Node.js, Python, Git) and internet tools (Apache, Nginx) come from Unix-based systems—if your background is in Windows, then you will be struggling with some underlying concepts.&lt;/li&gt;
&lt;li&gt;Many programming tools are built with the command line interface (CLI) in mind: the most important is Git, but other tools are often important as well—ESLint, Prettier, etc. If you have never used CLI tools, you might have gaps in knowledge that no project documentation will try to address.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I was starting to learn programming, I often got stuck on one or two sentences of the book that described a step I couldn’t overcome. Luckily, as time goes on and you gain experience, cases like this become less common.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unexpected differences
&lt;/h3&gt;

&lt;p&gt;There can be many differences between your machine and whoever builds the system you’re trying to start now. &lt;/p&gt;

&lt;p&gt;Differences in operating systems tend to cause the biggest issues. Linux's distros and macOS are usually compatible enough to be considered one camp. On the other side, we have different versions of Windows. If you join a project that was built on an operating system very different from yours, then you are likely to discover some incompatibles that nobody expected. In JS projects, it’s often expected to be able to run it on whatever OS you like, but it can require some effort to make it truly compatible between systems.&lt;/p&gt;

&lt;p&gt;Another surprise can come with the ways of installing tools you need to run the project. For example, last time I checked, Windows had three ways of installing Git—each method doing things slightly differently. Similarly, Node.js or Python can be installed in many ways on Unix systems, and sometimes developers forget about the ways that are different from their preferred one. I always use &lt;a href="https://github.com/nvm-sh/nvm"&gt;nvm&lt;/a&gt; to manage my Node.js, but it’s not what you find when you go to Node.js website to check for installation guides.&lt;/p&gt;

&lt;h3&gt;
  
  
  Containers to the rescue?
&lt;/h3&gt;

&lt;p&gt;Containerization, which was made popular with Docker, makes it simpler to move across machines and OSes. Unfortunately, you would still be lucky to have your whole developer journey paved with well-prepared, ready to use images. At my job, I had a good experience using Docker as a shortcut to getting a backend up and running quickly locally. Nonetheless, I still struggle to move the whole developer experience to containers so that everybody has the same dependencies available. Containers are a great tool, but any work at optimizing developer experience faces the same lower priority that we mentioned earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to deal with it
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Accept that it will take time&lt;/em&gt;. If your team tells you that the setup can be tricky, or that you can expect some issues—trust them, and don’t get frustrated.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ask questions&lt;/em&gt;. I’ve seen more devs erring on the side of asking too few questions or too late rather than asking too many or too early. If you don’t want to be annoying, or just want to be somehow independent, set an alarm clock to add an hour or two and ask a question when it rings if you are still stuck. Then you can take your time to describe your issue well, following the &lt;a href="https://how-to.dev/how-to-describe-your-technical-issue"&gt;tips&lt;/a&gt; I shared previously.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Improve the doc&lt;/em&gt;. Ultimately, try improving the experience for the next person that will take the same path. The places where you struggled are valuable indicators of where the docs are lacking. Maybe “install Node.js” needs more elaboration with respect to “from where” and “how.” Perhaps you are the first one to run the project on Windows, so you could help others take the same path quicker. In a way, during your installation, you become a beta tester of the documentation, and with everything running, you have enough experience to improve the docs.&lt;/p&gt;

&lt;h1&gt;
  
  
  What was your experience with getting onboarded on a project?
&lt;/h1&gt;

&lt;p&gt;Please share in the comments—I’m truly interested in hearing how it goes for newcomers to projects.&lt;/p&gt;

</description>
      <category>beginners</category>
    </item>
    <item>
      <title>How to write maintainable code: Straightforward logic</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Thu, 07 Sep 2023 11:49:53 +0000</pubDate>
      <link>https://dev.to/how-to-dev/how-to-write-maintainable-code-straightforward-logic-4nie</link>
      <guid>https://dev.to/how-to-dev/how-to-write-maintainable-code-straightforward-logic-4nie</guid>
      <description>&lt;p&gt;Maintaining code is more complicated than writing it. Before you make any changes, you need to understand what is there already, how it was supposed to work, and how it works now. The difficulty of this task will depend on how the code was structured and if it’s an easy read. In this article, I’ll show you how you can make your code more readable and therefore easier to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Obvious entry points
&lt;/h2&gt;

&lt;p&gt;When you start a ticket on an application, usually you have some information about where the change or fix should happen. You can make linking that place to the code easier if you consistently use some convention for naming and placing the files. Let’s take a look at a few examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Component-based app
&lt;/h3&gt;

&lt;p&gt;In my day job, I build and maintain a few Angular applications that are built with components. Each application has many routes defined, and for each route there is a top-level component that is responsible for this view. The naming convention we use is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simple route: &lt;code&gt;/home-page&lt;/code&gt;—&lt;code&gt;&amp;lt;home-page&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;nested route: &lt;code&gt;/long/nested-route&lt;/code&gt;—&lt;code&gt;&amp;lt;long-nested-route&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;route with parameter: &lt;code&gt;/user/:id/edit&lt;/code&gt;—&lt;code&gt;&amp;lt;user-edit&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this way, if I get the route where the changes should happen, I can immediately find related component files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;p&gt;On the backend, we have a few constraints put on the routes we use. The API is loosely inspired by the REST approach, and each endpoint is related to one of the collections that we have in the database. The routes are in a format &lt;code&gt;/collection/operation&lt;/code&gt;—for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/users/get&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/transactions/get-report&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code that is called by those endpoints is organized in files by the collection: so in one file we have methods related to users' collection and in another we have methods related to transactions. In this way, based on the first part of the API route, I know where to look for the code.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid unnecessary jumps
&lt;/h2&gt;

&lt;p&gt;One of the ways that I often see makes the code complicated is by sending the reader through many unnecessary jumps. When you read code, it’s inevitable that you will need to do some jumps between different parts. This becomes a problem when the jumps are many and unnecessary. Some examples based on what I’ve seen in real-world code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a function that does nothing besides creating an alias for another function
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;param1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;param2&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;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;param1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;param2&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 can make sense for some refactoring, but it would be good to have it in a temporary situation,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;named callback functions defined away from where they are used:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/*..success..*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/*..error..*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;getPromise&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same thing would be simpler to read if it were:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getPromise&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&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="cm"&gt;/*..success..*/&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="cm"&gt;/*..error..*/&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;expectations in a test set in variables, away from where they are used:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expectedObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/*..some big object..*/&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/*..many lines of code..*/&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;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expectedObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever we have a jump in code, we make it slightly more complicated to read. Let’s make sure that this inconvenience is balanced by some benefit—that there is a good reason to do it this way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep it simple
&lt;/h2&gt;

&lt;p&gt;The flow of your code should be straight. It should be easy to draw a chart of how the logic flows through the application and how things depend on each other. There should be no circular paths in your code, unless you are doing some recursion on purpose.&lt;/p&gt;

&lt;p&gt;It should be your goal to be always able to explain how user actions or some external events lead to data changes. If you cannot easily tell what is responsible for what, then it’s very likely your code is chaotic and difficult to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Displaying data
&lt;/h2&gt;

&lt;p&gt;Of the simple cases is transforming the data for display. It could be one of many things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;formatting dates in a user's locale,&lt;/li&gt;
&lt;li&gt;translating into user’s language,&lt;/li&gt;
&lt;li&gt;combining many properties of an object into one, ready to display string, or&lt;/li&gt;
&lt;li&gt;filtering an array based on a search.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these operations should have an easily identifiable input and output format and should be written in a form such that a reader knows what goes in and goes out. &lt;/p&gt;

&lt;p&gt;Formatting data for display should leave the original untouched—there is no reason to change the data just because it is displayed in some place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changing state
&lt;/h2&gt;

&lt;p&gt;When you change the state of your data, it should be possible to easily identify the following parts of the code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;source of the change—button that was clicked, the event that occurred in the system, etc.&lt;/li&gt;
&lt;li&gt;the change itself—the code that checks the constraints and updates the state of the data&lt;/li&gt;
&lt;li&gt;saving the changes to the storage—this could be an update to the database in the case of backend code or calling a save API in the case of the frontend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If, for some reason, it’s not easy for you to identify what parts of your code are responsible for some of those points, then reading this code will probably be pretty confusing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testability
&lt;/h2&gt;

&lt;p&gt;All the things we discussed here are consistent with writing testable code. Small, well-defined units with clear responsibilities are easy for developers to understand—and easy to test. For me, writing tests is a good exercise that can teach you to write more readable code: just pay attention when testing starts becoming painful and when the code becomes too convoluted to easily work with. &lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;If you are interested in hearing from me when I publish some new material about programming or related topics, you can &lt;a href="https://how-to-dev.ck.page/a5c69742db"&gt;sign up for my mailing list&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Writing maintainable code: Data model</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Fri, 01 Sep 2023 07:45:01 +0000</pubDate>
      <link>https://dev.to/how-to-dev/writing-maintainable-code-data-model-12g5</link>
      <guid>https://dev.to/how-to-dev/writing-maintainable-code-data-model-12g5</guid>
      <description>&lt;p&gt;In programming, a lot of the challenge is related to organizing data in a structure that makes sense and which helps to solve the problems and facilitates understanding of the code. In this article, I’ll show you what tools you have at your disposal and how to use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building blocks
&lt;/h2&gt;

&lt;p&gt;To simplify our discussion, let’s focus on what we have available in JSON—the data format that was created based on how data can be hard-coded in JavaScript. In this way, we don’t need to think about the performance implications of different data structures—we only focus on the usefulness of the data model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Primitive values
&lt;/h3&gt;

&lt;p&gt;These are the most basic value types we can have in our program. In JSON, those values are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;boolean—a true or false value,&lt;/li&gt;
&lt;li&gt;a number—a floating-point value,&lt;/li&gt;
&lt;li&gt;string—a sequence of letters, and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;null&lt;/code&gt;—a missing value, which is still useful for expressing certain states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Already with those basic types, we have the possibility of addressing the same thing in different ways. For example, for customer type, you could use some of the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;const customerType = “retail”;&lt;/code&gt;—which could accept any other string value, both valid or invalid ones&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;const isRetail = true;&lt;/code&gt;—a more rigid approach: its two options are obvious and clear, but it has no way of allowing more possibilities&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;const customerType = 2&lt;/code&gt;—can be expanded, but requires documentation for understanding what each number means&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Anything you decide will impact how easy it will be to change code later on. As you are picking the value type for your variable, it’s good practice to try to think about possible changes and pick a type that fits well for both current and future needs. &lt;/p&gt;

&lt;h3&gt;
  
  
  Arrays
&lt;/h3&gt;

&lt;p&gt;Arrays are ordered lists of values. The JavaScript arrays can mix any types of values, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;someArray&lt;/span&gt; &lt;span class="o"&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;another&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although it is a valid array, mixed types arrays are confusing to work with. It’s way easier to stick to keeping the same types of values in an array.&lt;/p&gt;

&lt;p&gt;An important feature of arrays is that they are ordered. This makes them a great match for places where you care about similar data points and where the order is meaningful. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;products in cart—you definitely want to display items from a cart in the same order; and&lt;/li&gt;
&lt;li&gt;students in a class—each one of them has their list number.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Arrays work well when you access many values in sequence. It’s less useful when you want to find whether a given value is in an array. When I find myself often using &lt;code&gt;includes()&lt;/code&gt; to see if an array has some object I’m looking for, I take it as a potential sign that I should reorganize the data structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Objects
&lt;/h3&gt;

&lt;p&gt;The object is a structure that consists of a set of key–value pairs. The structure is unordered, so it makes it a suitable choice for many places that don’t fit the array. Each value on an object can be understood independently of all the rest, so you can mix different types of values without worry. Example of an object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;lorem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ipsum&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;dolor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&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;Objects are a good match for collections of named, unordered properties. For example, a set of permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasAccessTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;blogAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Built-in objects
&lt;/h3&gt;

&lt;p&gt;JavaScript provides many object types that you can use on the code side to keep your values in a more suitable form—and with methods that make them more usable. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Date&lt;/code&gt;—for date time values,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Set&lt;/code&gt;—for unordered collections of unnamed values that don’t repeat, and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Symbol&lt;/code&gt;—a non-string identifier that will not collide with other values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those types are very useful, but in communication that goes through a web API that uses JSON to represent data, they all will be serialized to value types described above. In my daily job, where I program business applications, the only types that I use regularly are dates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick the appropriate structure
&lt;/h2&gt;

&lt;p&gt;The way we organize data impacts what can be easily done in our code. Let’s take a look at the permission example from above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasAccessTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&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 value can be used easily in conditional cases such as: &lt;code&gt;if (hasAccessTo.blog)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The same requirement for a permission list could be met with another data structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},{&lt;/span&gt;
    &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;blogAdmin&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},{&lt;/span&gt;
    &lt;span class="na"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;userAdmin&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;The same condition from above would need to be replaced by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blogPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;permissions&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;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="err"&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;blogPermissions&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;…&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much harder to read, and it’s easier to write code that will throw errors in some specific cases. By using arrays, the only thing we “gain” is the order of permissions, which shouldn’t matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a draft
&lt;/h2&gt;

&lt;p&gt;There are plenty of things to consider as we organize data in our codebase, and calls can get complicated pretty quickly. To avoid rewriting code, it makes sense to create some form of draft for the structures. In my case, I often describe them with the names I plan to use in the tickets I’m going to work on. Often, when you see your structure design written down, you’ll notice some issues with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep on improving
&lt;/h2&gt;

&lt;p&gt;The data structure for your code will never be finished—it should keep evolving with your application. Changing names &lt;em&gt;after&lt;/em&gt; they appear in many places in code, and in databases, &lt;em&gt;will&lt;/em&gt; be painful. However, it is necessary because otherwise the mismatch between names and their current understanding will only grow as things change over time. This is a common source of code debt that often slowly piles up until it makes working with the code an unpleasant and unproductive experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;If you want to receive an occasional email from me about programming or related topics, you can sign up &lt;a href="https://how-to-dev.ck.page/a5c69742db"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to write maintainable code: Naming things</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Wed, 23 Aug 2023 04:23:06 +0000</pubDate>
      <link>https://dev.to/how-to-dev/how-to-write-maintainable-code-naming-things-281h</link>
      <guid>https://dev.to/how-to-dev/how-to-write-maintainable-code-naming-things-281h</guid>
      <description>&lt;p&gt;Using the right names is an essential part of writing maintainable code. For a computer, any name will work just fine—they either match or not. For the humans who read the code, the names are the first thing they have in mind as they work on the code. We all have some capacity to deal with a wrong name. If necessary, we can do a mental translation when the name doesn’t match the concept, or we can ignore some typo. But doing so uses both our memory and mental capacities. It’s easier and more efficient to work with the code that has the naming done right.&lt;/p&gt;

&lt;h2&gt;
  
  
  One name for one thing
&lt;/h2&gt;

&lt;p&gt;For organizing our stuff, the general advice is to have &lt;em&gt;a place for everything and everything in its place&lt;/em&gt;. Similarly, our lives will be much easier if all the people involved in the same project use the same terminology. Usually, we developers don’t have a perfect understanding of the domain in which the project is used. As a result, it makes the most sense to learn the terminology that is used by our business colleagues and use it in the code as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parts of speech
&lt;/h2&gt;

&lt;p&gt;To create terminology that is easy to use, it makes sense to apply some of the grammatical knowledge we all got from school. Different types of words fit better in different use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nouns are a perfect fit for objects or primitive values: &lt;code&gt;user&lt;/code&gt;, &lt;code&gt;accountNumber&lt;/code&gt;, &lt;code&gt;customerEmail&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;adjectives work great for some Boolean flags: &lt;code&gt;allowed&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;verbs match functions or object methods &lt;code&gt;user.login()&lt;/code&gt;, &lt;code&gt;shutDown()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll likely find cases where it would make sense to bend this rule, but for me, it makes sense to try tweaking the names to match this pattern. For example, for a method that checks the current state, I would use &lt;code&gt;user.isActive()&lt;/code&gt; instead of  &lt;code&gt;user.active()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid abbreviation
&lt;/h2&gt;

&lt;p&gt;I’m always skeptical of abbreviations as names in code. Many abbreviations are obvious only when you are deep in the context of the code. A reader who is new to the code and the domain can be confused. Making names short doesn’t improve meaningful metrics. When we write code, we usually use code suggestions, and most lines fit on the screen anyway.&lt;/p&gt;

&lt;p&gt;When there is potential conflict between brevity and clarity, I always prefer to stay on the side of clarity. The only abbreviation I can think of now that I’m OK with seeing in code is VAT. It’s so commonly used that it is easier to understand than its expanded form: &lt;em&gt;value added tax&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pronunciation
&lt;/h2&gt;

&lt;p&gt;All names we put to code are used in two ways. In writing—in code or documentation, and in speech—and when we talk about them. It’s important to think about both use cases when choosing the name. Pronunciation is often another reason to avoid abbreviations: they often miss vowels, and you may need to say it letter by letter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid name collisions
&lt;/h2&gt;

&lt;p&gt;Try not to reuse the names with different meanings in other contexts. If you use some synonyms instead, then it will be easier for developers to intuitively understand the terms correctly when they hear it—without overthinking about the context in which they were used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Brainstorm ideas
&lt;/h2&gt;

&lt;p&gt;I have a high bar for naming things. Some names are easy to create; others are more difficult to come up with. For the most complicated cases, I try to write down as many ideas as I have in the ticket that will introduce a given concept to the code. I try to generate about 3 to 5 ideas—if it’s very difficult, I write down even the ones I don't like. With this in place, I ask my colleagues for their opinion. In this way, I get an external input and spend more time on thinking about the name. It helps in making the decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Newsletter
&lt;/h2&gt;

&lt;p&gt;If you want to get occasional emails about programming or related topics, you can &lt;a href="https://how-to-dev.ck.page/a5c69742db"&gt;sign up for my newsletter here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to manually test a web API</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Wed, 16 Aug 2023 05:51:47 +0000</pubDate>
      <link>https://dev.to/how-to-dev/how-to-manually-test-a-web-api-2il5</link>
      <guid>https://dev.to/how-to-dev/how-to-manually-test-a-web-api-2il5</guid>
      <description>&lt;p&gt;A few weeks ago, I showed the &lt;a href="https://how-to.dev/what-you-should-know-about-web-apis"&gt;basic ideas and terminology of web APIs&lt;/a&gt;. In this article, I will demonstrate how to apply this knowledge, and try an API with some manual testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tweak query
&lt;/h2&gt;

&lt;p&gt;The easy way to start testing any API is to find an example that works—and then tweak it. You can pick any website and see what requests it does. For example, when you open developer tools in Chrome and reload my blog at &lt;a href="https://how-to.dev/what-is-an-api"&gt;how-to.dev&lt;/a&gt;, you can see plenty of requests sent by the website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qaBwbloK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtgm0wayovldremnnl13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qaBwbloK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtgm0wayovldremnnl13.png" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the list, we have a few types or requests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;script&lt;/em&gt; or &lt;em&gt;stylesheet&lt;/em&gt; with names 4421.a65a… or 6238.6ee7…,&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;fetch&lt;/em&gt; with names such as user, tags, events, &lt;/li&gt;
&lt;li&gt;
&lt;em&gt;xhr&lt;/em&gt; with name event,&lt;/li&gt;
&lt;li&gt;and some other types with resources: &lt;em&gt;svg&lt;/em&gt;, &lt;em&gt;avif&lt;/em&gt;, &lt;em&gt;font&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are the most interested in &lt;em&gt;fetch&lt;/em&gt; and &lt;em&gt;xhr&lt;/em&gt; request types. Both could be triggered from the JavaScript side and used for talking to the web API. The other requests we can see here are requests to load some static files—the code or some media content. For each of the queries we see on the list, we can copy one of the formats:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iFd6bwoh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u040vk8t1qkauzvm45bj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iFd6bwoh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u040vk8t1qkauzvm45bj.png" alt="Image description" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copying the code allows you to easily do one of two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rerun the query exactly as it was done by the application, or&lt;/li&gt;
&lt;li&gt;tweak the query to see how the API works with different input.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fetch
&lt;/h3&gt;

&lt;p&gt;Fetch is a JavaScript interface to communicate with servers—for example, to talk to a web API. You can read more at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;MDN&lt;/a&gt;. Here we will see our example query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://how-to.dev/api/user&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;headers&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accept&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accept-language&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-GB,en-US;q=0.9,en;q=0.8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;baggage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sentry-environment=vercel-production,sentry-release=736267205a61e0548a85c08aab089d3f1421126b,sentry-transaction=%2F%5B...slug%5D,sentry-public_key=0fbf92e944b8468cb9706e15c488c84e,sentry-trace_id=a2a1dbab6f5b4c619173000812050469,sentry-sample_rate=0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;if-none-match&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;as45c9ut8od&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-ch-ua&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Not/A)Brand&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;v=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;99&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Google Chrome&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;v=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;115&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Chromium&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;v=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;115&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-ch-ua-mobile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;?0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-ch-ua-platform&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;macOS&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-fetch-dest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-fetch-mode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-fetch-site&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;same-origin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sentry-trace&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a2a1dbab6f5b4c619173000812050469-8d225d0201152147-0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;referrer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://how-to.dev/what-is-an-api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;referrerPolicy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;origin-when-cross-origin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;credentials&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;include&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, there are a lot of details. To run the query, paste this code in the console in dev tools and add &lt;code&gt;.then(console.log)&lt;/code&gt; at the end of it. The fetch function returns a promise, and adding &lt;code&gt;console.log&lt;/code&gt; as a callback will show us the output right there on the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jRArzMOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nubh7487wu2wva66letm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jRArzMOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nubh7487wu2wva66letm.png" alt="Image description" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can modify any of the parameters provided to the call, and in this way you can see how the API will behave.&lt;/p&gt;

&lt;p&gt;The big advantage of this approach is that you will reuse the credential information already available in your browser. If you have an open session, there will be a cookie in your browser, and it will be sent with your request: in this way, the server will know you are you, and where you should be given access.&lt;/p&gt;

&lt;h2&gt;
  
  
  GET request
&lt;/h2&gt;

&lt;p&gt;Another option to test the API is to put the URL where you want to send your GET request into the address bar. By default, the browser does the GET request to the endpoint and displays  the response on the screen. It will not always work as expected: in some rare cases, the API can be flexible enough to support different formats depending on the query headers. In such a case, it may be that address bar requests show HTML, whereas the API call gets JSON.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo API
&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://httpbin.org/"&gt;Httpbin&lt;/a&gt; is an example API we can use for our testing. Its main page is some documentation that shows all the endpoints available for us:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iXW69ge9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1x3pjeuzjdhusnzzibdh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iXW69ge9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1x3pjeuzjdhusnzzibdh.png" alt="Image description" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s try visiting some of the endpoints directly from the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Address bar
&lt;/h3&gt;

&lt;p&gt;When you open one of the endpoints &lt;a href="http://httpbin.org/uuid"&gt;http://httpbin.org/uuid&lt;/a&gt; you will get a response similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yJ51GxFO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42770rhvzllbqezw845v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yJ51GxFO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42770rhvzllbqezw845v.png" alt="Image description" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see more details by opening the dev tools and the network tab. When you refresh the page, you can see all the headers that were sent and received by the browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BanaXZ2D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9fwac7uf1hfqt1x5pon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BanaXZ2D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9fwac7uf1hfqt1x5pon.png" alt="Image description" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use this approach to test GET requests to web APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  POST request
&lt;/h2&gt;

&lt;p&gt;Creating a POST from scratch is more complicated. You could try writing &lt;code&gt;fetch&lt;/code&gt; calls, but as you saw earlier in this article, they can be quite complicated. Let’s use an API testing tool instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hoppscotch
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://hoppscotch.io/"&gt;Hoppscotch&lt;/a&gt; is an API development tool that we can use to send any type of request—POST included. If you’ve heard about Postman, this is an open-source alternative. For the testing, I’ll send a POST request with some JSON data to Httpbin’s POST endpoint. At the initial screen, I set the URL to &lt;code&gt;http://httpbin.org/post&lt;/code&gt;, the method to &lt;em&gt;POST&lt;/em&gt;. In the &lt;em&gt;Body&lt;/em&gt; tab, I set the &lt;em&gt;Content Type&lt;/em&gt; to &lt;code&gt;application/json&lt;/code&gt; and the &lt;em&gt;Raw Request Body&lt;/em&gt; to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s the request just before sending:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IT0kMkyM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hskfwwlobnkugvjimcvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IT0kMkyM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hskfwwlobnkugvjimcvm.png" alt="Image description" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The initial attempt fails because we are accessing an external server. There are few options to address it, with &lt;em&gt;Proxy&lt;/em&gt; being the easiest to get you off the ground:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3B75yaI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1coke2ktkvtb1xhr0wj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3B75yaI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1coke2ktkvtb1xhr0wj.png" alt="Image description" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The result after retrying the request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KKGlh5RS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hh4tmoksmm78rlsrgbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KKGlh5RS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hh4tmoksmm78rlsrgbr.png" alt="Image description" width="800" height="627"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the Httpbin API just returns a bunch  of technical information about the request and the body. &lt;/p&gt;

&lt;p&gt;This simple test skips the issue of authorization—many POST requests are only available to the user that is logged in on the server and fail for anonymous users. Covering this concept fully is a topic for another article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want to learn more?
&lt;/h2&gt;

&lt;p&gt;If you are interested in learning more about API or related topics, you can sign up for occasional emails from &lt;a href="https://how-to-dev.ck.page/a5c69742db"&gt;my newsletter&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>testing</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to build an impressive demo project</title>
      <dc:creator>Marcin Wosinek</dc:creator>
      <pubDate>Wed, 09 Aug 2023 05:23:50 +0000</pubDate>
      <link>https://dev.to/how-to-dev/how-to-build-an-impressive-demo-project-4hkl</link>
      <guid>https://dev.to/how-to-dev/how-to-build-an-impressive-demo-project-4hkl</guid>
      <description>&lt;p&gt;When applying for a job, it’s good to have a demo project to present as an example of your work. In this article, I’ll show you what to focus on while building such a project. I share conclusions from being on both sides: applying for a job and reviewing projects of applicants.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo project goals
&lt;/h2&gt;

&lt;p&gt;A demo project is a good opportunity to show off the wide range of your skills. You can do this the best by expanding your project in depth—having a simple set of features for the application but implemented with high-quality code. With a simple feature set, you can focus on showing all the aspects of programming that you would like to work with. With a demo project, you have an empty canvas you can fill in as you please. The only constraints are your creativity, skills, and how much time you want to put into it. You can use it to show the breadth of your knowledge.&lt;/p&gt;

&lt;p&gt;While working on a demo project, you don’t have to follow guidelines imposed on you by other developers. You can use this opportunity to show exactly what &lt;em&gt;you&lt;/em&gt; mean by good, quality code. Quality is something that good workplaces pay a lot of attention to. Even in places where they say &lt;em&gt;we have no time for quality code&lt;/em&gt;, it’s very likely that the technical interviewer will prefer people who can deliver maintainable code.&lt;/p&gt;

&lt;p&gt;By delivering a demo project, you prove that you can ship something. Any project that is completed is perfect proof that you both have the skills necessary to create it, and that you are not a perfectionist who can’t finish stuff. Both things will be valued in a workplace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side goals
&lt;/h2&gt;

&lt;p&gt;It can be tempting to add some side goals to the project to make the time investment more worthwhile. Depending on your situation, this could indeed be a good idea, but keep in mind that by adding additional priorities, you either water down the original purpose of the project, or you increase the scope of your undertaking. If you are thinking of applying for a job soon, try starting simple with technologies you know and add the new ones later on—if you have time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project scope
&lt;/h2&gt;

&lt;p&gt;Building a project from scratch is always a lot of work. Typically, projects go over the initial budget estimation: just look at any construction project in your area. If you follow my advice of demonstrating many of your skills, you will already have a lot of work to do. To avoid starting a project that is bigger than you can finish, the best idea is to keep the feature scope as little as necessary. You can always expand the feature scope in the following iterations—exactly the way you do in agile. If you want some inspiration for simple demo projects, here you have a few examples of what I discussed on this blog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;a href="https://how-to.dev/oh-my-bill-project-introduction"&gt;simple application&lt;/a&gt; to store a sequence of data points on energy consumption&lt;/li&gt;
&lt;li&gt;a &lt;a href="https://how-to.dev/how-to-collect-inputs-for-your-project"&gt;hello world app&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;As a frontend developer, I’m always focusing the most on that part. Even if your priorities are elsewhere, the frontend will be the part of the application the reviewer interacts with, so it makes sense to invest some effort in it.&lt;/p&gt;

&lt;p&gt;Depending on your priorities, you can include different qualities to it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your dream job involves UI/UX design, you can put in the effort to make it pretty. Otherwise, a standard UI framework or even no styled elements will be OK. &lt;/li&gt;
&lt;li&gt;If you aim for a frontend job with some framework, you can use this framework in your project. Otherwise, vanilla JS could be an interesting showcase for how you solve some common problems on your own.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;p&gt;For many applications, you will need some form of backend. Depending on your career goals, you can try some “serverless” backend from the cloud, or build a server for your application yourself. If you aim for full-stack or backend positions, this will be a great exercise. It will complicate a lot of your local and deployment environments, but it will bring your demo application to be much closer to real-world cases. &lt;/p&gt;

&lt;p&gt;With backend and frontend work, you will be confronted with many aspects of development that are not present in a project that involves only the frontend. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mono-repo vs. poly-repo, a topic I discussed in &lt;a href="https://how-to.dev/pros-and-cons-of-keeping-your-code-in-monorepo"&gt;another article&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;true end-to-end tests where you check both parts of the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Covering those aspects in the demo app will be a great way of showing your capacities to the interviewees.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;p&gt;Adding a database to your project would be yet another level of complexity. If you aim for a backend or full-stack job, it would be a great opportunity for you to show your work across all the parts of the stack. When your focus is the frontend, it will probably make more sense to skip the database and just keep data in the server’s memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology stack
&lt;/h2&gt;

&lt;p&gt;You will need many technologies to get your project up and running. Make sure to choose things that make sense together: use a combination of technologies that are often used together and avoid adding libraries that overlap with the features they provide.&lt;/p&gt;

&lt;p&gt;If possible, try using tools you are familiar with. Learning new things will make you slower in creating the application, and it’s more probable that you will make some mistakes while using it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to include
&lt;/h2&gt;

&lt;p&gt;When I review projects for other people, I focus on whether and how they approach certain aspects, which I discuss below. This list is my personal list, and others will put different weights on those things, but I’ve noticed many senior developers are paying attention to the considerations I mention here. At the same time, some of those things are things ignored by junior developers. &lt;/p&gt;

&lt;h3&gt;
  
  
  README
&lt;/h3&gt;

&lt;p&gt;When I visit a project for the first time, I expect a README file that will quickly bring me up to speed with the project. A great example is at &lt;a href="https://github.com/date-fns/date-fns"&gt;date-fns&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1QBFL3nh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wgj9hbyezyeqlu5bxer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1QBFL3nh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wgj9hbyezyeqlu5bxer.png" alt="Image description" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find more about how to write a good README in &lt;a href="https://how-to.dev/the-readme-file-how-to-help-others-understand-your-project"&gt;an article&lt;/a&gt; on my blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployed application
&lt;/h3&gt;

&lt;p&gt;When you try to show what you can build, it makes sense to make it easy for people to see the application in action and play with it. This gives them a context that is helpful to understand the code and will demonstrate the scope of the project. Besides, deploying is a critical part of the project life-cycle, and it makes sense to show you can take care of that too.&lt;/p&gt;

&lt;p&gt;If you build only the frontend, the deployment will be effortless: you can use GitHub or GitLab pages, or Netlify. Adding a custom backend or database will require more effort—the easiest would be to find an affordable cloud provider and deploy to the cheapest instances there. I liked the simplicity of the offer from Digital Ocean, but the details of the offering of those companies change every few months.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI/CD
&lt;/h3&gt;

&lt;p&gt;Continuous integration (CI) is a piece of your project’s infrastructure that checks whether everything is working as expected after each commit. Continuous delivery (CD) deploys the last version somewhere that it can be tested: in the case of a demo project, it could be to the main environment because you don’t need to create a production and staging split.&lt;/p&gt;

&lt;p&gt;For implementing continuous integration and delivery, you can use an offering of your Git hosting provider: for example, GitHub Actions or GitLab CI/CI. Another option is a dedicated CI service, for example, CircleCI. All those solutions have similar capabilities, and for simple pipelines, it shouldn’t matter much which one you are using.&lt;/p&gt;

&lt;p&gt;Setting up CI can be more time-consuming than expected. As you tweak the configuration, you often need to wait for many minutes to see the impact of your changes. Running the code on external machines makes troubleshooting more complicated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linter
&lt;/h3&gt;

&lt;p&gt;Linter is a program that analyzes your code, looking for errors or potentially problematic patterns. Each programming language has some tools like this available. In my frontend work, I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; for JavaScript and TypeScript code,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stylelint.io/"&gt;Stylelint&lt;/a&gt; for CSS and SCSS, and&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://htmlhint.com/"&gt;HTMLHint&lt;/a&gt; for HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those tools help to catch little, annoying bugs and teach you what structures in code you should avoid. They often have extensive configuration options, and can be expanded by plugins. I see no reason not to use them in any project, let alone a project where you have to show off your skills and dedication to the craft.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code style
&lt;/h3&gt;

&lt;p&gt;As a developer, you spend more time &lt;em&gt;reading&lt;/em&gt; code than writing it. Making the reading experience pleasant is important, and many senior developers insist on keeping the code as consistent as possible. Luckily, we have tools that take care of applying the code style across the project. For the frontend, Prettier is a tool that covers all JS/TS, HTML, and CSS. You can read more about it &lt;a href="https://how-to.dev/how-to-make-your-code-prettier"&gt;here&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The goal of unit tests is to check whether the part of the application—methods, classes, etc. are doing the thing they are supposed to do. There are many tools in JavaScript that you could use for writing unit tests, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jasmine&lt;/li&gt;
&lt;li&gt;Jest&lt;/li&gt;
&lt;li&gt;Mocha&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You have probably heard about the importance of unit tests many times before. On my blog, I have 2 related articles: &lt;a href="https://how-to.dev/how-to-write-unit-tests"&gt;how to write unit tests&lt;/a&gt; for a practical guide, and &lt;a href="https://how-to.dev/what-are-the-benefits-of-unit-testing"&gt;what are the benefits of unit tests&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  End-to-end test
&lt;/h3&gt;

&lt;p&gt;End-to-end (e2e) tests check that the application works as expected all the way from the frontend through the backend and to the database. Those tests can be complicated to set up because there are plenty of moving parts—frontend, backend, database—and they all should work fine both locally and in the CI setup. Even though it could be difficult to get it right, those tests allow automating a lot of repetitive quality assurance (QA) work. Including them in your demo project can be a great way of showing you care about the quality and efficiency of the development team.&lt;/p&gt;

&lt;p&gt;There are many e2e frameworks available: for example, Cypress, Playwright, and Nightwatch. Unless you have a specific reason to prefer some of them, for the demo project, I would use Cypress—it’s the most popular option. Even if the team uses other tools than Cypress, they will definitely recognize it.&lt;/p&gt;

&lt;p&gt;If you are new to automated QA, you might wonder what’s the point of having unit and e2e tests in one project. Many teams create both types of tests, and I went through reasons why it makes sense in &lt;a href="https://how-to.dev/does-my-web-application-need-end-to-end-and-unit-tests"&gt;another  article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Codebase documentation
&lt;/h3&gt;

&lt;p&gt;I already mentioned the README file that covers the main purpose of the project, and how to start playing with it. Besides this top-level documentation, it’s very helpful to explain briefly the purpose of the classes and methods you write. The best place to do it is in the code—so you can read and update the description as you work on the files. At the same time, it’s good to have the documentation available in other places too: as suggestions in your code editor or on a website other developers could access without downloading the code.&lt;/p&gt;

&lt;p&gt;JSDoc is a popular syntax for adding in-code documentation to JS projects. It integrates with many different tools—good code editors will manage to parse it and use it for code suggesting, or it could be built static.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meaningful commits
&lt;/h3&gt;

&lt;p&gt;One of the things I pay attention to in projects is the quality of the commit history. A good project history has the changes organized in commits that make sense as a whole and are described in a meaningful way. Well-maintained code history makes it much easier to understand the changes when one reviews code and simpler to look for a reason why something was changed. Small commits, with related changes, are easier to revert if necessary. I wrote more about how to use Git repositories efficiently &lt;a href="https://how-to.dev/how-to-get-the-most-value-out-of-your-git-repository"&gt;in a previous blog&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Want to learn more?
&lt;/h2&gt;

&lt;p&gt;If you are interested in learning more about building projects or other development related things, you can sign up for an occasional email from me &lt;a href="https://how-to-dev.ck.page/a5c69742db"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
