fetch-mock-one.com
Version:
Mock http requests made using fetch (or isomorphic-fetch) (FORK)
191 lines (151 loc) • 5.37 kB
JavaScript
'use strict';
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var compileRoute = require('./compile-route');
var FetchMock = {};
var makeRouteComparator = function makeRouteComparator(route, propName) {
var comparator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
return function (candidateRoute) {
if (route[propName] && candidateRoute[propName]) {
return comparator && typeof comparator === 'function' ? comparator(route[propName], candidateRoute[propName]) : route[propName] === candidateRoute[propName];
}
return !route[propName] && !candidateRoute[propName];
};
};
var RouteMatcherSpec = {
identifier: true,
method: true,
query: function query(routeQuery, candidateRouteQuery) {
var routeKeys = (0, _keys2.default)(routeQuery);
var candidateRouteKeys = (0, _keys2.default)(candidateRouteQuery);
if (routeKeys.length !== candidateRouteKeys.length) {
return false;
}
if (routeKeys.some(function (k) {
return candidateRouteKeys.indexOf(k) === -1;
})) {
return false;
}
for (var i = 0; i < routeKeys.length; i++) {
if (routeQuery[routeKeys[i]] !== candidateRouteQuery[routeKeys[i]]) {
return false;
}
}
return true;
},
repeat: true
};
var makeRoutMatcher = function makeRoutMatcher(route) {
return function (candidateRoute) {
return (0, _keys2.default)(RouteMatcherSpec).reduce(function (acc, prop) {
if (!acc) return false;
var compare = makeRouteComparator(route, prop, RouteMatcherSpec[prop]);
return compare(candidateRoute);
}, true);
};
};
FetchMock.mock = function (matcher, response) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var route = void 0;
// Handle the variety of parameters accepted by mock (see README)
if (matcher && response) {
route = (0, _assign2.default)({
matcher: matcher,
response: response
}, options);
} else if (matcher && matcher.matcher) {
route = matcher;
} else {
throw new Error('fetch-mock: Invalid parameters passed to fetch-mock');
}
this.addRoute(route);
return this._mock();
};
FetchMock.addRoute = function (uncompiledRoute) {
var _this = this;
var addRoute = function addRoute() {
_this._uncompiledRoutes.push(uncompiledRoute);
return _this.routes.push(route);
};
var route = this.compileRoute(uncompiledRoute);
var overwriteRoutes = 'overwriteRoutes' in route ? route.overwriteRoutes : this.config.overwriteRoutes;
var matcher = makeRoutMatcher(route);
var dupIndex = this.routes.findIndex(matcher);
if (!overwriteRoutes) {
if (dupIndex > -1) {
throw new Error(
// eslint-disable-next-line prettier/prettier
'fetch-mock: Adding route ' + route.identifier + ' with same name or matcher as existing route.\n\t\t\t\tSee `overwriteRoutes` option.');
}
return addRoute();
}
if (dupIndex > -1) {
this._uncompiledRoutes.splice(dupIndex, 1, uncompiledRoute);
return this.routes.splice(dupIndex, 1, route);
}
addRoute();
};
FetchMock._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.fetchHandler;
}
return this;
};
FetchMock.catch = function (response) {
if (this.fallbackResponse) {
console.warn('calling fetchMock.catch() twice - are you sure you want to overwrite the previous fallback response'); // eslint-disable-line
}
this.fallbackResponse = response || 'ok';
return this._mock();
};
FetchMock.spy = function () {
this._mock();
return this.catch(this.getNativeFetch());
};
FetchMock.compileRoute = compileRoute;
FetchMock.once = function (matcher, response) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return this.mock(matcher, response, (0, _assign2.default)({}, options, { repeat: 1 }));
};
['get', 'post', 'put', 'delete', 'head', 'patch'].forEach(function (method) {
var extendOptions = function extendOptions(options) {
return (0, _assign2.default)({}, options, { method: method.toUpperCase() });
};
FetchMock[method] = function (matcher, response) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return this.mock(matcher, response, extendOptions(options));
};
FetchMock[method + 'Once'] = function (matcher, response) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return this.once(matcher, response, extendOptions(options));
};
});
FetchMock.resetBehavior = function () {
if (this.realFetch) {
this.global.fetch = this.realFetch;
this.realFetch = undefined;
}
this.fallbackResponse = undefined;
this.routes = [];
this._uncompiledRoutes = [];
return this;
};
FetchMock.resetHistory = function () {
this._calls = [];
this._holdingPromises = [];
this.routes.forEach(function (route) {
return route.reset && route.reset();
});
return this;
};
FetchMock.restore = FetchMock.reset = function () {
this.resetBehavior();
this.resetHistory();
return this;
};
module.exports = FetchMock;