123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /**
- * Route tests
- */
- var koa = require('koa')
- , http = require('http')
- , request = require('supertest')
- , Router = require('../../lib/router')
- , should = require('should')
- , Route = require('../../lib/route');
- describe('Route', function() {
- it('supports regular expression route paths', function(done) {
- var app = koa();
- app.use(Router(app));
- app.get(/^\/blog\/\d{4}-\d{2}-\d{2}\/?$/i, function *(next) {
- this.status = 204;
- });
- request(http.createServer(app.callback()))
- .get('/blog/2013-04-20')
- .expect(204)
- .end(function(err) {
- if (err) return done(err);
- done();
- });
- });
- it('supports named regular express routes', function(done) {
- var app = koa();
- app.use(Router(app));
- app.get('test', /^\/test\/?/i, function *(next) {
- this.status = 204;
- yield next;
- });
- request(http.createServer(app.callback()))
- .get('/test')
- .expect(204)
- .end(function(err) {
- if (err) return done(err);
- done();
- });
- });
- it('composes multiple callbacks/middlware', function(done) {
- var app = koa();
- app.use(Router(app));
- app.get(
- '/:category/:title',
- function *(next) {
- this.status = 500;
- yield next;
- },
- function *(next) {
- this.status = 204;
- yield next;
- }
- );
- request(http.createServer(app.callback()))
- .get('/programming/how-to-node')
- .expect(204)
- .end(function(err) {
- if (err) return done(err);
- done();
- });
- });
- describe('Route#match()', function() {
- it('captures URL path parameters', function(done) {
- var app = koa();
- app.use(Router(app));
- app.get('/:category/:title', function *(next) {
- this.should.have.property('params');
- this.params.should.be.type('object');
- this.params.should.have.property('category', 'match');
- this.params.should.have.property('title', 'this');
- this.status = 204;
- done();
- });
- request(http.createServer(app.callback()))
- .get('/match/this')
- .expect(204)
- .end(function(err) {
- if (err) return done(err);
- });
- });
- it('return orginal path parameters when decodeURIComponent throw error', function(done) {
- var app = koa();
- app.use(Router(app));
- app.get('/:category/:title', function *(next) {
- this.should.have.property('params');
- this.params.should.be.type('object');
- this.params.should.have.property('category', '100%');
- this.params.should.have.property('title', '101%');
- this.status = 204;
- });
- request(http.createServer(app.callback()))
- .get('/100%/101%')
- .expect(204)
- .end(done);
- });
- it('populates ctx.params with regexp captures', function(done) {
- var app = koa();
- app.use(Router(app));
- app.get(/^\/api\/([^\/]+)\/?/i, function *(next) {
- this.should.have.property('params');
- this.params.should.be.type('object');
- this.params.should.have.property(0, '1');
- yield next;
- }, function *(next) {
- this.should.have.property('params');
- this.params.should.be.type('object');
- this.params.should.have.property(0, '1');
- this.status = 204;
- });
- request(http.createServer(app.callback()))
- .get('/api/1')
- .expect(204)
- .end(function(err) {
- if (err) return done(err);
- done();
- });
- });
- it('return orginal ctx.params when decodeURIComponent throw error', function(done) {
- var app = koa();
- app.use(Router(app));
- app.get(/^\/api\/([^\/]+)\/?/i, function *(next) {
- this.should.have.property('params');
- this.params.should.be.type('object');
- this.params.should.have.property(0, '101%');
- yield next;
- }, function *(next) {
- this.should.have.property('params');
- this.params.should.be.type('object');
- this.params.should.have.property(0, '101%');
- this.status = 204;
- });
- request(http.createServer(app.callback()))
- .get('/api/101%')
- .expect(204)
- .end(function(err) {
- if (err) return done(err);
- done();
- });
- });
- it('populates ctx.params with regexp captures include undefiend', function(done) {
- var app = koa();
- app.use(Router(app));
- app.get(/^\/api(\/.+)?/i, function *(next) {
- this.should.have.property('params');
- this.params.should.be.type('object');
- this.params.should.have.property(0, undefined);
- yield next;
- }, function *(next) {
- this.should.have.property('params');
- this.params.should.be.type('object');
- this.params.should.have.property(0, undefined);
- this.status = 204;
- });
- request(http.createServer(app.callback()))
- .get('/api')
- .expect(204)
- .end(function(err) {
- if (err) return done(err);
- done();
- });
- });
- it('should throw friendly error message when handle not exists', function() {
- var app = koa();
- app.use(Router(app));
- var notexistHandle = undefined;
- (function () {
- app.get('/foo', notexistHandle);
- }).should.throw('get `/foo`: `middleware` must be a function, not `undefined`');
- (function () {
- app.get('foo router', '/foo', notexistHandle);
- }).should.throw('get `foo router`: `middleware` must be a function, not `undefined`');
- (function () {
- app.post('/foo', function() {}, notexistHandle);
- }).should.throw('post `/foo`: `middleware` must be a function, not `undefined`');
- });
- });
- describe('Route#param()', function() {
- it('composes middleware for param fn', function(done) {
- var app = koa();
- var router = new Router();
- var route = new Route('/users/:user', ['GET'], [function *(next) {
- this.body = this.user;
- }]);
- route.param('user', function *(id, next) {
- this.user = { name: 'alex' };
- if (!id) return this.status = 404;
- yield next;
- });
- router.routes.push(route);
- app.use(router.middleware());
- request(http.createServer(app.callback()))
- .get('/users/3')
- .expect(200)
- .end(function(err, res) {
- if (err) return done(err);
- res.should.have.property('body');
- res.body.should.have.property('name', 'alex');
- done();
- });
- });
- it('ignores params which are not matched', function(done) {
- var app = koa();
- var router = new Router();
- var route = new Route('/users/:user', ['GET'], [function *(next) {
- this.body = this.user;
- }]);
- route.param('user', function *(id, next) {
- this.user = { name: 'alex' };
- if (!id) return this.status = 404;
- yield next;
- });
- route.param('title', function *(id, next) {
- this.user = { name: 'mark' };
- if (!id) return this.status = 404;
- yield next;
- });
- router.routes.push(route);
- app.use(router.middleware());
- request(http.createServer(app.callback()))
- .get('/users/3')
- .expect(200)
- .end(function(err, res) {
- if (err) return done(err);
- res.should.have.property('body');
- res.body.should.have.property('name', 'alex');
- done();
- });
- });
- });
- describe('Route#url()', function() {
- it('generates route URL', function() {
- var route = new Route('/:category/:title', ['get'], [function* () {}], 'books');
- var url = route.url({ category: 'programming', title: 'how-to-node' });
- url.should.equal('/programming/how-to-node');
- url = route.url('programming', 'how-to-node');
- url.should.equal('/programming/how-to-node');
- });
- it('escapes using encodeURIComponent()', function() {
- var route = new Route('/:category/:title', ['get'], [function *() {}], 'books');
- var url = route.url({ category: 'programming', title: 'how to node' });
- url.should.equal('/programming/how%20to%20node');
- });
- });
- });
|