Unit testing nodejs with Mocha and Chai

There are a lot of unit testing frameworks available for Javascript, Jasmine and Karma being some of the older and more popular ones.

Jasmine and Karma, though are, originally designed for browser-side JS, and hence, frameworks like NodeUnit and Mocha have become more popular with server-size JS.
We needed code coverage reports to work after the unit tests, and the Jasmine-Node reports were not sufficient, so we just moved to using Mocha.

When using Mocha, we can use some assert library (which is not necessary, but makes life a hell lot easier). We are using chai at the open-event-webapp..

First of all install mocha globally –

npm install -g mocha

And write your tests in the test/ folder that mocha by default considers as the folder containing your test specs. For example we have our tests here – https://github.com/fossasia/open-event-webapp/tree/master/test

Writing a simple mocha test is as easy as this –

var assert = require('chai').assert;
describe('Array', function() {
  describe('#indexOf()', function() {
    it('should return -1 when the value is not present', function() {
      assert.equal(-1, [1,2,3].indexOf(5));
      assert.equal(-1, [1,2,3].indexOf(0));
    });
  });
});

The first parameter inside describe() is just to show the tests in a aesthetic way in the console.

You can see our tests described in this file  – https://github.com/fossasia/open-event-webapp/blob/master/test/serverTest.js

And attached below is an screenshot of the terminal after I have run the command mocha in the root of my project

Screenshot from 2016-07-10 04-42-26

Continue ReadingUnit testing nodejs with Mocha and Chai

Debugging with Node

Nodejs is a powerful Event-driven I/O server-side JavaScript environment based on V8. Debugging of Node applications is not as easy as the browser code. But the node wonderful debugger can make it easy if it is used effectively.

How to start the debugger

For debugging node applications, we have to only run a debug command. Here for a quick demonstration, I have used Open-Event-Webapp fold.js code.

Suppose there is a problem in the script file and we have to debug it. All we have to do is to run the debug command from the directory containing the file.

node debug ./fold.js

The output screen will show something like this:

25

This brings us into the debug mode. When we are in debug mode, we can try various commands like ‘n’ for next, ‘s’ for the step into a function, ‘list(k)’ where k is the number of lines of the code you want on the screen.

26

The ‘n’ command always takes us to next instruction, hence in long codebases, it is always recommended to use ‘c’ or Continue Execution command for going to the next breakpoint.

To set the breakpoint, we can use the command:

setBreakpoint() or sb()

The snapshot shows the output once the breakpoint is set. We can check the values at the breakpoint by using command repl.

4

Debugging the code correctly can save a lot of time and effort. These techniques provided by the debugger are necessary to learn.

Alternates

Continue ReadingDebugging with Node

sTeam REST API

(ˢᵒᶜⁱᵉᵗʸserver) aims to be a platform for developing collaborative applications.
sTeam server project repository: sTeam.
sTeam-REST API repository: sTeam-REST

REST Services

REST is the software architectural style of the World Wide Web. REST (Representational State Transfer) was introduced by Roy Fielding in his doctoral dissertation in 2000. Its purpose is to induce performance, scalability, simplicity, modifiability, visibility, portability, and reliability.It has client/server relationship with a uniform interface and is stateless. REST is most commonly associated with HTTP but it is not strictly related to it.

REST Principles

  • Resources : Each and every component is a resource.A resource is accessed by a common interface using HTTP standard methods.
  • Messages use HTTP methods like GET, POST, PUT, and DELETE.
  • Resource identification through URI: Resources are identified using URI. Resources are represented using JSON or XML.
  • Stateless interactions take place between the server and the client. No context is saved for the requests at the server.The client maintains the state of the session.

HTTP methods

The CRUD(create, retrieve, update and delete ) operations are performed using the HTTP methods.

GET

It is used to retrieve information. GET requests executed any number of times with the same parameters, the results would not change. This makes it idempotent. Partial or conditional requests can be sent. It is a read only type of operation.

Retrieve a list of users:

GET /api.example.com/UserService/users

POST

POST is usually used to create a new entity. It can also be used to update an existing entity. The request will have to do something with the entity provided in the URI.

Create a new user with an ID 2:

POST /api.example.com/UserService/users/2

PUT

PUT request is always idempotent. Executing the same request any number of times will not change the output. PUT can be used to create or update an existing entity.

Modify the user with an ID of 1:

PUT /api.example.com/UserService/users/1

PATCH

It is idempotent. PATCH requests only updates the specified fields of an entity.

Modify a user with an id of 1:

PATCH /api.example.com/UserService/users/1

DELETE

It can be asynchronous or a long-running request. It removes the resource. It can be removed immediately or at a later instance of time.

Delete a user with an ID of 1:

DELETE /api.example.com/UserService/users/1

 sTeam-REST API

Installing and activating the REST API

The REST API is developed as an application inside the sTeam server. This simplifies development quite a lot, as we don’t need to restart the server for every change. Instead just the API code gets updated and reloaded. It may eventually be integrated into the core, however the longterm plan is actually to move functionality out of the core, to make development easier.

To get the current version of the API clone the steam-rest repo into your home or to any place where you keep your development repos. Then change to the tools directory of your installation and run import-from-git.

git clone https://github.com/societyserver/steam-rest
cd steam-rest
git checkout origin/rest.pike
export steamrest=`pwd`
cd /usr/local/lib/steam/tools
./import-from-git.pike -u root $steamrest /

Note: The new import-from-git.pike script supports importing documents of all mime types.

It is important that the first import is done as root because the API code needs to run with root privileges and it will only do that if the object that holds the source is created as root.

Once the api code is loaded there are just a few tweaks needed to make it work.

We need to fix the mime-type, as the import script is not doing that yet.

OBJ("/sources/rest.pike")->set_attribute("DOC_MIME_TYPE", "source/pike");

Changing the mime type will change the class of the rest api script from Document to DocLpc.

> OBJ("/sources/rest.pike");                                               
(1) Result: 127.0.0.1:1900/rest.pike(#840,/classes/Document,17,source/pike)
> OBJ("/sources/rest.pike");                                               
(2) Result: 127.0.0.1:1900/rest.pike+(#840,/classes/DocLpc,529,source/pike,0 Instances, ({  }))

This takes a moment, check the type a few times until it’s done. Then instantiate an object from the source, give it a proper name, and move it to the /scripts/ container”

object rest = OBJ("/sources/rest.pike")->provide_instance();
rest->set_attribute("OBJ_NAME", "rest.pike");
rest->move(OBJ("/scripts/"));

Instantiating the object needs to be done as sTeam-root, in order for it to have permissions to run on behalf of other users.

Once this is done you are ready to start using the API.

sTeam-REST API tests

The project contains a set of examples and tests for the RESTful API for the sTeam server.

The code is written in coffee script and needs node.js only for coffeescript translation. Deployment can be done as static javascript files, and does not need any kind of dynamic server for the front-end. The back-end is a RESTful API written for the sTeam server as used by steam.realss.com

Development instructions

step 1: install node.js

http://nodejs.org/download/

step 2: clone the repository

git clone https://github.com/societyserver/steam-rest

step 3: install node packages:

npm install

This installs all dependencies (including coffee) for our project into the project’s node_modules directory based on the ‘package.json’ file

step 4: start the server

node_modules/.bin/coffee scripts/server.coffee

but for convenience we can install coffee in the global node environment:

npm install -g coffee-script

so we can just say

coffee scripts/server.coffee

if the server is working you’ll see:

Listening on port 7000

Testing

FrisbyJS is used to test the API. It is run through Jasmine and is based on nodejs.

Once you have nodejs installed, run the following statement to install Frisby and Jasmine:

npm install -g jasmine-node frisby

Then execute the test by:

cd project/directory
jasmine-node test/

The karma testing framework is also used for testing the sTeam REST API.

There were some inherent issues with the test framework which were addressed.

Issue. Github Issue Github PR
Update Readme.md Update Readme PR-2
Add javascript dependencies Issue-4 PR-6
Add node dependencies Issue-5 PR-7
Add angular-mocks.js script for testing the REST services. Issue-8 PR-9

The project dependencies were not met and this resulted into the error when the project was run on the localhost. The angular-ui-router, angular-bootstrap and bootstrap js frameworks were not installed in the node modules of the project. As a result the bower.json script was modified to include these dependencies.

bower.json

{
  "name": "bower",
  "version": "0.1",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "angular": "",
    "angular-route": "~1.4.8",
    "angular-ui-router": "",
    "angular-bootstrap": "",
    "bootstrap": ""
  }
}

The node dependencies of karma, frisby and jasmine-node were included in the package.json. These would be installed when the npm install is executed.

package.json

{
"name": "TechGrind",
"version": "0.1.1",
"private": true,
"dependencies": {
"express": "",
"coffee-script": "",
"morgan": "",
"compression": "",
"method-override": "",
"body-parser": "",
"serve-static": "",
"errorhandler": "",
"bower": "",
"jasmine-node": "",
"frisby": "",
"karma": ""
},
"production_dirs": {
"coffee_src": "src/",
"src": "app/",
"dest": "app_production/"
},
"devDependencies": {
},
"scripts": {
"postinstall": "bower install"
}
}

Feel free to explore the repository. Suggestions for improvements are welcomed.

Checkout the FOSSASIA Idea’s page for more information on projects supported by FOSSASIA.

Continue ReadingsTeam REST API

Sending a streaming zip file in node.js

The webapp generator that we set up is now up and running on a heroku instance and is working to generate zips of generated websites.

One of the requirements was that when the front-end presses, the “Generate” button, a request is created to the backend node app to start creating the html pages, and pack them into a zip file. Then the said zip file will be made available to download.

I intended for the zip file to become available to download immediately and the server to continuously pack data into the zip, as the user downloads it – a process known as streaming zip serving. (If you might have noticed, Google Drive uses this too. You do not know the final zip size before the download has completed.)

If the server takes time in creating the contents of the zip, this method can help, as it will allow the user to start downloading the file, before all the contents are finalised.

 

To achieve the mentioned goal, the idea Node.js module to use archiver.

If you look at the app.js code you’ll find on the /generate POST endpoint, we take the ‘req’ params and pass to a pipeToRes() function, which is defined in generator.js

app.post('/generate', uploadedFiles, function(req, res, next) {
console.log(req.files);
console.log(req.body);
res.setHeader('Content-Type', 'application/zip');
generator.pipeZipToRes(req, res);
});

And in the generator, you can find this block of code that pipes the streaming archive to the response.

 

      const zipfile = archiver('zip');

      zipfile.on('error', (err) => {
        throw err;
      });

      zipfile.pipe(res);

      zipfile.directory(distHelper.distPath, '/').finalize();

We zip the directory defined in distPath and the archiver API has a fluent call to .finalize() that finished the download for the user, when the zip is completed.

Continue ReadingSending a streaming zip file in node.js