Repository: wheresrhys/fetch-mock (js)

Issue:
Remove support for passing in a `matcher` property in
> Use any of the `String` or `RegExp` matchers described above. *Note that the property name 'matcher' can be used instead of 'url', but this is deprecated and support will be dropped in the next major version, so prefer to use 'url'*

Pull request:
Rhys/drop support for matcher
fixes #708 

Patch:
diff --git a/docs/docs/@fetch-mock/core/route/matcher.md b/docs/docs/@fetch-mock/core/route/matcher.md
index b9b1a7f..ac7abe0 100644
--- a/docs/docs/@fetch-mock/core/route/matcher.md
+++ b/docs/docs/@fetch-mock/core/route/matcher.md
@@ -141,7 +141,7 @@ This option can also be [set in the global configuration](/fetch-mock/docs/@fetc
 
 For use cases not covered by all the built in matchers, a custom function can be used. It should return `true` to indicate a route should respond to a request. It will be passed the `url` and `options` `fetch` was called with. If `fetch` was called with a `Request` instance, it will be passed `url` and `options` inferred from the `Request` instance, with the original `Request` available as a third argument.
 
-As well as being passed as a standalone argument, it can also be added to the matcher object as the property `{func: ...}` when combining with other matchers or options.
+As well as being passed as a standalone argument, it can also be added to the matcher object as the property `{matcherFunction: ...}` when combining with other matchers or options.
 
 ### Examples
 
diff --git a/packages/core/src/CallHistory.js b/packages/core/src/CallHistory.js
index 0820823..3f57aa0 100644
--- a/packages/core/src/CallHistory.js
+++ b/packages/core/src/CallHistory.js
@@ -125,7 +125,7 @@ class CallHistory {
 			}
 		} else {
 			if (isUrlMatcher(filter)) {
-				options = { matcher: filter, ...(options || {}) };
+				options = { url: filter, ...(options || {}) };
 			} else {
 				options = { ...filter, ...(options || {}) };
 			}
diff --git a/packages/core/src/Matchers.js b/packages/core/src/Matchers.js
index c24ba2f..50f540c 100644
--- a/packages/core/src/Matchers.js
+++ b/packages/core/src/Matchers.js
@@ -196,7 +196,7 @@ const getFullUrlMatcher = (route, matcherUrl, query) => {
 /**
  * @type {MatcherGenerator}
  */
-const getFunctionMatcher = ({ func }) => func;
+const getFunctionMatcher = ({ matcherFunction }) => matcherFunction;
 /**
  * @type {MatcherGenerator}
  */
@@ -236,6 +236,6 @@ export const builtInMatchers = [
 	{ name: 'headers', matcher: getHeaderMatcher },
 	{ name: 'params', matcher: getParamsMatcher },
 	{ name: 'body', matcher: getBodyMatcher, usesBody: true },
-	{ name: 'func', matcher: getFunctionMatcher },
+	{ name: 'matcherFunction', matcher: getFunctionMatcher },
 	{ name: 'url', matcher: getUrlMatcher },
 ];
diff --git a/packages/core/src/Route.js b/packages/core/src/Route.js
index e7c7814..1341b44 100644
--- a/packages/core/src/Route.js
+++ b/packages/core/src/Route.js
@@ -1,5 +1,5 @@
 //@type-check
-import { builtInMatchers, isUrlMatcher, isFunctionMatcher } from './Matchers';
+import { builtInMatchers } from './Matchers';
 import statusTextMap from './StatusTextMap';
 
 /** @typedef {import('./Matchers').RouteMatcher} RouteMatcher */
@@ -41,7 +41,7 @@ import statusTextMap from './StatusTextMap';
  * @property {{ [key: string]: string }} [query]
  * @property {{ [key: string]: string }} [params]
  * @property {object} [body]
- * @property {RouteMatcherFunction} [func]
+ * @property {RouteMatcherFunction} [matcherFunction]
  * @property {RouteMatcher} [matcher]
  * @property {RouteMatcherUrl} [url]
  * @property {RouteResponse | RouteResponseFunction} [response]
@@ -134,13 +134,6 @@ class Route {
 		if (this.config.method) {
 			this.config.method = this.config.method.toLowerCase();
 		}
-		if (isUrlMatcher(this.config.matcher)) {
-			this.config.url = this.config.matcher;
-			delete this.config.matcher;
-		}
-		if (isFunctionMatcher(this.config.matcher)) {
-			this.config.func = this.config.matcher;
-		}
 	}
 	/**
 	 * @returns {void}
diff --git a/packages/core/src/Router.js b/packages/core/src/Router.js
index 7fed0ed..7e3c0fb 100644
--- a/packages/core/src/Router.js
+++ b/packages/core/src/Router.js
@@ -278,8 +278,8 @@ export default class Router {
 				if (typeof response[name] === 'function') {
 					//@ts-ignore
 					return new Proxy(response[name], {
-						apply: (func, thisArg, args) => {
-							const result = func.apply(response, args);
+						apply: (matcherFunction, thisArg, args) => {
+							const result = matcherFunction.apply(response, args);
 							if (result.then) {
 								pendingPromises.push(
 									result.catch(/** @type {function(): void} */ () => undefined),
@@ -318,8 +318,10 @@ export default class Router {
 	addRoute(matcher, response, nameOrOptions) {
 		/** @type {RouteConfig} */
 		const config = {};
-		if (isUrlMatcher(matcher) || isFunctionMatcher(matcher)) {
-			config.matcher = matcher;
+		if (isUrlMatcher(matcher)) {
+			config.url = matcher;
+		} else if (isFunctionMatcher(matcher)) {
+			config.matcherFunction = matcher;
 		} else {
 			Object.assign(config, matcher);
 		}
@@ -366,14 +368,7 @@ export default class Router {
 		}
 
 		this.fallbackRoute = new Route({
-			matcher: (url, options) => {
-				if (this.config.warnOnFallback) {
-					console.warn(
-						`Unmatched ${(options && options.method) || 'GET'} to ${url}`,
-					); // eslint-disable-line
-				}
-				return true;
-			},
+			matcherFunction: () => true,
 			response: response || 'ok',
 			...this.config,
 		});


Test patch:
diff --git a/packages/core/src/__tests__/Matchers/express.test.js b/packages/core/src/__tests__/Matchers/express.test.js
index 4973d6d..0f19ef1 100644
--- a/packages/core/src/__tests__/Matchers/express.test.js
+++ b/packages/core/src/__tests__/Matchers/express.test.js
@@ -4,7 +4,7 @@ import Route from '../../Route.js';
 describe('express path parameter matching', () => {
 	it('can match a path parameters', () => {
 		const route = new Route({
-			matcher: 'express:/type/:instance',
+			url: 'express:/type/:instance',
 			response: 200,
 			params: { instance: 'b' },
 		});
@@ -15,7 +15,7 @@ describe('express path parameter matching', () => {
 
 	it('can match multiple path parameters', () => {
 		const route = new Route({
-			matcher: 'express:/:type/:instance',
+			url: 'express:/:type/:instance',
 			response: 200,
 			params: { instance: 'b', type: 'cat' },
 		});
@@ -28,7 +28,7 @@ describe('express path parameter matching', () => {
 
 	it('can match a path parameter on a full url', () => {
 		const route = new Route({
-			matcher: 'express:/type/:instance',
+			url: 'express:/type/:instance',
 			response: 200,
 			params: { instance: 'b' },
 		});
@@ -38,7 +38,7 @@ describe('express path parameter matching', () => {
 	});
 
 	it('can match fully qualified url', () => {
-		const route = new Route({ matcher: 'express:/apps/:id', response: 200 });
+		const route = new Route({ url: 'express:/apps/:id', response: 200 });
 
 		expect(route.matcher('https://api.example.com/apps/abc')).toBe(true);
 	});
diff --git a/packages/core/src/__tests__/Matchers/function.test.js b/packages/core/src/__tests__/Matchers/function.test.js
index 46af89b..d0f4d0d 100644
--- a/packages/core/src/__tests__/Matchers/function.test.js
+++ b/packages/core/src/__tests__/Matchers/function.test.js
@@ -4,7 +4,7 @@ import Route from '../../Route.js';
 describe('function matching', () => {
 	it('match using custom function', () => {
 		const route = new Route({
-			matcher: (url, opts) =>
+			matcherFunction: (url, opts) =>
 				url.indexOf('logged-in') > -1 &&
 				opts &&
 				opts.headers &&
@@ -27,7 +27,7 @@ describe('function matching', () => {
 
 	it('match using custom function using request body', () => {
 		const route = new Route({
-			matcher: (url, opts) => opts.body === 'a string',
+			matcherFunction: (url, opts) => opts.body === 'a string',
 			response: 200,
 		});
 		expect(route.matcher('http://a.com/logged-in')).toBe(false);
@@ -41,9 +41,9 @@ describe('function matching', () => {
 
 	it('match using custom function alongside other matchers', () => {
 		const route = new Route({
-			matcher: 'end:profile',
+			url: 'end:profile',
 			response: 200,
-			func: (url, opts) =>
+			matcherFunction: (url, opts) =>
 				opts && opts.headers && opts.headers.authorized === true,
 		});
 
diff --git a/packages/core/src/__tests__/Matchers/method.test.js b/packages/core/src/__tests__/Matchers/method.test.js
index 92eb6c8..3d8a940 100644
--- a/packages/core/src/__tests__/Matchers/method.test.js
+++ b/packages/core/src/__tests__/Matchers/method.test.js
@@ -4,7 +4,7 @@ import Route from '../../Route.js';
 
 describe('method matching', () => {
 	it('match any method by default', () => {
-		const route = new Route({ matcher: '*', response: 200 });
+		const route = new Route({ url: '*', response: 200 });
 
 		expect(route.matcher('http://a.com/', { method: 'GET' })).toBe(true);
 		expect(route.matcher('http://a.com/', { method: 'POST' })).toBe(true);
@@ -43,7 +43,7 @@ describe('method matching', () => {
 	it('can be used alongside function matchers', () => {
 		const route = new Route({
 			method: 'POST',
-			matcher: (url) => /a\.com/.test(url),
+			matcherFunction: (url) => /a\.com/.test(url),
 
 			response: 200,
 		});
diff --git a/packages/core/src/__tests__/Matchers/route-config-object.test.js b/packages/core/src/__tests__/Matchers/route-config-object.test.js
index b9ad11a..fff37d0 100644
--- a/packages/core/src/__tests__/Matchers/route-config-object.test.js
+++ b/packages/core/src/__tests__/Matchers/route-config-object.test.js
@@ -5,7 +5,7 @@ import Route from '../../Route.js';
 // as it's mainly about the shape of optiosn passed into to addRoute
 describe('matcher object', () => {
 	it('use matcher object with matcher property', () => {
-		const route = new Route({ matcher: 'http://a.com', response: 200 });
+		const route = new Route({ url: 'http://a.com', response: 200 });
 		expect(route.matcher('http://a.com')).toBe(true);
 	});
 
@@ -14,10 +14,10 @@ describe('matcher object', () => {
 		expect(route.matcher('http://a.com')).toBe(true);
 	});
 
-	it('can use matcher and url simultaneously', () => {
+	it('can use function and url simultaneously', () => {
 		const route = new Route({
 			url: 'end:path',
-			matcher: (url, opts) =>
+			matcherFunction: (url, opts) =>
 				opts && opts.headers && opts.headers.authorized === true,
 			response: 200,
 		});
@@ -41,11 +41,11 @@ describe('matcher object', () => {
 		expect(route.matcher('http://a.com')).toBe(true);
 	});
 
-	//TODO be strionger on discouraging this
-	it.skip('deprecated message on using func (prefer matcher)', () => {
+	//TODO be stronger on discouraging this
+	it.skip('deprecated message on using matcherFunction (prefer matcher)', () => {
 		new Route({
 			url: 'end:profile',
-			func: (url, opts) =>
+			matcherFunction: (url, opts) =>
 				opts && opts.headers && opts.headers.authorized === true,
 			response: 200,
 		});
@@ -115,9 +115,6 @@ describe('matcher object', () => {
 		).toBe(true);
 	});
 
-	// TODO new tests for how multiple routes that match can be addeed
-	it.skip('support setting overwrite routes on matcher parameter', () => {});
-
 	it('support setting matchPartialBody on matcher parameter', () => {
 		const route = new Route({
 			body: { a: 1 },
diff --git a/packages/core/src/__tests__/Matchers/url.test.js b/packages/core/src/__tests__/Matchers/url.test.js
index f49bcfa..1178cad 100644
--- a/packages/core/src/__tests__/Matchers/url.test.js
+++ b/packages/core/src/__tests__/Matchers/url.test.js
@@ -3,7 +3,7 @@ import Route from '../../Route.js';
 
 describe('url matching', () => {
 	it('match exact strings', () => {
-		const route = new Route({ matcher: 'http://a.com/path', response: 200 });
+		const route = new Route({ url: 'http://a.com/path', response: 200 });
 		expect(route.matcher('http://a.com/pat')).toBe(false);
 		expect(route.matcher('http://a.com/paths')).toBe(false);
 		expect(route.matcher('http://a.co/path')).toBe(false);
@@ -12,32 +12,32 @@ describe('url matching', () => {
 	});
 
 	it('match string objects', () => {
-		const route = new Route({ matcher: 'http://a.com/path', response: 200 });
+		const route = new Route({ url: 'http://a.com/path', response: 200 });
 		expect(route.matcher(new String('http://a.com/path'))).toBe(true); // eslint-disable-line no-new-wrappers
 	});
 
 	it('match exact strings with relative url', () => {
-		const route = new Route({ matcher: '/path', response: 200 });
+		const route = new Route({ url: '/path', response: 200 });
 		expect(route.matcher('/pat')).toBe(false);
 		expect(route.matcher('/paths')).toBe(false);
 		expect(route.matcher('/path')).toBe(true);
 	});
 
 	it('match exact string against URL object', () => {
-		const route = new Route({ matcher: 'http://a.com/path', response: 200 });
+		const route = new Route({ url: 'http://a.com/path', response: 200 });
 		const url = new URL('http://a.com/path');
 		expect(route.matcher(url)).toBe(true);
 	});
 
 	it('match using URL object as matcher', () => {
 		const url = new URL('http://a.com/path');
-		const route = new Route({ matcher: url, response: 200 });
+		const route = new Route({ url: url, response: 200 });
 		expect(route.matcher('http://a.com/path')).toBe(true);
 	});
 
 	it('match begin: keyword', () => {
 		const route = new Route({
-			matcher: 'begin:http://a.com/path',
+			url: 'begin:http://a.com/path',
 			response: 200,
 		});
 
@@ -48,7 +48,7 @@ describe('url matching', () => {
 	});
 
 	it('match end: keyword', () => {
-		const route = new Route({ matcher: 'end:com/path', response: 200 });
+		const route = new Route({ url: 'end:com/path', response: 200 });
 		expect(route.matcher('http://a.com/paths')).toBe(false);
 		expect(route.matcher('http://a.com/pat')).toBe(false);
 		expect(route.matcher('http://a.com/path')).toBe(true);
@@ -56,14 +56,14 @@ describe('url matching', () => {
 	});
 
 	it('match glob: keyword', () => {
-		const route = new Route({ matcher: 'glob:/its/*/*', response: 200 });
+		const route = new Route({ url: 'glob:/its/*/*', response: 200 });
 		expect(route.matcher('/its/alive')).toBe(false);
 		expect(route.matcher('/its/a/boy')).toBe(true);
 		expect(route.matcher('/its/a/girl')).toBe(true);
 	});
 
 	it('match express: keyword', () => {
-		const route = new Route({ matcher: 'express:/its/:word', response: 200 });
+		const route = new Route({ url: 'express:/its/:word', response: 200 });
 
 		expect(route.matcher('/its')).toBe(false);
 		expect(route.matcher('/its/')).toBe(false);
@@ -72,7 +72,7 @@ describe('url matching', () => {
 	});
 
 	it('match path: keyword', () => {
-		const route = new Route({ matcher: 'path:/its/:word', response: 200 });
+		const route = new Route({ url: 'path:/its/:word', response: 200 });
 
 		expect(route.matcher('/its/boy')).toBe(false);
 		expect(route.matcher('/its/:word/still')).toBe(false);
@@ -81,14 +81,14 @@ describe('url matching', () => {
 	});
 
 	it('match wildcard string', () => {
-		const route = new Route({ matcher: '*', response: 200 });
+		const route = new Route({ url: '*', response: 200 });
 
 		expect(route.matcher('http://a.com')).toBe(true);
 	});
 
 	it('match regular expressions', () => {
 		const rx = /http\:\/\/a\.com\/\d+/;
-		const route = new Route({ matcher: rx, response: 200 });
+		const route = new Route({ url: rx, response: 200 });
 
 		expect(route.matcher('http://a.com/')).toBe(false);
 		expect(route.matcher('http://a.com/abcde')).toBe(false);
@@ -96,29 +96,29 @@ describe('url matching', () => {
 	});
 
 	it('match relative urls', () => {
-		const route = new Route({ matcher: '/a.com/', response: 200 });
+		const route = new Route({ url: '/a.com/', response: 200 });
 		expect(route.matcher('/a.com/')).toBe(true);
 	});
 
 	it('match relative urls with dots', () => {
-		const route = new Route({ matcher: '/it.at/there/', response: 200 });
+		const route = new Route({ url: '/it.at/there/', response: 200 });
 		expect(route.matcher('/it.at/not/../there/')).toBe(true);
 		expect(route.matcher('./it.at/there/')).toBe(true);
 	});
 
 	it('match absolute urls with dots', () => {
-		const route = new Route({ matcher: 'http://it.at/there/', response: 200 });
+		const route = new Route({ url: 'http://it.at/there/', response: 200 });
 		expect(route.matcher('http://it.at/not/../there/')).toBe(true);
 	});
 
 	describe('host normalisation', () => {
 		it('match exact pathless urls regardless of trailing slash', () => {
-			const route = new Route({ matcher: 'http://a.com/', response: 200 });
+			const route = new Route({ url: 'http://a.com/', response: 200 });
 
 			expect(route.matcher('http://a.com/')).toBe(true);
 			expect(route.matcher('http://a.com')).toBe(true);
 
-			const route2 = new Route({ matcher: 'http://b.com', response: 200 });
+			const route2 = new Route({ url: 'http://b.com', response: 200 });
 			expect(route2.matcher('http://b.com/')).toBe(true);
 			expect(route2.matcher('http://b.com')).toBe(true);
 		});
@@ -127,7 +127,7 @@ describe('url matching', () => {
 	describe('data: URLs', () => {
 		it('match exact strings', () => {
 			const route = new Route({
-				matcher: 'data:text/plain,path',
+				url: 'data:text/plain,path',
 				response: 200,
 			});
 			expect(route.matcher('data:text/plain,pat')).toBe(false);
@@ -137,7 +137,7 @@ describe('url matching', () => {
 		});
 		it('match exact string against URL object', () => {
 			const route = new Route({
-				matcher: 'data:text/plain,path',
+				url: 'data:text/plain,path',
 				response: 200,
 			});
 			const url = new URL('data:text/plain,path');
@@ -145,12 +145,12 @@ describe('url matching', () => {
 		});
 		it('match using URL object as matcher', () => {
 			const url = new URL('data:text/plain,path');
-			const route = new Route({ matcher: url, response: 200 });
+			const route = new Route({ url: url, response: 200 });
 			expect(route.matcher('data:text/plain,path')).toBe(true);
 		});
 		it('match begin: keyword', () => {
 			const route = new Route({
-				matcher: 'begin:data:text/plain',
+				url: 'begin:data:text/plain',
 				response: 200,
 			});
 			expect(route.matcher('http://a.com/path')).toBe(false);
@@ -159,25 +159,25 @@ describe('url matching', () => {
 			expect(route.matcher('data:text/plain;base64,cGF0aA')).toBe(true);
 		});
 		it('match end: keyword', () => {
-			const route = new Route({ matcher: 'end:sky', response: 200 });
+			const route = new Route({ url: 'end:sky', response: 200 });
 			expect(route.matcher('data:text/plain,blue lake')).toBe(false);
 			expect(route.matcher('data:text/plain,blue sky research')).toBe(false);
 			expect(route.matcher('data:text/plain,blue sky')).toBe(true);
 			expect(route.matcher('data:text/plain,grey sky')).toBe(true);
 		});
 		it('match glob: keyword', () => {
-			const route = new Route({ matcher: 'glob:data:* sky', response: 200 });
+			const route = new Route({ url: 'glob:data:* sky', response: 200 });
 			expect(route.matcher('data:text/plain,blue lake')).toBe(false);
 			expect(route.matcher('data:text/plain,blue sky')).toBe(true);
 			expect(route.matcher('data:text/plain,grey sky')).toBe(true);
 		});
 		it('match wildcard string', () => {
-			const route = new Route({ matcher: '*', response: 200 });
+			const route = new Route({ url: '*', response: 200 });
 			expect(route.matcher('data:text/plain,path')).toBe(true);
 		});
 		it('match regular expressions', () => {
 			const rx = /data\:text\/plain,\d+/;
-			const route = new Route({ matcher: rx, response: 200 });
+			const route = new Route({ url: rx, response: 200 });
 			expect(route.matcher('data:text/html,12345')).toBe(false);
 			expect(route.matcher('data:text/plain,path')).toBe(false);
 			expect(route.matcher('data:text/plain,12345')).toBe(true);