Skip to content

Commit

Permalink
More testing for the route modules.
Browse files Browse the repository at this point in the history
These functions need small integration tests just to verify their
behaviour.
  • Loading branch information
EdJ committed Jun 12, 2013
1 parent 0fa47b6 commit 6a6732a
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 17 deletions.
35 changes: 30 additions & 5 deletions Routes/routeHandler/routeFinder.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = (function() {
var findBestMatchingRoute = function(patterns, params) {
var findBestMatchingRoute = function(routes, params) {
var paramKeys = [];
for (var key in params) {
if (params[key]) {
Expand All @@ -13,8 +13,8 @@ module.exports = (function() {

var bestMatch = '';
var currentBest = 0;
for (var i = patterns.length; i--;) {
var pattern = patterns[i];
for (var i = routes.length; i--;) {
var pattern = routes[i];
var patternItems = pattern._parameters;

if (patternItems.length > paramKeys.length) {
Expand All @@ -35,12 +35,37 @@ module.exports = (function() {
}

return bestMatch;
};
};

var getUrl = function (bestMatch, params) {
var qs = [];

for (var key in params) {
var toMatch = '{' + key + '}';
if (!bestMatch.match(toMatch)) {
qs.push(key + '=' + encodeURIComponent(params[key]));
} else {
bestMatch = bestMatch.replace(toMatch, params[key]);
}
}

var qsString = '';

if (qs.length) {
qsString = '?' + qs.join('&');
}

return bestMatch + qsString;
};

var RouteFinder = function RouteFinder() {
var RouteFinder = function RouteFinder(routes, params) {
var bestMatch = findBestMatchingRoute(routes, params);
return getUrl(bestMatch, params);
};

// Expose a couple of methods for unit testing.
RouteFinder.findBestMatchingRoute = findBestMatchingRoute;
RouteFinder.getUrl = getUrl;

return RouteFinder;
})();
2 changes: 2 additions & 0 deletions Routes/routeHandler/routeParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ module.exports = (function() {
}
}

pattern.data = pattern.data || {};

pattern.func = generateParseFunction(pattern.url);
pattern._parameters = getParameters(pattern.url);
return pattern;
Expand Down
101 changes: 89 additions & 12 deletions test/Routes/routeHandler/routeFinder.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,10 @@ describe('RouteFinder', function() {
it('should fail to find a route if all routes have an additional parameter.', function() {
var match = routeFinder.findBestMatchingRoute([{
url: '/{something}/{test}/',
_parameters: ['something','test']
},
{
_parameters: ['something', 'test']
}, {
url: '/{something}/{controller}/{action}/{test}/',
_parameters: ['something','controller','action','test']
_parameters: ['something', 'controller', 'action', 'test']
}
], {
controller: 'test',
Expand All @@ -100,18 +99,16 @@ describe('RouteFinder', function() {
match.should.equal('');
});

it('should a route if all routes except the match have an additional parameter.', function() {
it('should find a route if all routes except the match have an additional parameter.', function() {
var match = routeFinder.findBestMatchingRoute([{
url: '/{something}/{test}/',
_parameters: ['something','test']
},
{
_parameters: ['something', 'test']
}, {
url: '/{something}/{controller}/{action}/{test}/',
_parameters: ['something','controller','action','test']
},
{
_parameters: ['something', 'controller', 'action', 'test']
}, {
url: '/{controller}/{action}/{test}/',
_parameters: ['controller','action','test']
_parameters: ['controller', 'action', 'test']
}
], {
controller: 'test',
Expand All @@ -122,4 +119,84 @@ describe('RouteFinder', function() {
match.should.equal('/{controller}/{action}/{test}/');
});
});

describe('#getUrl()', function() {
it('should use the query string if the best matching route has no parameters.', function() {
var parameters = {
test: 'testValue',
test2: 'testValue2'
};

var result = routeFinder.getUrl('/', parameters);

result.should.equal('/?test=testValue&test2=testValue2');
});

it('should use the query string and the route if a partial match is found.', function() {
var parameters = {
test: 'testValue',
test2: 'testValue2'
};

var result = routeFinder.getUrl('/{test}/', parameters);

result.should.equal('/testValue/?test2=testValue2');
});

it('should not use the query string if a full match is found.', function() {
var parameters = {
test: 'testValue',
test2: 'testValue2'
};

var result = routeFinder.getUrl('/{test}/{test2}/', parameters);

result.should.equal('/testValue/testValue2/');
});

it('should retain constants in a matching route.', function() {
var parameters = {
test: 'testValue',
test2: 'testValue2'
};

var result = routeFinder.getUrl('/{test}/hello/{test2}-!/', parameters);

result.should.equal('/testValue/hello/testValue2-!/');
});

it('should retain additional parameters in a route with too many bindings.', function() {
// This case should not be used, over-matched routes should not be passed to this method.
var parameters = {
test: 'testValue',
test2: 'testValue2'
};

var result = routeFinder.getUrl('/{test}/{test2}/{test3}/', parameters);

result.should.equal('/testValue/testValue2/{test3}/');
});
});

describe('public interface', function() {
it('should parse a route to the expected URL.', function() {
var url = routeFinder([{
url: '/{something}/{test}/',
_parameters: ['something', 'test']
}, {
url: '/{something}/{controller}/{action}/{test}/',
_parameters: ['something', 'controller', 'action', 'test']
}, {
url: '/{controller}/{action}/{test}/',
_parameters: ['controller', 'action', 'test']
}
], {
controller: 'test',
action: 'test',
test: 'test1'
});

url.should.equal('/test/test/test1/');
});
});
});
36 changes: 36 additions & 0 deletions test/Routes/routeHandler/routeParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,40 @@ describe('routeHandler', function() {
});
});
});

describe('public interface', function() {
it('should parse a route that is provided as a string.', function() {
var result = routeParser('/{test}/');

result.should.have.property('func');
result.data.should.eql({});
result._parameters.should.eql(['test']);
});

it('should parse a route that is provided as an object.', function() {
var result = routeParser({
url: '/{test}/'
});

result.should.have.property('func');
result.data.should.eql({});
result._parameters.should.eql(['test']);
});

it('should return any passed data as pre-set data.', function() {
var result = routeParser({
url: '/{test}/',
data: {
testData: 'test'
}
});

result.should.have.property('func');
result.data.should.eql({
testData: 'test'
});

result._parameters.should.eql(['test']);
});
});
});

0 comments on commit 6a6732a

Please sign in to comment.