Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Node v0.10 #5

Merged
merged 9 commits into from
Commits on Apr 4, 2013
  1. @hueniverse

    initial streams2

    hueniverse authored
  2. @hueniverse

    travis node 10

    hueniverse authored
  3. @hueniverse
Commits on Apr 5, 2013
  1. @hueniverse

    misc

    hueniverse authored
  2. @hueniverse

    restore req.destroy

    hueniverse authored
  3. @hueniverse
  4. @hueniverse

    Trailer heaers support

    hueniverse authored
  5. @hueniverse

    Full coverage

    hueniverse authored
  6. @hueniverse

    update deps

    hueniverse authored
This page is out of date. Refresh to see the latest.
Showing with 151 additions and 251 deletions.
  1. +1 −1  .travis.yml
  2. +38 −75 lib/index.js
  3. +3 −3 package.json
  4. +109 −172 test/index.js
View
2  .travis.yml
@@ -1,5 +1,5 @@
language: node_js
node_js:
- - 0.8
+ - 0.10
View
113 lib/index.js
@@ -14,7 +14,7 @@ internals.Request = function (options) {
var self = this;
- Stream.call(this);
+ Stream.Readable.call(this);
// options: method, url, payload, headers
@@ -26,103 +26,53 @@ internals.Request = function (options) {
// Use _shot namespace to avoid collision with Node
- this._shot = {};
- this._shot.payload = options.payload;
- this._shot.listeners = {};
- this._shot.isPlayed = false;
- this._shot.isPaused = false;
- this._shot.simulate = options.simulate || {};
-
- process.nextTick(function () {
-
- internals.play.call(self);
- });
+ this._shot = {
+ payload: options.payload || null,
+ listeners: {},
+ isDone: false,
+ simulate: options.simulate || {}
+ };
return this;
};
-Util.inherits(internals.Request, Stream);
+Util.inherits(internals.Request, Stream.Readable);
-internals.play = function () {
+internals.Request.prototype._read = function (size) {
- if (this._shot.isPaused) {
- return;
- }
+ var self = this;
- if (this._shot.isPlayed) {
+ if (self._shot.isDone) {
+ self.push(null);
return;
}
- this._shot.isPlayed = true;
+ self._shot.isDone = true;
- if (this._shot.payload &&
- this._shot.listeners.data) {
+ setImmediate(function () {
- for (var i = 0, il = this._shot.listeners.data.length; i < il; ++i) {
- this._shot.listeners.data[i](this._shot.payload);
+ if (self._shot.payload) {
+ self.push(self._shot.payload);
}
- }
- 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);
+ if (self._shot.simulate.error) {
+ self.emit('error', new Error('Simulated'));
}
- }
- if (this._shot.simulate.close) {
- for (i = 0, il = this._shot.listeners.close.length; i < il; ++i) {
- this._shot.listeners.close[i]();
+ if (self._shot.simulate.close) {
+ self.emit('close');
}
- }
-
- 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]();
+ if (self._shot.simulate.end !== false) { // 'end' defaults to true
+ self.push(null);
}
- }
-};
-
-
-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);
-};
-
-
-internals.Request.prototype.pause = function () {
-
- if (this._shot.isPaused) {
- return;
- }
-
- this._shot.isPaused = true;
-};
-
-
-internals.Request.prototype.resume = function () {
-
- if (!this._shot.isPaused) {
- return;
- }
-
- this._shot.isPaused = false;
- internals.play.call(this);
-};
-
-
-internals.Request.prototype.setEncoding = function () {
-
+ });
};
internals.Request.prototype.destroy = function () {
- this._shot.listeners = {};
};
@@ -203,7 +153,8 @@ internals.Response.prototype.end = function (data, encoding) {
}
}
- var sep = output.indexOf('\r\n\r\n');
+ var CRLF = '\r\n';
+ var sep = output.indexOf(CRLF + CRLF);
var payloadBlock = output.slice(sep + 4);
var headerBlock = output.slice(0, sep);
@@ -212,15 +163,27 @@ internals.Response.prototype.end = function (data, encoding) {
res.payload = '';
while (rest) {
- var next = rest.indexOf('\r\n');
+ var next = rest.indexOf(CRLF);
var size = parseInt(rest.slice(0, next), 16);
if (size === 0) {
+ rest = rest.slice(3);
break;
}
res.payload += rest.substr(next + 2, size);
rest = rest.slice(next + 2 + size + 2);
}
+
+ if (rest) {
+ var headers = rest.split(CRLF);
+ headers.forEach(function (header) {
+
+ var parts = header.split(':');
+ if (parts.length === 2) {
+ self._headers[parts[0].trim().toLowerCase()] = parts[1].trim();
+ }
+ });
+ }
}
else {
res.payload = payloadBlock;
View
6 package.json
@@ -1,7 +1,7 @@
{
"name": "shot",
"description": "Injects a fake HTTP request/response into a node HTTP server",
- "version": "0.1.3",
+ "version": "0.2.0",
"author": "Eran Hammer <eran@hueniverse.com> (http://hueniverse.com)",
"contributors":[
],
@@ -14,12 +14,12 @@
"test"
],
"engines": {
- "node": "0.8.x"
+ "node": "0.10.x"
},
"dependencies": {
},
"devDependencies": {
- "lab": "0.0.x",
+ "lab": "0.1.x",
"complexity-report": "0.x.x"
},
"scripts": {
View
281 test/index.js
@@ -1,6 +1,6 @@
// Load modules
-var Lab = require('lab');
+var Lab = require('lab');
var Shot = require('../lib');
@@ -11,305 +11,242 @@ var internals = {};
// Test shortcuts
-var expect = Lab.expect;
-var before = Lab.before;
-var after = Lab.after;
-var describe = Lab.experiment;
-var it = Lab.test;
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
-describe('Shot', function () {
+describe('Shot', function () {
- describe('#inject', function () {
+ describe('#inject', function () {
- it('returns single buffer payload', function (done) {
+ it('returns single buffer payload', function (done) {
var reply = 'Hello World';
- var dispatch = function (req, res) {
+ var dispatch = function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': reply.length });
- res.end(reply);
+ res.end(reply);
};
- Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
expect(res.payload).to.equal(reply);
- done();
- });
+ done();
+ });
});
- it('returns chunked payload', function (done) {
+ it('returns chunked payload', function (done) {
- var dispatch = function (req, res) {
+ var dispatch = function (req, res) {
res.writeHead(200, 'OK');
res.write('a');
res.write('b');
- res.end();
+ res.end();
};
- Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
expect(res.payload).to.equal('ab');
- done();
- });
+ done();
+ });
});
- it('returns multi buffer payload', function (done) {
+ it('returns chunked payload with trailer', function (done) {
+
+ var dispatch = function (req, res) {
+
+ res.setHeader('Trailer', 'Server-Authorization');
+ res.setHeader('Transfer-Encoding', 'chunked');
+ res.writeHead(200, 'OK');
+ res.write('a');
+ res.write('b');
+ res.addTrailers({ 'Test': 123 });
+ res.end();
+ };
- var dispatch = function (req, res) {
+ Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
+
+ expect(res.payload).to.equal('ab');
+ expect(res.headers.test).to.equal('123');
+ done();
+ });
+ });
+
+ it('returns multi buffer payload', function (done) {
+
+ var dispatch = function (req, res) {
res.writeHead(200);
res.write('a');
res.write(new Buffer('b'));
- res.end();
+ res.end();
};
- Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
expect(res.payload).to.equal('ab');
- done();
- });
+ done();
+ });
});
- it('returns null payload', function (done) {
+ it('returns null payload', function (done) {
- var dispatch = function (req, res) {
+ var dispatch = function (req, res) {
res.writeHead(200, { 'Content-Length': 0 });
- res.end();
+ res.end();
};
- Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
expect(res.payload).to.equal('');
- done();
- });
+ done();
+ });
});
- it('allows ending twice', function (done) {
+ it('allows ending twice', function (done) {
- var dispatch = function (req, res) {
+ var dispatch = function (req, res) {
res.writeHead(200, { 'Content-Length': 0 });
res.end();
- res.end();
+ res.end();
};
- Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
expect(res.payload).to.equal('');
- done();
- });
+ done();
+ });
});
- it('identifies injection object', function (done) {
+ it('identifies injection object', function (done) {
- var dispatch = function (req, res) {
+ var dispatch = function (req, res) {
expect(Shot.isInjection(req)).to.equal(true);
expect(Shot.isInjection(res)).to.equal(true);
res.writeHead(200, { 'Content-Length': 0 });
- res.end();
+ res.end();
};
- Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
- done();
- });
- });
+ done();
+ });
+ });
});
- describe('#writeHead', function () {
+ describe('#writeHead', function () {
- it('returns single buffer payload', function (done) {
+ it('returns single buffer payload', function (done) {
var reply = 'Hello World';
- var dispatch = function (req, res) {
+ var dispatch = function (req, res) {
res.writeHead(200, 'OK', { 'Content-Type': 'text/plain', 'Content-Length': reply.length });
- res.end(reply);
+ res.end(reply);
};
- Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/' }, function (res) {
expect(res.payload).to.equal(reply);
- done();
- });
- });
- });
-
- describe('#play', function () {
-
- it('plays payload', function (done) {
-
- var dispatch = function (req, res) {
-
- var buffer = '';
- req.on('data', function (chunk) {
-
- buffer += chunk;
- });
-
- req.on('error', function (err) {
- });
-
- req.on('close', function () {
- });
-
- req.on('end', function () {
-
- res.writeHead(200, { 'Content-Length': 0 });
- res.end(buffer);
- req.destroy();
- });
- };
-
- var body = 'something special just for you';
- Shot.inject(dispatch, { method: 'get', url: '/', payload: body }, function (res) {
-
- expect(res.payload).to.equal(body);
- done();
- });
+ done();
+ });
});
+ });
- it('plays payload with pause', function (done) {
+ describe('#_read', function () {
- var dispatch = function (req, res) {
+ it('plays payload', function (done) {
- req.pause();
- req.pause();
+ var dispatch = function (req, res) {
var buffer = '';
- req.on('data', function (chunk) {
+ req.on('readable', function () {
- buffer += chunk;
+ buffer += req.read() || '';
});
- req.on('error', function (err) {
+ req.on('error', function (err) {
});
- req.on('close', function () {
+ req.on('close', function () {
});
- req.on('end', function () {
+ req.on('end', function () {
res.writeHead(200, { 'Content-Length': 0 });
res.end(buffer);
- req.destroy();
+ req.destroy();
});
-
- req.resume();
- req.resume();
};
var body = 'something special just for you';
- Shot.inject(dispatch, { method: 'get', url: '/', payload: body }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/', payload: body }, function (res) {
expect(res.payload).to.equal(body);
- done();
- });
+ done();
+ });
});
- it('plays payload with nextTick', function (done) {
-
- var dispatch = function (req, res) {
-
- req.pause();
-
- var buffer = '';
- req.on('data', function (chunk) {
-
- buffer += chunk;
- });
+ it('simulates error', function (done) {
- req.on('error', function (err) {
- });
+ var dispatch = function (req, res) {
- req.on('close', function () {
+ req.on('readable', function () {
});
- req.on('end', function () {
-
- res.writeHead(200, { 'Content-Length': 0 });
- res.end(buffer);
- req.destroy();
- });
-
- process.nextTick(function () {
-
- req.resume();
- });
- };
-
- var body = 'something special just for you';
- Shot.inject(dispatch, { method: 'get', url: '/', payload: body }, function (res) {
-
- expect(res.payload).to.equal(body);
- done();
- });
- });
-
- it('simulates error', function (done) {
-
- var dispatch = function (req, res) {
-
- var buffer = '';
- req.on('data', function (chunk) {
-
- buffer += chunk;
- });
+ req.on('error', function (err) {
- req.on('error', function (err) {
res.writeHead(200, { 'Content-Length': 0 });
- res.end('error');
+ res.end('error');
});
-
- req.on('close', function () {
- });
-
- req.on('end', function () {
- });
};
var body = 'something special just for you';
- Shot.inject(dispatch, { method: 'get', url: '/', payload: body, simulate: { error: true } }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/', payload: body, simulate: { error: true } }, function (res) {
expect(res.payload).to.equal('error');
- done();
- });
+ done();
+ });
});
- it('simulates close', function (done) {
+ it('simulates close', function (done) {
- var dispatch = function (req, res) {
+ var dispatch = function (req, res) {
var buffer = '';
- req.on('data', function (chunk) {
+ req.on('readable', function () {
- buffer += chunk;
+ buffer += req.read() || '';
});
- req.on('error', function (err) {
+ req.on('error', function (err) {
});
- req.on('close', function () {
+ req.on('close', function () {
+
res.writeHead(200, { 'Content-Length': 0 });
- res.end('close');
+ res.end('close');
});
- req.on('end', function () {
- });
+ req.on('end', function () {
+ });
};
var body = 'something special just for you';
- Shot.inject(dispatch, { method: 'get', url: '/', payload: body, simulate: { close: true } }, function (res) {
+ Shot.inject(dispatch, { method: 'get', url: '/', payload: body, simulate: { close: true } }, function (res) {
expect(res.payload).to.equal('close');
- done();
- });
- });
- });
+ done();
+ });
+ });
+ });
});
Something went wrong with that request. Please try again.