<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Roaming Dev]]></title><description><![CDATA[Stop Roaming | Start Developing]]></description><link>https://blog.roamingdev.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1669583899183/GolWlF1SI.png</url><title>Roaming Dev</title><link>https://blog.roamingdev.com</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 10:20:20 GMT</lastBuildDate><atom:link href="https://blog.roamingdev.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[API Testing with Mocha, Chai and Supertest in NodeJs.]]></title><description><![CDATA[Introduction
Testing is essential today for building a robust application that may change frequently or extend later if you are learning Test Driven Development or looking to add API test cases in the backend, which may improve the debugging and test...]]></description><link>https://blog.roamingdev.com/api-testing-with-mocha-chai-and-supertest-in-nodejs</link><guid isPermaLink="true">https://blog.roamingdev.com/api-testing-with-mocha-chai-and-supertest-in-nodejs</guid><category><![CDATA[Supertest]]></category><category><![CDATA[mocha]]></category><category><![CDATA[chai]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><dc:creator><![CDATA[Gaurav Singh]]></dc:creator><pubDate>Sun, 27 Nov 2022 15:29:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/mZnx9429i94/upload/v1669562760386/cyPHdw2sfD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Testing is essential today for building a robust application that may change frequently or extend later if you are learning Test Driven Development or looking to add API test cases in the backend, which may improve the debugging and testing time of the application. In NodeJs we have a lot of testing tools like Jest and Mocha. In this tutorial we are going to use <code>mocha</code> and <code>chai</code> with <code>supertest</code> to create test cases and run them after adding a feature, deleting a feature, or changing something to see if it breaks anything. Note that we need chai along with mocha because it is an assertion library that provides us with many ways to write assertions. Supertest is an HTTP testing library that we will use along with mocha and chai.</p>
<h2 id="heading-installation">Installation</h2>
<p>First, you need to install all the required libraries for testing. We are using Mocha, Chai, and Supertest for testing the APIs. We are installing them as dev dependencies to use them during development.</p>
<pre><code>npm install --save-dev mocha chai supertest
</code></pre><h3 id="heading-test-script-setup">Test Script Setup</h3>
<p>create a <code>mocha</code> test script in <code>package.json</code>.</p>
<p>package.json</p>
<pre><code class="lang-javascript">  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"test"</span>: <span class="hljs-string">"mocha"</span>
  },
</code></pre>
<h2 id="heading-todo-api-example">Todo API Example</h2>
<p>We are using a basic todo example. In this example, we are using express.js to create server and private routes for todo CRUD operation.</p>
<h3 id="heading-user-data">User Data</h3>
<p>We need user data to authenticate and authorize users who can use the todo APIs. This is similar to having a user table.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> verifyUser = <span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (req.headers.userkey === <span class="hljs-literal">undefined</span> || req.headers.userkey === <span class="hljs-string">""</span>) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">401</span>);
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> user <span class="hljs-keyword">of</span> users) {
    <span class="hljs-keyword">if</span> (user.id == req.headers.userkey) {
      req.user = user;
      <span class="hljs-keyword">break</span>;
    }
  }
  <span class="hljs-keyword">if</span> (!req.user) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">401</span>);
  next();
};
</code></pre>
<h3 id="heading-authorization-middleware-setup">Authorization Middleware Setup</h3>
<p>We need to make sure the requests were made by registered users only, so for simplicity, we will use their <code>id</code> in the headers to authorize the user's request. This is similar to using JWT as an authorization header after authentication.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> verifyUser = <span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (req.headers.userkey === <span class="hljs-literal">undefined</span> || req.headers.userkey === <span class="hljs-string">""</span>) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">401</span>);
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> user <span class="hljs-keyword">of</span> users) {
    <span class="hljs-keyword">if</span> (user.id == req.headers.userkey) {
      req.user = user;
      <span class="hljs-keyword">break</span>;
    }
  }
  <span class="hljs-keyword">if</span> (!req.user) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">401</span>);
  next();
};
</code></pre>
<h2 id="heading-test-setup">Test Setup</h2>
<p>We need to create tests for two routes, Create todo and Delete todo. To let mocha discover the test files we need to create a <code>test</code> directory and inside it, we can put all of our test files.
We will create <code>todo.api.js</code> inside the <code>test</code> directory.</p>
<p>We use the <code>describe</code> function to describe a function and <code>it</code> to create the test case which will run with assertions set up in it. <code>describe</code> takes two parameters, 1. Description of the whole test case 2.  Callback Function which can take <code>it</code> statements or other <code>describe</code> functions. The <code>it</code> function takes the description of what the test case does in the first parameter and a callback function which is used to set up assertions.</p>
<p>Chai provides us many assertion styles like <code>assert</code>, <code>should</code>, and <code>expect</code>. We are using expect in this tutorial.</p>
<h3 id="heading-1-create-before-function">1. create before function</h3>
<p>The <code>before</code> function runs before all tests in the file.  It's mostly used to set the user authorization token received after login to test protected APIs. In our case, we are using the <code>userkey</code> as the user authorization key.</p>
<p>test.api.js</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> chai = <span class="hljs-built_in">require</span>(<span class="hljs-string">"chai"</span>);
<span class="hljs-keyword">const</span> request = <span class="hljs-built_in">require</span>(<span class="hljs-string">"supertest"</span>);
<span class="hljs-keyword">const</span> expect = chai.expect;
<span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../server"</span>);

