Getting Started with Node.js and Jasmine

Semaphore

It's a shame that, almost since its creation, JavaScript had been considered
more of a quick hack than an actual programming language. Lacking the
tools and the community that other popular languages had, for a long time
it was a language that many people enjoyed to hate. Fortunately, with the
inception of Node.js, JavaScript got a chance to shine
with an awesome community and the toolset it always deserved.

This article shows how to leverage the power that these new tools bring by
creating a Jasmine-tested Node.js web server. We will create a simple Hello World web server and practice our Jasmine
test-writing skills on it.

Bootstrapping the Server

We'll start by creating an empty Node.js project:

mkdir hello_world
cd hello_world

To set up and download various dependencies, we will use
Node's official package manager — npm.
One of the nice features that npm offers is initializing an empty
project directory using its init command line option. Running
npm init will create an empty package.json file and launch a wizard
asking some basic questions about your project so it can populate it with
data. Answer the questions according to the following package.json file:

With this in place, we will set up two directories in our project's root
directory — one for the server's source code, and another one for
the Jasmine test files. By convention, tests written
in Jasmine are called specs (short for specification), and are stored
inside the spec directory.

mkdir app
mkdir spec

At this point, your project tree should have the following structure:

.
├── app
├── node_modules
├── package.json
└── spec

Installing Dependencies

Our project will require several dependencies.

For writing specifications in Jasmine, we need to install
its npm package. Run the following command in your project's
root directory:

npm install jasmine-node --save

The --save option will automatically append the package
to your package.json file and save the version of the
package that your project is depending on.

Later in this tutorial, we will execute several requests
facing our application. We will use the
request
npm package for that purpose. Similar to the above package, we will install
it with:

npm install request --save

The last package we need to install is
Express.js. This package
defines a simple DSL (domain specific language) for routing and
handling incoming HTTP requests. Install it with:

npm install express --save

One final step is needed before we can start writing some code.
We will set up npm's test command to run Jasmine specs.
Our jasmine-node is installed locally in the node_packages
directory inside our project's root directory. To run it, invoke its
binary, and point it to our spec folder. The following command
does just that:

./node_packages/.bin/jasmine-node spec

We will now put the above command in the package.json file, after
which that file should look like this:

Next, we will use the request package to send a GET request toward
our web server. We can load the package with the require keyword
in Node.js, and to execute a request, we need to pass it a URL
and a function that it will invoke once the request is returned.

Finally, we can now write our first expectation. Jasmine implements
expectations with the expect() function that tests if a tested object
matches some of the expected conditions. For example, the following
expect will match the value of the response.status to the number
200, with the .toBe matcher:

Our test is almost finished, but there is just one more little detail we
need to take care of. Node.js is an asynchronous environment, so
there is a chance that the it block will finish before the expectation.
To mitigate this problem, we will use the
done callback
— a callback available only in Jasmine-node, and not in pure Jasmine —
to synchronize it with its expect:

The done() function should only be called if the expectation is executed.
If, for some reason (code error or similar), done() is not called,
Jasmine will terminate this it block and consider it as a failed
example.

Similar to the above, we'll write another expectation to test
if the body of the response contains the string "Hello World".

The Hello World Generator

The above is a fairly trivial example of testing with Jasmine. Let's juice it
up a little by creating a Hello World generator.

Never heard of one? It's a fairly simple technology. You can request the number
of Hello Worlds you need, and our server will return it as a JSON array.

We will first create a function which takes a number as its parameter
and returns an Array with that many "Hello World" strings in it.
Let's write the specs for our Hello World generator:

touch spec/generatorSpec.js

vargenerator=require("../app/generator");describe("Hello World Generator",function(){it("returns an array",function(){expect(generator.generateHelloWorlds(0)).toBe([]);});it("returns the correct number of Hello Worlds",function(){varresult=generator.generateHelloWorlds(3);expect(result.length).toBe(3);});it("returns only Hello Worlds",function(){varresult=generator.generateHelloWorlds(3);result.forEach(function(element){expect(element).toBe("Hello World");});});});

Closely following its specification, we can write a simple
for loop that will populate an Array: