154 lines
3.4 KiB
JavaScript

/**
* `connect` or `express` http request test helper.
*
* Source codes come from https://github.com/senchalabs/connect/blob/master/test/support/http.js.
*
* Modified by @fengmk2
*/
/**
* Module dependencies.
*/
var EventEmitter = require('events').EventEmitter;
var methods = ['get', 'post', 'put', 'delete', 'head'];
var express = require('express');
var connect = null;
try {
connect = require('connect');
} catch (e) {
}
var http = require('http');
var querystring = require('querystring');
// need to change > 0.3.x
express.HTTPServer.prototype.request = function (address) {
return new Request(this, address);
};
if (connect && connect.HTTPServer) {
connect.HTTPServer.prototype.request = express.HTTPServer.prototype.request;
}
// not support < 0.2.0
// connect.proto.request = function(){
// return request(this);
// };
function Request(app, address) {
this.data = [];
this.header = {};
this.app = app;
this.server = app;
this.addr = address || this.server.address();
}
/**
* Inherit from `EventEmitter.prototype`.
*/
Request.prototype.__proto__ = EventEmitter.prototype;
methods.forEach(function (method) {
Request.prototype[method] = function (path) {
return this.request(method, path);
};
});
Request.prototype.set = function (field, val) {
this.header[field] = val;
return this;
};
Request.prototype.setBody = function (body) {
this.set('Content-Type', 'application/x-www-form-urlencoded');
this.write(querystring.stringify(body));
return this;
};
Request.prototype.write = function (data) {
this.data.push(data);
return this;
};
Request.prototype.request = function (method, path) {
this.method = method;
this.path = path;
return this;
};
Request.prototype.expect = function (body, fn) {
var args = arguments;
this.end(function (res) {
if (args.length === 3) {
res.headers.should.have.property(body.toLowerCase(), args[1]);
args[2]();
} else {
if ('number' === typeof body) {
res.statusCode.should.equal(body);
} else {
res.body.toString().should.equal(body);
}
fn();
}
});
};
Request.prototype.end = function (fn) {
var self = this;
var req = http.request({
method: this.method,
port: this.addr.port,
host: this.addr.address,
path: this.path,
headers: this.header
});
this.data.forEach(function (chunk) {
req.write(chunk);
});
req.on('response', function (res) {
var chunks = [], size = 0;
res.on('data', function (chunk) {
chunks.push(chunk);
size += chunk.length;
});
res.on('end', function () {
var buf = null;
switch (chunks.length) {
case 0:
buf = new Buffer(0);
break;
case 1:
buf = chunks[0];
break;
default:
buf = new Buffer(size);
var pos = 0;
for (var i = 0, l = chunks.length; i < l; i++) {
var chunk = chunks[i];
chunk.copy(buf, pos);
pos += chunk.length;
}
break;
}
res.body = buf;
res.bodyJSON = function () {
return JSON.parse(res.body);
};
res.shouldRedirect = function (status, url) {
res.should.status(status);
var addr = self.app.address();
res.headers.location.should.equal('http://' + addr.address + ':' + addr.port + url);
};
fn(res);
});
});
req.end();
return this;
};