Skip to content

Commit

Permalink
Fix server.table() and coverage. Closes #1520
Browse files Browse the repository at this point in the history
  • Loading branch information
Eran Hammer committed Mar 24, 2014
1 parent c970341 commit bc2f96a
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 26 deletions.
8 changes: 5 additions & 3 deletions docs/Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
- [Route prerequisites](#route-prerequisites)
- [Route not found](#route-not-found)
- [`server.route(routes)`](#serverrouteroutes)
- [`server.table()`](#servertable)
- [`server.table([host])`](#servertablehost)
- [`server.log(tags, [data, [timestamp]])`](#serverlogtags-data-timestamp)
- [`server.state(name, [options])`](#serverstatename-options)
- [`server.views(options)`](#serverviewsoptions)
Expand Down Expand Up @@ -810,10 +810,12 @@ server.route([
]);
```

#### `server.table()`
#### `server.table([host])`

Returns a copy of the routing table. The return value is an array of routes where each route contains:
Returns a copy of the routing table where:
- `host` - optional host to filter routes matching a specific virtual host. Defaults to all virtual hosts.

The return value is an array of routes where each route contains:
- `settings` - the route config with defaults applied.
- `method` - the HTTP method in lower case.
- `path` - the route path.
Expand Down
8 changes: 7 additions & 1 deletion lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,13 @@ internals.Router.prototype.table = function (host) {
});
};

collect(host && this.vhosts && this.vhosts[host]);
if (this.vhosts) {
var vhosts = (host && [].concat(host)) || Object.keys(this.vhosts);
for (var i = 0, il = vhosts.length; i < il; ++i) {
collect(this.vhosts[vhosts[i]]);
}
}

collect(this.routes);

return result;
Expand Down
2 changes: 1 addition & 1 deletion lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ internals.routeConfigSchema = {
errorFields: Joi.object()
}),
response: Joi.object({
schema: Joi.alternatives(Joi.object(), Joi.func()).allow(null),
schema: Joi.alternatives(Joi.object(), Joi.func()).required(),
sample: Joi.number().min(0).max(100),
failAction: Joi.string().valid('error', 'log')
}).allow(true, false),
Expand Down
10 changes: 5 additions & 5 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ exports = module.exports = internals.Server = function (/* host, port, options *

this.settings.cors = Utils.applyToDefaults(Defaults.cors, this.settings.cors);
if (this.settings.cors) {
this.settings.cors._headers = (this.settings.cors.headers || []).concat(this.settings.cors.additionalHeaders || []).join(', ');
this.settings.cors._methods = (this.settings.cors.methods || []).concat(this.settings.cors.additionalMethods || []).join(', ');
this.settings.cors._exposedHeaders = (this.settings.cors.exposedHeaders || []).concat(this.settings.cors.additionalExposedHeaders || []).join(', ');
this.settings.cors._headers = this.settings.cors.headers.concat(this.settings.cors.additionalHeaders).join(', ');
this.settings.cors._methods = this.settings.cors.methods.concat(this.settings.cors.additionalMethods).join(', ');
this.settings.cors._exposedHeaders = this.settings.cors.exposedHeaders.concat(this.settings.cors.additionalExposedHeaders).join(', ');

if (this.settings.cors.origin && this.settings.cors.origin.length) {
this.settings.cors._origin = {
Expand Down Expand Up @@ -256,9 +256,9 @@ internals.Server.prototype._dispatch = function (options) {
};


internals.Server.prototype.table = function () {
internals.Server.prototype.table = function (host) {

return this._router.table();
return this._router.table(host);
};


Expand Down
2 changes: 1 addition & 1 deletion lib/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ exports.response = function (request, next) {
return next(Boom.badImplementation(err.message));
};

var schema = request.route.response.schema || {};
var schema = request.route.response.schema;
if (typeof schema === 'function') {
return schema(request.response.source, request.server.settings.validation, postValidate);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/views.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ internals.path = function (base, path, file) {
if (path &&
path[0] === '/') {

return Path.join(path || '', file || '');
return Path.join(path, file || '');
}

return Path.join(base || '', path || '', file || '');
Expand Down
22 changes: 21 additions & 1 deletion test/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('Router', function () {
var server = new Hapi.Server();
server.route({ method: 'GET', path: '/head', handler: function (request, reply) { reply('ok-common'); } });
server.route({ method: 'GET', path: '/head', vhost: 'special.example.com', handler: function (request, reply) { reply('ok-vhost'); } });
server.route({ method: 'GET', path: '/get', vhost: 'special.example.com', handler: function (request, reply) { reply('just-get'); } });
server.route({ method: 'HEAD', path: '/head', handler: function (request, reply) { reply('ok').header('x1', '123'); } });
server.route({ method: 'HEAD', path: '/head', vhost: 'special.example.com', handler: function (request, reply) { reply('ok').header('x1', '456'); } });

Expand All @@ -45,7 +46,12 @@ describe('Router', function () {

expect(res.result).to.equal('ok-common');
expect(res.headers.x1).to.not.exist;
done();

server.inject({ method: 'HEAD', url: 'http://special.example.com/get' }, function (res) {

expect(res.result).to.equal('just-get');
done();
});
});
});
});
Expand Down Expand Up @@ -179,6 +185,20 @@ describe('Router', function () {
});
});

it('matches wildcard vhost method', function (done) {

var server = new Hapi.Server();

server.route({ method: '*', path: '/', handler: function (request, reply) { reply('global'); } });
server.route({ method: '*', vhost: 'special.example.com', path: '/', handler: function (request, reply) { reply('vhost'); } });
server.inject('http://special.example.com/', function (res) {

expect(res.statusCode).to.equal(200);
expect(res.payload).to.equal('vhost');
done();
});
});

it('allows methods array', function (done) {

var server = new Hapi.Server();
Expand Down
10 changes: 10 additions & 0 deletions test/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,14 @@ describe('Schema', function () {
done();
});
});

describe('#view', function () {

it('fails on invalid config', function (done) {

var config = {};
expect(Schema.view(config)).to.exist;
done();
});
});
});
60 changes: 60 additions & 0 deletions test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,66 @@ describe('Server', function () {
expect(routes[0].path).to.equal('/test/');
done();
});

it('combines global and vhost routes', function (done) {

var server = new Hapi.Server();

server.route({ path: '/test/', method: 'get', handler: function () { } });
server.route({ path: '/test/', vhost: 'one.example.com', method: 'get', handler: function () { } });
server.route({ path: '/test/', vhost: 'two.example.com', method: 'get', handler: function () { } });
server.route({ path: '/test/{p}/end', method: 'get', handler: function () { } });

var routes = server.table();

expect(routes.length).to.equal(4);
done();
});

it('combines global and vhost routes and filters based on host', function (done) {

var server = new Hapi.Server();

server.route({ path: '/test/', method: 'get', handler: function () { } });
server.route({ path: '/test/', vhost: 'one.example.com', method: 'get', handler: function () { } });
server.route({ path: '/test/', vhost: 'two.example.com', method: 'get', handler: function () { } });
server.route({ path: '/test/{p}/end', method: 'get', handler: function () { } });

var routes = server.table('one.example.com');

expect(routes.length).to.equal(3);
done();
});

it('accepts a list of hosts', function (done) {

var server = new Hapi.Server();

server.route({ path: '/test/', method: 'get', handler: function () { } });
server.route({ path: '/test/', vhost: 'one.example.com', method: 'get', handler: function () { } });
server.route({ path: '/test/', vhost: 'two.example.com', method: 'get', handler: function () { } });
server.route({ path: '/test/{p}/end', method: 'get', handler: function () { } });

var routes = server.table(['one.example.com', 'two.example.com']);

expect(routes.length).to.equal(4);
done();
});

it('ignores unknown host', function (done) {

var server = new Hapi.Server();

server.route({ path: '/test/', method: 'get', handler: function () { } });
server.route({ path: '/test/', vhost: 'one.example.com', method: 'get', handler: function () { } });
server.route({ path: '/test/', vhost: 'two.example.com', method: 'get', handler: function () { } });
server.route({ path: '/test/{p}/end', method: 'get', handler: function () { } });

var routes = server.table('three.example.com');

expect(routes.length).to.equal(2);
done();
});
});

describe('#log', function () {
Expand Down
72 changes: 59 additions & 13 deletions test/views.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('Views', function () {
});
});

it('should work and not throw with valid (no layouts)', function (done) {
it('allows valid (no layouts)', function (done) {

var testView = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand All @@ -95,7 +95,38 @@ describe('Views', function () {
});
});

it('should work and not throw with valid (with layouts)', function (done) {
it('renders without context', function (done) {

var testView = new Views.Manager({
engines: { 'html': 'handlebars' },
path: __dirname + '/templates'
});

testView.render('valid/test', null, null, function (err, rendered, config) {

expect(rendered).to.exist;
expect(rendered).to.equal('<div>\n <h1></h1>\n</div>\n');
done();
});
});

it('allows relative path with no base', function (done) {

var testView = new Views.Manager({
engines: { 'html': 'handlebars' },
path: './test/templates',
layout: false
});

testView.render('valid/test', { title: 'test', message: 'Hapi' }, null, function (err, rendered, config) {

expect(rendered).to.exist;
expect(rendered).to.equal('<div>\n <h1>Hapi</h1>\n</div>\n');
done();
});
});

it('allows valid (with layouts)', function (done) {

var testViewWithLayouts = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand Down Expand Up @@ -160,7 +191,7 @@ describe('Views', function () {
});
});

it('should work and not throw with valid jade layouts', function (done) {
it('allows valid jade layouts', function (done) {

var testViewWithJadeLayouts = new Views.Manager({
engines: { 'jade': 'jade' },
Expand Down Expand Up @@ -190,7 +221,7 @@ describe('Views', function () {
});
});

it('should work and not throw with basePath, template name, and no path', function (done) {
it('allows basePath, template name, and no path', function (done) {

var views = new Views.Manager({ engines: { 'html': 'handlebars' } });
views.render('test', { title: 'test', message: 'Hapi' }, { basePath: __dirname + '/templates/valid' }, function (err, rendered, config) {
Expand All @@ -201,7 +232,7 @@ describe('Views', function () {
});
});

it('should return error when referencing non existant partial (with layouts)', function (done) {
it('errors when referencing non existant partial (with layouts)', function (done) {

var testViewWithLayouts = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand All @@ -216,7 +247,7 @@ describe('Views', function () {
});
});

it('should return error when referencing non existant partial (no layouts)', function (done) {
it('errors when referencing non existant partial (no layouts)', function (done) {

var testView = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand All @@ -232,7 +263,7 @@ describe('Views', function () {

});

it('should return error if context uses layoutKeyword as a key', function (done) {
it('errors if context uses layoutKeyword as a key', function (done) {

var testViewWithLayouts = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand All @@ -248,7 +279,7 @@ describe('Views', function () {
});
});

it('should return error on compile error (invalid template code)', function (done) {
it('errors on compile error (invalid template code)', function (done) {

var testView = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand All @@ -263,7 +294,7 @@ describe('Views', function () {
});
});

it('should load partials and be able to render them', function (done) {
it('loads partials and be able to render them', function (done) {

var tempView = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand All @@ -278,7 +309,22 @@ describe('Views', function () {
});
});

it('should load partials and render them EVEN if viewsPath has trailing slash', function (done) {
it('loads partials from relative path without base', function (done) {

var tempView = new Views.Manager({
engines: { 'html': 'handlebars' },
path: __dirname + '/templates/valid',
partialsPath: './test/templates/valid/partials'
});

tempView.render('testPartials', {}, null, function (err, rendered, config) {

expect(rendered).to.equal(' Nav:<nav>Nav</nav>|<nav>Nested</nav>');
done();
});
});

it('loads partials and render them EVEN if viewsPath has trailing slash', function (done) {

var tempView = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand All @@ -294,7 +340,7 @@ describe('Views', function () {
});
});

it('should skip loading partials and helpers if engine does not support them', function (done) {
it('skips loading partials and helpers if engine does not support them', function (done) {

var tempView = new Views.Manager({
path: __dirname + '/templates/valid',
Expand All @@ -310,7 +356,7 @@ describe('Views', function () {
});
});

it('should load helpers and render them', function (done) {
it('loads helpers and render them', function (done) {

var tempView = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand All @@ -325,7 +371,7 @@ describe('Views', function () {
});
});

it('should load helpers and render them when helpersPath ends with a slash', function (done) {
it('loads helpers and render them when helpersPath ends with a slash', function (done) {

var tempView = new Views.Manager({
engines: { 'html': 'handlebars' },
Expand Down

0 comments on commit bc2f96a

Please sign in to comment.