Exercise 22: Writing Basic Tests with Lab

In this exercise, we will introduce the concept of writing unit tests for the Hapi.js web API, mainly using the third-party lab module and the built-in assert module. Ideally, we should have a separate database for our tests, but for the sake of simplicity here, we will share our development database for tests too:

  1. Let's first start by installing the necessary packages. Notice that we are using --save-dev since tests are not needed for production, therefore, they are development dependencies:
npm install lab --save-dev

Use the Code/Lesson-3/exercise-c for your reference.
  1. Create a test folder at the root of the project—that is where we will have our tests. Since our API is a simple one, we will only have one file with all our tests.
  2. In test, create a file test-todo.js.
  3. As a set up, test/test-todo.js requires the necessary modules that we need for our test:
const assert = require('assert');
// lab set-up
const Lab = require('lab');
const lab = exports.lab = Lab.script();
// get our server(API)
const server = require('../server');
In the first line, we are requiring assert, which is an inbuilt module if you recall from Chapter 1, Introduction to Node.js. Alternatively, you can use any other assertion libraries such as chai (https://github.com/chaijs/chai), should.js (https://github.com/tj/should.js), and others.

Lab test files must require the lab module and export a test script, as seen on line 4 prior. We will be getting the rest of the items from lab in the following line; we're going to see them in action shortly.
  1. Since we are requiring the server in line 6 of our test-todo.js file, we need to go back to our server.js file and export the server object, on the last line:
module.exports = server;
  1. For the DB configuration, let's modify our db.js file to include configurations for the test environment, pointing to the development configurations. Add this line right after the configs definition:
configs.test = configs.development;
  1. Let's modify the server connection setup code so that the port for our testing server is set from the environment variables when running the tests. This allows us to have the test server run on a different port, while our development server is running:
server.connection(
{
host: 'localhost',
port: process.env.PORT || 8000,
routes:
{
cors: true,
}
});
  1. There are a number of methods that we will use from the lab module; we will need to use object destructuring to get them. Add the following line in our test-todo.js file:
const
{
experiment,
test,
before,
} = lab;
  1. Let's start by writing a simple test that makes sure that the GET: / request goes through, and returns { message: 'hello, world' } as defined:
experiment('Base API', () => 
{
test('GET: /', () =>
{
const options =
{
...
assert.equal(response.result.message, 'hello, world');
});
});
});

You can find the complete code from the test-todo.js file at Code/Lesson-3/exercise-c/test.
We now see experiment, test, and assert.equal methods in action. experiment is basically a way of grouping together the tests, and the actual tests are written within the test method's callback function (known as test cases). assert.equal here is just comparing the two values to make sure they are equal, and if not, an assertion error will be thrown.
  1. Now, let's run our tests:
    1. On the Terminal (open a new Terminal if you're running the API on one of them), navigate to the root of our project and run the following command:
PORT=8001 ./node_modules/lab/bin/lab test --leaks
We're adding an optional --leaks option to turn off memory leak detection since we don't need it now.
At the beginning of the command, we're adding PORT=8001; this is a way of passing an environment variable to our script, which is why we changed our code at step 7 previously. We're now running our test server on port 8001 while our development server is still running on port 8000.
    1. When you run the command, you should see something close to this:
  1. We can make our test command shorter by adding it as a script on our package.json file:
    1. Replace the following line of code:
"test": "echo "Error: no test specified" && exit 1"
    1. With the following line:
"test": "PORT=8001 ./node_modules/lab/bin/lab test --leaks"
    1. Now, go back to the Terminal and just run:
npm test
  1. Now, let's test that our authentication is working correctly. Add the following
    segment after the previous one:
experiment('Authentication', () =>
{
test('GET: /todo without auth', () =>
{
const options =
{
method: 'GET',
url: '/todo'
};
server.inject(options, (response) =>
{
assert.equal(response.statusCode, 401);
});
});
});
  1. Now, go back and run npm test. Both tests should be passing:
  1. You realize that we're having to go back to the Terminal every other time to run the tests. This is just as cumbersome as testing on the API client (Insomnia); we need some automation:
    1. We will need gulp.js for this, and two other Gulp plugins. Let's install them:
install gulp gulp-shell gulp-watch --save-dev
    1. Now, let's write a simple gulpfile.js at the root of our project to automate our testing task:
const gulp = require('gulp');
const shell = require('gulp-shell');
const watch = require('gulp-watch');
...
gulp.task('test', shell.task('npm test'));

You can find the complete code from the gulpfile.js file at Code/Lesson-3/exercise-c.
    1. Now, let's go to package.json and add another script option for our gulp task, next to the previous test:
"scripts": 
{
"test": "PORT=8001 ./node_modules/lab/bin/lab test --leaks",
"test:dev": "./node_modules/.bin/gulp test:dev"
},
    1. Now, go to the Terminal and instead of npm test, run the following:
npm run test:dev
    1. The watch task will be fired up, and therefore, any changes made in any of the files within the src array in the preceding point, the test will automatically run. This mean you can go on with your development work and periodically check that the tests are all good:
  1. Let's now write a sample test for GET: /todo route. Remember that for all the authenticated routes, we need the token first, for us to make a successful request. We will therefore need a script to get us the token before any tests begin. This is where the before function that we got in step 8 kicks in. In our test-todo.js file, add the following segment:
experiment('/todo/* routes', () => 
{
const headers =
{
Authorization: 'Bearer ',
};
before(() =>
{
const options =
{
method: 'POST',
url: '/auth',
...
});

You can find the complete code from the test-todo.js file at Code/Lesson-3/exercise-c/test.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset