Skip to content

Commit 1a8d961

Browse files
committed
Using refactored URL matcher detection in $state, fixes #154
- Refactoring $urlRouterProvider.when() for improved composability - Adding tests for $urlRouterProvider
1 parent 6fc0e32 commit 1a8d961

File tree

4 files changed

+59
-38
lines changed

4 files changed

+59
-38
lines changed

src/state.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,8 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
3535
}
3636
return (state.parent.navigable || root).url.concat(url);
3737
}
38-
var isMatcher = (
39-
isObject(url) && isFunction(url.exec) && isFunction(url.format) && isFunction(url.concat)
40-
);
4138

42-
if (isMatcher || url == null) {
39+
if ($urlMatcherFactory.isMatcher(url) || url == null) {
4340
return url;
4441
}
4542
throw new Error("Invalid url '" + url + "' in state '" + state + "'");

src/urlMatcherFactory.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function UrlMatcher(pattern) {
5858
// \{(?:[^{}\\]+|\\.)*\} - a matched set of curly braces containing other atoms
5959
var placeholder = /([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
6060
names = {}, compiled = '^', last = 0, m,
61-
segments = this.segments = [],
61+
segments = this.segments = [],
6262
params = this.params = [];
6363

6464
function addParameter(id) {
@@ -244,7 +244,7 @@ function $UrlMatcherFactory() {
244244
* @return {boolean}
245245
*/
246246
this.isMatcher = function (o) {
247-
return o instanceof UrlMatcher;
247+
return isObject(o) && isFunction(o.exec) && isFunction(o.format) && isFunction(o.concat);
248248
};
249249

250250
this.$get = function () {

src/urlRouter.js

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,43 +44,48 @@ function $UrlRouterProvider( $urlMatcherFactory) {
4444

4545
this.when =
4646
function (what, handler) {
47-
var rule, redirect;
48-
if (isString(what))
49-
what = $urlMatcherFactory.compile(what);
50-
51-
if ($urlMatcherFactory.isMatcher(what)) {
52-
if (isString(handler)) {
53-
redirect = $urlMatcherFactory.compile(handler);
54-
handler = ['$match', function ($match) { return redirect.format($match); }];
55-
}
56-
else if (!isFunction(handler) && !isArray(handler))
57-
throw new Error("invalid 'handler' in when()");
47+
var redirect, handlerIsString = isString(handler);
48+
if (isString(what)) what = $urlMatcherFactory.compile(what);
5849

59-
rule = function ($injector, $location) {
60-
return handleIfMatch($injector, handler, what.exec($location.path(), $location.search()));
61-
};
62-
rule.prefix = isString(what.prefix) ? what.prefix : '';
63-
}
64-
else if (what instanceof RegExp) {
65-
if (isString(handler)) {
66-
redirect = handler;
67-
handler = ['$match', function ($match) { return interpolate(redirect, $match); }];
50+
if (!handlerIsString && !isFunction(handler) && !isArray(handler))
51+
throw new Error("invalid 'handler' in when()");
52+
53+
var strategies = {
54+
matcher: function (what, handler) {
55+
if (handlerIsString) {
56+
redirect = $urlMatcherFactory.compile(handler);
57+
handler = ['$match', function ($match) { return redirect.format($match); }];
58+
}
59+
return extend(function ($injector, $location) {
60+
return handleIfMatch($injector, handler, what.exec($location.path(), $location.search()));
61+
}, {
62+
prefix: isString(what.prefix) ? what.prefix : ''
63+
});
64+
},
65+
regex: function (what, handler) {
66+
if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky");
67+
68+
if (handlerIsString) {
69+
redirect = handler;
70+
handler = ['$match', function ($match) { return interpolate(redirect, $match); }];
71+
}
72+
return extend(function ($injector, $location) {
73+
return handleIfMatch($injector, handler, what.exec($location.path()));
74+
}, {
75+
prefix: regExpPrefix(what)
76+
});
6877
}
69-
else if (!isFunction(handler) && !isArray(handler))
70-
throw new Error("invalid 'handler' in when()");
78+
};
7179

72-
if (what.global || what.sticky)
73-
throw new Error("when() RegExp must not be global or sticky");
80+
var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp };
7481

75-
rule = function ($injector, $location) {
76-
return handleIfMatch($injector, handler, what.exec($location.path()));
77-
};
78-
rule.prefix = regExpPrefix(what);
82+
for (var n in check) {
83+
if (check[n]) {
84+
return this.rule(strategies[n](what, handler));
85+
}
7986
}
80-
else
81-
throw new Error("invalid 'what' in when()");
8287

83-
return this.rule(rule);
88+
throw new Error("invalid 'what' in when()");
8489
};
8590

8691
this.$get =

test/urlRouterSpec.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ describe("UrlRouter", function () {
6161
scope.$emit("$locationChangeSuccess");
6262
expect(location.path()).toBe("/lastrule");
6363
});
64+
65+
it("should allow custom URL matchers", function () {
66+
var custom = {
67+
url: { exec: function() {}, format: function() {}, concat: function() {} },
68+
handler: function() {}
69+
};
70+
71+
spyOn(custom.url, "exec").andReturn({});
72+
spyOn(custom.url, "format").andReturn("/foo-bar");
73+
spyOn(custom, "handler").andReturn(true);
74+
75+
$urp.when(custom.url, custom.handler);
76+
scope.$broadcast("$locationChangeSuccess");
77+
scope.$apply();
78+
79+
expect(custom.url.exec).toHaveBeenCalled();
80+
expect(custom.url.format).not.toHaveBeenCalled();
81+
expect(custom.handler).toHaveBeenCalled();
82+
});
6483
});
6584

66-
});
85+
});

0 commit comments

Comments
 (0)