fetch-mock-one.com
Version:
Mock http requests made using fetch (or isomorphic-fetch) (FORK)
108 lines (91 loc) • 3.25 kB
JavaScript
const { normalizeUrl } = require('./request-utils');
const FetchMock = {};
const { sanitizeRoute } = require('./compile-route');
const generateMatcher = require('./generate-matcher');
const isName = nameOrMatcher =>
typeof nameOrMatcher === 'string' && /^[\da-zA-Z\-]+$/.test(nameOrMatcher);
const filterCallsWithMatcher = (matcher, options = {}, calls) => {
matcher = generateMatcher(sanitizeRoute(Object.assign({ matcher }, options)));
return calls.filter(([url, options]) => matcher(normalizeUrl(url), options));
};
FetchMock.filterCalls = function(nameOrMatcher, options) {
let calls = this._calls;
let matcher = '*';
if (nameOrMatcher === true) {
calls = calls.filter(({ isUnmatched }) => !isUnmatched);
} else if (nameOrMatcher === false) {
calls = calls.filter(({ isUnmatched }) => isUnmatched);
} else if (typeof nameOrMatcher === 'undefined') {
calls = calls;
} else if (isName(nameOrMatcher)) {
calls = calls.filter(({ identifier }) => identifier === nameOrMatcher);
} else {
matcher = normalizeUrl(nameOrMatcher);
if (this.routes.some(({ identifier }) => identifier === matcher)) {
calls = calls.filter(call => call.identifier === matcher);
}
}
if ((options || matcher !== '*') && calls.length) {
if (typeof options === 'string') {
options = { method: options };
}
calls = filterCallsWithMatcher(matcher, options, calls);
}
return calls;
};
FetchMock.calls = function(nameOrMatcher, options) {
return this.filterCalls(nameOrMatcher, options);
};
FetchMock.lastCall = function(nameOrMatcher, options) {
return [...this.filterCalls(nameOrMatcher, options)].pop();
};
FetchMock.lastUrl = function(nameOrMatcher, options) {
return (this.lastCall(nameOrMatcher, options) || [])[0];
};
FetchMock.lastOptions = function(nameOrMatcher, options) {
return (this.lastCall(nameOrMatcher, options) || [])[1];
};
FetchMock.called = function(nameOrMatcher, options) {
return !!this.filterCalls(nameOrMatcher, options).length;
};
FetchMock.flush = function(waitForResponseMethods) {
const queuedPromises = this._holdingPromises;
this._holdingPromises = [];
return Promise.all(queuedPromises).then(() => {
if (waitForResponseMethods && this._holdingPromises.length) {
return this.flush(waitForResponseMethods);
}
});
};
FetchMock.done = function(nameOrMatcher) {
const routesToCheck =
nameOrMatcher && typeof nameOrMatcher !== 'boolean'
? [{ identifier: nameOrMatcher }]
: this.routes;
// Can't use array.every because would exit after first failure, which would
// break the logging
return routesToCheck
.map(({ identifier }) => {
if (!this.called(identifier)) {
console.warn(`Warning: ${identifier} not called`); // eslint-disable-line
return false;
}
const expectedTimes = (
this.routes.find(r => r.identifier === identifier) || {}
).repeat;
if (!expectedTimes) {
return true;
}
const actualTimes = this.filterCalls(identifier).length;
if (expectedTimes > actualTimes) {
console.warn(
`Warning: ${identifier} only called ${actualTimes} times, but ${expectedTimes} expected`
); // eslint-disable-line
return false;
} else {
return true;
}
})
.every(isDone => isDone);
};
module.exports = FetchMock;