describe(<span class="hljs-string">"Todo Routes"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">let</span> testUser;

  before(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">// This code wil run before all other test cases in this file. Use api code to get user authorization token in this block.</span>
    <span class="hljs-comment">// we are using userkey in our case. It can be replaced with jwt.</span>
    testUser = {
      <span class="hljs-attr">userkey</span>: <span class="hljs-number">1</span>,
    };
  });

});
</code></pre>
<h3 id="heading-2-write-tests-for-todos-apis">2. write tests for todos APIs</h3>
<p>Now the next step is to write down test cases for the API according to the design we have thought. We are going to create <code>GET /todos</code> and <code>Post /todos</code> API route test cases.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// describe a function with a description</span>
describe(<span class="hljs-string">"Todo Routes"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">let</span> testUser;

  before(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">// This code wil run before all other test cases in this file. Use api code to get user authorization token in this block.</span>
    <span class="hljs-comment">// we are using userkey in our case. It can be replaced with jwt.</span>
    testUser = {
      <span class="hljs-attr">userkey</span>: <span class="hljs-number">1</span>,
    };
  });

  describe(<span class="hljs-string">"POST /todos"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> todo = { <span class="hljs-attr">title</span>: <span class="hljs-string">"first todo"</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">"first description"</span> };

    <span class="hljs-comment">// it is used to write a test case</span>
    it(<span class="hljs-string">"returns unauthorized"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).post(<span class="hljs-string">"/todos"</span>).send(todo).set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      <span class="hljs-comment">// you expect the api to return 401 without userKey</span>
      expect(res.status).to.be.equal(<span class="hljs-number">401</span>);
    });

    it(<span class="hljs-string">"creates a todo"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).post(<span class="hljs-string">"/todos"</span>).send(todo).set(<span class="hljs-string">"userkey"</span>, testUser.userkey).set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      <span class="hljs-comment">// match the expected respose which is 201 if a resource is created on server and the values sent.</span>
      expect(res.status).to.be.equal(<span class="hljs-number">201</span>);
      expect(res.body).to.be.an(<span class="hljs-string">"object"</span>).with.keys(<span class="hljs-string">"id"</span>, <span class="hljs-string">"title"</span>, <span class="hljs-string">"description"</span>);
      expect(res.body.id).to.be.a(<span class="hljs-string">"number"</span>);
      expect(res.body.title).to.be.equal(todo.title);
      expect(res.body.description).to.be.equal(todo.description);
    });
  });

  describe(<span class="hljs-string">"GET /todos"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"returns unauthorized"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).get(<span class="hljs-string">"/todos"</span>).set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">401</span>);
    });

    it(<span class="hljs-string">"returns todos"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).get(<span class="hljs-string">"/todos"</span>).set(<span class="hljs-string">"userkey"</span>, testUser.userkey).set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">200</span>);
      res.body.todos.map(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> {
        expect(todo).to.be.an(<span class="hljs-string">"object"</span>).with.keys(<span class="hljs-string">"id"</span>, <span class="hljs-string">"title"</span>, <span class="hljs-string">"description"</span>);
      });
    });
  });

  describe(<span class="hljs-string">"PUT /todos/:id"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> todo = { <span class="hljs-attr">title</span>: <span class="hljs-string">"updated todo title"</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">"updated todo description"</span> };
    it(<span class="hljs-string">"returns unauthorized"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)
        .put(<span class="hljs-string">"/todos/"</span> + <span class="hljs-number">1</span>)
        .send(todo)
        .set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">401</span>);
    });

    it(<span class="hljs-string">"updates todo"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)
        .put(<span class="hljs-string">"/todos/"</span> + <span class="hljs-number">1</span>)
        .send(todo)
        .set(<span class="hljs-string">"userkey"</span>, testUser.userkey)
        .set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">200</span>);
      expect(res.body).to.be.an(<span class="hljs-string">"object"</span>).with.keys(<span class="hljs-string">"id"</span>, <span class="hljs-string">"title"</span>, <span class="hljs-string">"description"</span>);
      expect(res.body.id).to.be.a(<span class="hljs-string">"number"</span>);
      expect(res.body.title).to.be.equal(todo.title);
      expect(res.body.description).to.be.equal(todo.description);
    });
  });

  describe(<span class="hljs-string">"DELETE /todos/:id"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"returns unauthorized"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).delete(<span class="hljs-string">"/todos/"</span> + <span class="hljs-number">1</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">401</span>);
    });

    it(<span class="hljs-string">"deletes todo"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)
        .delete(<span class="hljs-string">"/todos/"</span> + <span class="hljs-number">1</span>)
        .set(<span class="hljs-string">"userkey"</span>, testUser.userkey);

      expect(res.status).to.be.equal(<span class="hljs-number">204</span>);
    });
  });
});
</code></pre>
<h3 id="heading-3-create-api-routes-and-todos-crud-logic">3. create API routes and todos CRUD logic</h3>
<p>As we have setup test cases and following the concept of Test Driven Development, now we need to create routes and functions to create, get, update and delete todos.</p>
<p>Here we are using <code>verifyuser</code> middleware before todo logic to make the routes protected.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> todos = [];
router.post(<span class="hljs-string">"/todos"</span>, verifyUser, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.user;
  <span class="hljs-keyword">let</span> todo = { <span class="hljs-attr">id</span>: todos.length + <span class="hljs-number">1</span>, <span class="hljs-attr">userId</span>: user.id, <span class="hljs-attr">title</span>: req.body.title, <span class="hljs-attr">description</span>: req.body.description };
  todos.push(todo);
  res.status(<span class="hljs-number">201</span>).json({ <span class="hljs-attr">id</span>: todo.id, <span class="hljs-attr">title</span>: todo.title, <span class="hljs-attr">description</span>: todo.description });
});

router.get(<span class="hljs-string">"/todos"</span>, verifyUser, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.user;
  <span class="hljs-keyword">let</span> filterTodos = todos.filter(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.userId === user.id);
  res.status(<span class="hljs-number">200</span>).json({
    <span class="hljs-attr">todos</span>: filterTodos.map(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> ({ <span class="hljs-attr">id</span>: todo.id, <span class="hljs-attr">title</span>: todo.title, <span class="hljs-attr">description</span>: todo.description })),
  });
});

router.put(<span class="hljs-string">"/todos/:id"</span>, verifyUser, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.user;
  <span class="hljs-keyword">let</span> updatedTodo;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> todo <span class="hljs-keyword">of</span> todos) {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Number</span>(req.params.id) === todo.id &amp;&amp; todo.userId === user.id) {
      todo.title = req.body.title;
      todo.description = req.body.description;
      updatedTodo = todo;
      <span class="hljs-keyword">break</span>;
    }
  }
  <span class="hljs-keyword">if</span> (!updatedTodo) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"not found!"</span>, <span class="hljs-attr">message</span>: <span class="hljs-string">"todo not found!"</span> });

  res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">id</span>: updatedTodo.id, <span class="hljs-attr">title</span>: updatedTodo.title, <span class="hljs-attr">description</span>: updatedTodo.description });
});

