node.jstestingvows

Nodejs: Unable to get response body when working with vows and nodejs http module


I am playing around vows and nodejs.

var vows = require('vows');
var http = require('http');
var suite = vows.describe('testing');
var host = 'www.google.com', port = '80', path = '/', method = 'GET';

suite.addBatch({
    'A context': {
        topic: function(){
            http.get({
              host: host,
              port: port,
              path: path,
              method: method
            }, this.callback);
        },
        "sample test": function(res, extra){//here extra is just to prevent vows error
            res.on('data', function (chunk) {
                console.log('BODY: ' + chunk);//It never gets logged
            });
            console.log('HEADERS: ' + JSON.stringify(res.headers));//it is working
        }
    }
});

suite.export(module);

But I am unable to get the response body. What am I doing wrong.

I am using nodejs v 0.6.6 and vows v0.6.2


Solution

  • From what I can see, it looks like Vows doesn't directly invoke the test when this.callback runs. It is delayed by processnextTick. If I had to guess, maybe the 'data' event is being emitted during that time. That means you don't bind your 'data' function until after all the data events have been triggered.

    Really though, the issue is that Vows tests are supposed to separate all async logic like this into the topic itself. If you really want to check the chunks in a test, then do it like this.

    Also note that you can have any number of chunks, there isn't just a single data event. You may want to set the stream encoding, and join the data as strings. Your current code implicitly converts a Buffer to string, which can break for multi-byte characters.

    suite.addBatch({
        'A context': {
            topic: function(){
                var cb = this.callback;
                var req = http.get({
                  host: host,
                  port: port,
                  path: path,
                  method: method
                });
    
                // Aggregate all chunks before running callback
                req.on('response', function(res) {
                  var chunks = []
                  res.on('data', function(chunk) {
                    chunks.push(chunk);
                  });
                  res.on('end', function() {
                    cb(null, res, chunks);
                  });
                });
    
                // Handle connection failures.
                req.on('error', cb);
            },
            "sample test": function(err, res, chunks){
                chunks.forEach(function (chunk, i) {
                    console.log('BODY piece ' + i + ': ' + chunk);
                });
                console.log('HEADERS: ' + JSON.stringify(res.headers));
            }
        }
    });