node

Test Execution Order in Mocha

In synchronous tests, both describe and it statements are executed in the order they are laid out.

Test Foo should run before Bar:

1
2
3
4
5
6
7
describe('Suite', function () {
it('Foo', function () {
});
it('Bar', function () {
});
});

Suite Foo should run before Bar:

1
2
3
4
5
describe('Foo', function () {
});
describe('Bar', function () {
});

In asynchronous tests, the same ordering applies.

Test Foo should run before Bar even Foo takes much longer to execute, and Suite B should also run after Suite A:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var should = require('should');
describe('Suite A', function () {
it('Foo', function (done) {
setTimeout(function () {
(true).should.equal(true);
done();
}, 1000);
});
it('Bar', function () {
(true).should.equal(true);
});
});
describe('Suite B', function () {
it('Foo', function () {
(true).should.equal(true);
});
});

Result:

1
2
3
4
5
6
7
8
9
Suite A
✓ Foo (1002ms)
✓ Bar
Suite B
✓ Foo
3 passing (1s)

This is the great feature in Mocha.

SuperTest: Listen at Random Port

In the example section of SuperTest (v0.15.0), it mentions something about ephemeral port:

You may pass an http.Server, or a Function to request() - if the server is not already listening for connections then it is bound to an ephemeral port for you so there is no need to keep track of ports. - https://github.com/visionmedia/supertest#example

Let’s dissect this sentence. There are a few key concepts to grasp:

  1. The request function will accept either a function or an http.Server object.
  2. When does the server not listening for connections?
  3. What is an ephemeral port?

Taking a peek at the index.js file in SuperTest source code, it is easy to see that it accepts both function and http.Server object, but prefer latter:

1
2
3
4
5
6
7
8
9
10
11
// See `index.js` in [SuperTest] source code.
if ('function' == typeof app) app = http.createServer(app);
// See `lib/test.js` in [SuperTest] source code.
Test.prototype.serverAddress = function (app, path) {
var addr = app.address();
if (!addr) this._server = app.listen(0);
var port = app.address().port;
var protocol = app instanceof htts.Server ? 'https' : 'http';
return protocol + '://1270.0.0.1:' + port + path;
});

Why it does this? This has to do with Express:

1
2
3
4
5
6
7
8
> typeof require('http').createServer()
'object'
> typeof require('express')()
'function'
> typeof require('koa')()
'object'
> require('http').createServer(require('express')()).address()
null

Only when initiating an Express app, it returns a function, not an object. And follows up on lib/test.js, when SuperTest detects the created server is yet to bind to any port number, it will invoke app.listen(0), so called ephemeral port. In fact, it is just a random port.

When something is ephemeral, it last for a very short time. When allowing a server to accept connections, we usually do is setting the server to listen on a specific port:

1
app.listen(3001);

What if setting this to 0 like above or omit this port number?

Locate HTTP Port Number from http.Server Instance

This is a bare minimal HTTP server:

1
require('http').createServer().listen(port);

If the port number is evaluated to be falsy, such as 0, null, undefined or an empty string, a random port will be assigned.

Begin accepting connections on the specified port and hostname. If the hostname is omitted, the server will accept connections on any IPv6 address (::) when IPv6 is available, or any IPv4 address (0.0.0.0) otherwise. A port value of zero will assign a random port. - https://iojs.org/api/http.html#http_server_listen_port_hostname_backlog_callback

We can use command line tool such as netstat to find out the port number:

1
2
$ netstat -ltpn | grep node
tcp6 0 0 :::44055 :::* LISTEN 5624/node

However, it will be very convenient without relying on external tools.

Luckily, we can find out the port number by using the address method:

1
require('http').createServer().listen().address()

The result will be similar to:

1
{ address: '::', family: 'IPv6', port: 44055 }

Furthermore, it works with all popular libraries that create an http.Server instance:

Use Array of Middleware in Koa Router

Koa Router v4.2 does not support an array of middleware, multiple middleware must be entered one by one:

1
app.get('/foo', middleware1, middleware2);

Using an array is much cleaner than multiple arguments.

1
app.get('/foo', [middleware1, middleware2]);

But the above will throw error:

1
Error: GET: `middleware` must be a function, not `object`

This can be easily fixed by using Koa Compose:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var app = require('koa')();
var router = require('koa-router');
var compose = require('koa-compose');
app.use(router(app));
app.get('/foo', compose([
function *(next) {
this.body = {};
yield next;
},
function *(next) {
this.body.foo = 'foo';
yield next;
},
function *(next) {
this.body.bar = 'bar';
yield next;
}
]));

Hence:

1
app.get('/foo', compose([middleware1, middleware2]));

Synchronous Console Methods

In Node v0.10.x, the console functions are synchronous when the destination is a terminal or a file (to avoid lost messages in case of premature exit) and asynchronous when it’s a pipe (to avoid blocking for long periods of time). See console. We can test it with the following script:

Dirname Does Not Follow Symlink

Node’s global object __dirname returns the name of the directory that the currently executing script resides in. However, if a directory is symbolic linked or a symlink, it still return the original path.

For example, the following directory structure:

1
2
3
4
5
6
7
8
/tmp/dirname/
├── foo
│ └── app.js
└── lib
├── bar -> ../foo
└── util.js
3 directories, 2 files

The app.js contains the following line:

1
console.log(__dirname);

Run the script:

1
2
$ cd /tmp/dirname/foo && node app.js
/tmp/dirname/foo

You get the directory the app.js script is residing it. But if you do the same from the symlinked directory:

1
2
$ cd /tmp/dirname/lib/bar && node app.js
/tmp/dirname/foo

Well, you get the same answer, even the current working directory is different:

1
2
$ cd /tmp/dirname/lib/bar && pwd
/tmp/dirname/lib/bar

The return of __dirname does not follow symbolic link.

So, have to be extra careful when requiring files that is symbolic linked. If you think you are in lib/bar directory and try to require the util.js script in app.js:

1
2
3
var path = require('path');
console.log(require('../util'));
console.log(require(path.join(__dirname, '..', 'util')));

Both statements will throw module not found error. Path join does not help either.

The best practice is to avoid symlinks and relative directory requiring. Instead, set up required as modules, and install them in node_modules directory, then they will become top-level modules.

Tiny HTTP Servers

This is a simple way to run a tiny web server via command line:

$ python -m SimpleHTTPServer 8080

which will server static files from the current directory.

There is Knod for Ruby, and of course there is one for Node: http-server.

To install:

$ sudo npm install -g http-server

To run:

$ http-server

Server will be accessible via http://localhost:8080/.