Node JS testing examples with Mocha, Proxyquire, Assert and Sinon

it("it should map the options", function (done) {
    var objMappingServiceMapSpy = sinon.spy(objMappingServiceMock, "map");

    target.callPublic(reqMock, resMock).then(function () {
        try {
            assert(objMappingServiceMapSpy.withArgs("HttpServiceOptions", optionsMock).calledOnce);
            done();
        }
        catch (err) {
            done(err);
        }
    });
});

describe("when the response is a success", function () {
    beforeEach(function () {
        requestPromiseMock = sinon.stub().returns(
            new Promise(function (resolve, reject) {
                resolve("api data");
            })
        );

        target = proxyquire("api/services/factories/httpServiceFactory", {
            "request-promise": requestPromiseMock,
            "api/services/api/apiConfigService": apiConfigServiceMock
        });

        instance = target.make("frankie");
    });

    it("it should return the data", function (done) {
        instance.call(optionsMock).then(function (data) {
            try {
                assert.deepEqual(data, "api data");
                done();
            }
            catch (err) {
                done(err);
            }
        });
    });
});

Node JS – REST calls with ES6 Promises + Co JS Module

Here is an example of factory that creates an httpService to communicate with an external API with REST. We are using the npm module “request” to perform the HTTP calls. We are using as well ECMAScript 6 classes and promises, as long as the npm module “co”, that allows us to take advantage on the ES6 generators to await for async elaborations that returns a promise.

https://www.npmjs.com/package/co

"use strict";

var request = require("request-promise");
var co = require("co");

class HttpService {
     constructor(baseUri) {
          this.baseUri = baseUri;
          Object.seal(this);
     }

     call(options) {
          var self = this;

          console.log("Calling", self.baseUri + options.uri + "..");

          return new Promise(function (resolve, reject) {
               co(function* () {
                    try {
                         var data = yield request({
                              uri: self.baseUri + options.uri,
                              method: options.method,
                              headers: options.headers,
                              form: options.postData,
                              json: true
                         });
                         console.log(data);
                         resolve(data);
                    } catch (err) {
                         if (err.name == "StatusCodeError") {
                              console.log("ERROR: returned status code was", err.message);
                              reject(err.statusCode);
                         } else {
                              console.log("ERROR:", err.message);
                              reject(500);
                         }
                    }
               });
          });
     }
}

module.exports = {
     make: function (baseUri) {
          return new HttpService(baseUri);
     }
};

Node JS – Services + Globals (Sails JS)

We can define our services inside the “api/services” folder. Each service defined here will be globally accessible by its file name (without extension).

module.exports = {
     myServiceMethod: function (args) {
          return ...;
     }
};

However this approach has some limitation: all the services have to stay on the same level (sub-folders are not supported). So is better to disable this behaviour and to directly go through the standard Node JS require() mechanism.

To disable it we can edit the “config/globals.js” file in this way:

module.exports.globals = {
     ...

     services: false
}

Then we can refer the service we need from any controller or other service in this way (please note that we are using the npm module “app-root-path” to get the root path):

var appRoot = require("app-root-path");
var myService = require(appRoot + "/api/services/myService");

module.exports = {
     ...
}

This is the standard way in Node JS to require a module given its path.


Having a service globally available

Since we disabled the automatic behaviour we now have to explicitly require every service we need. However it could be useful to have some service automatically available without needing to request it everywhere. To have this we can add them to the global object by editing the “config/bootstrap.js” file:

global.appRoot = require('app-root-path');
global.myUtilService = require(global.appRoot + "/api/services/utils/myUtilService");

module.exports.bootstrap = function(cb) {
     ...
};

In this way we can refer the service through global.myUtilService (or even just myUtilService)from everywhere.


Specifying the current path to Node JS (NODE_PATH)

To avoid using external modules like “app-root-path” we can launch Node JS with the information of the current path we want it to consider when we require for modules. In this way we can use relative paths with no problems.

In order to do this we can specify the path with an environment variable before starting the app (in any of the ways we can start it), here is an example:

NODE_PATH=. npm start

In order to have VS Code doing the same thing when we debug the application we can edit its launch configuration (under “.vscode/launch.json”) to add “NODE_PATH”: “.” to the “env” node of the “launch” configuration.

Node JS – Authorisations (Sails JS)

In Sails JS we can define authorisations (among other things) with the policies. Policies are operations (usually checks) that are executed before any call to a controller. Since a policy is agnostic about what controller will be associated to and what other policies will be associated to the same controller, it behaves as a chain’s ring: if the result of a policy is positive it will just call the next ring, that could be another policy or the controller, depending on the configuration.

We define policies under the “api/policies” folder, here is an example of authentication policy reply with an “unauthorised” message whether the user isn’t logged in (we check this by searching for the user’s object in the session).

module.exports = function (req, res, next) {
     if (req.session.userObj) {
          return next();
     }

     return res.json("unauthorized");
};

To apply the policy to our controllers we have to edit the “config/policies.js” file in this way:

module.exports.policies = {
     ...

     "*": “<myPolicyFileNameWithoutExtension>",

     loginController: {
          "index": true
     }
}

With this configuration we are telling Sails JS that we want to apply our policy to all the controllers/actions, apart the loginController/index actions, that will be free to access.

In case our controller is inside a subfolder we can refer to it in this way:

“myFolder/myController”: {
     “myAction”: ...
}

Node JS – Session stored in MySQL (Sails JS)

In order to have the session stored in MySQL we can use the npm module “express-mysql-session”, that works directly with the Express JS framework that lies under Sails JS.

To configure our session we have to edit file “config/session.js” file in this way:

var MySQLSessionStore = require('express-mysql-session');

module.exports.session = {
     ...
     
     store: new MySQLSessionStore({
          host: 'localhost',
          port: 3306,
          user: 'root',
          password: 'root',
          database: 'test-node-sails'
     })
}

We can save data into the session from any controller through req.session:

req.session.user = { … };

Node JS – Controllers (Sails JS)

We can auto-generate a new controller by typing “sails generate controller []” from a terminal. For instance we can type:

sails generate controller test action1 action2 action3

to generate a “TestController.js” file like this:

module.exports = {
     action1: function (req, res) {
          return res.json({
               todo: 'not implemented yet'
          });
     },

     action2: function (req, res) {
          return res.json({
               todo: 'not implemented yet'
          });
     },

     action3: function (req, res) {
          return res.json({
               todo: 'not implemented yet'
          });
     }
};

The controller is generated inside the “controllers” folder. Is however possible to have subfolders, whose controllers will be automatically bound (and referred) with the corresponding subpath.

A controller’s behaviour is quite usual, we can return the default view (or a different one if we specify it with a parameter) by writing:

action2: function (req, res) {
     return res.view();
}

The default view is normally located under “views//.ejs”, so in this case will be under “views/test/action2.ejs”. Here is an example about what it can contain:

<h1>
     action 2
</h1>
<h2>
     this is raw html <%-'<button>button</button'%>
</h2>

By default every view in injected inside the general layout defined in the “views/layout.ejs” file, so we don’t need to define things such the page’s header or title. The place where our view will be rendered inside the layout is specified by “”.


Custom routing + viewModels

Is of course possible to define custom routes by editing the “config/routes.js” file. For instance we can add a new parametrised root that calls the “action3” action of our controller in this way:

'/test/:value/action3': {
     controller: 'test',
     action: 'action3'
}

Then inside our action we can read the parameter and pass it to the view through the viewModel in this way:

action3: function (req, res) {
     var value = req.param('value');

     return res.view({
          receivedValue: value
     });
}

Finally here is how to render something from the viewModel in the view:

<h1>
     action 3
</h1>
<h2>
     the received value is <%=receivedValue%>
</h2>
<h3>
     <%if(receivedValue == 'bingo') {%>
          <p>bingo!</p>
     <%} else {%>
          <p>not bingo..</p>
     <%}%>
</h3>

Node JS – Working with Sails JS in Unix with VS Code

https://www.codementor.io/nodejs/tutorial/how-to-setup-sailsjs-tutorial-beginners
https://code.visualstudio.com/docs/runtimes/nodejs

Setting up a new project

Install node.js from https://nodejs.org/en

To test that node.js has been installed run “node” from a terminal (is then possible to exit from the node.js console by typing “.exit”).

When using node.js for web development is a good option to use a web framework rather than doing everything from scratch with the raw platform. The most common frameworks are express.js (described in a previous note) and sails.js. The second one, built on top of express.js, simplifies some activity and solves some problem of the original framework. For these reasons this time we’ll use sails.js for our purposes.

Is possible to install sails.js from npm (npm.js is the default package manager for node.js and is automatically installed together with it)

sudo npm -g install sails

The -g parameter tells npm to install the named module so that it’s accessible globally. Is typically only used for packages that provide command-line utilities so that their executable components are available in the system PATH.

To test that sails.js has been installed run “sails” from a terminal.

In order to create a new sails.js project navigate to the folder you want the new project to be created and run:

sails new

To run the new project navigate inside the newly created project folder and then run:

sails lift

Other ways to run the application are the usual pure Node JS way “node app.js” and “npm start”. The last command deserve some additional explanation: npm supports the option “npm run

The new project will be browsable from http://localhost:1337

As always is possible to stop the server by pressing CTRL+C.


Working with NPM

Every Node JS module is normally added through NPM (Node Package Manager) with the command “npm install —save”. This will normally load the module under the “node_modules” folder and will add an entry in the “package.json” file (if we used the “—save” option to save it as a dependency). The entry is useful to be able to restore all the packages (for instance if we just checked in the solution from Git, where the actual modules weren’t included into the branch) by running “npm install” (very similar to NuGet).

In order to globally install a module (like what we did to install Sails JS) we can use the “-g” option (administrator rights required).


Working with VS Code

After installing VS Code from https://code.visualstudio.com/ a very useful option is to add it to the system PATH in order to be able to open it from the terminal. This can be easily done through the GUI by pressing F1 to show the command palette and typing “shell command” to display the “Shell Command: Install ‘code’ command in PATH” command.

From this moment on we’ll be able to open VS Code for a specific location (like the project we just created) by running “code ” from a terminal.

Since we are already on the project’s folder we can open VS Code by running:

code .

We can debug the application by pressing F5 (or from the Debug tab). At the first attempt to start the application we’ll be prompted to select the target platform (we select node.js) and, as result, a “launch.json” configuration file will be created under the “.vscode” folder. From now on we’ll be able to run our application from here (VS Code runs the “app.js” file with Node JS in debug mode).

The “api” folder is where we’ll write the most of our MVC code. Here is where controller and models are defined. By default the root url is bound to display the content of the “views/homepage.ejs” page. This in configured in the “config/routes.js” file, where is possible to define associations between routes and controllers, or even just with views like in this case.


By default VS Code doesn’t recognize the .ejs files used by sails JS to define views, so they will be rendered as normal .txt files. In order to fix this we can click on the label “Plain Text” on the right side of the status bar, then we can choose the “Configure File Association for ‘.ejs'” option to access the “settings.json” where we can override the VS Code default settings. Here is what we have to add:

"files.associations": {
     "*.ejs": "html"
}

After this change we need to restart VS Code to have the .ejs files rendered as .html files.

Node JS – Introduction

https://nodejs.org

Node JS is a framework which whom is possible to generate JS server side applications. It take advantage from the V8 Google’s engine, which compiles to native machine code and dynamically optimizes it at run time by using heuristic on the execution profile. Even though is very diffused in the Unix systems is becoming used in the Windows platform as well, since Microsoft has strongly invested for its porting and its support.

The first thing to do is to download Node and to install it. It will be installed also NPM, the packet manager which whom we’ll be able to add other features to the base framework.

First Application

In order to create a Node JS application we have to create a JS file and to execute it with Node. Within the file (that is the entry point for the server side application) we insert the server configuration and the various functions that we’ll use to manage the routes. Here is an example:

var http = require("http");
 
http.createServer(function (request, response) {
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("Hello World");
    response.end();
}).listen(8888);
 
console.log("server started");

To launch the application we have to start the console (running as administrator) and to execute Node JS with our file as parameter, in this way:

We can see the message “server started” printed by the application. If we try to connect to http://localhost:8888 (the port in which we set out application to listen) we’ll see the message “hello world” that we are returning to the from server side. To end the application we can press on CTRL + C.


Node JS application with Express

Express is an additional framework very useful to create Node JS applications in a way that is more similar to when we work with a “classic” web server. It can be installed from NPM (we can use the npm search express command to find it), but before we need to create a file named package.json, which describes our application and, most important, our dependencies. When we launch the npm install command upon our site’s root (that should be the correct location for this file) the file is read and the dependencies are automatically downloaded and installed. In our case, since we want to use Express, the package.json file will be similar to this example:

{
    "name": "hello-world",
    "version": "0.0.1",
    "dependencies": {
        "express": "latest"
    }
}

After correctly installed Express we can create our application and to launch it in a similar way as we have done previously. Here is an example of an application which uses Node JS with Express:

var express = require('express');
var app = express();
 
app.get('/', function (req, res) {
    res.send('This is the home page');
});
 
app.get('/about', function (req, res) {
    res.send('This is the about page');
});
 
app.listen(3000);

If we try to connect to http://localhost:3000 we will see the message “this is the home page”. If we try to connect to “http://localhost:3000/about we will see the message “this is the about page”.