diff --git a/src/urlMatcherFactory.js b/src/urlMatcherFactory.js index 4e49e5708..0bb9878f5 100644 --- a/src/urlMatcherFactory.js +++ b/src/urlMatcherFactory.js @@ -449,13 +449,22 @@ function $UrlMatcherFactory() { * @methodOf ui.router.util.$urlMatcherFactory * * @description - * Returns true if the specified object is a UrlMatcher, or false otherwise. + * Returns true if the specified object is a `UrlMatcher`, or false otherwise. * * @param {Object} object The object to perform the type check against. - * @returns {Boolean} Returns `true` if the object has the following functions: `exec`, `format`, and `concat`. + * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by + * implementing all the same methods. */ this.isMatcher = function (o) { - return isObject(o) && isFunction(o.exec) && isFunction(o.format) && isFunction(o.concat); + if (!isObject(o)) return false; + var result = true; + + forEach(UrlMatcher.prototype, function(val, name) { + if (isFunction(val)) { + result = result && (isDefined(o[name]) && isFunction(o[name])); + } + }); + return result; }; this.type = function (name, def) { diff --git a/test/urlMatcherFactorySpec.js b/test/urlMatcherFactorySpec.js index 12fc4b33f..5be15d9b2 100644 --- a/test/urlMatcherFactorySpec.js +++ b/test/urlMatcherFactorySpec.js @@ -29,6 +29,14 @@ describe("UrlMatcher", function () { provider.strictMode(false); expect(provider.compile('/hello').exec('/hello/')).toEqual({}); }); + + it("should correctly validate UrlMatcher interface", function () { + var m = new UrlMatcher("/"); + expect(provider.isMatcher(m)).toBe(true); + + m.validates = null; + expect(provider.isMatcher(m)).toBe(false); + }); }); it("should match static URLs", function () { @@ -177,7 +185,13 @@ describe("urlMatcherFactory", function () { it("recognizes matchers", function () { expect($umf.isMatcher(new UrlMatcher('/'))).toBe(true); - var custom = { format: angular.noop, exec: angular.noop, concat: angular.noop }; + var custom = { + format: angular.noop, + exec: angular.noop, + concat: angular.noop, + validates: angular.noop, + parameters: angular.noop + }; expect($umf.isMatcher(custom)).toBe(true); });