/** * `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; };