fetch-mock
Advanced tools
Comparing version 5.5.0 to 5.6.0
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.fetchMock = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
'use strict'; | ||
var fetchMock = require('./fetch-mock'); | ||
var FetchMock = require('./fetch-mock'); | ||
var statusTextMap = require('./status-text'); | ||
var theGlobal = typeof window !== 'undefined' ? window : self; | ||
module.exports = fetchMock({ | ||
FetchMock.setGlobals({ | ||
global: theGlobal, | ||
@@ -15,2 +15,4 @@ Request: theGlobal.Request, | ||
}); | ||
module.exports = new FetchMock(); | ||
},{"./fetch-mock":3,"./status-text":4}],2:[function(require,module,exports){ | ||
@@ -157,311 +159,309 @@ 'use strict'; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var compileRoute = require('./compile-route'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var FetchMock = function FetchMock() { | ||
var compileRoute = require('./compile-route'); | ||
this.config = { | ||
sendAsJson: true | ||
}; | ||
var FetchMock = function () { | ||
function FetchMock(opts) { | ||
_classCallCheck(this, FetchMock); | ||
// if (opts) { | ||
// FetchMock.Headers = opts.Headers; | ||
// FetchMock.Request = opts.Request; | ||
// FetchMock.Response = opts.Response; | ||
// FetchMock.stream = opts.stream; | ||
// FetchMock.global = opts.global; | ||
// FetchMock.statusTextMap = opts.statusTextMap; | ||
// } | ||
this.config = { | ||
sendAsJson: true | ||
this.routes = []; | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.bindMethods(); | ||
}; | ||
FetchMock.prototype.bindMethods = function () { | ||
this.fetchMock = FetchMock.prototype.fetchMock.bind(this); | ||
this.restore = FetchMock.prototype.restore.bind(this); | ||
this.reset = FetchMock.prototype.reset.bind(this); | ||
}; | ||
FetchMock.prototype.mock = function (matcher, response, options) { | ||
var route = void 0; | ||
// Handle the variety of parameters accepted by mock (see README) | ||
// Old method matching signature | ||
if (options && /^[A-Z]+$/.test(response)) { | ||
throw new Error('The API for method matching has changed.\n\t\t\tNow use .get(), .post(), .put(), .delete() and .head() shorthand methods,\n\t\t\tor pass in, e.g. {method: \'PATCH\'} as a third paramter'); | ||
} else if (options) { | ||
route = _extends({ | ||
matcher: matcher, | ||
response: response | ||
}, options); | ||
} else if (matcher && response) { | ||
route = { | ||
matcher: matcher, | ||
response: response | ||
}; | ||
this.Headers = opts.Headers; | ||
this.Request = opts.Request; | ||
this.Response = opts.Response; | ||
this.stream = opts.stream; | ||
this.global = opts.global; | ||
this.statusTextMap = opts.statusTextMap; | ||
this.routes = []; | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.fetchMock = this.fetchMock.bind(this); | ||
this.restore = this.restore.bind(this); | ||
this.reset = this.reset.bind(this); | ||
} else if (matcher && matcher.matcher) { | ||
route = matcher; | ||
} else { | ||
throw new Error('Invalid parameters passed to fetch-mock'); | ||
} | ||
_createClass(FetchMock, [{ | ||
key: 'mock', | ||
value: function mock(matcher, response, options) { | ||
this.addRoute(route); | ||
var route = void 0; | ||
return this._mock(); | ||
}; | ||
// Handle the variety of parameters accepted by mock (see README) | ||
FetchMock.prototype.once = function (matcher, response, options) { | ||
return this.mock(matcher, response, _extends({}, options, { times: 1 })); | ||
}; | ||
// Old method matching signature | ||
if (options && /^[A-Z]+$/.test(response)) { | ||
throw new Error('The API for method matching has changed.\n\t\t\t\tNow use .get(), .post(), .put(), .delete() and .head() shorthand methods,\n\t\t\t\tor pass in, e.g. {method: \'PATCH\'} as a third paramter'); | ||
} else if (options) { | ||
route = _extends({ | ||
matcher: matcher, | ||
response: response | ||
}, options); | ||
} else if (matcher && response) { | ||
route = { | ||
matcher: matcher, | ||
response: response | ||
}; | ||
} else if (matcher && matcher.matcher) { | ||
route = matcher; | ||
} else { | ||
throw new Error('Invalid parameters passed to fetch-mock'); | ||
} | ||
FetchMock.prototype._mock = function () { | ||
if (!this.isSandbox) { | ||
// Do this here rather than in the constructor to ensure it's scoped to the test | ||
this.realFetch = this.realFetch || FetchMock.global.fetch; | ||
FetchMock.global.fetch = this.fetchMock; | ||
} | ||
return this; | ||
}; | ||
this.addRoute(route); | ||
FetchMock.prototype._unMock = function () { | ||
if (this.realFetch) { | ||
FetchMock.global.fetch = this.realFetch; | ||
this.realFetch = null; | ||
} | ||
this.fallbackResponse = null; | ||
return this; | ||
}; | ||
return this._mock(); | ||
} | ||
}, { | ||
key: 'once', | ||
value: function once(matcher, response, options) { | ||
return this.mock(matcher, response, _extends({}, options, { times: 1 })); | ||
} | ||
}, { | ||
key: '_mock', | ||
value: function _mock() { | ||
// Do this here rather than in the constructor to ensure it's scoped to the test | ||
this.realFetch = this.realFetch || this.global.fetch; | ||
this.global.fetch = this.fetchMock; | ||
return this; | ||
} | ||
}, { | ||
key: '_unMock', | ||
value: function _unMock() { | ||
if (this.realFetch) { | ||
this.global.fetch = this.realFetch; | ||
this.realFetch = null; | ||
} | ||
this.fallbackResponse = null; | ||
return this; | ||
} | ||
}, { | ||
key: 'catch', | ||
value: function _catch(response) { | ||
if (this.fallbackResponse) { | ||
console.warn('calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response'); | ||
} | ||
this.fallbackResponse = response || 'ok'; | ||
return this._mock(); | ||
} | ||
}, { | ||
key: 'spy', | ||
value: function spy() { | ||
this._mock(); | ||
return this.catch(this.realFetch); | ||
} | ||
}, { | ||
key: 'fetchMock', | ||
value: function fetchMock(url, opts) { | ||
var _this = this; | ||
FetchMock.prototype.catch = function (response) { | ||
if (this.fallbackResponse) { | ||
console.warn('calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response'); | ||
} | ||
this.fallbackResponse = response || 'ok'; | ||
return this._mock(); | ||
}; | ||
var response = this.router(url, opts); | ||
FetchMock.prototype.spy = function () { | ||
this._mock(); | ||
return this.catch(this.realFetch); | ||
}; | ||
if (!response) { | ||
console.warn('unmatched call to ' + url); | ||
this.push(null, [url, opts]); | ||
FetchMock.prototype.fetchMock = function (url, opts) { | ||
var _this = this; | ||
if (this.fallbackResponse) { | ||
response = this.fallbackResponse; | ||
} else { | ||
throw new Error('unmatched call to ' + url); | ||
} | ||
} | ||
var response = this.router(url, opts); | ||
if (typeof response === 'function') { | ||
response = response(url, opts); | ||
} | ||
if (!response) { | ||
console.warn('unmatched call to ' + url); | ||
this.push(null, [url, opts]); | ||
if (typeof response.then === 'function') { | ||
return response.then(function (response) { | ||
return _this.mockResponse(url, response, opts); | ||
}); | ||
} else { | ||
return this.mockResponse(url, response, opts); | ||
} | ||
if (this.fallbackResponse) { | ||
response = this.fallbackResponse; | ||
} else { | ||
throw new Error('unmatched call to ' + url); | ||
} | ||
}, { | ||
key: 'router', | ||
value: function router(url, opts) { | ||
var route = void 0; | ||
for (var i = 0, il = this.routes.length; i < il; i++) { | ||
route = this.routes[i]; | ||
if (route.matcher(url, opts)) { | ||
this.push(route.name, [url, opts]); | ||
return route.response; | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'addRoute', | ||
value: function addRoute(route) { | ||
} | ||
if (!route) { | ||
throw new Error('.mock() must be passed configuration for a route'); | ||
} | ||
if (typeof response === 'function') { | ||
response = response(url, opts); | ||
} | ||
// Allows selective application of some of the preregistered routes | ||
this.routes.push(compileRoute(route, this.Request)); | ||
if (typeof response.then === 'function') { | ||
return response.then(function (response) { | ||
return _this.mockResponse(url, response, opts); | ||
}); | ||
} else { | ||
return this.mockResponse(url, response, opts); | ||
} | ||
}; | ||
FetchMock.prototype.router = function (url, opts) { | ||
var route = void 0; | ||
for (var i = 0, il = this.routes.length; i < il; i++) { | ||
route = this.routes[i]; | ||
if (route.matcher(url, opts)) { | ||
this.push(route.name, [url, opts]); | ||
return route.response; | ||
} | ||
}, { | ||
key: 'mockResponse', | ||
value: function mockResponse(url, responseConfig, fetchOpts) { | ||
// It seems odd to call this in here even though it's already called within fetchMock | ||
// It's to handle the fact that because we want to support making it very easy to add a | ||
// delay to any sort of response (including responses which are defined with a function) | ||
// while also allowing function responses to return a Promise for a response config. | ||
if (typeof responseConfig === 'function') { | ||
responseConfig = responseConfig(url, fetchOpts); | ||
} | ||
} | ||
}; | ||
if (this.Response.prototype.isPrototypeOf(responseConfig)) { | ||
return Promise.resolve(responseConfig); | ||
} | ||
FetchMock.prototype.addRoute = function (route) { | ||
if (responseConfig.throws) { | ||
return Promise.reject(responseConfig.throws); | ||
} | ||
if (!route) { | ||
throw new Error('.mock() must be passed configuration for a route'); | ||
} | ||
if (typeof responseConfig === 'number') { | ||
responseConfig = { | ||
status: responseConfig | ||
}; | ||
} else if (typeof responseConfig === 'string' || !(responseConfig.body || responseConfig.headers || responseConfig.throws || responseConfig.status)) { | ||
responseConfig = { | ||
body: responseConfig | ||
}; | ||
} | ||
// Allows selective application of some of the preregistered routes | ||
this.routes.push(compileRoute(route, FetchMock.Request)); | ||
}; | ||
var opts = responseConfig.opts || {}; | ||
opts.url = url; | ||
opts.sendAsJson = responseConfig.sendAsJson === undefined ? this.config.sendAsJson : responseConfig.sendAsJson; | ||
if (responseConfig.status && (typeof responseConfig.status !== 'number' || parseInt(responseConfig.status, 10) !== responseConfig.status || responseConfig.status < 200 || responseConfig.status > 599)) { | ||
throw new TypeError('Invalid status ' + responseConfig.status + ' passed on response object.\nTo respond with a JSON object that has status as a property assign the object to body\ne.g. {"body": {"status: "registered"}}'); | ||
} | ||
opts.status = responseConfig.status || 200; | ||
opts.statusText = this.statusTextMap['' + opts.status]; | ||
// The ternary operator is to cope with new Headers(undefined) throwing in Chrome | ||
// https://code.google.com/p/chromium/issues/detail?id=335871 | ||
opts.headers = responseConfig.headers ? new this.Headers(responseConfig.headers) : new this.Headers(); | ||
FetchMock.prototype.mockResponse = function (url, responseConfig, fetchOpts) { | ||
// It seems odd to call this in here even though it's already called within fetchMock | ||
// It's to handle the fact that because we want to support making it very easy to add a | ||
// delay to any sort of response (including responses which are defined with a function) | ||
// while also allowing function responses to return a Promise for a response config. | ||
if (typeof responseConfig === 'function') { | ||
responseConfig = responseConfig(url, fetchOpts); | ||
} | ||
var body = responseConfig.body; | ||
if (opts.sendAsJson && responseConfig.body != null && (typeof body === 'undefined' ? 'undefined' : _typeof(body)) === 'object') { | ||
//eslint-disable-line | ||
body = JSON.stringify(body); | ||
} | ||
if (FetchMock.Response.prototype.isPrototypeOf(responseConfig)) { | ||
return Promise.resolve(responseConfig); | ||
} | ||
if (this.stream) { | ||
var s = new this.stream.Readable(); | ||
if (body != null) { | ||
//eslint-disable-line | ||
s.push(body, 'utf-8'); | ||
} | ||
s.push(null); | ||
body = s; | ||
} | ||
if (responseConfig.throws) { | ||
return Promise.reject(responseConfig.throws); | ||
} | ||
return Promise.resolve(new this.Response(body, opts)); | ||
if (typeof responseConfig === 'number') { | ||
responseConfig = { | ||
status: responseConfig | ||
}; | ||
} else if (typeof responseConfig === 'string' || !(responseConfig.body || responseConfig.headers || responseConfig.throws || responseConfig.status)) { | ||
responseConfig = { | ||
body: responseConfig | ||
}; | ||
} | ||
var opts = responseConfig.opts || {}; | ||
opts.url = url; | ||
opts.sendAsJson = responseConfig.sendAsJson === undefined ? this.config.sendAsJson : responseConfig.sendAsJson; | ||
if (responseConfig.status && (typeof responseConfig.status !== 'number' || parseInt(responseConfig.status, 10) !== responseConfig.status || responseConfig.status < 200 || responseConfig.status > 599)) { | ||
throw new TypeError('Invalid status ' + responseConfig.status + ' passed on response object.\nTo respond with a JSON object that has status as a property assign the object to body\ne.g. {"body": {"status: "registered"}}'); | ||
} | ||
opts.status = responseConfig.status || 200; | ||
opts.statusText = FetchMock.statusTextMap['' + opts.status]; | ||
// The ternary operator is to cope with new Headers(undefined) throwing in Chrome | ||
// https://code.google.com/p/chromium/issues/detail?id=335871 | ||
opts.headers = responseConfig.headers ? new FetchMock.Headers(responseConfig.headers) : new FetchMock.Headers(); | ||
var body = responseConfig.body; | ||
if (opts.sendAsJson && responseConfig.body != null && (typeof body === 'undefined' ? 'undefined' : _typeof(body)) === 'object') { | ||
//eslint-disable-line | ||
body = JSON.stringify(body); | ||
} | ||
if (FetchMock.stream) { | ||
var s = new FetchMock.stream.Readable(); | ||
if (body != null) { | ||
//eslint-disable-line | ||
s.push(body, 'utf-8'); | ||
} | ||
}, { | ||
key: 'push', | ||
value: function push(name, call) { | ||
if (name) { | ||
this._calls[name] = this._calls[name] || []; | ||
this._calls[name].push(call); | ||
this._matchedCalls.push(call); | ||
} else { | ||
this._unmatchedCalls.push(call); | ||
} | ||
} | ||
}, { | ||
key: 'restore', | ||
value: function restore() { | ||
this._unMock(); | ||
this.reset(); | ||
this.routes = []; | ||
return this; | ||
} | ||
}, { | ||
key: 'reset', | ||
value: function reset() { | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.routes.forEach(function (route) { | ||
return route.reset && route.reset(); | ||
}); | ||
return this; | ||
} | ||
}, { | ||
key: 'calls', | ||
value: function calls(name) { | ||
return name ? this._calls[name] || [] : { | ||
matched: this._matchedCalls, | ||
unmatched: this._unmatchedCalls | ||
}; | ||
} | ||
}, { | ||
key: 'lastCall', | ||
value: function lastCall(name) { | ||
var calls = name ? this.calls(name) : this.calls().matched; | ||
if (calls && calls.length) { | ||
return calls[calls.length - 1]; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
}, { | ||
key: 'lastUrl', | ||
value: function lastUrl(name) { | ||
var call = this.lastCall(name); | ||
return call && call[0]; | ||
} | ||
}, { | ||
key: 'lastOptions', | ||
value: function lastOptions(name) { | ||
var call = this.lastCall(name); | ||
return call && call[1]; | ||
} | ||
}, { | ||
key: 'called', | ||
value: function called(name) { | ||
if (!name) { | ||
return !!(this._matchedCalls.length || this._unmatchedCalls.length); | ||
} | ||
return !!(this._calls[name] && this._calls[name].length); | ||
} | ||
}, { | ||
key: 'done', | ||
value: function done(name) { | ||
var _this2 = this; | ||
s.push(null); | ||
body = s; | ||
} | ||
var names = name ? [name] : this.routes.map(function (r) { | ||
return r.name; | ||
}); | ||
// Ideally would use array.every, but not widely supported | ||
return names.map(function (name) { | ||
if (!_this2.called(name)) { | ||
return false; | ||
} | ||
// would use array.find... but again not so widely supported | ||
var expectedTimes = (_this2.routes.filter(function (r) { | ||
return r.name === name; | ||
}) || [{}])[0].times; | ||
return !expectedTimes || expectedTimes <= _this2.calls(name).length; | ||
}).filter(function (bool) { | ||
return !bool; | ||
}).length === 0; | ||
return Promise.resolve(new FetchMock.Response(body, opts)); | ||
}; | ||
FetchMock.prototype.push = function (name, call) { | ||
if (name) { | ||
this._calls[name] = this._calls[name] || []; | ||
this._calls[name].push(call); | ||
this._matchedCalls.push(call); | ||
} else { | ||
this._unmatchedCalls.push(call); | ||
} | ||
}; | ||
FetchMock.prototype.restore = function () { | ||
this._unMock(); | ||
this.reset(); | ||
this.routes = []; | ||
return this; | ||
}; | ||
FetchMock.prototype.reset = function () { | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.routes.forEach(function (route) { | ||
return route.reset && route.reset(); | ||
}); | ||
return this; | ||
}; | ||
FetchMock.prototype.calls = function (name) { | ||
return name ? this._calls[name] || [] : { | ||
matched: this._matchedCalls, | ||
unmatched: this._unmatchedCalls | ||
}; | ||
}; | ||
FetchMock.prototype.lastCall = function (name) { | ||
var calls = name ? this.calls(name) : this.calls().matched; | ||
if (calls && calls.length) { | ||
return calls[calls.length - 1]; | ||
} else { | ||
return undefined; | ||
} | ||
}; | ||
FetchMock.prototype.lastUrl = function (name) { | ||
var call = this.lastCall(name); | ||
return call && call[0]; | ||
}; | ||
FetchMock.prototype.lastOptions = function (name) { | ||
var call = this.lastCall(name); | ||
return call && call[1]; | ||
}; | ||
FetchMock.prototype.called = function (name) { | ||
if (!name) { | ||
return !!(this._matchedCalls.length || this._unmatchedCalls.length); | ||
} | ||
return !!(this._calls[name] && this._calls[name].length); | ||
}; | ||
FetchMock.prototype.done = function (name) { | ||
var _this2 = this; | ||
var names = name ? [name] : this.routes.map(function (r) { | ||
return r.name; | ||
}); | ||
// Ideally would use array.every, but not widely supported | ||
return names.map(function (name) { | ||
if (!_this2.called(name)) { | ||
return false; | ||
} | ||
}, { | ||
key: 'configure', | ||
value: function configure(opts) { | ||
_extends(this.config, opts); | ||
} | ||
}]); | ||
// would use array.find... but again not so widely supported | ||
var expectedTimes = (_this2.routes.filter(function (r) { | ||
return r.name === name; | ||
}) || [{}])[0].times; | ||
return !expectedTimes || expectedTimes <= _this2.calls(name).length; | ||
}).filter(function (bool) { | ||
return !bool; | ||
}).length === 0; | ||
}; | ||
return FetchMock; | ||
}(); | ||
FetchMock.prototype.configure = function (opts) { | ||
_extends(this.config, opts); | ||
}; | ||
FetchMock.prototype.sandbox = function () { | ||
if (this.routes.length || this.fallbackResponse) { | ||
throw new Error('.sandbox() can only be called on fetch-mock instances that don\'t have routes configured already'); | ||
} | ||
var instance = new FetchMock(); | ||
_extends(instance.fetchMock, // the function | ||
FetchMock.prototype, // all prototype methods | ||
instance // instance data | ||
); | ||
instance.fetchMock.bindMethods(); | ||
instance.fetchMock.isSandbox = true; | ||
this.restore(); | ||
return instance.fetchMock; | ||
}; | ||
FetchMock.setGlobals = function (globals) { | ||
_extends(FetchMock, globals); | ||
}; | ||
['get', 'post', 'put', 'delete', 'head', 'patch'].forEach(function (method) { | ||
@@ -476,5 +476,3 @@ FetchMock.prototype[method] = function (matcher, response, options) { | ||
module.exports = function (opts) { | ||
return new FetchMock(opts); | ||
}; | ||
module.exports = FetchMock; | ||
},{"./compile-route":2}],4:[function(require,module,exports){ | ||
@@ -481,0 +479,0 @@ 'use strict'; |
'use strict'; | ||
var fetchMock = require('./fetch-mock'); | ||
var FetchMock = require('./fetch-mock'); | ||
var statusTextMap = require('./status-text'); | ||
var theGlobal = typeof window !== 'undefined' ? window : self; | ||
module.exports = fetchMock({ | ||
FetchMock.setGlobals({ | ||
global: theGlobal, | ||
@@ -13,2 +13,4 @@ Request: theGlobal.Request, | ||
statusTextMap: statusTextMap | ||
}); | ||
}); | ||
module.exports = new FetchMock(); |
@@ -7,311 +7,309 @@ 'use strict'; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var compileRoute = require('./compile-route'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var FetchMock = function FetchMock() { | ||
var compileRoute = require('./compile-route'); | ||
this.config = { | ||
sendAsJson: true | ||
}; | ||
var FetchMock = function () { | ||
function FetchMock(opts) { | ||
_classCallCheck(this, FetchMock); | ||
// if (opts) { | ||
// FetchMock.Headers = opts.Headers; | ||
// FetchMock.Request = opts.Request; | ||
// FetchMock.Response = opts.Response; | ||
// FetchMock.stream = opts.stream; | ||
// FetchMock.global = opts.global; | ||
// FetchMock.statusTextMap = opts.statusTextMap; | ||
// } | ||
this.config = { | ||
sendAsJson: true | ||
this.routes = []; | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.bindMethods(); | ||
}; | ||
FetchMock.prototype.bindMethods = function () { | ||
this.fetchMock = FetchMock.prototype.fetchMock.bind(this); | ||
this.restore = FetchMock.prototype.restore.bind(this); | ||
this.reset = FetchMock.prototype.reset.bind(this); | ||
}; | ||
FetchMock.prototype.mock = function (matcher, response, options) { | ||
var route = void 0; | ||
// Handle the variety of parameters accepted by mock (see README) | ||
// Old method matching signature | ||
if (options && /^[A-Z]+$/.test(response)) { | ||
throw new Error('The API for method matching has changed.\n\t\t\tNow use .get(), .post(), .put(), .delete() and .head() shorthand methods,\n\t\t\tor pass in, e.g. {method: \'PATCH\'} as a third paramter'); | ||
} else if (options) { | ||
route = _extends({ | ||
matcher: matcher, | ||
response: response | ||
}, options); | ||
} else if (matcher && response) { | ||
route = { | ||
matcher: matcher, | ||
response: response | ||
}; | ||
this.Headers = opts.Headers; | ||
this.Request = opts.Request; | ||
this.Response = opts.Response; | ||
this.stream = opts.stream; | ||
this.global = opts.global; | ||
this.statusTextMap = opts.statusTextMap; | ||
this.routes = []; | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.fetchMock = this.fetchMock.bind(this); | ||
this.restore = this.restore.bind(this); | ||
this.reset = this.reset.bind(this); | ||
} else if (matcher && matcher.matcher) { | ||
route = matcher; | ||
} else { | ||
throw new Error('Invalid parameters passed to fetch-mock'); | ||
} | ||
_createClass(FetchMock, [{ | ||
key: 'mock', | ||
value: function mock(matcher, response, options) { | ||
this.addRoute(route); | ||
var route = void 0; | ||
return this._mock(); | ||
}; | ||
// Handle the variety of parameters accepted by mock (see README) | ||
FetchMock.prototype.once = function (matcher, response, options) { | ||
return this.mock(matcher, response, _extends({}, options, { times: 1 })); | ||
}; | ||
// Old method matching signature | ||
if (options && /^[A-Z]+$/.test(response)) { | ||
throw new Error('The API for method matching has changed.\n\t\t\t\tNow use .get(), .post(), .put(), .delete() and .head() shorthand methods,\n\t\t\t\tor pass in, e.g. {method: \'PATCH\'} as a third paramter'); | ||
} else if (options) { | ||
route = _extends({ | ||
matcher: matcher, | ||
response: response | ||
}, options); | ||
} else if (matcher && response) { | ||
route = { | ||
matcher: matcher, | ||
response: response | ||
}; | ||
} else if (matcher && matcher.matcher) { | ||
route = matcher; | ||
} else { | ||
throw new Error('Invalid parameters passed to fetch-mock'); | ||
} | ||
FetchMock.prototype._mock = function () { | ||
if (!this.isSandbox) { | ||
// Do this here rather than in the constructor to ensure it's scoped to the test | ||
this.realFetch = this.realFetch || FetchMock.global.fetch; | ||
FetchMock.global.fetch = this.fetchMock; | ||
} | ||
return this; | ||
}; | ||
this.addRoute(route); | ||
FetchMock.prototype._unMock = function () { | ||
if (this.realFetch) { | ||
FetchMock.global.fetch = this.realFetch; | ||
this.realFetch = null; | ||
} | ||
this.fallbackResponse = null; | ||
return this; | ||
}; | ||
return this._mock(); | ||
} | ||
}, { | ||
key: 'once', | ||
value: function once(matcher, response, options) { | ||
return this.mock(matcher, response, _extends({}, options, { times: 1 })); | ||
} | ||
}, { | ||
key: '_mock', | ||
value: function _mock() { | ||
// Do this here rather than in the constructor to ensure it's scoped to the test | ||
this.realFetch = this.realFetch || this.global.fetch; | ||
this.global.fetch = this.fetchMock; | ||
return this; | ||
} | ||
}, { | ||
key: '_unMock', | ||
value: function _unMock() { | ||
if (this.realFetch) { | ||
this.global.fetch = this.realFetch; | ||
this.realFetch = null; | ||
} | ||
this.fallbackResponse = null; | ||
return this; | ||
} | ||
}, { | ||
key: 'catch', | ||
value: function _catch(response) { | ||
if (this.fallbackResponse) { | ||
console.warn('calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response'); | ||
} | ||
this.fallbackResponse = response || 'ok'; | ||
return this._mock(); | ||
} | ||
}, { | ||
key: 'spy', | ||
value: function spy() { | ||
this._mock(); | ||
return this.catch(this.realFetch); | ||
} | ||
}, { | ||
key: 'fetchMock', | ||
value: function fetchMock(url, opts) { | ||
var _this = this; | ||
FetchMock.prototype.catch = function (response) { | ||
if (this.fallbackResponse) { | ||
console.warn('calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response'); | ||
} | ||
this.fallbackResponse = response || 'ok'; | ||
return this._mock(); | ||
}; | ||
var response = this.router(url, opts); | ||
FetchMock.prototype.spy = function () { | ||
this._mock(); | ||
return this.catch(this.realFetch); | ||
}; | ||
if (!response) { | ||
console.warn('unmatched call to ' + url); | ||
this.push(null, [url, opts]); | ||
FetchMock.prototype.fetchMock = function (url, opts) { | ||
var _this = this; | ||
if (this.fallbackResponse) { | ||
response = this.fallbackResponse; | ||
} else { | ||
throw new Error('unmatched call to ' + url); | ||
} | ||
} | ||
var response = this.router(url, opts); | ||
if (typeof response === 'function') { | ||
response = response(url, opts); | ||
} | ||
if (!response) { | ||
console.warn('unmatched call to ' + url); | ||
this.push(null, [url, opts]); | ||
if (typeof response.then === 'function') { | ||
return response.then(function (response) { | ||
return _this.mockResponse(url, response, opts); | ||
}); | ||
} else { | ||
return this.mockResponse(url, response, opts); | ||
} | ||
if (this.fallbackResponse) { | ||
response = this.fallbackResponse; | ||
} else { | ||
throw new Error('unmatched call to ' + url); | ||
} | ||
}, { | ||
key: 'router', | ||
value: function router(url, opts) { | ||
var route = void 0; | ||
for (var i = 0, il = this.routes.length; i < il; i++) { | ||
route = this.routes[i]; | ||
if (route.matcher(url, opts)) { | ||
this.push(route.name, [url, opts]); | ||
return route.response; | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'addRoute', | ||
value: function addRoute(route) { | ||
} | ||
if (!route) { | ||
throw new Error('.mock() must be passed configuration for a route'); | ||
} | ||
if (typeof response === 'function') { | ||
response = response(url, opts); | ||
} | ||
// Allows selective application of some of the preregistered routes | ||
this.routes.push(compileRoute(route, this.Request)); | ||
if (typeof response.then === 'function') { | ||
return response.then(function (response) { | ||
return _this.mockResponse(url, response, opts); | ||
}); | ||
} else { | ||
return this.mockResponse(url, response, opts); | ||
} | ||
}; | ||
FetchMock.prototype.router = function (url, opts) { | ||
var route = void 0; | ||
for (var i = 0, il = this.routes.length; i < il; i++) { | ||
route = this.routes[i]; | ||
if (route.matcher(url, opts)) { | ||
this.push(route.name, [url, opts]); | ||
return route.response; | ||
} | ||
}, { | ||
key: 'mockResponse', | ||
value: function mockResponse(url, responseConfig, fetchOpts) { | ||
// It seems odd to call this in here even though it's already called within fetchMock | ||
// It's to handle the fact that because we want to support making it very easy to add a | ||
// delay to any sort of response (including responses which are defined with a function) | ||
// while also allowing function responses to return a Promise for a response config. | ||
if (typeof responseConfig === 'function') { | ||
responseConfig = responseConfig(url, fetchOpts); | ||
} | ||
} | ||
}; | ||
if (this.Response.prototype.isPrototypeOf(responseConfig)) { | ||
return Promise.resolve(responseConfig); | ||
} | ||
FetchMock.prototype.addRoute = function (route) { | ||
if (responseConfig.throws) { | ||
return Promise.reject(responseConfig.throws); | ||
} | ||
if (!route) { | ||
throw new Error('.mock() must be passed configuration for a route'); | ||
} | ||
if (typeof responseConfig === 'number') { | ||
responseConfig = { | ||
status: responseConfig | ||
}; | ||
} else if (typeof responseConfig === 'string' || !(responseConfig.body || responseConfig.headers || responseConfig.throws || responseConfig.status)) { | ||
responseConfig = { | ||
body: responseConfig | ||
}; | ||
} | ||
// Allows selective application of some of the preregistered routes | ||
this.routes.push(compileRoute(route, FetchMock.Request)); | ||
}; | ||
var opts = responseConfig.opts || {}; | ||
opts.url = url; | ||
opts.sendAsJson = responseConfig.sendAsJson === undefined ? this.config.sendAsJson : responseConfig.sendAsJson; | ||
if (responseConfig.status && (typeof responseConfig.status !== 'number' || parseInt(responseConfig.status, 10) !== responseConfig.status || responseConfig.status < 200 || responseConfig.status > 599)) { | ||
throw new TypeError('Invalid status ' + responseConfig.status + ' passed on response object.\nTo respond with a JSON object that has status as a property assign the object to body\ne.g. {"body": {"status: "registered"}}'); | ||
} | ||
opts.status = responseConfig.status || 200; | ||
opts.statusText = this.statusTextMap['' + opts.status]; | ||
// The ternary operator is to cope with new Headers(undefined) throwing in Chrome | ||
// https://code.google.com/p/chromium/issues/detail?id=335871 | ||
opts.headers = responseConfig.headers ? new this.Headers(responseConfig.headers) : new this.Headers(); | ||
FetchMock.prototype.mockResponse = function (url, responseConfig, fetchOpts) { | ||
// It seems odd to call this in here even though it's already called within fetchMock | ||
// It's to handle the fact that because we want to support making it very easy to add a | ||
// delay to any sort of response (including responses which are defined with a function) | ||
// while also allowing function responses to return a Promise for a response config. | ||
if (typeof responseConfig === 'function') { | ||
responseConfig = responseConfig(url, fetchOpts); | ||
} | ||
var body = responseConfig.body; | ||
if (opts.sendAsJson && responseConfig.body != null && (typeof body === 'undefined' ? 'undefined' : _typeof(body)) === 'object') { | ||
//eslint-disable-line | ||
body = JSON.stringify(body); | ||
} | ||
if (FetchMock.Response.prototype.isPrototypeOf(responseConfig)) { | ||
return Promise.resolve(responseConfig); | ||
} | ||
if (this.stream) { | ||
var s = new this.stream.Readable(); | ||
if (body != null) { | ||
//eslint-disable-line | ||
s.push(body, 'utf-8'); | ||
} | ||
s.push(null); | ||
body = s; | ||
} | ||
if (responseConfig.throws) { | ||
return Promise.reject(responseConfig.throws); | ||
} | ||
return Promise.resolve(new this.Response(body, opts)); | ||
if (typeof responseConfig === 'number') { | ||
responseConfig = { | ||
status: responseConfig | ||
}; | ||
} else if (typeof responseConfig === 'string' || !(responseConfig.body || responseConfig.headers || responseConfig.throws || responseConfig.status)) { | ||
responseConfig = { | ||
body: responseConfig | ||
}; | ||
} | ||
var opts = responseConfig.opts || {}; | ||
opts.url = url; | ||
opts.sendAsJson = responseConfig.sendAsJson === undefined ? this.config.sendAsJson : responseConfig.sendAsJson; | ||
if (responseConfig.status && (typeof responseConfig.status !== 'number' || parseInt(responseConfig.status, 10) !== responseConfig.status || responseConfig.status < 200 || responseConfig.status > 599)) { | ||
throw new TypeError('Invalid status ' + responseConfig.status + ' passed on response object.\nTo respond with a JSON object that has status as a property assign the object to body\ne.g. {"body": {"status: "registered"}}'); | ||
} | ||
opts.status = responseConfig.status || 200; | ||
opts.statusText = FetchMock.statusTextMap['' + opts.status]; | ||
// The ternary operator is to cope with new Headers(undefined) throwing in Chrome | ||
// https://code.google.com/p/chromium/issues/detail?id=335871 | ||
opts.headers = responseConfig.headers ? new FetchMock.Headers(responseConfig.headers) : new FetchMock.Headers(); | ||
var body = responseConfig.body; | ||
if (opts.sendAsJson && responseConfig.body != null && (typeof body === 'undefined' ? 'undefined' : _typeof(body)) === 'object') { | ||
//eslint-disable-line | ||
body = JSON.stringify(body); | ||
} | ||
if (FetchMock.stream) { | ||
var s = new FetchMock.stream.Readable(); | ||
if (body != null) { | ||
//eslint-disable-line | ||
s.push(body, 'utf-8'); | ||
} | ||
}, { | ||
key: 'push', | ||
value: function push(name, call) { | ||
if (name) { | ||
this._calls[name] = this._calls[name] || []; | ||
this._calls[name].push(call); | ||
this._matchedCalls.push(call); | ||
} else { | ||
this._unmatchedCalls.push(call); | ||
} | ||
} | ||
}, { | ||
key: 'restore', | ||
value: function restore() { | ||
this._unMock(); | ||
this.reset(); | ||
this.routes = []; | ||
return this; | ||
} | ||
}, { | ||
key: 'reset', | ||
value: function reset() { | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.routes.forEach(function (route) { | ||
return route.reset && route.reset(); | ||
}); | ||
return this; | ||
} | ||
}, { | ||
key: 'calls', | ||
value: function calls(name) { | ||
return name ? this._calls[name] || [] : { | ||
matched: this._matchedCalls, | ||
unmatched: this._unmatchedCalls | ||
}; | ||
} | ||
}, { | ||
key: 'lastCall', | ||
value: function lastCall(name) { | ||
var calls = name ? this.calls(name) : this.calls().matched; | ||
if (calls && calls.length) { | ||
return calls[calls.length - 1]; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
}, { | ||
key: 'lastUrl', | ||
value: function lastUrl(name) { | ||
var call = this.lastCall(name); | ||
return call && call[0]; | ||
} | ||
}, { | ||
key: 'lastOptions', | ||
value: function lastOptions(name) { | ||
var call = this.lastCall(name); | ||
return call && call[1]; | ||
} | ||
}, { | ||
key: 'called', | ||
value: function called(name) { | ||
if (!name) { | ||
return !!(this._matchedCalls.length || this._unmatchedCalls.length); | ||
} | ||
return !!(this._calls[name] && this._calls[name].length); | ||
} | ||
}, { | ||
key: 'done', | ||
value: function done(name) { | ||
var _this2 = this; | ||
s.push(null); | ||
body = s; | ||
} | ||
var names = name ? [name] : this.routes.map(function (r) { | ||
return r.name; | ||
}); | ||
// Ideally would use array.every, but not widely supported | ||
return names.map(function (name) { | ||
if (!_this2.called(name)) { | ||
return false; | ||
} | ||
// would use array.find... but again not so widely supported | ||
var expectedTimes = (_this2.routes.filter(function (r) { | ||
return r.name === name; | ||
}) || [{}])[0].times; | ||
return !expectedTimes || expectedTimes <= _this2.calls(name).length; | ||
}).filter(function (bool) { | ||
return !bool; | ||
}).length === 0; | ||
return Promise.resolve(new FetchMock.Response(body, opts)); | ||
}; | ||
FetchMock.prototype.push = function (name, call) { | ||
if (name) { | ||
this._calls[name] = this._calls[name] || []; | ||
this._calls[name].push(call); | ||
this._matchedCalls.push(call); | ||
} else { | ||
this._unmatchedCalls.push(call); | ||
} | ||
}; | ||
FetchMock.prototype.restore = function () { | ||
this._unMock(); | ||
this.reset(); | ||
this.routes = []; | ||
return this; | ||
}; | ||
FetchMock.prototype.reset = function () { | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.routes.forEach(function (route) { | ||
return route.reset && route.reset(); | ||
}); | ||
return this; | ||
}; | ||
FetchMock.prototype.calls = function (name) { | ||
return name ? this._calls[name] || [] : { | ||
matched: this._matchedCalls, | ||
unmatched: this._unmatchedCalls | ||
}; | ||
}; | ||
FetchMock.prototype.lastCall = function (name) { | ||
var calls = name ? this.calls(name) : this.calls().matched; | ||
if (calls && calls.length) { | ||
return calls[calls.length - 1]; | ||
} else { | ||
return undefined; | ||
} | ||
}; | ||
FetchMock.prototype.lastUrl = function (name) { | ||
var call = this.lastCall(name); | ||
return call && call[0]; | ||
}; | ||
FetchMock.prototype.lastOptions = function (name) { | ||
var call = this.lastCall(name); | ||
return call && call[1]; | ||
}; | ||
FetchMock.prototype.called = function (name) { | ||
if (!name) { | ||
return !!(this._matchedCalls.length || this._unmatchedCalls.length); | ||
} | ||
return !!(this._calls[name] && this._calls[name].length); | ||
}; | ||
FetchMock.prototype.done = function (name) { | ||
var _this2 = this; | ||
var names = name ? [name] : this.routes.map(function (r) { | ||
return r.name; | ||
}); | ||
// Ideally would use array.every, but not widely supported | ||
return names.map(function (name) { | ||
if (!_this2.called(name)) { | ||
return false; | ||
} | ||
}, { | ||
key: 'configure', | ||
value: function configure(opts) { | ||
_extends(this.config, opts); | ||
} | ||
}]); | ||
// would use array.find... but again not so widely supported | ||
var expectedTimes = (_this2.routes.filter(function (r) { | ||
return r.name === name; | ||
}) || [{}])[0].times; | ||
return !expectedTimes || expectedTimes <= _this2.calls(name).length; | ||
}).filter(function (bool) { | ||
return !bool; | ||
}).length === 0; | ||
}; | ||
return FetchMock; | ||
}(); | ||
FetchMock.prototype.configure = function (opts) { | ||
_extends(this.config, opts); | ||
}; | ||
FetchMock.prototype.sandbox = function () { | ||
if (this.routes.length || this.fallbackResponse) { | ||
throw new Error('.sandbox() can only be called on fetch-mock instances that don\'t have routes configured already'); | ||
} | ||
var instance = new FetchMock(); | ||
_extends(instance.fetchMock, // the function | ||
FetchMock.prototype, // all prototype methods | ||
instance // instance data | ||
); | ||
instance.fetchMock.bindMethods(); | ||
instance.fetchMock.isSandbox = true; | ||
this.restore(); | ||
return instance.fetchMock; | ||
}; | ||
FetchMock.setGlobals = function (globals) { | ||
_extends(FetchMock, globals); | ||
}; | ||
['get', 'post', 'put', 'delete', 'head', 'patch'].forEach(function (method) { | ||
@@ -326,4 +324,2 @@ FetchMock.prototype[method] = function (matcher, response, options) { | ||
module.exports = function (opts) { | ||
return new FetchMock(opts); | ||
}; | ||
module.exports = FetchMock; |
@@ -8,6 +8,6 @@ 'use strict'; | ||
var stream = require('stream'); | ||
var fetchMock = require('./fetch-mock'); | ||
var FetchMock = require('./fetch-mock'); | ||
var http = require('http'); | ||
module.exports = fetchMock({ | ||
FetchMock.setGlobals({ | ||
global: global, | ||
@@ -19,2 +19,4 @@ Request: Request, | ||
statusTextMap: http.STATUS_CODES | ||
}); | ||
}); | ||
module.exports = new FetchMock(); |
{ | ||
"name": "fetch-mock", | ||
"version": "5.5.0", | ||
"version": "5.6.0", | ||
"description": "Mock http requests made using fetch (or isomorphic-fetch)", | ||
@@ -5,0 +5,0 @@ "main": "src/server.js", |
@@ -100,8 +100,3 @@ # fetch-mock [![Build Status](https://travis-ci.org/wheresrhys/fetch-mock.svg?branch=master)](https://travis-ci.org/wheresrhys/fetch-mock) | ||
##### `get()` | ||
##### `post()` | ||
##### `put()` | ||
##### `delete()` | ||
##### `head()` | ||
##### `patch()` | ||
##### `get()`, `post()`, `put()`, `delete()`, `head()`, `patch()` | ||
Shorthands for `mock()` restricted to a particular method *Tip: if you use some other method a lot you can easily define your own shorthands e.g.:* | ||
@@ -116,8 +111,3 @@ | ||
##### `getOnce()` | ||
##### `postOnce()` | ||
##### `putOnce()` | ||
##### `deleteOnce()` | ||
##### `headOnce()` | ||
##### `patchOnce()` | ||
##### `getOnce()`, `postOnce()`, `putOnce()`, `deleteOnce()`, `headOnce()`, `patchOnce()` | ||
Shorthands for `mock()` restricted to a particular method and that can only be called one time only | ||
@@ -128,5 +118,2 @@ | ||
##### `spy()` | ||
Similar to `catch()`, this records the call history of unmatched calls, but instead of responding with a stubbed response, the request is passed through to native `fetch()` and is allowed to communicate over the network. | ||
``` | ||
@@ -138,2 +125,12 @@ fetchMock | ||
##### `spy()` | ||
Similar to `catch()`, this records the call history of unmatched calls, but instead of responding with a stubbed response, the request is passed through to native `fetch()` and is allowed to communicate over the network. | ||
##### `sandbox()` *experimental* | ||
This returns a drop-in mock for fetch which can be passed to other mocking libraries. It implements the full fetch-mock api and maintains its own state independent of other instances, so tests can be run in parallel. e.g. | ||
``` | ||
fetchMock.sandbox().mock('http://domain.com', 200) | ||
``` | ||
##### `restore()` | ||
@@ -149,3 +146,3 @@ Chainable method that restores `fetch()` to its unstubbed state and clears all data recorded for its calls. | ||
**For the methods below `matcherName`, if given, should be either the name of a route (see advanced usage below) or equal to `matcher.toString()` for any unnamed route.** | ||
**For the methods below `matcherName`, if given, should be either the name of a route (see advanced usage below) or equal to `matcher.toString()` for any unnamed route. You _can_ pass in the original regex or function used as a matcher, but they will be converted to strings and used to look up values in fetch-mock's internal maps of calls, rather than used as regexes or functions** | ||
@@ -152,0 +149,0 @@ ##### `called(matcherName)` |
'use strict'; | ||
const fetchMock = require('./fetch-mock'); | ||
const FetchMock = require('./fetch-mock'); | ||
const statusTextMap = require('./status-text'); | ||
const theGlobal = typeof window !== 'undefined' ? window : self; | ||
module.exports = fetchMock({ | ||
FetchMock.setGlobals({ | ||
global: theGlobal, | ||
@@ -14,1 +14,3 @@ Request: theGlobal.Request, | ||
}); | ||
module.exports = new FetchMock() |
@@ -5,272 +5,300 @@ 'use strict'; | ||
class FetchMock { | ||
constructor (opts) { | ||
this.config = { | ||
sendAsJson: true | ||
} | ||
this.Headers = opts.Headers; | ||
this.Request = opts.Request; | ||
this.Response = opts.Response; | ||
this.stream = opts.stream; | ||
this.global = opts.global; | ||
this.statusTextMap = opts.statusTextMap; | ||
this.routes = []; | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.fetchMock = this.fetchMock.bind(this); | ||
this.restore = this.restore.bind(this); | ||
this.reset = this.reset.bind(this); | ||
const FetchMock = function () { | ||
this.config = { | ||
sendAsJson: true | ||
} | ||
mock (matcher, response, options) { | ||
// if (opts) { | ||
// FetchMock.Headers = opts.Headers; | ||
// FetchMock.Request = opts.Request; | ||
// FetchMock.Response = opts.Response; | ||
// FetchMock.stream = opts.stream; | ||
// FetchMock.global = opts.global; | ||
// FetchMock.statusTextMap = opts.statusTextMap; | ||
// } | ||
let route; | ||
this.routes = []; | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.bindMethods(); | ||
} | ||
// Handle the variety of parameters accepted by mock (see README) | ||
FetchMock.prototype.bindMethods = function () { | ||
this.fetchMock = FetchMock.prototype.fetchMock.bind(this); | ||
this.restore = FetchMock.prototype.restore.bind(this); | ||
this.reset = FetchMock.prototype.reset.bind(this); | ||
} | ||
// Old method matching signature | ||
if (options && /^[A-Z]+$/.test(response)) { | ||
throw new Error(`The API for method matching has changed. | ||
Now use .get(), .post(), .put(), .delete() and .head() shorthand methods, | ||
or pass in, e.g. {method: 'PATCH'} as a third paramter`); | ||
} else if (options) { | ||
route = Object.assign({ | ||
matcher, | ||
response | ||
}, options); | ||
} else if (matcher && response) { | ||
route = { | ||
matcher, | ||
response | ||
} | ||
} else if (matcher && matcher.matcher) { | ||
route = matcher | ||
} else { | ||
throw new Error('Invalid parameters passed to fetch-mock') | ||
} | ||
FetchMock.prototype.mock = function (matcher, response, options) { | ||
let route; | ||
this.addRoute(route); | ||
// Handle the variety of parameters accepted by mock (see README) | ||
return this._mock(); | ||
// Old method matching signature | ||
if (options && /^[A-Z]+$/.test(response)) { | ||
throw new Error(`The API for method matching has changed. | ||
Now use .get(), .post(), .put(), .delete() and .head() shorthand methods, | ||
or pass in, e.g. {method: 'PATCH'} as a third paramter`); | ||
} else if (options) { | ||
route = Object.assign({ | ||
matcher, | ||
response | ||
}, options); | ||
} else if (matcher && response) { | ||
route = { | ||
matcher, | ||
response | ||
} | ||
} else if (matcher && matcher.matcher) { | ||
route = matcher | ||
} else { | ||
throw new Error('Invalid parameters passed to fetch-mock') | ||
} | ||
once (matcher, response, options) { | ||
return this.mock(matcher, response, Object.assign({}, options, {times: 1})); | ||
} | ||
_mock () { | ||
this.addRoute(route); | ||
return this._mock(); | ||
} | ||
FetchMock.prototype.once = function (matcher, response, options) { | ||
return this.mock(matcher, response, Object.assign({}, options, {times: 1})); | ||
} | ||
FetchMock.prototype._mock = function () { | ||
if (!this.isSandbox) { | ||
// Do this here rather than in the constructor to ensure it's scoped to the test | ||
this.realFetch = this.realFetch || this.global.fetch; | ||
this.global.fetch = this.fetchMock; | ||
return this; | ||
this.realFetch = this.realFetch || FetchMock.global.fetch; | ||
FetchMock.global.fetch = this.fetchMock; | ||
} | ||
return this; | ||
} | ||
_unMock () { | ||
if (this.realFetch) { | ||
this.global.fetch = this.realFetch; | ||
this.realFetch = null; | ||
} | ||
this.fallbackResponse = null; | ||
return this; | ||
FetchMock.prototype._unMock = function () { | ||
if (this.realFetch) { | ||
FetchMock.global.fetch = this.realFetch; | ||
this.realFetch = null; | ||
} | ||
this.fallbackResponse = null; | ||
return this; | ||
} | ||
catch (response) { | ||
if (this.fallbackResponse) { | ||
console.warn(`calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response`); | ||
} | ||
this.fallbackResponse = response || 'ok'; | ||
return this._mock(); | ||
FetchMock.prototype.catch = function (response) { | ||
if (this.fallbackResponse) { | ||
console.warn(`calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response`); | ||
} | ||
this.fallbackResponse = response || 'ok'; | ||
return this._mock(); | ||
} | ||
spy () { | ||
this._mock(); | ||
return this.catch(this.realFetch) | ||
} | ||
FetchMock.prototype.spy = function () { | ||
this._mock(); | ||
return this.catch(this.realFetch) | ||
} | ||
fetchMock (url, opts) { | ||
FetchMock.prototype.fetchMock = function (url, opts) { | ||
let response = this.router(url, opts); | ||
let response = this.router(url, opts); | ||
if (!response) { | ||
console.warn(`unmatched call to ${url}`); | ||
this.push(null, [url, opts]); | ||
if (!response) { | ||
console.warn(`unmatched call to ${url}`); | ||
this.push(null, [url, opts]); | ||
if (this.fallbackResponse) { | ||
response = this.fallbackResponse; | ||
} else { | ||
throw new Error(`unmatched call to ${url}`) | ||
} | ||
} | ||
if (typeof response === 'function') { | ||
response = response (url, opts); | ||
} | ||
if (typeof response.then === 'function') { | ||
return response.then(response => this.mockResponse(url, response, opts)) | ||
if (this.fallbackResponse) { | ||
response = this.fallbackResponse; | ||
} else { | ||
return this.mockResponse(url, response, opts) | ||
throw new Error(`unmatched call to ${url}`) | ||
} | ||
} | ||
if (typeof response === 'function') { | ||
response = response (url, opts); | ||
} | ||
router (url, opts) { | ||
let route; | ||
for (let i = 0, il = this.routes.length; i < il ; i++) { | ||
route = this.routes[i]; | ||
if (route.matcher(url, opts)) { | ||
this.push(route.name, [url, opts]); | ||
return route.response; | ||
} | ||
} | ||
if (typeof response.then === 'function') { | ||
return response.then(response => this.mockResponse(url, response, opts)) | ||
} else { | ||
return this.mockResponse(url, response, opts) | ||
} | ||
addRoute (route) { | ||
} | ||
if (!route) { | ||
throw new Error('.mock() must be passed configuration for a route') | ||
FetchMock.prototype.router = function (url, opts) { | ||
let route; | ||
for (let i = 0, il = this.routes.length; i < il ; i++) { | ||
route = this.routes[i]; | ||
if (route.matcher(url, opts)) { | ||
this.push(route.name, [url, opts]); | ||
return route.response; | ||
} | ||
} | ||
} | ||
// Allows selective application of some of the preregistered routes | ||
this.routes.push(compileRoute(route, this.Request)); | ||
FetchMock.prototype.addRoute = function (route) { | ||
if (!route) { | ||
throw new Error('.mock() must be passed configuration for a route') | ||
} | ||
// Allows selective application of some of the preregistered routes | ||
this.routes.push(compileRoute(route, FetchMock.Request)); | ||
} | ||
mockResponse (url, responseConfig, fetchOpts) { | ||
// It seems odd to call this in here even though it's already called within fetchMock | ||
// It's to handle the fact that because we want to support making it very easy to add a | ||
// delay to any sort of response (including responses which are defined with a function) | ||
// while also allowing function responses to return a Promise for a response config. | ||
if (typeof responseConfig === 'function') { | ||
responseConfig = responseConfig(url, fetchOpts); | ||
} | ||
if (this.Response.prototype.isPrototypeOf(responseConfig)) { | ||
return Promise.resolve(responseConfig); | ||
} | ||
FetchMock.prototype.mockResponse = function (url, responseConfig, fetchOpts) { | ||
// It seems odd to call this in here even though it's already called within fetchMock | ||
// It's to handle the fact that because we want to support making it very easy to add a | ||
// delay to any sort of response (including responses which are defined with a function) | ||
// while also allowing function responses to return a Promise for a response config. | ||
if (typeof responseConfig === 'function') { | ||
responseConfig = responseConfig(url, fetchOpts); | ||
} | ||
if (responseConfig.throws) { | ||
return Promise.reject(responseConfig.throws); | ||
} | ||
if (FetchMock.Response.prototype.isPrototypeOf(responseConfig)) { | ||
return Promise.resolve(responseConfig); | ||
} | ||
if (typeof responseConfig === 'number') { | ||
responseConfig = { | ||
status: responseConfig | ||
}; | ||
} else if (typeof responseConfig === 'string' || !(responseConfig.body || responseConfig.headers || responseConfig.throws || responseConfig.status)) { | ||
responseConfig = { | ||
body: responseConfig | ||
}; | ||
} | ||
if (responseConfig.throws) { | ||
return Promise.reject(responseConfig.throws); | ||
} | ||
const opts = responseConfig.opts || {}; | ||
opts.url = url; | ||
opts.sendAsJson = responseConfig.sendAsJson === undefined ? this.config.sendAsJson : responseConfig.sendAsJson; | ||
if (responseConfig.status && (typeof responseConfig.status !== 'number' || parseInt(responseConfig.status, 10) !== responseConfig.status || responseConfig.status < 200 || responseConfig.status > 599)) { | ||
throw new TypeError(`Invalid status ${responseConfig.status} passed on response object. | ||
if (typeof responseConfig === 'number') { | ||
responseConfig = { | ||
status: responseConfig | ||
}; | ||
} else if (typeof responseConfig === 'string' || !(responseConfig.body || responseConfig.headers || responseConfig.throws || responseConfig.status)) { | ||
responseConfig = { | ||
body: responseConfig | ||
}; | ||
} | ||
const opts = responseConfig.opts || {}; | ||
opts.url = url; | ||
opts.sendAsJson = responseConfig.sendAsJson === undefined ? this.config.sendAsJson : responseConfig.sendAsJson; | ||
if (responseConfig.status && (typeof responseConfig.status !== 'number' || parseInt(responseConfig.status, 10) !== responseConfig.status || responseConfig.status < 200 || responseConfig.status > 599)) { | ||
throw new TypeError(`Invalid status ${responseConfig.status} passed on response object. | ||
To respond with a JSON object that has status as a property assign the object to body | ||
e.g. {"body": {"status: "registered"}}`); | ||
} | ||
opts.status = responseConfig.status || 200; | ||
opts.statusText = this.statusTextMap['' + opts.status]; | ||
// The ternary operator is to cope with new Headers(undefined) throwing in Chrome | ||
// https://code.google.com/p/chromium/issues/detail?id=335871 | ||
opts.headers = responseConfig.headers ? new this.Headers(responseConfig.headers) : new this.Headers(); | ||
} | ||
opts.status = responseConfig.status || 200; | ||
opts.statusText = FetchMock.statusTextMap['' + opts.status]; | ||
// The ternary operator is to cope with new Headers(undefined) throwing in Chrome | ||
// https://code.google.com/p/chromium/issues/detail?id=335871 | ||
opts.headers = responseConfig.headers ? new FetchMock.Headers(responseConfig.headers) : new FetchMock.Headers(); | ||
let body = responseConfig.body; | ||
if (opts.sendAsJson && responseConfig.body != null && typeof body === 'object') { //eslint-disable-line | ||
body = JSON.stringify(body); | ||
} | ||
if (this.stream) { | ||
let s = new this.stream.Readable(); | ||
if (body != null) { //eslint-disable-line | ||
s.push(body, 'utf-8'); | ||
} | ||
s.push(null); | ||
body = s; | ||
} | ||
return Promise.resolve(new this.Response(body, opts)); | ||
let body = responseConfig.body; | ||
if (opts.sendAsJson && responseConfig.body != null && typeof body === 'object') { //eslint-disable-line | ||
body = JSON.stringify(body); | ||
} | ||
push (name, call) { | ||
if (name) { | ||
this._calls[name] = this._calls[name] || []; | ||
this._calls[name].push(call); | ||
this._matchedCalls.push(call); | ||
} else { | ||
this._unmatchedCalls.push(call); | ||
if (FetchMock.stream) { | ||
let s = new FetchMock.stream.Readable(); | ||
if (body != null) { //eslint-disable-line | ||
s.push(body, 'utf-8'); | ||
} | ||
s.push(null); | ||
body = s; | ||
} | ||
restore () { | ||
this._unMock(); | ||
this.reset(); | ||
this.routes = []; | ||
return this; | ||
} | ||
return Promise.resolve(new FetchMock.Response(body, opts)); | ||
} | ||
reset () { | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.routes.forEach(route => route.reset && route.reset()) | ||
return this; | ||
FetchMock.prototype.push = function (name, call) { | ||
if (name) { | ||
this._calls[name] = this._calls[name] || []; | ||
this._calls[name].push(call); | ||
this._matchedCalls.push(call); | ||
} else { | ||
this._unmatchedCalls.push(call); | ||
} | ||
} | ||
calls (name) { | ||
return name ? (this._calls[name] || []) : { | ||
matched: this._matchedCalls, | ||
unmatched: this._unmatchedCalls | ||
}; | ||
} | ||
FetchMock.prototype.restore = function () { | ||
this._unMock(); | ||
this.reset(); | ||
this.routes = []; | ||
return this; | ||
} | ||
lastCall (name) { | ||
const calls = name ? this.calls(name) : this.calls().matched; | ||
if (calls && calls.length) { | ||
return calls[calls.length - 1]; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
FetchMock.prototype.reset = function () { | ||
this._calls = {}; | ||
this._matchedCalls = []; | ||
this._unmatchedCalls = []; | ||
this.routes.forEach(route => route.reset && route.reset()) | ||
return this; | ||
} | ||
lastUrl (name) { | ||
const call = this.lastCall(name); | ||
return call && call[0]; | ||
FetchMock.prototype.calls = function (name) { | ||
return name ? (this._calls[name] || []) : { | ||
matched: this._matchedCalls, | ||
unmatched: this._unmatchedCalls | ||
}; | ||
} | ||
FetchMock.prototype.lastCall = function (name) { | ||
const calls = name ? this.calls(name) : this.calls().matched; | ||
if (calls && calls.length) { | ||
return calls[calls.length - 1]; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
lastOptions (name) { | ||
const call = this.lastCall(name); | ||
return call && call[1]; | ||
FetchMock.prototype.lastUrl = function (name) { | ||
const call = this.lastCall(name); | ||
return call && call[0]; | ||
} | ||
FetchMock.prototype.lastOptions = function (name) { | ||
const call = this.lastCall(name); | ||
return call && call[1]; | ||
} | ||
FetchMock.prototype.called = function (name) { | ||
if (!name) { | ||
return !!(this._matchedCalls.length || this._unmatchedCalls.length); | ||
} | ||
return !!(this._calls[name] && this._calls[name].length); | ||
} | ||
called (name) { | ||
if (!name) { | ||
return !!(this._matchedCalls.length || this._unmatchedCalls.length); | ||
FetchMock.prototype.done = function (name) { | ||
const names = name ? [name] : this.routes.map(r => r.name); | ||
// Ideally would use array.every, but not widely supported | ||
return names.map(name => { | ||
if (!this.called(name)) { | ||
return false | ||
} | ||
return !!(this._calls[name] && this._calls[name].length); | ||
} | ||
// would use array.find... but again not so widely supported | ||
const expectedTimes = (this.routes.filter(r => r.name === name) || [{}])[0].times; | ||
return !expectedTimes || (expectedTimes <= this.calls(name).length) | ||
}) | ||
.filter(bool => !bool).length === 0 | ||
} | ||
done (name) { | ||
const names = name ? [name] : this.routes.map(r => r.name); | ||
// Ideally would use array.every, but not widely supported | ||
return names.map(name => { | ||
if (!this.called(name)) { | ||
return false | ||
} | ||
// would use array.find... but again not so widely supported | ||
const expectedTimes = (this.routes.filter(r => r.name === name) || [{}])[0].times; | ||
return !expectedTimes || (expectedTimes <= this.calls(name).length) | ||
}) | ||
.filter(bool => !bool).length === 0 | ||
} | ||
FetchMock.prototype.configure = function (opts) { | ||
Object.assign(this.config, opts); | ||
} | ||
configure (opts) { | ||
Object.assign(this.config, opts); | ||
FetchMock.prototype.sandbox = function () { | ||
if (this.routes.length || this.fallbackResponse) { | ||
throw new Error('.sandbox() can only be called on fetch-mock instances that don\'t have routes configured already') | ||
} | ||
} | ||
const instance = new FetchMock(); | ||
Object.assign( | ||
instance.fetchMock, // the function | ||
FetchMock.prototype, // all prototype methods | ||
instance // instance data | ||
); | ||
instance.fetchMock.bindMethods(); | ||
instance.fetchMock.isSandbox = true; | ||
this.restore(); | ||
return instance.fetchMock | ||
}; | ||
FetchMock.setGlobals = function (globals) { | ||
Object.assign(FetchMock, globals) | ||
}; | ||
['get','post','put','delete','head', 'patch'] | ||
@@ -286,4 +314,2 @@ .forEach(method => { | ||
module.exports = function (opts) { | ||
return new FetchMock(opts); | ||
} | ||
module.exports = FetchMock; |
@@ -7,6 +7,6 @@ 'use strict'; | ||
const stream = require('stream'); | ||
const fetchMock = require('./fetch-mock'); | ||
const FetchMock = require('./fetch-mock'); | ||
const http = require('http'); | ||
module.exports = fetchMock({ | ||
FetchMock.setGlobals({ | ||
global: global, | ||
@@ -19,1 +19,3 @@ Request: Request, | ||
}); | ||
module.exports = new FetchMock() |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
62489
1399
214