Permalink
Browse files

Chuck support, tests

  • Loading branch information...
1 parent 67b0d66 commit 9701be122fa1a36aeee374cebffc05b90225f7f5 @hueniverse hueniverse committed Mar 4, 2013
Showing with 370 additions and 109 deletions.
  1. +1 −1 README.md
  2. +3 −3 examples/http.js
  3. +97 −90 lib/index.js
  4. +1 −1 package.json
  5. +268 −14 test/index.js
View
@@ -32,7 +32,7 @@ internals.main = function () {
Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
- console.log(res.readPayload());
+ console.log(res.payload);
});
};
View
@@ -1,7 +1,7 @@
// Load modules
var Http = require('http');
-var Shot = require('../lib/shot');
+var Shot = require('..');
// Declare internals
@@ -14,7 +14,7 @@ internals.main = function () {
var dispatch = function (req, res) {
var reply = 'Hello World';
- res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': reply.length });
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(reply);
};
@@ -24,7 +24,7 @@ internals.main = function () {
Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
- console.log(res.readPayload());
+ console.log(res.payload);
});
};
View
@@ -10,7 +10,7 @@ var Stream = require('stream');
var internals = {};
-internals.Request = function (options) {
+internals.Request = function (options) {
var self = this;
@@ -33,216 +33,223 @@ internals.Request = function (options) {
this._shot.isPaused = false;
this._shot.simulate = options.simulate || {};
- process.nextTick(function () {
+ process.nextTick(function () {
- internals.play.call(self);
+ internals.play.call(self);
});
- return this;
+ return this;
};
Util.inherits(internals.Request, Stream);
-internals.play = function () {
+internals.play = function () {
- if (this._shot.isPaused) {
- return;
+ if (this._shot.isPaused) {
+ return;
}
- if (this._shot.isPlayed) {
- return;
+ if (this._shot.isPlayed) {
+ return;
}
this._shot.isPlayed = true;
if (this._shot.payload &&
- this._shot.listeners.data) {
+ this._shot.listeners.data) {
- for (var i = 0, il = this._shot.listeners.data.length; i < il; ++i) {
- this._shot.listeners.data[i](this._shot.payload);
- }
+ for (var i = 0, il = this._shot.listeners.data.length; i < il; ++i) {
+ this._shot.listeners.data[i](this._shot.payload);
+ }
}
- if (this._shot.simulate.error) {
+ if (this._shot.simulate.error) {
var error = new Error('Simulated');
- for (i = 0, il = this._shot.listeners.error.length; i < il; ++i) {
- this._shot.listeners.error[i](error);
- }
+ for (i = 0, il = this._shot.listeners.error.length; i < il; ++i) {
+ this._shot.listeners.error[i](error);
+ }
}
- if (this._shot.simulate.close) {
- for (i = 0, il = this._shot.listeners.close.length; i < il; ++i) {
- this._shot.listeners.close[i]();
- }
+ if (this._shot.simulate.close) {
+ for (i = 0, il = this._shot.listeners.close.length; i < il; ++i) {
+ this._shot.listeners.close[i]();
+ }
}
if (this._shot.listeners.end &&
this._shot.simulate.end !== false) { // 'end' defaults to true
- for (i = 0, il = this._shot.listeners.end.length; i < il; ++i) {
- this._shot.listeners.end[i]();
- }
- }
+ for (i = 0, il = this._shot.listeners.end.length; i < il; ++i) {
+ this._shot.listeners.end[i]();
+ }
+ }
};
-internals.Request.prototype.on = internals.Request.prototype.addListener = function (event, callback) {
+internals.Request.prototype.on = internals.Request.prototype.addListener = function (event, callback) {
this._shot.listeners[event] = this._shot.listeners[event] || [];
- this._shot.listeners[event].push(callback);
+ this._shot.listeners[event].push(callback);
};
-internals.Request.prototype.pause = function () {
+internals.Request.prototype.pause = function () {
- if (this._shot.isPaused) {
- return;
+ if (this._shot.isPaused) {
+ return;
}
- this._shot.isPaused = true;
+ this._shot.isPaused = true;
};
-internals.Request.prototype.resume = function () {
+internals.Request.prototype.resume = function () {
- if (!this._shot.isPaused) {
- return;
+ if (!this._shot.isPaused) {
+ return;
}
this._shot.isPaused = false;
- internals.play.call(this);
+ internals.play.call(this);
};
-internals.Request.prototype.setEncoding = function () {
+internals.Request.prototype.setEncoding = function () {
};
-internals.Request.prototype.destroy = function () {
+internals.Request.prototype.destroy = function () {
- this._shot.listeners = {};
+ this._shot.listeners = {};
};
-internals.Response = function (req, onEnd) {
+internals.Response = function (req, onEnd) {
Http.ServerResponse.call(this, { method: req.method, httpVersionMajor: 1, httpVersionMinor: 1 });
- this._shot = {
+ this._shot = {
req: req,
- onEnd: onEnd
+ onEnd: onEnd
};
- return this;
+ return this;
};
Util.inherits(internals.Response, Http.ServerResponse);
-internals.Response.prototype.writeHead = function () {
+internals.Response.prototype.writeHead = function () {
var headers = ((arguments.length === 2 && typeof arguments[1] === 'object') ? arguments[1] : (arguments.length === 3 ? arguments[2] : {}));
var result = Http.ServerResponse.prototype.writeHead.apply(this, arguments);
this._headers = this._headers || {};
var keys = Object.keys(headers);
- for (var i = 0, il = keys.length; i < il; ++i) {
- this._headers[keys[i]] = headers[keys[i]];
+ for (var i = 0, il = keys.length; i < il; ++i) {
+ this._headers[keys[i]] = headers[keys[i]];
}
- return result;
+ return result;
};
-internals.Response.prototype.write = function (chunk, encoding) {
+internals.Response.prototype.write = function (chunk, encoding) {
Http.ServerResponse.prototype.write.call(this, chunk, encoding);
- return true;
+ return true;
};
-internals.Response.prototype.end = function (data, encoding) {
+internals.Response.prototype.end = function (data, encoding) {
var self = this;
- if (!this._shot) {
- return;
+ if (!this._shot) {
+ return;
}
Http.ServerResponse.prototype.end.call(this, data, encoding);
this.emit('finish'); // Will not be emitted internally on an inactive socket
// Prepare response object
- var res = {
- raw: {
+ var res = {
+ raw: {
req: this._shot.req,
- res: this
+ res: this
},
headers: this._headers,
- statusCode: this.statusCode,
-
- readPayload: function () {
+ statusCode: this.statusCode
+ };
- if (!self.output ||
- !(self.output instanceof Array) ||
- !self.output.length) {
+ // Parse payload
- // Missing or invalid output
- return null;
- }
+ var output = '';
- var decode = function (value, encoding) {
- return new Buffer(value, encoding).toString();
- };
+ if (self.output &&
+ self.output instanceof Array &&
+ self.output.length) {
- if (self.output.length === 1) {
- // Single string output
- return decode(self.output[0].slice(self.output[0].indexOf('\r\n\r\n') + 4), self.outputEncodings[0]);
- }
-
- var output = '';
- for (var i = 1, il = self.output.length; i < il; ++i) { // Skip header
- if (self.output[i] instanceof Buffer) {
- // Buffer
- output += self.output[i].toString();
- }
- else {
- // String
- output += decode(self.output[i], self.outputEncodings[i]);
- }
+ for (var i = 0, il = self.output.length; i < il; ++i) {
+ if (self.output[i] instanceof Buffer) {
+ output += self.output[i].toString();
}
+ else {
+ output += new Buffer(self.output[i], self.outputEncodings[i]).toString();
+ }
+ }
+ }
- return output;
- }
- };
+ var sep = output.indexOf('\r\n\r\n');
+ var payloadBlock = output.slice(sep + 4);
+ var headerBlock = output.slice(0, sep);
+
+ if (headerBlock.indexOf('Transfer-Encoding: chunked') !== -1) {
+ var rest = payloadBlock;
+ res.payload = '';
+
+ while (rest) {
+ var next = rest.indexOf('\r\n');
+ var size = parseInt(rest.slice(0, next), 16);
+ if (size === 0) {
+ break;
+ }
+
+ res.payload += rest.substr(next + 2, size);
+ rest = rest.slice(next + 2 + size + 2);
+ }
+ }
+ else {
+ res.payload = payloadBlock;
+ }
// Callback response
var onEnd = this._shot.onEnd;
delete this._shot;
- onEnd(res);
+ onEnd(res);
};
-internals.Response.prototype.destroy = function () {
+internals.Response.prototype.destroy = function () {
};
-exports.inject = function (dispatchFunc, options, callback) {
+exports.inject = function (dispatchFunc, options, callback) {
var req = new internals.Request(options);
var res = new internals.Response(req, callback);
- dispatchFunc(req, res);
+ dispatchFunc(req, res);
};
-exports.isInjection = function (obj) {
+exports.isInjection = function (obj) {
- return (obj instanceof internals.Request || obj instanceof internals.Response);
+ return (obj instanceof internals.Request || obj instanceof internals.Response);
};
View
@@ -1,7 +1,7 @@
{
"name": "shot",
"description": "Injects a fake HTTP request/response into a node HTTP server",
- "version": "0.0.13",
+ "version": "0.1.0",
"author": "Eran Hammer <eran@hueniverse.com> (http://hueniverse.com)",
"contributors":[
],
Oops, something went wrong.

0 comments on commit 9701be1

Please sign in to comment.