diff --git a/lib/scope.js b/lib/scope.js index 52662db67..bc1e15c9e 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -1,4 +1,4 @@ -/** +/** * @module nock/scope */ var path = require('path') @@ -26,9 +26,9 @@ function startScope(basePath, options) { urlParts = url.parse(basePath), port = urlParts.port || ((urlParts.protocol === 'http:') ? 80 : 443), persist = false; - + basePath = urlParts.protocol + '//' + urlParts.hostname + ':' + port; - + function add(key, interceptor, scope) { if (! interceptors.hasOwnProperty(key)) { interceptors[key] = []; @@ -36,7 +36,7 @@ function startScope(basePath, options) { interceptors[key].push(interceptor); globalIntercept(basePath, interceptor, scope); } - + function remove(key, interceptor) { if (persist) return; var arr = interceptors[key]; @@ -45,7 +45,7 @@ function startScope(basePath, options) { if (arr.length === 0) { delete interceptors[key]; } } } - + function intercept(uri, method, requestBody, interceptorOptions) { var interceptorMatchHeaders = []; var key = method.toUpperCase() + ' ' + basePath + uri; @@ -60,14 +60,6 @@ function startScope(basePath, options) { } } - if (typeof(body) !== 'string' && typeof(body) !== 'function' && !Buffer.isBuffer(body) && !isStream(body)) { - try { - body = JSON.stringify(body); - } catch(err) { - throw new Error('Error encoding response body into JSON'); - } - } - if (scope._defaultReplyHeaders) { headers || (headers = {}); headers = mixin(scope._defaultReplyHeaders, headers); @@ -84,18 +76,32 @@ function startScope(basePath, options) { } } + if (typeof(body) !== 'string' && typeof(body) !== 'function' && !Buffer.isBuffer(body) && !isStream(body)) { + try { + body = JSON.stringify(body); + if (!this.headers) { + this.headers = {}; + } + if (!this.headers['content-type']) { + this.headers['content-type'] = 'application/json'; + } + } catch(err) { + throw new Error('Error encoding response body into JSON'); + } + } + this.body = body; add(key, this, scope); return scope; } - + function replyWithFile(statusCode, filePath, headers) { var readStream = fs.createReadStream(filePath); readStream.pause(); this.filePath = filePath; return reply.call(this, statusCode, readStream, headers); } - + var matchStringOrRegexp = function(target, pattern) { if (pattern instanceof RegExp) { return target.match(pattern); @@ -111,7 +117,7 @@ function startScope(basePath, options) { , path = options.path , matches , proto = options.proto; - + if (transformPathFunction) { path = transformPathFunction(path); } if (typeof(body) !== 'string') { body = body.toString(); @@ -122,7 +128,7 @@ function startScope(basePath, options) { var checkHeaders = function(header) { return matchStringOrRegexp(options.getHeader(header.name), header.value); }; - + if (!matchHeaders.every(checkHeaders) || !interceptorMatchHeaders.every(checkHeaders)) { return false; @@ -148,7 +154,7 @@ function startScope(basePath, options) { , path = options.path , matches , proto = options.proto; - + if (transformPathFunction) { path = transformPathFunction(path); } var checkHeaders = function(header) { @@ -162,14 +168,14 @@ function startScope(basePath, options) { var matchKey = method + ' ' + proto + '://' + options.host + path; return this._key === matchKey } - + function filteringPath() { if (typeof arguments[0] === 'function') { this.transformFunction = arguments[0]; } return this; } - + function discard() { if (persist && this.filePath) { this.body = fs.createReadStream(this.filePath); @@ -183,7 +189,7 @@ function startScope(basePath, options) { interceptorMatchHeaders.push({ name: name, value: value }); return this; } - + /** * Set number of times will repeat the interceptor * @name times @@ -195,12 +201,12 @@ function startScope(basePath, options) { */ function times(newCounter) { if (newCounter < 1) return this; - + this.counter = newCounter; return this; } - + /** * An sugar sintaxe for times(1) * @name once @@ -224,7 +230,7 @@ function startScope(basePath, options) { function twice() { return this.times(2); } - + /** * An sugar sintaxe for times(3). * @name thrice @@ -253,14 +259,14 @@ function startScope(basePath, options) { , twice: twice , thrice: thrice }; - + return interceptor; } function get(uri, requestBody, options) { return intercept(uri, 'GET', requestBody, options); } - + function post(uri, requestBody, options) { return intercept(uri, 'POST', requestBody, options); } @@ -268,7 +274,7 @@ function startScope(basePath, options) { function put(uri, requestBody, options) { return intercept(uri, 'PUT', requestBody, options); } - + function head(uri, requestBody, options) { return intercept(uri, 'HEAD', requestBody, options); } @@ -276,7 +282,7 @@ function startScope(basePath, options) { function patch(uri, requestBody, options) { return intercept(uri, 'PATCH', requestBody, options); } - + function merge(uri, requestBody, options) { return intercept(uri, 'MERGE', requestBody, options); } @@ -284,13 +290,13 @@ function startScope(basePath, options) { function _delete(uri, requestBody, options) { return intercept(uri, 'DELETE', requestBody, options); } - + function pendingMocks() { return Object.keys(interceptors); } - + function isDone() { - + // if nock is turned off, it always says it's done if (! globalIntercept.isOn()) { return true; } @@ -317,14 +323,14 @@ function startScope(basePath, options) { return (doneHostCount === keys.length); } } - + function done() { assert.ok(isDone(), "Mocks not yet satisfied:\n" + pendingMocks().join("\n")); } - + function buildFilter() { var filteringArguments = arguments; - + if (arguments[0] instanceof RegExp) { return function(path) { if (path) { @@ -343,7 +349,7 @@ function startScope(basePath, options) { throw new Error('Invalid arguments: filtering path should be a function or a regular expression'); return this; } - + function filteringRequestBody() { transformRequestBodyFunction = buildFilter.apply(undefined, arguments); if (!transformRequestBodyFunction) @@ -360,7 +366,7 @@ function startScope(basePath, options) { this._defaultReplyHeaders = headers; return this; } - + function log(newLogger) { logger = newLogger; return this; @@ -374,7 +380,7 @@ function startScope(basePath, options) { function shouldPersist() { return persist; } - + scope = { get: get , post: post diff --git a/tests/test_intercept.js b/tests/test_intercept.js index 2af330918..1c54324a8 100644 --- a/tests/test_intercept.js +++ b/tests/test_intercept.js @@ -1523,6 +1523,49 @@ test("default reply headers work", function(t) { }, done).end(); }); +test("JSON encoded replies set the content-type header", function(t) { + var scope = nock('http://localhost') + .get('/') + .reply(200, { + A: 'b' + }); + + function done(res) { + scope.done(); + t.equal(res.statusCode, 200); + t.equal(res.headers['content-type'], 'application/json'); + t.end(); + } + + http.request({ + host: 'localhost' + , path: '/' + }, done).end(); +}); + + +test("JSON encoded replies does not overwrite existing content-type header", function(t) { + var scope = nock('http://localhost') + .get('/') + .reply(200, { + A: 'b' + }, { + 'Content-Type': 'unicorns' + }); + + function done(res) { + scope.done(); + t.equal(res.statusCode, 200); + t.equal(res.headers['content-type'], 'unicorns'); + t.end(); + } + + http.request({ + host: 'localhost' + , path: '/' + }, done).end(); +}); + test('clean all works', function(t) { var scope = nock('http://amazon.com') .get('/nonexistent')