Skip to content

Commit 3688fe0

Browse files
committed
fix(UrlMatcher): fix configuring param type in config block
Fixes #2304
1 parent facf613 commit 3688fe0

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

src/url/urlMatcher.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export class UrlMatcher {
131131
regexp,
132132
cfg: this.config.params[id],
133133
segment: pattern.substring(last, m.index),
134-
type: paramTypes.type(regexp || "string") || inherit(paramTypes.type("string"), {
134+
type: !regexp ? null : paramTypes.type(regexp || "string") || inherit(paramTypes.type("string"), {
135135
pattern: new RegExp(regexp, this.config.caseInsensitive ? 'i' : undefined)
136136
})
137137
};

test/stateSpec.js

+31-1
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ describe('state', function () {
250250
},
251251
OPT = { url: '/opt/:param', params: { param: "100" }, template: "opt" },
252252
OPT2 = { url: '/opt2/:param2/:param3', params: { param3: "300", param4: "400" }, template: "opt2" },
253+
URLLESS = { url: '/urllessparams', params: { myparam: { type: 'int' } } },
253254
AppInjectable = {};
254255

255256
beforeEach(module(function ($stateProvider, $provide) {
@@ -274,6 +275,7 @@ describe('state', function () {
274275
.state('dynamicstate', dynamicstate)
275276
.state('OPT', OPT)
276277
.state('OPT.OPT2', OPT2)
278+
.state('URLLESS', URLLESS)
277279
.state('home', { url: "/" })
278280
.state('home.item', { url: "front/:id" })
279281
.state('about', {
@@ -1110,7 +1112,7 @@ describe('state', function () {
11101112

11111113
it("should return all of the state's config", inject(function ($state) {
11121114
var list = $state.get().sort(function(a, b) { return (a.name > b.name) - (b.name > a.name); });
1113-
var names = ['', 'A', 'B', 'C', 'D', 'DD', 'E', 'F', 'H', 'HH', 'HHH', 'OPT', 'OPT.OPT2', 'RS',
1115+
var names = ['', 'A', 'B', 'C', 'D', 'DD', 'E', 'F', 'H', 'HH', 'HHH', 'OPT', 'OPT.OPT2', 'RS', 'URLLESS',
11141116
'about', 'about.person', 'about.person.item', 'about.sidebar', 'about.sidebar.item',
11151117
'badParam', 'badParam2', 'dynamicTemplate', 'dynamicstate', 'first', 'home', 'home.item', 'home.redirect',
11161118
'json', 'logA', 'logA.logB', 'logA.logB.logC', 'resolveFail', 'resolveTimeout',
@@ -1357,6 +1359,34 @@ describe('state', function () {
13571359
extend(params, { p5: true });
13581360
check('types.substate', "/types/foo/2014-11-15/sub/10/%7B%22baz%22:%22qux%22%7D?p5=1", params, defaults, nonurl);
13591361
}));
1362+
1363+
it('should support non-url parameters', inject(function($state, $q, $stateParams) {
1364+
$state.transitionTo(A); $q.flush();
1365+
expect($state.is(A)).toBe(true);
1366+
1367+
$state.go('URLLESS', { myparam: "0" }); $q.flush(); // string "0" decodes to 0
1368+
expect($state.current.name).toBe("URLLESS");
1369+
expect($stateParams.myparam).toBe(0);
1370+
1371+
$state.go('URLLESS', { myparam: "1" }); $q.flush(); // string "1" decodes to 1
1372+
expect($stateParams.myparam).toBe(1);
1373+
}));
1374+
1375+
it('should not transition if a required non-url parameter is missing', inject(function($state, $q, $stateParams) {
1376+
$state.transitionTo(A); $q.flush();
1377+
expect($state.current.name).toBe("A");
1378+
1379+
$state.go('URLLESS'); $q.flush(); // Missing required parameter; transition fails
1380+
expect($state.current.name).toBe("A");
1381+
}));
1382+
1383+
it('should not transition if a required non-url parameter is invalid', inject(function($state, $q, $stateParams) {
1384+
$state.transitionTo(A); $q.flush();
1385+
expect($state.current.name).toBe("A");
1386+
1387+
$state.go('URLLESS', { myparam: "somestring"}); $q.flush(); // string "somestring" is not an int
1388+
expect($state.current.name).toBe("A");
1389+
}));
13601390
});
13611391

13621392
it('should revert to last known working url on state change failure', inject(function ($state, $rootScope, $location, $q) {

test/urlMatcherFactorySpec.js

+21
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,27 @@ describe("urlMatcherFactory", function () {
570570
expect(m.format({ foo: 5, flag: true })).toBe("/5/1");
571571
});
572572

573+
it("should match types named only in params", function () {
574+
var m = new UrlMatcher("/{foo}/{flag}", {
575+
params: {
576+
foo: { type: 'int'},
577+
flag: { type: 'bool'}
578+
}
579+
});
580+
expect(m.exec("/1138/1")).toEqual({ foo: 1138, flag: true });
581+
expect(m.format({ foo: 5, flag: true })).toBe("/5/1");
582+
});
583+
584+
it("should throw an error if a param type is declared twice", function () {
585+
expect(function() {
586+
new UrlMatcher("/{foo:int}", {
587+
params: {
588+
foo: { type: 'int' }
589+
}
590+
});
591+
}).toThrow(new Error("Param 'foo' has two type configurations."));
592+
});
593+
573594
it("should encode/decode dates", function () {
574595
var m = new UrlMatcher("/calendar/{date:date}"),
575596
result = m.exec("/calendar/2014-03-26");

0 commit comments

Comments
 (0)