Skip to content

Commit

Permalink
Support symbols as route names (#143)
Browse files Browse the repository at this point in the history
* Test symbols as route names and related error handling

* Better support for symbols as route names, and add error handling for router.redirect
  • Loading branch information
noinkling committed Jul 4, 2022
1 parent 6ba3efa commit 13a634d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 12 deletions.
15 changes: 12 additions & 3 deletions lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,10 +540,19 @@ Router.prototype.all = function (name, path, middleware) {

Router.prototype.redirect = function (source, destination, code) {
// lookup source route by name
if (source[0] !== '/') source = this.url(source);
if (typeof source === 'symbol' || source[0] !== '/') {
source = this.url(source);
if (source instanceof Error) throw source;
}

// lookup destination route by name
if (destination[0] !== '/' && !destination.includes('://')) destination = this.url(destination);
if (
typeof destination === 'symbol' ||
destination[0] !== '/' && !destination.includes('://')
) {
destination = this.url(destination);
if (destination instanceof Error) throw destination;
}

return this.all(source, ctx => {
ctx.redirect(destination);
Expand Down Expand Up @@ -662,7 +671,7 @@ Router.prototype.url = function (name, params) {
return route.url.apply(route, args);
}

return new Error(`No route found for name: ${name}`);
return new Error(`No route found for name: ${String(name)}`);
};

/**
Expand Down
63 changes: 54 additions & 9 deletions test/lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,33 @@ describe('Router', function () {
});
});

it('redirects using symbols as route names', function (done) {
const app = new Koa();
const router = new Router();
app.use(router.routes());
const homeSymbol = Symbol('home');
const signUpFormSymbol = Symbol('sign-up-form');
router.get(homeSymbol, '/', function () { });
router.get(signUpFormSymbol, '/sign-up-form', function () { });
router.redirect(homeSymbol, signUpFormSymbol);
request(http.createServer(app.callback()))
.post('/')
.expect(301)
.end(function (err, res) {
if (err) return done(err);
res.header.should.have.property('location', '/sign-up-form');
done();
});
});

it('throws an error if no route is found for name', function () {
const router = new Router();
expect(() => router.redirect('missing', '/destination')).to.throwError();
expect(() => router.redirect('/source', 'missing')).to.throwError();
expect(() => router.redirect(Symbol('missing'), '/destination')).to.throwError();
expect(() => router.redirect('/source', Symbol('missing'))).to.throwError();
});

it('redirects to external sites', function (done) {
const app = new Koa();
const router = new Router();
Expand Down Expand Up @@ -1371,10 +1398,26 @@ describe('Router', function () {
expect(router.route('child')).to.have.property('name', 'child');
});

it('should return false if no name matches', function () {
const value = Router().route('Picard')
value.should.be.false()
})
it('supports symbols as names', function () {
const childSymbol = Symbol('child');
const subrouter = Router().get(childSymbol, '/hello', function (ctx) {
ctx.body = { hello: 'world' };
});
const router = Router().use(subrouter.routes());
expect(router.route(childSymbol)).to.have.property('name', childSymbol);
});

it('returns false if no name matches', function () {
const router = new Router();
router.get('books', '/books', function (ctx) {
ctx.status = 204;
});
router.get(Symbol('Picard'), '/enterprise', function (ctx) {
ctx.status = 204;
});
router.route('Picard').should.be.false();
router.route(Symbol('books')).should.be.false();
});
});

describe('Router#url()', function () {
Expand Down Expand Up @@ -1510,17 +1553,19 @@ describe('Router', function () {
done();
})

it("should test Error flow if no route is found for name", function () {
it('returns an Error if no route is found for name', function () {
const app = new Koa();
const router = new Router();
app.use(router.routes());
router.get("books", "/:category/:title", function (ctx) {
router.get('books', '/books', function (ctx) {
ctx.status = 204;
});
router.get(Symbol('Picard'), '/enterprise', function (ctx) {
ctx.status = 204;
});

router
.url("Picard", "Enterprise")
.should.Error();
router.url('Picard').should.be.Error();
router.url(Symbol('books')).should.be.Error();
});
});

Expand Down

0 comments on commit 13a634d

Please sign in to comment.