From be815fb7c03a020a156a05615c9cdc557bf55455 Mon Sep 17 00:00:00 2001 From: ikhilko Date: Mon, 12 Oct 2015 11:56:55 +0300 Subject: [PATCH 1/8] fixed loosing calling context --- index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 7daea87..20707b6 100644 --- a/index.js +++ b/index.js @@ -80,7 +80,7 @@ function mock(superagent) { var oldSet = reqProto.set; reqProto.set = function(key, val) { if (!state.current) { - return oldSet(key, val); + return oldSet.call(this, key, val); } // Recursively set keys if passed an object if (isObject(key)) { @@ -94,17 +94,17 @@ function mock(superagent) { } state.request.headers[key.toLowerCase()] = val; return this; - } + }; // Patch Request.send() - var oldSend = reqProto.send + var oldSend = reqProto.send; reqProto.send = function(data) { if (!state.current) { - return oldSend(data); + return oldSend.call(this, data); } state.request.body = mergeObjects(state.current.body, data); return this; - } + }; return mock; // chaining From 1b0b2bfb6f806e8b0f2840cfb722bc0d00f6274e Mon Sep 17 00:00:00 2001 From: ikhilko Date: Tue, 13 Oct 2015 13:18:25 +0300 Subject: [PATCH 2/8] added "patch" method; added "clearRoute" method; --- index.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 20707b6..222fd0b 100644 --- a/index.js +++ b/index.js @@ -14,6 +14,7 @@ mock.get = defineRoute.bind(null, 'GET'); mock.post = defineRoute.bind(null, 'POST'); mock.put = defineRoute.bind(null, 'PUT'); mock.del = defineRoute.bind(null, 'DELETE'); +mock.patch = defineRoute.bind(null, 'PATCH'); /** * Request timeout @@ -31,7 +32,16 @@ var routes = []; */ mock.clearRoutes = function() { routes.splice(0, routes.length) -} +}; + +/** + * Unregister specific route + */ +mock.clearRoute = function(method, url) { + routes = routes.filter(function(route) { + return route.url !== url && route.method.toLowerCase() !== method; + }); +}; /** * Mock @@ -55,6 +65,7 @@ function mock(superagent) { patch(superagent, 'get', 'GET', state); patch(superagent, 'post', 'POST', state); patch(superagent, 'put', 'PUT', state); + patch(superagent, 'patch', 'PATCH', state); patch(superagent, 'del', 'DELETE', state); var reqProto = superagent.Request.prototype; From 802ce192c4c6278b048d725489991e83ac0743b7 Mon Sep 17 00:00:00 2001 From: ikhilko Date: Tue, 13 Oct 2015 15:20:35 +0300 Subject: [PATCH 3/8] added unmock method; --- index.js | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index 222fd0b..ab69d9d 100644 --- a/index.js +++ b/index.js @@ -27,6 +27,18 @@ mock.timeout = 0; */ var routes = []; +/** + * List of methods to patch + * @type {string[]} + */ +var methods = ['get', 'post', 'put', 'patch', 'del']; + +/** + * Original superagent methods + * @type {{}} + */ +var originalMethods = {}; + /** * Unregister all routes */ @@ -61,17 +73,14 @@ function mock(superagent) { } }; - // Patch superagent - patch(superagent, 'get', 'GET', state); - patch(superagent, 'post', 'POST', state); - patch(superagent, 'put', 'PUT', state); - patch(superagent, 'patch', 'PATCH', state); - patch(superagent, 'del', 'DELETE', state); + methods.forEach(function(method) { + patch(superagent, method, method.toUpperCase(), state); + }); var reqProto = superagent.Request.prototype; // Patch Request.end() - var oldEnd = superagent.Request.prototype.end; + var oldEnd = originalMethods.end = superagent.Request.prototype.end; reqProto.end = function(cb) { var current = state.current; if (current) { @@ -88,7 +97,7 @@ function mock(superagent) { }; // Patch Request.set() - var oldSet = reqProto.set; + var oldSet = originalMethods.set = reqProto.set; reqProto.set = function(key, val) { if (!state.current) { return oldSet.call(this, key, val); @@ -108,7 +117,7 @@ function mock(superagent) { }; // Patch Request.send() - var oldSend = reqProto.send; + var oldSend = originalMethods.send = reqProto.send; reqProto.send = function(data) { if (!state.current) { return oldSend.call(this, data); @@ -121,6 +130,18 @@ function mock(superagent) { } +mock.unmock = function(superagent) { + methods.forEach(function(method) { + superagent[method] = originalMethods[method]; + }); + + var reqProto = superagent.Request.prototype; + + ['end', 'set', 'send'].forEach(function(method) { + reqProto[method] = originalMethods[method]; + }); +}; + /** * find route that matched with url and method * TODO: Remove data @@ -148,7 +169,7 @@ function defineRoute(method, url, handler) { * Patch superagent method */ function patch(superagent, prop, method, state) { - var old = superagent[prop]; + var old = originalMethods[prop] = superagent[prop]; superagent[prop] = function (url, data, fn) { state.current = match(method, url, data); state.request = { From 3f2cf8c0f36552d5d19931c90b619689b363ef92 Mon Sep 17 00:00:00 2001 From: ikhilko Date: Wed, 14 Oct 2015 10:55:14 +0300 Subject: [PATCH 4/8] added test for patch method --- test.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test.js b/test.js index f47c3bc..dd06d6c 100644 --- a/test.js +++ b/test.js @@ -63,6 +63,20 @@ describe('superagent mock', function() { ; }); + it('should mock for patch', function(done) { + mock.patch('/topics/:id', function(req) { + return { id: req.params.id, content: req.body.content }; + }); + request + .patch('/topics/7', { id: 7, content: 'hello world, bitch!11' }) + .end(function(_, data) { + data.should.have.property('id', '7'); + data.should.have.property('content', 'hello world, bitch!11'); + done(); + }) + ; + }); + it('should mock for delete', function(done) { mock.del('/topics/:id', function(req) { return { id: req.params.id, content: req.body.content }; From 7f3cb9a2fee6cc344a469b4d13d21a5968d2544a Mon Sep 17 00:00:00 2001 From: ikhilko Date: Wed, 14 Oct 2015 11:25:44 +0300 Subject: [PATCH 5/8] rolled back methods auto patching --- index.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index ab69d9d..7538574 100644 --- a/index.js +++ b/index.js @@ -27,12 +27,6 @@ mock.timeout = 0; */ var routes = []; -/** - * List of methods to patch - * @type {string[]} - */ -var methods = ['get', 'post', 'put', 'patch', 'del']; - /** * Original superagent methods * @type {{}} @@ -73,9 +67,11 @@ function mock(superagent) { } }; - methods.forEach(function(method) { - patch(superagent, method, method.toUpperCase(), state); - }); + patch(superagent, 'get', 'GET', state); + patch(superagent, 'post', 'POST', state); + patch(superagent, 'put', 'PUT', state); + patch(superagent, 'patch', 'PATCH', state); + patch(superagent, 'del', 'DELETE', state); var reqProto = superagent.Request.prototype; @@ -131,7 +127,7 @@ function mock(superagent) { } mock.unmock = function(superagent) { - methods.forEach(function(method) { + ['get', 'post', 'put', 'patch', 'del'].forEach(function(method) { superagent[method] = originalMethods[method]; }); From 93475c63bdc29a454aee93b94938e75100fc3ca9 Mon Sep 17 00:00:00 2001 From: ikhilko Date: Wed, 14 Oct 2015 12:21:41 +0300 Subject: [PATCH 6/8] added test & fix for clearRoute method --- index.js | 27 ++++++++++++++++++++------- test.js | 28 ++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 7538574..4127e35 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,6 @@ */ var pathtoRegexp = require('path-to-regexp'); - /** * Expose public API */ @@ -40,12 +39,24 @@ mock.clearRoutes = function() { routes.splice(0, routes.length) }; +/** + * Map api method to http method + */ +var methodsMapping = { + get: 'GET', + post: 'POST', + put: 'PUT', + del: 'DELETE', + patch: 'PATCH' +}; + /** * Unregister specific route */ mock.clearRoute = function(method, url) { + method = methodsMapping[method] || method; routes = routes.filter(function(route) { - return route.url !== url && route.method.toLowerCase() !== method; + return !(route.url === url && route.method === method); }); }; @@ -67,11 +78,13 @@ function mock(superagent) { } }; - patch(superagent, 'get', 'GET', state); - patch(superagent, 'post', 'POST', state); - patch(superagent, 'put', 'PUT', state); - patch(superagent, 'patch', 'PATCH', state); - patch(superagent, 'del', 'DELETE', state); + // patch api methods (http) + for (var method in methodsMapping) { + if (methodsMapping.hasOwnProperty(method)) { + var httpMethod = methodsMapping[method]; + patch(superagent, method, httpMethod, state); + } + } var reqProto = superagent.Request.prototype; diff --git a/test.js b/test.js index dd06d6c..f9100f2 100644 --- a/test.js +++ b/test.js @@ -11,7 +11,6 @@ var mock = process.env.SM_COV ? require('./index-cov')(request) : require('./index')(request); - describe('superagent mock', function() { beforeEach(function() { @@ -153,6 +152,29 @@ describe('superagent mock', function() { }); }); + it('should clear registered specific route', function(done) { + mock + .get('/topics', noop) + .get('/posters', function() { + return { id: 7 }; + }); + mock.clearRoute('get', '/topics'); + request + .get('/topics') + .end(function(err, res) { + should.throws(function() { + should.ifError(err); + }, /ECONNREFUSED/); + + request + .get('/posters') + .end(function(_, data) { + data.should.have.property('id', 7); + done(); + }); + }); + }); + it('should provide error when method throws', function(done) { var error = Error('This should be in the callback!'); mock.get('http://example.com', function(req) { @@ -231,7 +253,7 @@ describe('superagent mock', function() { return req.body; }); request - .post('/topics/5', { content: 'Hello Universe'}) + .post('/topics/5', { content: 'Hello Universe' }) .send({ content: 'Hello world', title: 'Yay!' }) .end(function(_, data) { data.should.have.property('title', 'Yay!'); @@ -245,8 +267,6 @@ describe('superagent mock', function() { }); - - /** * Just noop */ From 4315188c2f78a704d48bab83b6f78e13db79d241 Mon Sep 17 00:00:00 2001 From: ikhilko Date: Wed, 14 Oct 2015 15:56:11 +0300 Subject: [PATCH 7/8] added fix and test for unmock functional --- index.js | 2 ++ test.js | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/index.js b/index.js index 4127e35..23425f6 100644 --- a/index.js +++ b/index.js @@ -149,6 +149,8 @@ mock.unmock = function(superagent) { ['end', 'set', 'send'].forEach(function(method) { reqProto[method] = originalMethods[method]; }); + + delete superagent._patchedBySuperagentMocker; }; /** diff --git a/test.js b/test.js index f9100f2..a4f52ba 100644 --- a/test.js +++ b/test.js @@ -263,6 +263,11 @@ describe('superagent mock', function() { ; }); + it('should remove patches by unmock()', function() { + mock.unmock(request); + (request._patchedBySuperagentMocker === void 0).should.be.true; + }); + }); }); From 643f998c9094636ba1992e398e8df498205d5772 Mon Sep 17 00:00:00 2001 From: ikhilko Date: Wed, 14 Oct 2015 16:08:06 +0300 Subject: [PATCH 8/8] updated docs --- readme.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index c7041a7..d065043 100644 --- a/readme.md +++ b/readme.md @@ -92,7 +92,7 @@ request ; ``` -`mock.put()` method works in a similar way. +`mock.put()`, `mock.patch()` methods works in a similar way. ### Teardown @@ -124,6 +124,24 @@ define('My API module', function(){ }) ``` +Or you can remove only one specified route (by method and url) + +```js +// to register route +mock.get('/me', function(){done()}) + +... + +// to remove registered handler +mock.clearRoute('get', '/me'); + +``` + +### Rollback library effect + +In some cases it will be useful to remove patches from superagent lib after using mocks. +In this cases you can use ```mock.unmock()``` method, that will rollback all patches that ```mock(superagent)``` call make. + ## License MIT © [Shuvalov Anton](http://shuvalov.info)