Browse files

recording HTTP interactions

  • Loading branch information...
1 parent 45b3e66 commit 70b3089853eb47e09ee538659389170044a1899d @pgte pgte committed Dec 1, 2011
Showing with 180 additions and 5 deletions.
  1. +42 −1 README.md
  2. +9 −1 index.js
  3. +96 −0 lib/recorder.js
  4. +4 −3 package.json
  5. +29 −0 tests/test_recorder.js
View
43 README.md
@@ -162,7 +162,48 @@ Nock can log matches if you pass in a log function like this:
var google = nock('http://google.com')
.log(console.log)
...
+# Restoring
+
+You can restore the HTTP interceptor to the normal unmocked behaviour by calling:
+
+ nock.restore();
+
+# Recording
+
+This is a cool feature:
+
+Guessing what the HTTP calls are is a mess, specially if you are introducing nock on your already-coded tests.
+
+For these cases where you want to mock an existing live system you can record and playback the HTTP calls like this:
+
+ nock.rec();
+ // Some HTTP calls happen and the nock code necessary to mock
+ // those calls will be outputted to console
+
+If you just want to capture the generated code into a var as an array you can use:
+
+ nock.rec(true); // :no_output = true
+ // ... some HTTP calls
+ var nockCalls = nock.play();
+
+The `nockCalls` var will contain an array of strings representing the generated code you need.
+
+Copy and paste that code into your tests, customize at will, and you're done!
# How does it work?
-Nock works by overriding Node's http.request function.
+Nock works by overriding Node's http.request function.
+
+# License
+
+(The MIT License)
+
+Copyright (c) 2011 Pedro Teixeira. http://about.me/pedroteixeira
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+FUCK YEAH.
View
10 index.js
@@ -1 +1,9 @@
-module.exports = require('./lib/scope');
+var recorder = require('./lib/recorder')
+module.exports = require('./lib/scope');
+
+module.exports.recorder = {
+ rec : recorder.record
+ , clear : recorder.clear
+ , play : recorder.outputs
+};
+module.exports.restore = recorder.restore;
View
96 lib/recorder.js
@@ -0,0 +1,96 @@
+var http = require('http');
+var oldRequest = http.request;
+var inspect = require('util').inspect;
+
+var SEPARATOR = '\n<<<<<<-- cut here -->>>>>>\n';
+
+var outputs = [];
+
+function generateRequestAndResponse(body, options, res, datas) {
+ var requestBody = body.map(function(buffer) {
+ return buffer.toString('utf8');
+ }).join('');
+
+ var responseBody = datas.map(function(buffer) {
+ return buffer.toString('utf8');
+ }).join('');
+
+ ret = [];
+ ret.push('\nnock(\'');
+ ret.push(options.host);
+ ret.push('\')\n');
+ ret.push(' .');
+ ret.push((options.method || 'GET').toLowerCase());
+ ret.push('(\'');
+ ret.push(options.path);
+ if (requestBody) {
+ ret.push(', ');
+ ret.push(JSON.stringify(requestBody));
+ }
+ ret.push(')\n');
+
+ ret.push(' .(')
+ ret.push(res.statusCode.toString());
+ ret.push(', ');
+ ret.push(JSON.stringify(responseBody));
+ if (res.headers) {
+ ret.push(', ');
+ ret.push(inspect(res.headers));
+ }
+ ret.push(');\n');
+
+ return ret.join('');
+}
+
+function record(dont_print) {
+ var body = [];
+ http.request = function(options, callback) {
+ var req, oldWrite, oldEnd;
+ req = oldRequest.call(http, options, function(res) {
+ var datas = [];
+
+ res.on('data', function(data) {
+ datas.push(data);
+ });
+
+ res.once('end', function() {
+ var out = generateRequestAndResponse(body, options, res, datas);
+ outputs.push(out);
+ if (! dont_print) { console.log(SEPARATOR + out + SEPARATOR); }
+ });
+
+ callback.apply(res, arguments);
+
+ });
+ oldWrite = req.write;
+ req.write = function(data) {
+ if ('undefined' !== typeof(data)) {
+ if (data) {body.push(data); }
+ oldWrite.call(req, data);
+ }
+ }
+ oldEnd = req.end;
+ req.end = function(data) {
+ if ('undefined' !== typeof(data)) {
+ req.write(data);
+ }
+ oldEnd.apply(req, arguments);
+ }
+ return req;
+ }
+}
+
+function restore() {
+ http.request = oldRequest;
+}
+
+function clear() {
+ outputs = [];
+}
+
+exports.record = record;
+exports.outputs = function() {
+ return outputs;
+};
+exports.restore = restore;
+exports.clear = clear;
View
7 package.json
@@ -1,11 +1,12 @@
{ "name" : "nock"
, "description" : "HTTP Server mocking for Node.js"
, "tags" : ["Mock", "HTTP", "testing", "isolation"]
-, "version" : "0.4.0"
+, "version" : "0.5.0"
, "author" : "Pedro Teixeira <pedro.teixeira@gmail.com>"
, "contributors" :
- [ "Roly Fentanes"
- , "Alexander Simmerl"
+ [ {name:"Roly Fentanes" }
+ , {name:"Alexander Simmerl"}
+ , {name:"Pedro Teixeira"}
]
, "repository" :
{ "type" : "git"
View
29 tests/test_recorder.js
@@ -0,0 +1,29 @@
+var nock = require('../.')
+ , tap = require('tap')
+ , http = require('http');
+
+tap.test('records', function(t) {
+ nock.restore();
+ var cb1 = false
+ , options = { method: 'POST'
+ , host:'expensecat.iriscouch.com'
+ , port:80
+ , path:'/' }
+ ;
+
+ nock.recorder.rec(true);
+ var req = http.request(options, function(res) {
+ cb1 = true
+ var ret;
+ res.once('end', function() {
+ nock.restore();
+ ret = nock.recorder.play();
+ t.equal(ret.length, 1);
+ t.equal(ret[0].indexOf("\nnock('expensecat.iriscouch.com')\n .post('/, \"ABCDEF\")\n .("), 0);
+ t.end();
+ });
+ });
+ req.write('ABCDEF');
+ req.end();
+ return req;
+});

0 comments on commit 70b3089

Please sign in to comment.