router.delete(<span class="hljs-string">"/todos/:id"</span>, verifyUser, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.user;
  <span class="hljs-keyword">let</span> index = <span class="hljs-number">-1</span>;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; todos.length; i++) {
    <span class="hljs-keyword">if</span> (todos[i].id === <span class="hljs-built_in">Number</span>(req.params.id)) {
      index = i;
    }
  }
  todos.splice(index, <span class="hljs-number">1</span>);

  res.sendStatus(<span class="hljs-number">204</span>);
});
</code></pre>
<h3 id="heading-4-setup-the-test-command-and-run-the-test-cases">4. setup the test command and run the test cases</h3>
<p>Wrap up the code and start testing using the <code>npm test</code> command from the terminal in the project directory.</p>
<pre><code>npm test
</code></pre><p>The test results will be the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1669562570971/PARwIFI1G.PNG" alt="todos_crud_test.PNG" /></p>
<p><strong>Note</strong>: In case any test don't pass, you should check what's wrong with the code and fix and re-test.</p>
<h2 id="heading-complete-snippets">Complete Snippets</h2>
<p>server.js</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> router = express.Router();

app.use(express.json());

<span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">name</span>: <span class="hljs-string">"John"</span>,
  },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Mary"</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Sara"</span> },
];

<span class="hljs-keyword">const</span> verifyUser = <span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (req.headers.userkey === <span class="hljs-literal">undefined</span> || req.headers.userkey === <span class="hljs-string">""</span>) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">401</span>);
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> user <span class="hljs-keyword">of</span> users) {
    <span class="hljs-keyword">if</span> (user.id == req.headers.userkey) {
      req.user = user;
      <span class="hljs-keyword">break</span>;
    }
  }
  <span class="hljs-keyword">if</span> (!req.user) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">401</span>);
  next();
};

app.use(<span class="hljs-string">"/"</span>, router);

<span class="hljs-keyword">let</span> todos = [];
router.post(<span class="hljs-string">"/todos"</span>, verifyUser, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.user;
  <span class="hljs-keyword">let</span> todo = { <span class="hljs-attr">id</span>: todos.length + <span class="hljs-number">1</span>, <span class="hljs-attr">userId</span>: user.id, <span class="hljs-attr">title</span>: req.body.title, <span class="hljs-attr">description</span>: req.body.description };
  todos.push(todo);
  res.status(<span class="hljs-number">201</span>).json({ <span class="hljs-attr">id</span>: todo.id, <span class="hljs-attr">title</span>: todo.title, <span class="hljs-attr">description</span>: todo.description });
});

router.get(<span class="hljs-string">"/todos"</span>, verifyUser, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.user;
  <span class="hljs-keyword">let</span> filterTodos = todos.filter(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> todo.userId === user.id);
  res.status(<span class="hljs-number">200</span>).json({
    <span class="hljs-attr">todos</span>: filterTodos.map(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> ({ <span class="hljs-attr">id</span>: todo.id, <span class="hljs-attr">title</span>: todo.title, <span class="hljs-attr">description</span>: todo.description })),
  });
});

router.put(<span class="hljs-string">"/todos/:id"</span>, verifyUser, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.user;
  <span class="hljs-keyword">let</span> updatedTodo;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> todo <span class="hljs-keyword">of</span> todos) {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Number</span>(req.params.id) === todo.id &amp;&amp; todo.userId === user.id) {
      todo.title = req.body.title;
      todo.description = req.body.description;
      updatedTodo = todo;
      <span class="hljs-keyword">break</span>;
    }
  }
  <span class="hljs-keyword">if</span> (!updatedTodo) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"not found!"</span>, <span class="hljs-attr">message</span>: <span class="hljs-string">"todo not found!"</span> });

  res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">id</span>: updatedTodo.id, <span class="hljs-attr">title</span>: updatedTodo.title, <span class="hljs-attr">description</span>: updatedTodo.description });
});

router.delete(<span class="hljs-string">"/todos/:id"</span>, verifyUser, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.user;
  <span class="hljs-keyword">let</span> index = <span class="hljs-number">-1</span>;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; todos.length; i++) {
    <span class="hljs-keyword">if</span> (todos[i].id === <span class="hljs-built_in">Number</span>(req.params.id)) {
      index = i;
    }
  }
  todos.splice(index, <span class="hljs-number">1</span>);

  res.sendStatus(<span class="hljs-number">204</span>);
});

app.listen(<span class="hljs-number">4000</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`app listening on port <span class="hljs-subst">${<span class="hljs-number">4000</span>}</span>`</span>);
});

<span class="hljs-built_in">module</span>.exports = app;
</code></pre>
<p>test.api.js</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> chai = <span class="hljs-built_in">require</span>(<span class="hljs-string">"chai"</span>);
<span class="hljs-keyword">const</span> request = <span class="hljs-built_in">require</span>(<span class="hljs-string">"supertest"</span>);
<span class="hljs-keyword">const</span> expect = chai.expect;
<span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../server"</span>);

