Socket
Socket
Sign inDemoInstall

fetch-mock

Package Overview
Dependencies
8
Maintainers
3
Versions
213
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 8.3.2 to 9.0.0-beta.2

cjs/lib/debug.js

36

cjs/lib/compile-route.js

@@ -0,1 +1,2 @@

const { getDebug } = require('./debug');
const generateMatcher = require('./generate-matcher');

@@ -17,2 +18,3 @@

(typeof matcher === 'object' && 'href' in matcher);
const isFunctionMatcher = matcher => typeof matcher === 'function';

@@ -40,8 +42,12 @@

const sanitizeRoute = route => {
const debug = getDebug('sanitizeRoute()');
debug('Sanitizing route properties');
route = Object.assign({}, route);
if (route.method) {
debug(`Converting method ${route.method} to lower case`);
route.method = route.method.toLowerCase();
}
if (isUrlMatcher(route.matcher)) {
debug('Mock uses a url matcher', route.matcher);
route.url = route.matcher;

@@ -53,3 +59,8 @@ delete route.matcher;

debug('Setting route.identifier...');
debug(` route.name is ${route.name}`);
debug(` route.url is ${route.url}`);
debug(` route.functionMatcher is ${route.functionMatcher}`);
route.identifier = route.name || route.url || route.functionMatcher;
debug(` -> route.identifier set to ${route.identifier}`);
return route;

@@ -70,7 +81,13 @@ };

const limitMatcher = route => {
const limit = route => {
const debug = getDebug('limit()');
debug('Limiting number of requests to handle by route');
if (!route.repeat) {
debug(
' No `repeat` value set on route. Will match any number of requests'
);
return;
}
debug(` Route set to repeat ${route.repeat} times`);
const matcher = route.matcher;

@@ -89,7 +106,16 @@ let timesLeft = route.repeat;

const delayResponse = route => {
const debug = getDebug('delayResponse()');
debug(`Applying response delay settings`);
const { delay } = route;
if (delay) {
debug(` Wrapping response in delay of ${delay} miliseconds`);
const response = route.response;
route.response = () =>
new Promise(res => setTimeout(() => res(response), delay));
route.response = () => {
debug(`Delaying response by ${delay} miliseconds`);
return new Promise(res => setTimeout(() => res(response), delay));
};
} else {
debug(
` No delay set on route. Will respond 'immediately' (but asynchronously)`
);
}

@@ -99,6 +125,8 @@ };

const compileRoute = function(args) {
const debug = getDebug('compileRoute()');
debug('Compiling route');
const route = sanitizeRoute(argsToRoute(args));
validateRoute(route);
route.matcher = generateMatcher(route);
limitMatcher(route);
limit(route);
delayResponse(route);

@@ -105,0 +133,0 @@ return route;

@@ -0,1 +1,2 @@

const { debug, setDebugPhase, getDebug } = require('./debug');
const responseBuilder = require('./response-builder');

@@ -26,2 +27,4 @@ const requestUtils = require('./request-utils');

) => {
const debug = getDebug('resolve()');
debug('Recursively resolving function and promise responses');
// We want to allow things like

@@ -36,11 +39,23 @@ // - function returning a Promise for a response

if (typeof response === 'function') {
debug(' Response is a function');
// in the case of falling back to the network we need to make sure we're using
// the original Request instance, not our normalised url + options
response =
request && responseIsFetch
? response(request)
: response(url, options, request);
if (responseIsFetch) {
if (request) {
debug(' -> Calling fetch with Request instance');
return response(request);
}
debug(' -> Calling fetch with url and options');
return response(url, options);
} else {
debug(' -> Calling response function');
response = response(url, options, request);
}
} else if (typeof response.then === 'function') {
debug(' Response is a promise');
debug(' -> Resolving promise');
response = await response;
} else {
debug(' Response is not a function or a promise');
debug(' -> Exiting response resolution recursion');
return response;

@@ -52,2 +67,5 @@ }

FetchMock.fetchHandler = function(url, options, request) {
setDebugPhase('handle');
const debug = getDebug('fetchHandler()');
debug('fetch called with:', url, options);
const normalizedRequest = requestUtils.normalizeRequest(

@@ -63,2 +81,8 @@ url,

debug('Request normalised');
debug(' url', url);
debug(' options', options);
debug(' request', request);
debug(' signal', signal);
const route = this.executeRouter(url, options, request);

@@ -74,3 +98,5 @@

if (signal) {
debug('signal exists - enabling fetch abort');
const abort = () => {
debug('aborting fetch');
// note that DOMException is not available in node.js; even node-fetch uses a custom error class: https://github.com/bitinn/node-fetch/blob/master/src/abort-error.js

@@ -85,2 +111,3 @@ rej(

if (signal.aborted) {
debug('signal is already aborted - aborting the fetch');
abort();

@@ -93,3 +120,6 @@ }

.then(res, rej)
.then(done, done);
.then(done, done)
.then(() => {
setDebugPhase();
});
});

@@ -101,3 +131,8 @@ };

FetchMock.executeRouter = function(url, options, request) {
const debug = getDebug('executeRouter()');
debug(`Attempting to match request to a route`);
if (this.config.fallbackToNetwork === 'always') {
debug(
' Configured with fallbackToNetwork=always - passing through to fetch'
);
return { response: this.getNativeFetch(), responseIsFetch: true };

@@ -109,2 +144,3 @@ }

if (match) {
debug(' Matching route found');
return match;

@@ -120,2 +156,3 @@ }

if (this.fallbackResponse) {
debug(' No matching route found - using fallbackResponse');
return { response: this.fallbackResponse };

@@ -132,2 +169,3 @@ }

debug(' Configured to fallbackToNetwork - passing through to fetch');
return { response: this.getNativeFetch(), responseIsFetch: true };

@@ -137,2 +175,3 @@ };

FetchMock.generateResponse = async function(route, url, options, request) {
const debug = getDebug('generateResponse()');
const response = await resolve(route, url, options, request);

@@ -143,2 +182,3 @@

if (response.throws && typeof response !== 'function') {
debug('response.throws is defined - throwing an error');
throw response.throws;

@@ -149,2 +189,3 @@ }

if (this.config.Response.prototype.isPrototypeOf(response)) {
debug('response is already a Response instance - returning it');
return response;

@@ -163,3 +204,6 @@ }

FetchMock.router = function(url, options, request) {
const route = this.routes.find(route => route.matcher(url, options, request));
const route = this.routes.find((route, i) => {
debug(`Trying to match route ${i}`);
return route.matcher(url, options, request);
});

@@ -181,3 +225,3 @@ if (route) {

throw new Error(
'fetch-mock: Falling back to network only available on gloabl fetch-mock, or by setting config.fetch on sandboxed fetch-mock'
'fetch-mock: Falling back to network only available on global fetch-mock, or by setting config.fetch on sandboxed fetch-mock'
);

@@ -189,2 +233,9 @@ }

FetchMock.push = function({ url, options, request, isUnmatched, identifier }) {
debug('Recording fetch call', {
url,
options,
request,
isUnmatched,
identifier
});
const args = [url, options];

@@ -191,0 +242,0 @@ args.request = request;

@@ -0,1 +1,2 @@

const { debug, setDebugNamespace } = require('./debug');
const glob = require('glob-to-regexp');

@@ -12,23 +13,38 @@ const pathToRegexp = require('path-to-regexp');

const debuggableUrlFunc = func => url => {
debug('Actual url:', url);
return func(url);
};
const stringMatchers = {
begin: targetString => url => url.indexOf(targetString) === 0,
end: targetString => url => url.substr(-targetString.length) === targetString,
begin: targetString =>
debuggableUrlFunc(url => url.indexOf(targetString) === 0),
end: targetString =>
debuggableUrlFunc(url => url.substr(-targetString.length) === targetString),
glob: targetString => {
const urlRX = glob(targetString);
return url => urlRX.test(url);
return debuggableUrlFunc(url => urlRX.test(url));
},
express: targetString => {
const urlRX = pathToRegexp(targetString);
return url => urlRX.test(getPath(url));
return debuggableUrlFunc(url => urlRX.test(getPath(url)));
},
path: targetString => url => getPath(url) === targetString
path: targetString => debuggableUrlFunc(url => getPath(url) === targetString)
};
const getHeaderMatcher = ({ headers: expectedHeaders }) => {
debug('Generating header matcher');
if (!expectedHeaders) {
debug(' No header expectations defined - skipping');
return;
}
const expectation = headerUtils.toLowerCase(expectedHeaders);
debug(' Expected headers:', expectation);
return (url, { headers = {} }) => {
debug('Attempting to match headers');
const lowerCaseHeaders = headerUtils.toLowerCase(
headerUtils.normalize(headers)
);
debug(' Expected headers:', expectation);
debug(' Actual headers:', lowerCaseHeaders);
return Object.keys(expectation).every(headerName =>

@@ -41,10 +57,30 @@ headerUtils.equal(lowerCaseHeaders[headerName], expectation[headerName])

const getMethodMatcher = ({ method: expectedMethod }) => {
return (url, { method }) =>
expectedMethod === (method ? method.toLowerCase() : 'get');
debug('Generating method matcher');
if (!expectedMethod) {
debug(' No method expectations defined - skipping');
return;
}
debug(' Expected method:', expectedMethod);
return (url, { method }) => {
debug('Attempting to match method');
const actualMethod = method ? method.toLowerCase() : 'get';
debug(' Expected method:', expectedMethod);
debug(' Actual method:', actualMethod);
return expectedMethod === actualMethod;
};
};
const getQueryStringMatcher = ({ query: expectedQuery }) => {
debug('Generating query parameters matcher');
if (!expectedQuery) {
debug(' No query parameters expectations defined - skipping');
return;
}
debug(' Expected query parameters:', expectedQuery);
const keys = Object.keys(expectedQuery);
return url => {
debug('Attempting to match query parameters');
const query = querystring.parse(getQuery(url));
debug(' Expected query parameters:', expectedQuery);
debug(' Actual query parameters:', query);
return keys.every(key => query[key] === expectedQuery[key]);

@@ -54,4 +90,9 @@ };

const getParamsMatcher = ({ params: expectedParams, url: matcheUrl }) => {
if (!/express:/.test(matcheUrl)) {
const getParamsMatcher = ({ params: expectedParams, url: matcherUrl }) => {
debug('Generating path parameters matcher');
if (!expectedParams) {
debug(' No path parameters expectations defined - skipping');
return;
}
if (!/express:/.test(matcherUrl)) {
throw new Error(

@@ -61,6 +102,8 @@ 'fetch-mock: matching on params is only possible when using an express: matcher'

}
debug(' Expected path parameters:', expectedParams);
const expectedKeys = Object.keys(expectedParams);
const keys = [];
const re = pathToRegexp(matcheUrl.replace(/^express:/, ''), keys);
const re = pathToRegexp(matcherUrl.replace(/^express:/, ''), keys);
return url => {
debug('Attempting to match path parameters');
const vals = re.exec(getPath(url)) || [];

@@ -73,2 +116,4 @@ vals.shift();

);
debug(' Expected path parameters:', expectedParams);
debug(' Actual path parameters:', params);
return expectedKeys.every(key => params[key] === expectedParams[key]);

@@ -79,4 +124,7 @@ };

const getBodyMatcher = ({ body: expectedBody }) => {
debug('Generating body matcher');
return (url, { body, method = 'get' }) => {
debug('Attempting to match body');
if (method.toLowerCase() === 'get') {
debug(' GET request - skip matching body');
// GET requests don’t send a body so the body matcher should be ignored for them

@@ -89,4 +137,9 @@ return true;

try {
debug(' Parsing request body as JSON');
sentBody = JSON.parse(body);
} catch (_) {}
} catch (err) {
debug(' Failed to parse request body as JSON', err);
}
debug('Expected body:', expectedBody);
debug('Actual body:', sentBody);

@@ -102,4 +155,7 @@ return sentBody && isEqual(sentBody, expectedBody);

// from http://it.at.there/ once we start generating Request/Url objects
debug(' Matching using full url', matcherUrl);
const expectedUrl = normalizeUrl(matcherUrl);
debug(' Normalised url to:', matcherUrl);
if (route.identifier === matcherUrl) {
debug(' Updating route identifier to match normalized url:', matcherUrl);
route.identifier = expectedUrl;

@@ -109,3 +165,6 @@ }

return matcherUrl => {
debug('Expected url:', expectedUrl);
debug('Actual url:', matcherUrl);
if (query && expectedUrl.indexOf('?')) {
debug('Ignoring query string when matching url');
return matcherUrl.indexOf(expectedUrl) === 0;

@@ -117,8 +176,16 @@ }

const getFunctionMatcher = ({ functionMatcher }) => functionMatcher;
const getFunctionMatcher = ({ functionMatcher }) => {
debug('Detected user defined function matcher', functionMatcher);
return (...args) => {
debug('Calling function matcher with arguments', args);
return functionMatcher(...args);
};
};
const getUrlMatcher = route => {
debug('Generating url matcher');
const { url: matcherUrl, query } = route;
if (matcherUrl === '*') {
debug(' Using universal * rule to match any url');
return () => true;

@@ -128,2 +195,3 @@ }

if (matcherUrl instanceof RegExp) {
debug(' Using regular expression to match url:', matcherUrl);
return url => matcherUrl.test(url);

@@ -133,2 +201,3 @@ }

if (matcherUrl.href) {
debug(` Using URL object to match url`, matcherUrl);
return getFullUrlMatcher(route, matcherUrl.href, query);

@@ -139,2 +208,3 @@ }

if (matcherUrl.indexOf(shorthand + ':') === 0) {
debug(` Using ${shorthand}: pattern to match url`, matcherUrl);
const urlFragment = matcherUrl.replace(new RegExp(`^${shorthand}:`), '');

@@ -149,2 +219,4 @@ return stringMatchers[shorthand](urlFragment);

module.exports = route => {
setDebugNamespace('generateMatcher()');
debug('Compiling matcher for route');
const matchers = [

@@ -160,4 +232,6 @@ route.query && getQueryStringMatcher(route),

debug('Compiled matcher for route');
setDebugNamespace();
return (url, options = {}, request) =>
matchers.every(matcher => matcher(url, options, request));
};

@@ -0,1 +1,2 @@

const { debug } = require('./debug');
const setUpAndTearDown = require('./set-up-and-tear-down');

@@ -16,2 +17,3 @@ const fetchHandler = require('./fetch-handler');

FetchMock.createInstance = function() {
debug('Creating fetch-mock instance');
const instance = Object.create(FetchMock);

@@ -38,2 +40,3 @@ instance._uncompiledRoutes = (this._uncompiledRoutes || []).slice();

FetchMock.sandbox = function() {
debug('Creating sandboxed fetch-mock instance');
// this construct allows us to create a fetch-mock instance which is also

@@ -40,0 +43,0 @@ // a callable function, while circumventing circularity when defining the

117

cjs/lib/inspecting.js

@@ -0,1 +1,2 @@

const { setDebugPhase, setDebugNamespace, debug } = require('./debug');
const { normalizeUrl } = require('./request-utils');

@@ -13,3 +14,13 @@ const FetchMock = {};

const formatDebug = func => {
return function(...args) {
setDebugPhase('inspect');
const result = func.call(this, ...args);
setDebugPhase();
return result;
};
};
FetchMock.filterCalls = function(nameOrMatcher, options) {
debug('Filtering fetch calls');
let calls = this._calls;

@@ -19,8 +30,16 @@ let matcher = '*';

if ([true, 'matched'].includes(nameOrMatcher)) {
debug(`Filter provided is ${nameOrMatcher}. Returning matched calls only`);
calls = calls.filter(({ isUnmatched }) => !isUnmatched);
} else if ([false, 'unmatched'].includes(nameOrMatcher)) {
debug(
`Filter provided is ${nameOrMatcher}. Returning unmatched calls only`
);
calls = calls.filter(({ isUnmatched }) => isUnmatched);
} else if (typeof nameOrMatcher === 'undefined') {
debug(`Filter provided is undefined. Returning all calls`);
calls = calls;
} else if (isName(nameOrMatcher)) {
debug(
`Filter provided, looks like the name of a named route. Returning only calls handled by that route`
);
calls = calls.filter(({ identifier }) => identifier === nameOrMatcher);

@@ -30,2 +49,5 @@ } else {

if (this.routes.some(({ identifier }) => identifier === matcher)) {
debug(
`Filter provided, ${nameOrMatcher}, identifies a route. Returning only calls handled by that route`
);
calls = calls.filter(call => call.identifier === matcher);

@@ -39,49 +61,82 @@ }

}
debug(
'Compiling filter and options to route in order to filter all calls',
nameOrMatcher
);
calls = filterCallsWithMatcher(matcher, options, calls);
}
debug(`Retrieved ${calls.length} calls`);
return calls;
};
FetchMock.calls = function(nameOrMatcher, options) {
FetchMock.calls = formatDebug(function(nameOrMatcher, options) {
debug('retrieving matching calls');
return this.filterCalls(nameOrMatcher, options);
};
});
FetchMock.lastCall = function(nameOrMatcher, options) {
FetchMock.lastCall = formatDebug(function(nameOrMatcher, options) {
debug('retrieving last matching call');
return [...this.filterCalls(nameOrMatcher, options)].pop();
};
});
FetchMock.lastUrl = function(nameOrMatcher, options) {
FetchMock.lastUrl = formatDebug(function(nameOrMatcher, options) {
debug('retrieving url of last matching call');
return (this.lastCall(nameOrMatcher, options) || [])[0];
};
});
FetchMock.lastOptions = function(nameOrMatcher, options) {
FetchMock.lastOptions = formatDebug(function(nameOrMatcher, options) {
debug('retrieving options of last matching call');
return (this.lastCall(nameOrMatcher, options) || [])[1];
};
});
FetchMock.called = function(nameOrMatcher, options) {
FetchMock.called = formatDebug(function(nameOrMatcher, options) {
debug('checking if matching call was made');
return !!this.filterCalls(nameOrMatcher, options).length;
};
});
FetchMock.flush = function(waitForResponseMethods) {
FetchMock.flush = formatDebug(async function(waitForResponseMethods) {
setDebugNamespace('flush');
debug(
`flushing all fetch calls. ${
waitForResponseMethods ? '' : 'Not '
}waiting for response bodies to complete download`
);
const queuedPromises = this._holdingPromises;
this._holdingPromises = [];
debug(`${queuedPromises.length} fetch calls to be awaited`);
return Promise.all(queuedPromises).then(() => {
if (waitForResponseMethods && this._holdingPromises.length) {
return this.flush(waitForResponseMethods);
}
});
};
await Promise.all(queuedPromises);
debug(`All fetch calls have completed`);
if (waitForResponseMethods && this._holdingPromises.length) {
debug(`Awaiting all fetch bodies to download`);
await this.flush(waitForResponseMethods);
debug(`All fetch bodies have completed downloading`);
}
setDebugNamespace();
});
FetchMock.done = function(nameOrMatcher) {
const routesToCheck =
nameOrMatcher && typeof nameOrMatcher !== 'boolean'
? [{ identifier: nameOrMatcher }]
: this.routes;
FetchMock.done = formatDebug(function(nameOrMatcher) {
setDebugPhase('inspect');
setDebugNamespace('done');
debug('Checking to see if expected calls have been made');
let routesToCheck;
if (nameOrMatcher && typeof nameOrMatcher !== 'boolean') {
debug(
'Checking to see if expected calls have been made for single route:',
nameOrMatcher
);
routesToCheck = [{ identifier: nameOrMatcher }];
} else {
debug('Checking to see if expected calls have been made for all routes');
routesToCheck = this.routes;
}
// Can't use array.every because would exit after first failure, which would
// break the logging
return routesToCheck
const result = routesToCheck
.map(({ identifier }) => {
if (!this.called(identifier)) {
debug('No calls made for route:', identifier);
console.warn(`Warning: ${identifier} not called`); // eslint-disable-line

@@ -96,6 +151,16 @@ return false;

if (!expectedTimes) {
debug(
'Route has been called at least once, and no expectation of more set:',
identifier
);
return true;
}
const actualTimes = this.filterCalls(identifier).length;
debug(`Route called ${actualTimes} times:`, identifier);
if (expectedTimes > actualTimes) {
debug(
`Route called ${actualTimes} times, but expected ${expectedTimes}:`,
identifier
);
console.warn(

@@ -110,4 +175,8 @@ `Warning: ${identifier} only called ${actualTimes} times, but ${expectedTimes} expected`

.every(isDone => isDone);
};
setDebugNamespace();
setDebugPhase();
return result;
});
module.exports = FetchMock;

@@ -0,1 +1,2 @@

const { getDebug } = require('./debug');
const responseConfigProps = [

@@ -11,2 +12,4 @@ 'body',

constructor(options) {
this.debug = getDebug('ResponseBuilder()');
this.debug('Response builder created with options', options);
Object.assign(this, options);

@@ -16,2 +19,3 @@ }

exec() {
this.debug('building response');
this.normalizeResponseConfig();

@@ -44,2 +48,3 @@ this.constructFetchOpts();

if (typeof this.responseConfig === 'number') {
this.debug('building response using status', this.responseConfig);
this.responseConfig = {

@@ -51,2 +56,3 @@ status: this.responseConfig

} else if (typeof this.responseConfig === 'string' || this.sendAsObject()) {
this.debug('building text response from', this.responseConfig);
this.responseConfig = {

@@ -60,2 +66,3 @@ body: this.responseConfig

if (!status) {
this.debug('No status provided. Defaulting to 200');
return 200;

@@ -70,2 +77,3 @@ }

) {
this.debug('Valid status provided', status);
return status;

@@ -105,2 +113,3 @@ }

) {
this.debug('Stringifying JSON response body');
this.body = JSON.stringify(this.body);

@@ -120,2 +129,3 @@ if (!this.options.headers.has('Content-Type')) {

) {
this.debug('Setting content-length header:', this.body.length.toString());
this.options.headers.set('Content-Length', this.body.length.toString());

@@ -134,2 +144,3 @@ }

if (this.Stream) {
this.debug('Creating response stream');
const stream = new this.Stream.Readable();

@@ -151,2 +162,3 @@ if (this.body != null) { //eslint-disable-line

// promises returned by res.json(), res.text() etc
this.debug('Wrappipng Response in ES proxy for observability');
return new Proxy(response, {

@@ -156,2 +168,6 @@ get: (originalResponse, name) => {

if (name === 'url') {
this.debug(
'Retrieving redirect url',
this.responseConfig.redirectUrl
);
return this.responseConfig.redirectUrl;

@@ -161,2 +177,3 @@ }

if (name === 'redirected') {
this.debug('Retrieving redirected status', true);
return true;

@@ -167,4 +184,6 @@ }

if (typeof originalResponse[name] === 'function') {
this.debug('Wrapping body promises in ES proxies for observability');
return new Proxy(originalResponse[name], {
apply: (func, thisArg, args) => {
this.debug(`Calling res.${name}`);
const result = func.apply(response, args);

@@ -171,0 +190,0 @@ if (result.then) {

@@ -0,1 +1,2 @@

const { debug, setDebugPhase } = require('./debug');
const { compileRoute } = require('./compile-route');

@@ -5,2 +6,3 @@ const FetchMock = {};

FetchMock.mock = function(...args) {
setDebugPhase('setup');
if (args.length) {

@@ -14,2 +16,3 @@ this.addRoute(args);

FetchMock.addRoute = function(uncompiledRoute) {
debug('Adding route', uncompiledRoute);
const route = this.compileRoute(uncompiledRoute);

@@ -38,3 +41,2 @@ const clashes = this.routes.filter(

});
return this.routes;

@@ -59,2 +61,3 @@ }

}
setDebugPhase();
return this;

@@ -61,0 +64,0 @@ };

@@ -21,2 +21,5 @@ 'use strict';

var _require = require('./debug'),
getDebug = _require.getDebug;
var generateMatcher = require('./generate-matcher');

@@ -29,2 +32,3 @@

};
var isFunctionMatcher = function isFunctionMatcher(matcher) {

@@ -58,8 +62,12 @@ return typeof matcher === 'function';

var sanitizeRoute = function sanitizeRoute(route) {
var debug = getDebug('sanitizeRoute()');
debug('Sanitizing route properties');
route = (0, _assign2.default)({}, route);
if (route.method) {
debug('Converting method ' + route.method + ' to lower case');
route.method = route.method.toLowerCase();
}
if (isUrlMatcher(route.matcher)) {
debug('Mock uses a url matcher', route.matcher);
route.url = route.matcher;

@@ -71,3 +79,8 @@ delete route.matcher;

debug('Setting route.identifier...');
debug(' route.name is ' + route.name);
debug(' route.url is ' + route.url);
debug(' route.functionMatcher is ' + route.functionMatcher);
route.identifier = route.name || route.url || route.functionMatcher;
debug(' -> route.identifier set to ' + route.identifier);
return route;

@@ -88,7 +101,11 @@ };

var limitMatcher = function limitMatcher(route) {
var limit = function limit(route) {
var debug = getDebug('limit()');
debug('Limiting number of requests to handle by route');
if (!route.repeat) {
debug(' No `repeat` value set on route. Will match any number of requests');
return;
}
debug(' Route set to repeat ' + route.repeat + ' times');
var matcher = route.matcher;

@@ -109,7 +126,11 @@ var timesLeft = route.repeat;

var delayResponse = function delayResponse(route) {
var debug = getDebug('delayResponse()');
debug('Applying response delay settings');
var delay = route.delay;
if (delay) {
debug(' Wrapping response in delay of ' + delay + ' miliseconds');
var response = route.response;
route.response = function () {
debug('Delaying response by ' + delay + ' miliseconds');
return new _promise2.default(function (res) {

@@ -121,2 +142,4 @@ return setTimeout(function () {

};
} else {
debug(' No delay set on route. Will respond \'immediately\' (but asynchronously)');
}

@@ -126,6 +149,8 @@ };

var compileRoute = function compileRoute(args) {
var debug = getDebug('compileRoute()');
debug('Compiling route');
var route = sanitizeRoute(argsToRoute(args));
validateRoute(route);
route.matcher = generateMatcher(route);
limitMatcher(route);
limit(route);
delayResponse(route);

@@ -132,0 +157,0 @@ return route;

@@ -29,2 +29,7 @@ 'use strict';

var _require = require('./debug'),
debug = _require.debug,
setDebugPhase = _require.setDebugPhase,
getDebug = _require.getDebug;
var responseBuilder = require('./response-builder');

@@ -63,2 +68,3 @@ var requestUtils = require('./request-utils');

responseIsFetch = _ref$responseIsFetch === undefined ? false : _ref$responseIsFetch;
var debug;
return _regenerator2.default.wrap(function _callee$(_context) {

@@ -68,4 +74,16 @@ while (1) {

case 0:
debug = getDebug('resolve()');
debug('Recursively resolving function and promise responses');
// We want to allow things like
// - function returning a Promise for a response
// - delaying (using a timeout Promise) a function's execution to generate
// a response
// Because of this we can't safely check for function before Promisey-ness,
// or vice versa. So to keep it DRY, and flexible, we keep trying until we
// have something that looks like neither Promise nor function
case 2:
if (!true) {
_context.next = 14;
_context.next = 30;
break;

@@ -75,34 +93,61 @@ }

if (!(typeof response === 'function')) {
_context.next = 5;
_context.next = 17;
break;
}
debug(' Response is a function');
// in the case of falling back to the network we need to make sure we're using
// the original Request instance, not our normalised url + options
response = request && responseIsFetch ? response(request) : response(url, options, request);
_context.next = 12;
if (!responseIsFetch) {
_context.next = 13;
break;
}
if (!request) {
_context.next = 9;
break;
}
debug(' -> Calling fetch with Request instance');
return _context.abrupt('return', response(request));
case 9:
debug(' -> Calling fetch with url and options');
return _context.abrupt('return', response(url, options));
case 13:
debug(' -> Calling response function');
response = response(url, options, request);
case 15:
_context.next = 28;
break;
case 5:
case 17:
if (!(typeof response.then === 'function')) {
_context.next = 11;
_context.next = 25;
break;
}
_context.next = 8;
debug(' Response is a promise');
debug(' -> Resolving promise');
_context.next = 22;
return response;
case 8:
case 22:
response = _context.sent;
_context.next = 12;
_context.next = 28;
break;
case 11:
case 25:
debug(' Response is not a function or a promise');
debug(' -> Exiting response resolution recursion');
return _context.abrupt('return', response);
case 12:
_context.next = 0;
case 28:
_context.next = 2;
break;
case 14:
case 30:
case 'end':

@@ -123,2 +168,5 @@ return _context.stop();

setDebugPhase('handle');
var debug = getDebug('fetchHandler()');
debug('fetch called with:', url, options);
var normalizedRequest = requestUtils.normalizeRequest(url, options, this.config.Request);

@@ -132,2 +180,8 @@

debug('Request normalised');
debug(' url', url);
debug(' options', options);
debug(' request', request);
debug(' signal', signal);
var route = this.executeRouter(url, options, request);

@@ -145,3 +199,5 @@

if (signal) {
debug('signal exists - enabling fetch abort');
var abort = function abort() {
debug('aborting fetch');
// note that DOMException is not available in node.js; even node-fetch uses a custom error class: https://github.com/bitinn/node-fetch/blob/master/src/abort-error.js

@@ -152,2 +208,3 @@ rej(typeof DOMException !== 'undefined' ? new DOMException('The operation was aborted.', 'AbortError') : new AbortError());

if (signal.aborted) {
debug('signal is already aborted - aborting the fetch');
abort();

@@ -158,3 +215,5 @@ }

_this2.generateResponse(route, url, options, request).then(res, rej).then(done, done);
_this2.generateResponse(route, url, options, request).then(res, rej).then(done, done).then(function () {
setDebugPhase();
});
});

@@ -166,3 +225,6 @@ };

FetchMock.executeRouter = function (url, options, request) {
var debug = getDebug('executeRouter()');
debug('Attempting to match request to a route');
if (this.config.fallbackToNetwork === 'always') {
debug(' Configured with fallbackToNetwork=always - passing through to fetch');
return { response: this.getNativeFetch(), responseIsFetch: true };

@@ -174,2 +236,3 @@ }

if (match) {
debug(' Matching route found');
return match;

@@ -185,2 +248,3 @@ }

if (this.fallbackResponse) {
debug(' No matching route found - using fallbackResponse');
return { response: this.fallbackResponse };

@@ -193,2 +257,3 @@ }

debug(' Configured to fallbackToNetwork - passing through to fetch');
return { response: this.getNativeFetch(), responseIsFetch: true };

@@ -199,3 +264,3 @@ };

var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(route, url, options, request) {
var response;
var debug, response;
return _regenerator2.default.wrap(function _callee2$(_context2) {

@@ -205,24 +270,27 @@ while (1) {

case 0:
_context2.next = 2;
debug = getDebug('generateResponse()');
_context2.next = 3;
return resolve(route, url, options, request);
case 2:
case 3:
response = _context2.sent;
if (!(response.throws && typeof response !== 'function')) {
_context2.next = 5;
_context2.next = 7;
break;
}
debug('response.throws is defined - throwing an error');
throw response.throws;
case 5:
case 7:
if (!this.config.Response.prototype.isPrototypeOf(response)) {
_context2.next = 7;
_context2.next = 10;
break;
}
debug('response is already a Response instance - returning it');
return _context2.abrupt('return', response);
case 7:
case 10:
return _context2.abrupt('return', responseBuilder({

@@ -235,3 +303,3 @@ url: url,

case 8:
case 11:
case 'end':

@@ -250,3 +318,4 @@ return _context2.stop();

FetchMock.router = function (url, options, request) {
var route = this.routes.find(function (route) {
var route = this.routes.find(function (route, i) {
debug('Trying to match route ' + i);
return route.matcher(url, options, request);

@@ -269,3 +338,3 @@ });

if (!func) {
throw new Error('fetch-mock: Falling back to network only available on gloabl fetch-mock, or by setting config.fetch on sandboxed fetch-mock');
throw new Error('fetch-mock: Falling back to network only available on global fetch-mock, or by setting config.fetch on sandboxed fetch-mock');
}

@@ -282,2 +351,9 @@ return func;

debug('Recording fetch call', {
url: url,
options: options,
request: request,
isUnmatched: isUnmatched,
identifier: identifier
});
var args = [url, options];

@@ -284,0 +360,0 @@ args.request = request;

@@ -17,2 +17,6 @@ 'use strict';

var _require = require('./debug'),
debug = _require.debug,
setDebugNamespace = _require.setDebugNamespace;
var _glob = require('glob-to-regexp');

@@ -22,37 +26,44 @@ var pathToRegexp = require('path-to-regexp');

var _require = require('./request-utils'),
headerUtils = _require.headers,
getPath = _require.getPath,
getQuery = _require.getQuery,
normalizeUrl = _require.normalizeUrl;
var _require2 = require('./request-utils'),
headerUtils = _require2.headers,
getPath = _require2.getPath,
getQuery = _require2.getQuery,
normalizeUrl = _require2.normalizeUrl;
var isEqual = require('lodash.isequal');
var debuggableUrlFunc = function debuggableUrlFunc(func) {
return function (url) {
debug('Actual url:', url);
return func(url);
};
};
var stringMatchers = {
begin: function begin(targetString) {
return function (url) {
return debuggableUrlFunc(function (url) {
return url.indexOf(targetString) === 0;
};
});
},
end: function end(targetString) {
return function (url) {
return debuggableUrlFunc(function (url) {
return url.substr(-targetString.length) === targetString;
};
});
},
glob: function glob(targetString) {
var urlRX = _glob(targetString);
return function (url) {
return debuggableUrlFunc(function (url) {
return urlRX.test(url);
};
});
},
express: function express(targetString) {
var urlRX = pathToRegexp(targetString);
return function (url) {
return debuggableUrlFunc(function (url) {
return urlRX.test(getPath(url));
};
});
},
path: function path(targetString) {
return function (url) {
return debuggableUrlFunc(function (url) {
return getPath(url) === targetString;
};
});
}

@@ -64,3 +75,9 @@ };

debug('Generating header matcher');
if (!expectedHeaders) {
debug(' No header expectations defined - skipping');
return;
}
var expectation = headerUtils.toLowerCase(expectedHeaders);
debug(' Expected headers:', expectation);
return function (url, _ref2) {

@@ -70,4 +87,6 @@ var _ref2$headers = _ref2.headers,

debug('Attempting to match headers');
var lowerCaseHeaders = headerUtils.toLowerCase(headerUtils.normalize(headers));
debug(' Expected headers:', expectation);
debug(' Actual headers:', lowerCaseHeaders);
return (0, _keys2.default)(expectation).every(function (headerName) {

@@ -82,5 +101,16 @@ return headerUtils.equal(lowerCaseHeaders[headerName], expectation[headerName]);

debug('Generating method matcher');
if (!expectedMethod) {
debug(' No method expectations defined - skipping');
return;
}
debug(' Expected method:', expectedMethod);
return function (url, _ref4) {
var method = _ref4.method;
return expectedMethod === (method ? method.toLowerCase() : 'get');
debug('Attempting to match method');
var actualMethod = method ? method.toLowerCase() : 'get';
debug(' Expected method:', expectedMethod);
debug(' Actual method:', actualMethod);
return expectedMethod === actualMethod;
};

@@ -92,5 +122,14 @@ };

debug('Generating query parameters matcher');
if (!expectedQuery) {
debug(' No query parameters expectations defined - skipping');
return;
}
debug(' Expected query parameters:', expectedQuery);
var keys = (0, _keys2.default)(expectedQuery);
return function (url) {
debug('Attempting to match query parameters');
var query = querystring.parse(getQuery(url));
debug(' Expected query parameters:', expectedQuery);
debug(' Actual query parameters:', query);
return keys.every(function (key) {

@@ -104,11 +143,18 @@ return query[key] === expectedQuery[key];

var expectedParams = _ref6.params,
matcheUrl = _ref6.url;
matcherUrl = _ref6.url;
if (!/express:/.test(matcheUrl)) {
debug('Generating path parameters matcher');
if (!expectedParams) {
debug(' No path parameters expectations defined - skipping');
return;
}
if (!/express:/.test(matcherUrl)) {
throw new Error('fetch-mock: matching on params is only possible when using an express: matcher');
}
debug(' Expected path parameters:', expectedParams);
var expectedKeys = (0, _keys2.default)(expectedParams);
var keys = [];
var re = pathToRegexp(matcheUrl.replace(/^express:/, ''), keys);
var re = pathToRegexp(matcherUrl.replace(/^express:/, ''), keys);
return function (url) {
debug('Attempting to match path parameters');
var vals = re.exec(getPath(url)) || [];

@@ -120,2 +166,4 @@ vals.shift();

}, {});
debug(' Expected path parameters:', expectedParams);
debug(' Actual path parameters:', params);
return expectedKeys.every(function (key) {

@@ -130,2 +178,3 @@ return params[key] === expectedParams[key];

debug('Generating body matcher');
return function (url, _ref9) {

@@ -136,3 +185,5 @@ var body = _ref9.body,

debug('Attempting to match body');
if (method.toLowerCase() === 'get') {
debug(' GET request - skip matching body');
// GET requests don’t send a body so the body matcher should be ignored for them

@@ -145,4 +196,9 @@ return true;

try {
debug(' Parsing request body as JSON');
sentBody = JSON.parse(body);
} catch (_) {}
} catch (err) {
debug(' Failed to parse request body as JSON', err);
}
debug('Expected body:', expectedBody);
debug('Actual body:', sentBody);

@@ -158,4 +214,7 @@ return sentBody && isEqual(sentBody, expectedBody);

// from http://it.at.there/ once we start generating Request/Url objects
debug(' Matching using full url', matcherUrl);
var expectedUrl = normalizeUrl(matcherUrl);
debug(' Normalised url to:', matcherUrl);
if (route.identifier === matcherUrl) {
debug(' Updating route identifier to match normalized url:', matcherUrl);
route.identifier = expectedUrl;

@@ -165,3 +224,6 @@ }

return function (matcherUrl) {
debug('Expected url:', expectedUrl);
debug('Actual url:', matcherUrl);
if (query && expectedUrl.indexOf('?')) {
debug('Ignoring query string when matching url');
return matcherUrl.indexOf(expectedUrl) === 0;

@@ -175,6 +237,16 @@ }

var functionMatcher = _ref10.functionMatcher;
return functionMatcher;
debug('Detected user defined function matcher', functionMatcher);
return function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
debug('Calling function matcher with arguments', args);
return functionMatcher.apply(undefined, args);
};
};
var getUrlMatcher = function getUrlMatcher(route) {
debug('Generating url matcher');
var matcherUrl = route.url,

@@ -185,2 +257,3 @@ query = route.query;

if (matcherUrl === '*') {
debug(' Using universal * rule to match any url');
return function () {

@@ -192,2 +265,3 @@ return true;

if (matcherUrl instanceof RegExp) {
debug(' Using regular expression to match url:', matcherUrl);
return function (url) {

@@ -199,2 +273,3 @@ return matcherUrl.test(url);

if (matcherUrl.href) {
debug(' Using URL object to match url', matcherUrl);
return getFullUrlMatcher(route, matcherUrl.href, query);

@@ -205,2 +280,3 @@ }

if (matcherUrl.indexOf(shorthand + ':') === 0) {
debug(' Using ' + shorthand + ': pattern to match url', matcherUrl);
var urlFragment = matcherUrl.replace(new RegExp('^' + shorthand + ':'), '');

@@ -215,2 +291,4 @@ return stringMatchers[shorthand](urlFragment);

module.exports = function (route) {
setDebugNamespace('generateMatcher()');
debug('Compiling matcher for route');
var matchers = [route.query && getQueryStringMatcher(route), route.method && getMethodMatcher(route), route.headers && getHeaderMatcher(route), route.params && getParamsMatcher(route), route.body && getBodyMatcher(route), route.functionMatcher && getFunctionMatcher(route), route.url && getUrlMatcher(route)].filter(function (matcher) {

@@ -220,2 +298,4 @@ return !!matcher;

debug('Compiled matcher for route');
setDebugNamespace();
return function (url) {

@@ -222,0 +302,0 @@ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

@@ -13,2 +13,5 @@ 'use strict';

var _require = require('./debug'),
debug = _require.debug;
var setUpAndTearDown = require('./set-up-and-tear-down');

@@ -29,2 +32,3 @@ var fetchHandler = require('./fetch-handler');

FetchMock.createInstance = function () {
debug('Creating fetch-mock instance');
var instance = (0, _create2.default)(FetchMock);

@@ -51,2 +55,3 @@ instance._uncompiledRoutes = (this._uncompiledRoutes || []).slice();

FetchMock.sandbox = function () {
debug('Creating sandboxed fetch-mock instance');
// this construct allows us to create a fetch-mock instance which is also

@@ -53,0 +58,0 @@ // a callable function, while circumventing circularity when defining the

'use strict';
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _promise = require('babel-runtime/core-js/promise');

@@ -7,2 +11,6 @@

var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');

@@ -22,9 +30,14 @@

var _require = require('./request-utils'),
normalizeUrl = _require.normalizeUrl;
var _require = require('./debug'),
setDebugPhase = _require.setDebugPhase,
setDebugNamespace = _require.setDebugNamespace,
debug = _require.debug;
var _require2 = require('./request-utils'),
normalizeUrl = _require2.normalizeUrl;
var FetchMock = {};
var _require2 = require('./compile-route'),
sanitizeRoute = _require2.sanitizeRoute;
var _require3 = require('./compile-route'),
sanitizeRoute = _require3.sanitizeRoute;

@@ -50,3 +63,18 @@ var generateMatcher = require('./generate-matcher');

var formatDebug = function formatDebug(func) {
return function () {
setDebugPhase('inspect');
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var result = func.call.apply(func, [this].concat(args));
setDebugPhase();
return result;
};
};
FetchMock.filterCalls = function (nameOrMatcher, options) {
debug('Filtering fetch calls');
var calls = this._calls;

@@ -56,2 +84,3 @@ var matcher = '*';

if ([true, 'matched'].includes(nameOrMatcher)) {
debug('Filter provided is ' + nameOrMatcher + '. Returning matched calls only');
calls = calls.filter(function (_ref3) {

@@ -62,2 +91,3 @@ var isUnmatched = _ref3.isUnmatched;

} else if ([false, 'unmatched'].includes(nameOrMatcher)) {
debug('Filter provided is ' + nameOrMatcher + '. Returning unmatched calls only');
calls = calls.filter(function (_ref4) {

@@ -68,4 +98,6 @@ var isUnmatched = _ref4.isUnmatched;

} else if (typeof nameOrMatcher === 'undefined') {
debug('Filter provided is undefined. Returning all calls');
calls = calls;
} else if (isName(nameOrMatcher)) {
debug('Filter provided, looks like the name of a named route. Returning only calls handled by that route');
calls = calls.filter(function (_ref5) {

@@ -81,2 +113,3 @@ var identifier = _ref5.identifier;

})) {
debug('Filter provided, ' + nameOrMatcher + ', identifies a route. Returning only calls handled by that route');
calls = calls.filter(function (call) {

@@ -92,51 +125,106 @@ return call.identifier === matcher;

}
debug('Compiling filter and options to route in order to filter all calls', nameOrMatcher);
calls = filterCallsWithMatcher(matcher, options, calls);
}
debug('Retrieved ' + calls.length + ' calls');
return calls;
};
FetchMock.calls = function (nameOrMatcher, options) {
FetchMock.calls = formatDebug(function (nameOrMatcher, options) {
debug('retrieving matching calls');
return this.filterCalls(nameOrMatcher, options);
};
});
FetchMock.lastCall = function (nameOrMatcher, options) {
FetchMock.lastCall = formatDebug(function (nameOrMatcher, options) {
debug('retrieving last matching call');
return [].concat((0, _toConsumableArray3.default)(this.filterCalls(nameOrMatcher, options))).pop();
};
});
FetchMock.lastUrl = function (nameOrMatcher, options) {
FetchMock.lastUrl = formatDebug(function (nameOrMatcher, options) {
debug('retrieving url of last matching call');
return (this.lastCall(nameOrMatcher, options) || [])[0];
};
});
FetchMock.lastOptions = function (nameOrMatcher, options) {
FetchMock.lastOptions = formatDebug(function (nameOrMatcher, options) {
debug('retrieving options of last matching call');
return (this.lastCall(nameOrMatcher, options) || [])[1];
};
});
FetchMock.called = function (nameOrMatcher, options) {
FetchMock.called = formatDebug(function (nameOrMatcher, options) {
debug('checking if matching call was made');
return !!this.filterCalls(nameOrMatcher, options).length;
};
});
FetchMock.flush = function (waitForResponseMethods) {
var _this = this;
FetchMock.flush = formatDebug(function () {
var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(waitForResponseMethods) {
var queuedPromises;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
setDebugNamespace('flush');
debug('flushing all fetch calls. ' + (waitForResponseMethods ? '' : 'Not ') + 'waiting for response bodies to complete download');
var queuedPromises = this._holdingPromises;
this._holdingPromises = [];
queuedPromises = this._holdingPromises;
return _promise2.default.all(queuedPromises).then(function () {
if (waitForResponseMethods && _this._holdingPromises.length) {
return _this.flush(waitForResponseMethods);
}
});
};
this._holdingPromises = [];
debug(queuedPromises.length + ' fetch calls to be awaited');
FetchMock.done = function (nameOrMatcher) {
var _this2 = this;
_context.next = 7;
return _promise2.default.all(queuedPromises);
var routesToCheck = nameOrMatcher && typeof nameOrMatcher !== 'boolean' ? [{ identifier: nameOrMatcher }] : this.routes;
case 7:
debug('All fetch calls have completed');
if (!(waitForResponseMethods && this._holdingPromises.length)) {
_context.next = 13;
break;
}
debug('Awaiting all fetch bodies to download');
_context.next = 12;
return this.flush(waitForResponseMethods);
case 12:
debug('All fetch bodies have completed downloading');
case 13:
setDebugNamespace();
case 14:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
return function (_x2) {
return _ref7.apply(this, arguments);
};
}());
FetchMock.done = formatDebug(function (nameOrMatcher) {
var _this = this;
setDebugPhase('inspect');
setDebugNamespace('done');
debug('Checking to see if expected calls have been made');
var routesToCheck = void 0;
if (nameOrMatcher && typeof nameOrMatcher !== 'boolean') {
debug('Checking to see if expected calls have been made for single route:', nameOrMatcher);
routesToCheck = [{ identifier: nameOrMatcher }];
} else {
debug('Checking to see if expected calls have been made for all routes');
routesToCheck = this.routes;
}
// Can't use array.every because would exit after first failure, which would
// break the logging
return routesToCheck.map(function (_ref7) {
var identifier = _ref7.identifier;
var result = routesToCheck.map(function (_ref8) {
var identifier = _ref8.identifier;
if (!_this2.called(identifier)) {
if (!_this.called(identifier)) {
debug('No calls made for route:', identifier);
console.warn('Warning: ' + identifier + ' not called'); // eslint-disable-line

@@ -146,3 +234,3 @@ return false;

var expectedTimes = (_this2.routes.find(function (r) {
var expectedTimes = (_this.routes.find(function (r) {
return r.identifier === identifier;

@@ -152,6 +240,10 @@ }) || {}).repeat;

if (!expectedTimes) {
debug('Route has been called at least once, and no expectation of more set:', identifier);
return true;
}
var actualTimes = _this2.filterCalls(identifier).length;
var actualTimes = _this.filterCalls(identifier).length;
debug('Route called ' + actualTimes + ' times:', identifier);
if (expectedTimes > actualTimes) {
debug('Route called ' + actualTimes + ' times, but expected ' + expectedTimes + ':', identifier);
console.warn('Warning: ' + identifier + ' only called ' + actualTimes + ' times, but ' + expectedTimes + ' expected'); // eslint-disable-line

@@ -165,4 +257,8 @@ return false;

});
};
setDebugNamespace();
setDebugPhase();
return result;
});
module.exports = FetchMock;

@@ -29,2 +29,5 @@ 'use strict';

var _require = require('./debug'),
getDebug = _require.getDebug;
var responseConfigProps = ['body', 'headers', 'throws', 'status', 'redirectUrl'];

@@ -36,2 +39,4 @@

this.debug = getDebug('ResponseBuilder()');
this.debug('Response builder created with options', options);
(0, _assign2.default)(this, options);

@@ -43,2 +48,3 @@ }

value: function exec() {
this.debug('building response');
this.normalizeResponseConfig();

@@ -73,2 +79,3 @@ this.constructFetchOpts();

if (typeof this.responseConfig === 'number') {
this.debug('building response using status', this.responseConfig);
this.responseConfig = {

@@ -80,2 +87,3 @@ status: this.responseConfig

} else if (typeof this.responseConfig === 'string' || this.sendAsObject()) {
this.debug('building text response from', this.responseConfig);
this.responseConfig = {

@@ -90,2 +98,3 @@ body: this.responseConfig

if (!status) {
this.debug('No status provided. Defaulting to 200');
return 200;

@@ -95,2 +104,3 @@ }

if (typeof status === 'number' && parseInt(status, 10) !== status && status >= 200 || status < 600) {
this.debug('Valid status provided', status);
return status;

@@ -124,2 +134,3 @@ }

(0, _typeof3.default)(this.body) === 'object') {
this.debug('Stringifying JSON response body');
this.body = (0, _stringify2.default)(this.body);

@@ -136,2 +147,3 @@ if (!this.options.headers.has('Content-Type')) {

if (this.getOption('includeContentLength') && typeof this.body === 'string' && !this.options.headers.has('Content-Length')) {
this.debug('Setting content-length header:', this.body.length.toString());
this.options.headers.set('Content-Length', this.body.length.toString());

@@ -151,2 +163,3 @@ }

if (this.Stream) {
this.debug('Creating response stream');
var stream = new this.Stream.Readable();

@@ -172,2 +185,3 @@ if (this.body != null) {

// promises returned by res.json(), res.text() etc
this.debug('Wrappipng Response in ES proxy for observability');
return new Proxy(response, {

@@ -177,2 +191,3 @@ get: function get(originalResponse, name) {

if (name === 'url') {
_this2.debug('Retrieving redirect url', _this2.responseConfig.redirectUrl);
return _this2.responseConfig.redirectUrl;

@@ -182,2 +197,3 @@ }

if (name === 'redirected') {
_this2.debug('Retrieving redirected status', true);
return true;

@@ -188,4 +204,6 @@ }

if (typeof originalResponse[name] === 'function') {
_this2.debug('Wrapping body promises in ES proxies for observability');
return new Proxy(originalResponse[name], {
apply: function apply(func, thisArg, args) {
_this2.debug('Calling res.' + name);
var result = func.apply(response, args);

@@ -192,0 +210,0 @@ if (result.then) {

@@ -9,8 +9,14 @@ 'use strict';

var _require = require('./compile-route'),
compileRoute = _require.compileRoute;
var _require = require('./debug'),
debug = _require.debug,
setDebugPhase = _require.setDebugPhase;
var _require2 = require('./compile-route'),
compileRoute = _require2.compileRoute;
var FetchMock = {};
FetchMock.mock = function () {
setDebugPhase('setup');
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {

@@ -30,2 +36,3 @@ args[_key] = arguments[_key];

debug('Adding route', uncompiledRoute);
var route = this.compileRoute(uncompiledRoute);

@@ -51,3 +58,2 @@ var clashes = this.routes.filter(function (_ref) {

});
return this.routes;

@@ -70,2 +76,3 @@ }

}
setDebugPhase();
return this;

@@ -72,0 +79,0 @@ };

{
"name": "fetch-mock",
"type": "module",
"version": "8.3.2",
"version": "9.0.0-beta.2",
"description": "Mock http requests made using fetch (or isomorphic-fetch)",
"main": "./cjs/server.js",
"browser": "./esm/client.mjs",
"module": "./esm/server.mjs",
"browser": "./esm/client.js",
"module": "./esm/server.js",
"types": "./types/index.d.ts",

@@ -58,2 +58,3 @@ "scripts": {

"core-js": "^3.0.0",
"debug": "^4.1.1",
"glob-to-regexp": "^0.4.0",

@@ -60,0 +61,0 @@ "lodash.isequal": "^4.5.0",

@@ -5,3 +5,3 @@ # fetch-mock

*New* If using jest, try the new [fetch-mock-jest](https://www.npmjs.com/package/fetch-mock-jest) wrapper.
_New_ If using jest, try the new [fetch-mock-jest](https://www.npmjs.com/package/fetch-mock-jest) wrapper.

@@ -8,0 +8,0 @@ ![node version](https://img.shields.io/node/v/fetch-mock.svg?style=flat-square)

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc