From e529363355aa69f4bcc397fd3292ad27f558cbbb Mon Sep 17 00:00:00 2001 From: Simon Flack Date: Sat, 15 Apr 2017 14:04:51 +0200 Subject: [PATCH 1/2] Add `.asRegExp()` method to return regexp for route --- README.md | 1 + lib/route.js | 11 +++++++++++ test/test.js | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/README.md b/README.md index ee8d214..d7d1193 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Route = require('route-parser'); var route = new Route('/my/fancy/route/page/:page'); route.match('/my/fancy/route/page/7') // { page: 7 } route.reverse({page: 3}) // -> '/my/fancy/route/page/3' +route.asRegExp() // new RegExp(/^\/my\/fancy\/route\/page\/([^/\?]+))?(?=\?|$)/) ``` ## What can I use in my routes? diff --git a/lib/route.js b/lib/route.js index 6acdb77..cfd8263 100644 --- a/lib/route.js +++ b/lib/route.js @@ -68,5 +68,16 @@ Route.prototype.reverse = function (params) { return ReverseVisitor.visit(this.ast, params); }; +/** + * Returns a regular expression for matching the route + * @example + * var route = new Route('/route/:one/(:two)') + * route.asRegExp() // -> /\/route\/([^\\/\\?]+)\/(?:([^\\/\\?]+))?/ + * @return {RegExp} The route expressed as a regular expression + */ +Route.prototype.asRegExp = function () { + var matcher = RegexpVisitor.visit(this.ast); + return matcher.re; +}; module.exports = Route; diff --git a/test/test.js b/test/test.js index 446787e..741801d 100644 --- a/test/test.js +++ b/test/test.js @@ -171,4 +171,55 @@ describe('Route', function () { ); }); }); + + describe('asRegExp', function () { + it('returns regexp for route without params', function () { + var route = RouteParser('/foo'); + var expected = /^\/foo(?=\?|$)/; + var actual = route.asRegExp(); + assert.typeOf(actual, 'regexp'); + assert.equal(actual.toString(), expected); + }); + + it('returns regexp for route with simple params', function () { + var route = RouteParser('/:foo/:bar'); + // eslint-disable-next-line no-useless-escape + var expected = /^\/([^/\?]+)\/([^/\?]+)(?=\?|$)/; + var actual = route.asRegExp(); + assert.typeOf(actual, 'regexp'); + if (!global.window) { + assert.equal(actual.toString(), expected); + } + }); + + it('returns regexp for route with optional params', function () { + var route = RouteParser('/things/(option/:first)'); + // eslint-disable-next-line no-useless-escape + var expected = /^\/things\/(?:option\/([^/\?]+))?(?=\?|$)/; + var actual = route.asRegExp(); + assert.typeOf(actual, 'regexp'); + if (!global.window) { + assert.equal(actual.toString(), expected); + } + }); + + it('returns regexp for route with nested optional params', function () { + var route = RouteParser('/things/(option/:first(/second/:second))'); + // eslint-disable-next-line no-useless-escape + var expected = /^\/things\/(?:option\/([^/\?]+)(?:\/second\/([^/\?]+))?)?(?=\?|$)/; + var actual = route.asRegExp(); + assert.typeOf(actual, 'regexp'); + if (!global.window) { + assert.equal(actual.toString(), expected); + } + }); + + it('returns regexp for route with splat', function () { + var route = RouteParser('/*a/foo/*b'); + var expected = /^\/([^?]*?)\/foo\/([^?]*?)(?=\?|$)/; + var actual = route.asRegExp(); + assert.typeOf(actual, 'regexp'); + assert.equal(actual.toString(), expected); + }); + }); }); From ef55cc5b1241c65dead31461038d17e8958b3ed9 Mon Sep 17 00:00:00 2001 From: Simon Flack Date: Sat, 15 Apr 2017 14:40:18 +0200 Subject: [PATCH 2/2] Test the regexp result, rather than assert its value --- test/test.js | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/test/test.js b/test/test.js index 741801d..e1de066 100644 --- a/test/test.js +++ b/test/test.js @@ -175,51 +175,43 @@ describe('Route', function () { describe('asRegExp', function () { it('returns regexp for route without params', function () { var route = RouteParser('/foo'); - var expected = /^\/foo(?=\?|$)/; - var actual = route.asRegExp(); - assert.typeOf(actual, 'regexp'); - assert.equal(actual.toString(), expected); + var regexp = route.asRegExp(); + assert.typeOf(regexp, 'regexp'); + assert.match('/foo', regexp); + assert.match('/foo?', regexp); + assert.notMatch('/foo/', regexp); }); it('returns regexp for route with simple params', function () { var route = RouteParser('/:foo/:bar'); - // eslint-disable-next-line no-useless-escape - var expected = /^\/([^/\?]+)\/([^/\?]+)(?=\?|$)/; - var actual = route.asRegExp(); - assert.typeOf(actual, 'regexp'); - if (!global.window) { - assert.equal(actual.toString(), expected); - } + var regexp = route.asRegExp(); + assert.typeOf(regexp, 'regexp'); + assert.match('/red/green', regexp); }); it('returns regexp for route with optional params', function () { var route = RouteParser('/things/(option/:first)'); - // eslint-disable-next-line no-useless-escape - var expected = /^\/things\/(?:option\/([^/\?]+))?(?=\?|$)/; - var actual = route.asRegExp(); - assert.typeOf(actual, 'regexp'); - if (!global.window) { - assert.equal(actual.toString(), expected); - } + var regexp = route.asRegExp(); + assert.typeOf(regexp, 'regexp'); + assert.match('/things/', regexp); + assert.notMatch('/things/option/', regexp); + assert.match('/things/option/blue', regexp); }); it('returns regexp for route with nested optional params', function () { var route = RouteParser('/things/(option/:first(/second/:second))'); - // eslint-disable-next-line no-useless-escape - var expected = /^\/things\/(?:option\/([^/\?]+)(?:\/second\/([^/\?]+))?)?(?=\?|$)/; - var actual = route.asRegExp(); - assert.typeOf(actual, 'regexp'); - if (!global.window) { - assert.equal(actual.toString(), expected); - } + var regexp = route.asRegExp(); + assert.typeOf(regexp, 'regexp'); + assert.match('/things/', regexp); + assert.match('/things/option/blue', regexp); + assert.match('/things/option/blue/second/red', regexp); }); it('returns regexp for route with splat', function () { var route = RouteParser('/*a/foo/*b'); - var expected = /^\/([^?]*?)\/foo\/([^?]*?)(?=\?|$)/; - var actual = route.asRegExp(); - assert.typeOf(actual, 'regexp'); - assert.equal(actual.toString(), expected); + var regexp = route.asRegExp(); + assert.typeOf(regexp, 'regexp'); + assert.match('/zoo/woo/foo/bar/baz', regexp); }); }); });