<span class="hljs-comment">// describe a function with a description</span>
describe(<span class="hljs-string">"Todo Routes"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">let</span> testUser;

  before(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">// This code wil run before all other test cases in this file. Use api code to get user authorization token in this block.</span>
    <span class="hljs-comment">// we are using userkey in our case. It can be replaced with jwt.</span>
    testUser = {
      <span class="hljs-attr">userkey</span>: <span class="hljs-number">1</span>,
    };
  });

  describe(<span class="hljs-string">"POST /todos"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> todo = { <span class="hljs-attr">title</span>: <span class="hljs-string">"first todo"</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">"first description"</span> };

    <span class="hljs-comment">// it is used to write a test case</span>
    it(<span class="hljs-string">"returns unauthorized"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).post(<span class="hljs-string">"/todos"</span>).send(todo).set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      <span class="hljs-comment">// you expect the api to return 401 without userKey</span>
      expect(res.status).to.be.equal(<span class="hljs-number">401</span>);
    });

    it(<span class="hljs-string">"creates a todo"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).post(<span class="hljs-string">"/todos"</span>).send(todo).set(<span class="hljs-string">"userkey"</span>, testUser.userkey).set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      <span class="hljs-comment">// match the expected respose which is 201 if a resource is created on server and the values sent.</span>
      expect(res.status).to.be.equal(<span class="hljs-number">201</span>);
      expect(res.body).to.be.an(<span class="hljs-string">"object"</span>).with.keys(<span class="hljs-string">"id"</span>, <span class="hljs-string">"title"</span>, <span class="hljs-string">"description"</span>);
      expect(res.body.id).to.be.a(<span class="hljs-string">"number"</span>);
      expect(res.body.title).to.be.equal(todo.title);
      expect(res.body.description).to.be.equal(todo.description);
    });
  });

  describe(<span class="hljs-string">"GET /todos"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"returns unauthorized"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).get(<span class="hljs-string">"/todos"</span>).set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">401</span>);
    });

    it(<span class="hljs-string">"returns todos"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).get(<span class="hljs-string">"/todos"</span>).set(<span class="hljs-string">"userkey"</span>, testUser.userkey).set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">200</span>);
      res.body.todos.map(<span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> {
        expect(todo).to.be.an(<span class="hljs-string">"object"</span>).with.keys(<span class="hljs-string">"id"</span>, <span class="hljs-string">"title"</span>, <span class="hljs-string">"description"</span>);
      });
    });
  });

  describe(<span class="hljs-string">"PUT /todos/:id"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> todo = { <span class="hljs-attr">title</span>: <span class="hljs-string">"updated todo title"</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">"updated todo description"</span> };
    it(<span class="hljs-string">"returns unauthorized"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)
        .put(<span class="hljs-string">"/todos/"</span> + <span class="hljs-number">1</span>)
        .send(todo)
        .set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">401</span>);
    });

    it(<span class="hljs-string">"updates todo"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)
        .put(<span class="hljs-string">"/todos/"</span> + <span class="hljs-number">1</span>)
        .send(todo)
        .set(<span class="hljs-string">"userkey"</span>, testUser.userkey)
        .set(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">200</span>);
      expect(res.body).to.be.an(<span class="hljs-string">"object"</span>).with.keys(<span class="hljs-string">"id"</span>, <span class="hljs-string">"title"</span>, <span class="hljs-string">"description"</span>);
      expect(res.body.id).to.be.a(<span class="hljs-string">"number"</span>);
      expect(res.body.title).to.be.equal(todo.title);
      expect(res.body.description).to.be.equal(todo.description);
    });
  });

  describe(<span class="hljs-string">"DELETE /todos/:id"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"returns unauthorized"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app).delete(<span class="hljs-string">"/todos/"</span> + <span class="hljs-number">1</span>);

      expect(res.status).to.be.equal(<span class="hljs-number">401</span>);
    });

    it(<span class="hljs-string">"deletes todo"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request(app)
        .delete(<span class="hljs-string">"/todos/"</span> + <span class="hljs-number">1</span>)
        .set(<span class="hljs-string">"userkey"</span>, testUser.userkey);

      expect(res.status).to.be.equal(<span class="hljs-number">204</span>);
    });
  });
});
</code></pre>
]]></content:encoded></item></channel></rss>