Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detached route creation #587

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/Route/index.js
Expand Up @@ -10,8 +10,7 @@ const isUrlMatcher = (matcher) =>
const isFunctionMatcher = (matcher) => typeof matcher === 'function';

class Route {
constructor(args, fetchMock) {
this.fetchMock = fetchMock;
constructor(args) {
wheresrhys marked this conversation as resolved.
Show resolved Hide resolved
const debug = getDebug('compileRoute()');
debug('Compiling route');
this.init(args);
Expand Down Expand Up @@ -84,16 +83,16 @@ class Route {
const activeMatchers = Route.registeredMatchers
.map(
({ name, matcher, usesBody }) =>
this[name] && { matcher: matcher(this, this.fetchMock), usesBody }
this[name] && { matcher: matcher(this), usesBody }
)
.filter((matcher) => Boolean(matcher));

this.usesBody = activeMatchers.some(({ usesBody }) => usesBody);

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

limit() {
Expand Down
6 changes: 3 additions & 3 deletions src/Route/matchers.js
Expand Up @@ -129,12 +129,12 @@ const getParamsMatcher = ({ params: expectedParams, url: matcherUrl }) => {
};
};

const getBodyMatcher = (route, fetchMock) => {
const matchPartialBody = fetchMock.getOption('matchPartialBody', route);
const getBodyMatcher = (route) => {
const { body: expectedBody } = route;

debug('Generating body matcher');
return (url, { body, method = 'get' }) => {
return (url, { body, method = 'get' }, request, fetchMock) => {
const matchPartialBody = fetchMock.getOption('matchPartialBody', route);
debug('Attempting to match body');
if (method.toLowerCase() === 'get') {
debug(' GET request - skip matching body');
Expand Down
2 changes: 1 addition & 1 deletion src/lib/fetch-handler.js
Expand Up @@ -281,7 +281,7 @@ FetchMock.generateResponse = async function ({
FetchMock.router = function (url, options, request) {
const route = this.routes.find((route, i) => {
debug(`Trying to match route ${i}`);
return route.matcher(url, options, request);
return route.matcher(url, options, request, this);
});

if (route) {
Expand Down
8 changes: 1 addition & 7 deletions src/lib/index.js
Expand Up @@ -2,13 +2,10 @@ const { debug } = require('./debug');
const setUpAndTearDown = require('./set-up-and-tear-down');
const fetchHandler = require('./fetch-handler');
const inspecting = require('./inspecting');
const Route = require('../Route');


const FetchMock = Object.assign({}, fetchHandler, setUpAndTearDown, inspecting);

FetchMock.addMatcher = function (matcher) {
Route.addMatcher(matcher);
};

FetchMock.config = {
fallbackToNetwork: false,
Expand All @@ -33,9 +30,6 @@ FetchMock.createInstance = function () {
return instance;
};

FetchMock.compileRoute = function (config) {
return new Route(config, this);
};

FetchMock.bindMethods = function () {
this.fetchHandler = FetchMock.fetchHandler.bind(this);
Expand Down
3 changes: 1 addition & 2 deletions src/lib/inspecting.js
Expand Up @@ -8,10 +8,9 @@ const isName = (nameOrMatcher) =>
const filterCallsWithMatcher = function (matcher, options = {}, calls) {
({ matcher } = new Route(
[Object.assign({ matcher, response: 'ok' }, options)],
this
));
return calls.filter(({ url, options }) =>
matcher(normalizeUrl(url), options)
matcher(normalizeUrl(url), options, null, this)
);
};

Expand Down
50 changes: 37 additions & 13 deletions src/lib/set-up-and-tear-down.js
@@ -1,13 +1,26 @@
const { debug, setDebugPhase } = require('./debug');
const FetchMock = {};

FetchMock.mock = function (...args) {
const Route = require('../Route');
FetchMock.addMatcher = function (matcher) {
Route.addMatcher(matcher);
};

FetchMock.compileRoute = function (config) {
return new Route(config);
};

FetchMock.$mock = function (...args) {
setDebugPhase('setup');
this._mock();
if (args.length) {
this.addRoute(args);
return this.addRoute(args);
}
};

return this._mock();
FetchMock.mock = function (...args) {
this.$mock(...args)
return this;
};

FetchMock.addRoute = function (uncompiledRoute) {
Expand Down Expand Up @@ -41,6 +54,7 @@ FetchMock.addRoute = function (uncompiledRoute) {

this._uncompiledRoutes.push(uncompiledRoute);
this.routes.push(route);
return route;
};

FetchMock._mock = function () {
Expand Down Expand Up @@ -73,7 +87,7 @@ FetchMock.spy = function (route) {
: this.catch(this.getNativeFetch());
};

const defineShorthand = (methodName, underlyingMethod, shorthandOptions) => {
const _defineShorthand = (methodName, underlyingMethod, shorthandOptions) => {
FetchMock[methodName] = function (matcher, response, options) {
return this[underlyingMethod](
matcher,
Expand All @@ -83,22 +97,32 @@ const defineShorthand = (methodName, underlyingMethod, shorthandOptions) => {
};
};

const defineGreedyShorthand = (methodName, underlyingMethod) => {
const defineShorthands = (methodName, underlyingMethod, shorthandOptions) => {
_defineShorthand(methodName, underlyingMethod, shorthandOptions)
_defineShorthand(`$${methodName}`, `$${underlyingMethod}`, shorthandOptions)
}

const _defineGreedyShorthand = (methodName, underlyingMethod) => {
FetchMock[methodName] = function (response, options) {
return this[underlyingMethod]({}, response, options);
};
};

defineShorthand('sticky', 'mock', { sticky: true });
defineShorthand('once', 'mock', { repeat: 1 });
defineGreedyShorthand('any', 'mock');
defineGreedyShorthand('anyOnce', 'once');
const defineGreedyShorthands = (methodName, underlyingMethod, shorthandOptions) => {
_defineGreedyShorthand(methodName, underlyingMethod)
_defineGreedyShorthand(`$${methodName}`, `$${underlyingMethod}`)
}

defineShorthands('sticky', 'mock', { sticky: true });
defineShorthands('once', 'mock', { repeat: 1 });
defineGreedyShorthands('any', 'mock');
defineGreedyShorthands('anyOnce', 'once');

['get', 'post', 'put', 'delete', 'head', 'patch'].forEach((method) => {
defineShorthand(method, 'mock', { method });
defineShorthand(`${method}Once`, 'once', { method });
defineGreedyShorthand(`${method}Any`, method);
defineGreedyShorthand(`${method}AnyOnce`, `${method}Once`);
defineShorthands(method, 'mock', { method });
defineShorthands(`${method}Once`, 'once', { method });
defineGreedyShorthands(`${method}Any`, method);
defineGreedyShorthands(`${method}AnyOnce`, `${method}Once`);
});

const mochaAsyncHookWorkaround = (options) => {
Expand Down