UNPKG

http-hash

Version:

HTTP router based on a strict path tree structure

495 lines (379 loc) 11.7 kB
'use strict'; var test = require('tape'); var HttpHash = require('../index.js'); test('httpHash is a function', function (assert) { assert.equal(typeof HttpHash, 'function'); assert.end(); }); test('http hash inserts root', function (assert) { // Arrange function routeHandler() {} var hash = HttpHash(); // Act hash.set('/', routeHandler); // Assert assert.strictEqual(hash._hash.handler, routeHandler); assert.end(); }); test('http hash inserts fixed route', function (assert) { // Arrange function routeHandler() {} var hash = HttpHash(); // Act hash.set('/test', routeHandler); // Assert assert.strictEqual( hash._hash.staticPaths.test.handler, routeHandler ); assert.end(); }); test('http hash inserts variable route', function (assert) { // Arrange function routeHandler() {} var hash = HttpHash(); // Act hash.set('/:test', routeHandler); // Assert assert.strictEqual( hash._hash.variablePaths.handler, routeHandler ); assert.end(); }); test('http hash retrieves root', function (assert) { // Arrange function routeHandler() {} var hash = HttpHash(); hash.set('/', routeHandler); var expectedParams = {}; // Act var result = hash.get('/'); // Assert assert.strictEqual(result.handler, routeHandler); assert.strictEqual(result.src, '/'); assert.strictEqual(result.splat, null); assert.deepEqual(result.params, expectedParams); assert.end(); }); test('http hash retrieves fixed route', function (assert) { // Arrange function routeHandler() {} var hash = HttpHash(); hash.set('/test', routeHandler); var expectedParams = {}; // Act var result = hash.get('/test'); // Assert assert.strictEqual(result.handler, routeHandler); assert.strictEqual(result.src, '/test'); assert.strictEqual(result.splat, null); assert.deepEqual(result.params, expectedParams); assert.end(); }); test('http hash retrieves variable route', function (assert) { // Arrange function routeHandler() {} var hash = HttpHash(); hash.set('/:test', routeHandler); var expectedParams = { test: 'hello' }; // Act var result = hash.get('/hello'); // Assert assert.strictEqual(result.handler, routeHandler); assert.strictEqual(result.src, '/:test'); assert.strictEqual(result.splat, null); assert.deepEqual(result.params, expectedParams); assert.end(); }); test('http hash retrieves null root', function (assert) { // Arrange var hash = HttpHash(); // Act var rootResult = hash.get('/'); var staticResult = hash.get('/a'); // Assert assert.strictEqual(rootResult.handler, null); assert.strictEqual(staticResult.handler, null); assert.end(); }); test('http hash retrieves null static', function (assert) { // Arrange function routeHandler() {} var hash = HttpHash(); hash.set('/a/b/c', routeHandler); // Act var rootResult = hash.get('/a/b/'); var staticResult = hash.get('/a/b/foo'); // Assert assert.strictEqual(staticResult.handler, null); assert.strictEqual(rootResult.handler, null); assert.end(); }); test('http hash retrieves null variable', function (assert) { // Arrange function routeHandler() {} var hash = HttpHash(); hash.set('/a/:b/c', routeHandler); // Act var rootResult = hash.get('/a/b/'); var staticResult = hash.get('/a/b/foo'); // Assert assert.strictEqual(staticResult.handler, null); assert.strictEqual(rootResult.handler, null); assert.end(); }); test('conflicting root exception', function (assert) { // Arrage function routeHandler() {} var hash = HttpHash(); hash.set('/', routeHandler); // Act var exception; try { hash.set('/', routeHandler); } catch (e) { exception = e; } // Assert assert.ok(exception); assert.strictEqual(exception.message, 'Route conflict'); assert.strictEqual(exception.attemptedPath, '/'); assert.strictEqual(exception.conflictPath, '/'); assert.end(); }); test('conflicting static route exception', function (assert) { // Arrage function routeHandler() {} var hash = HttpHash(); hash.set('/test', routeHandler); // Act var exception; try { hash.set('/test', routeHandler); } catch (e) { exception = e; } // Assert assert.ok(exception); assert.strictEqual(exception.message, 'Route conflict'); assert.strictEqual(exception.attemptedPath, '/test'); assert.strictEqual(exception.conflictPath, '/test/'); assert.end(); }); test('conflicting variable route exception', function (assert) { // Arrage function routeHandler() {} var hash = HttpHash(); hash.set('/:test', routeHandler); // Act var exception; try { hash.set('/:test', routeHandler); } catch (e) { exception = e; } // Assert assert.ok(exception); assert.strictEqual(exception.message, 'Route conflict'); assert.strictEqual(exception.message, 'Route conflict'); assert.strictEqual(exception.attemptedPath, '/:test'); assert.strictEqual(exception.conflictPath, '/:test/'); assert.end(); }); test('nesting routes', function (assert) { // Arrange var hash = HttpHash(); var firstRoutes = [ '/', '/test', '/:test' ]; var secondRoutes = [ '/', '/var', '/:var' ]; var conflicts = []; for (var i = 0; i < firstRoutes.length; i++) { for (var j = 0; j < secondRoutes.length; j++) { try { hash.set(firstRoutes[i] + secondRoutes[j], i + ',' + j); } catch (e) { conflicts.push(i + ',' + j); } } } // Act var results = {}; for (var k = 0; k < firstRoutes.length; k++) { for (var l = 0; l < secondRoutes.length; l++) { results[k + ',' + l] = hash.get(firstRoutes[k] + secondRoutes[l]); } } // Assert for (var m = 0; m < firstRoutes.length; m++) { for (var n = 0; n < secondRoutes.length; n++) { var index = m + ',' + n; if (conflicts.indexOf(index) >= 0) { continue; } assert.strictEqual(results[index].handler, index); } } // there should be 3 conflicts violation of variable name assert.strictEqual(conflicts.length, 3); assert.strictEqual(conflicts[0], '2,0'); assert.strictEqual(conflicts[1], '2,1'); assert.strictEqual(conflicts[2], '2,2'); assert.end(); }); test('deep route with splat test', function (assert) { // Arrange var hash = HttpHash(); function routeHandler() {} hash.set('/a/:varA/b/:varB/c/*', routeHandler); var expectedParams = { varA: '123456', varB: 'testing' }; var expectedSplat = 'kersplat'; // Act var result = hash.get('/a/123456///b///testing/c/kersplat'); // Assert assert.strictEqual(result.src, '/a/:varA/b/:varB/c/*'); assert.strictEqual(result.handler, routeHandler); assert.strictEqual(result.splat, expectedSplat); assert.deepEqual(result.params, expectedParams); assert.end(); }); test('splat in the middle causes splat error', function (assert) { // Arrange var hash = HttpHash(); // Act var exception; try { hash.set('/a/*/b'); } catch (e) { exception = e; } // Assert assert.ok(exception); assert.strictEqual( exception.message, 'The splat * must be the last segment of the path' ); assert.strictEqual(exception.pathname, '/a/*/b'); assert.end(); }); test('static routes work on splat nodes', function (assert) { // Arrange var hash = HttpHash(); function splatHandler() {} function staticHandler() {} hash.set('*', splatHandler); hash.set('/static', staticHandler); // Act var splatResult = hash.get('/testing'); var staticResult = hash.get('/static'); // Assert assert.strictEqual(splatResult.src, '*'); assert.strictEqual(splatResult.handler, splatHandler); assert.strictEqual(splatResult.splat, 'testing'); assert.deepEqual(splatResult.params, {}); assert.strictEqual(staticResult.src, '/static'); assert.strictEqual(staticResult.handler, staticHandler); assert.strictEqual(staticResult.splat, null); assert.deepEqual(staticResult.params, {}); assert.end(); }); test('vairable routes do not work on splat nodes', function (assert) { // Arrange var hash = HttpHash(); function splatHandler() {} hash.set('*', splatHandler); function variableHandler() {} // Act var exception; try { hash.set('/:var', variableHandler); } catch (e) { exception = e; } // Assert assert.ok(exception); assert.strictEqual(exception.message, 'Route conflict'); assert.strictEqual(exception.attemptedPath, '/:var'); assert.strictEqual(exception.conflictPath, '/*'); assert.end(); }); test('splat routes do not work on variable nodes', function (assert) { // Arrange var hash = HttpHash(); function splatHandler() {} hash.set('/:var', splatHandler); function variableHandler() {} // Act var exception; try { hash.set('*', variableHandler); } catch (e) { exception = e; } // Assert assert.ok(exception); assert.strictEqual(exception.message, 'Route conflict'); assert.strictEqual(exception.attemptedPath, '*'); assert.strictEqual(exception.conflictPath, '/:var/'); assert.end(); }); test('does not conflict with prototype', function (assert) { // Arrange var hash = HttpHash(); function validHandler() {} hash.set('/toString/valueOf', validHandler); // Act var toStringResult = hash.get('toString'); var valueOfResult = hash.get('valueOf'); var pathResult = hash.get('/toString/valueOf'); // Assert assert.strictEqual(toStringResult.handler, null); assert.strictEqual(valueOfResult.handler, null); assert.strictEqual(pathResult.handler, validHandler); assert.strictEqual(pathResult.src, '/toString/valueOf'); assert.end(); }); test('does not conflict with __proto__', function (assert) { // Arrage var hash = HttpHash(); function validHandler() {} function validSubHandler() {} hash.set('/__proto__', validHandler); hash.set('/__proto__/sub', validSubHandler); // Act var validResult = hash.get('/__proto__'); var validSubResult = hash.get('/__proto__/sub'); var invalidResult = hash.get('/__proto__/__proto__'); // Assert assert.strictEqual(validResult.handler, validHandler); assert.strictEqual(validResult.src, '/__proto__'); assert.strictEqual(validSubResult.handler, validSubHandler); assert.strictEqual(validSubResult.src, '/__proto__/sub'); assert.strictEqual(invalidResult.handler, null); assert.end(); }); test('root splat matches all', function (assert) { // Arrage var hash = HttpHash(); function validHandler() {} hash.set('*', validHandler); // Act var validEmptyResult = hash.get(''); var validRootResult = hash.get('/'); var validNestedResult = hash.get('/a/b/c'); // Assert assert.strictEqual(validEmptyResult.handler, validHandler); assert.strictEqual(validRootResult.handler, validHandler); assert.strictEqual(validNestedResult.handler, validHandler); assert.end(); });