diff --git a/lib/route-recognizer.js b/lib/route-recognizer.js index 6a8bcaa..f62f279 100644 --- a/lib/route-recognizer.js +++ b/lib/route-recognizer.js @@ -12,6 +12,19 @@ function isArray(test) { return Object.prototype.toString.call(test) === "[object Array]"; } +function getParam(params, key) { + if (typeof params !== "object" || params === null) { + throw new Error("You must pass an object as the second argument to `generate`."); + } + if (!params.hasOwnProperty(key)) { + throw new Error("You must provide param `" + key + "` to `generate`."); + } + if (params[key].length === 0) { + throw new Error("You must provide a param `" + key + "`."); + } + + return params[key]; +} // A Segment represents a segment in the original route description. // Each Segment type provides an `eachChar` and `regex` method. @@ -63,10 +76,7 @@ DynamicSegment.prototype = { }, generate: function(params) { - var value = params[this.name]; - if (value.length === 0) { - throw new Error("You must provide a param `" + this.name + "`."); - } + var value = getParam(params, this.name); if (RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS) { return encodePathSegment(value); @@ -87,12 +97,7 @@ StarSegment.prototype = { }, generate: function(params) { - var value = params[this.name]; - if (value.length === 0) { - throw new Error("You must provide a param `" + this.name + "`."); - } - - return value; + return getParam(params, this.name); } }; diff --git a/tests/recognizer-tests.js b/tests/recognizer-tests.js index dd7ddfb..d18ad8e 100644 --- a/tests/recognizer-tests.js +++ b/tests/recognizer-tests.js @@ -922,6 +922,68 @@ test("Throws when generating dynamic routes with an empty string", function() { }, /You must provide a param `secret`./); }); +test("Fails reasonably when bad params passed to dynamic segment", function() { + var router = new RouteRecognizer(); + router.add([{"path":"/posts","handler":"posts"},{"path":"/:secret/edit","handler":"edit"}], { as: "edit" }) + router.add([{ "path": "/posts", "handler": "posts" }, { "path": "/*secret/create", "handler": "create" }], { as: "create" }) + + QUnit.throws(function() { + router.generate("edit"); + }, /You must pass an object as the second argument to `generate`./, "No argument passed."); + + QUnit.throws(function() { + router.generate("edit", false); + }, /You must pass an object as the second argument to `generate`./, "Boolean passed."); + + QUnit.throws(function() { + router.generate("edit", null); + }, /You must pass an object as the second argument to `generate`./, "`null` passed."); + + QUnit.throws(function() { + router.generate("edit", "123"); + }, /You must pass an object as the second argument to `generate`./, "String passed."); + + QUnit.throws(function() { + router.generate("edit", new String("foo")); + }, /You must provide param `secret` to `generate`./, "`new String()` passed."); + + QUnit.throws(function() { + router.generate("edit", []); + }, /You must provide param `secret` to `generate`./, "Array passed."); + + QUnit.throws(function() { + router.generate("edit", {}); + }, /You must provide param `secret` to `generate`./, "Object without own property passed."); + + QUnit.throws(function() { + router.generate("create"); + }, /You must pass an object as the second argument to `generate`./, "No argument passed."); + + QUnit.throws(function() { + router.generate("create", false); + }, /You must pass an object as the second argument to `generate`./, "Boolean passed."); + + QUnit.throws(function() { + router.generate("create", null); + }, /You must pass an object as the second argument to `generate`./, "`null` passed."); + + QUnit.throws(function() { + router.generate("create", "123"); + }, /You must pass an object as the second argument to `generate`./, "String passed."); + + QUnit.throws(function() { + router.generate("create", new String("foo")); + }, /You must provide param `secret` to `generate`./, "`new String()` passed."); + + QUnit.throws(function() { + router.generate("create", []); + }, /You must provide param `secret` to `generate`./, "Array passed."); + + QUnit.throws(function() { + router.generate("create", {}); + }, /You must provide param `secret` to `generate`./, "Object without own property passed."); +}); + test("Parsing and generation results into the same input string", function() { var query = "filter%20data=date"; equal(router.generateQueryString(router.parseQueryString(query)), '?' + query);