Browse files

started 3x support

  • Loading branch information...
1 parent 8929790 commit 862e1b9e2e82ae491eec2d319f83836216a18e61 @tj tj committed Jul 20, 2012
View
5 Makefile
@@ -1,6 +1,7 @@
test:
- @./node_modules/expresso/bin/expresso \
- -I support
+ @./node_modules/.bin/mocha \
+ --require should \
+ --reporter spec
.PHONY: test
View
55 examples/content-negotiation.js
@@ -1,54 +1,13 @@
-require.paths.unshift(__dirname + '/../support');
-
-/**
- * Module dependencies.
- */
-
var express = require('express')
- , resource = require('../')
- , app = express.createServer();
-
-var db = ['tobi', 'loki', 'jane']
- , toys = ['ball', 'tunnel'];
-
-var pet = {
- index: {
- json: function(req, res){
- res.send(db);
- },
-
- default: function(req, res){
- res.send(db.join(', '), { 'Content-Type': 'text/plain' });
- }
- }
-};
-
-var pets = app.resource('pets', pet);
-
-pets.load(function(id, fn){
- fn(null, db[id]);
-});
-
-// GET /pets/toys.xml
-// this action must be defined above
-// the one below as the :pet placeholder
-// will otherwise match "/toys".
-
-pets.get('/toys', {
- xml: function(req, res){
- res.send('<toys>' + toys.map(function(toy){
- return '<toy>' + toy + '</toy>';
- }).join('\n') + '</toys>');
- }
-});
+ , resource = require('..')
+ , app = express();
-// GET /pets/1.xml
+var users = app.resource('users', require('./controllers/user'));
-pets.get({
- xml: function(req, res){
- res.send('<pet>' + req.pet + '</pet>');
- }
+app.get('/', function(req, res){
+ res.send('<a href="/users">View users</a>');
});
-app.listen(3000);
+app.listen(3000);
+console.log('Listening on :3000');
View
14 examples/nesting.js → examples/controllers.js
@@ -1,16 +1,12 @@
-require.paths.unshift(__dirname + '/../support');
-
-/**
- * Module dependencies.
- */
-
var express = require('express')
- , resource = require('../')
- , app = express.createServer();
+ , resource = require('..')
+ , app = express();
+var main = app.resource(require('./controllers/main'));
var forums = app.resource('forums', require('./controllers/forum'));
var threads = app.resource('threads', require('./controllers/thread'));
forums.add(threads);
-app.listen(3000);
+app.listen(3000);
+console.log('Listening on :3000');
View
4 examples/controllers/main.js
@@ -0,0 +1,4 @@
+
+exports.index = function(req, res){
+ res.send('main index');
+}
View
67 examples/controllers/user.js
@@ -0,0 +1,67 @@
+
+var users = [];
+
+users.push({ name: 'tobi' });
+users.push({ name: 'loki' });
+users.push({ name: 'jane' });
+
+/**
+ * GET index.
+ */
+
+exports.index = {
+ html: function(req, res){
+ res.send('<h1>Users</h1>'
+ + users.map(function(user, id){
+ return '<a href="/users/' + id + '">' + user.name + '</a>';
+ }).join('\n'));
+ },
+
+ json: function(req, res){
+ res.send(users);
+ },
+
+ xml: function(req, res){
+ res.send(users.map(function(user){
+ return '<user>' + user.name + '</user>'
+ }).join(''));
+ }
+};
+
+/**
+ * POST create.
+ */
+
+exports.create = function(req, res){
+ res.send('created');
+};
+
+/**
+ * GET show.
+ */
+
+exports.show = {
+ html: function(req, res){
+ res.send('<h1>' + req.user.name + '</h1>');
+ },
+
+ json: function(req, res){
+ res.send(req.user);
+ },
+
+ xml: function(req, res){
+ res.send('<user>' + req.user.name + '</user>');
+ }
+};
+
+/**
+ * Auto-load user re-source for actions.
+ */
+
+exports.load = function(id, fn){
+ var user = users[id];
+ if (!user) return fn(new Error('not found'));
+ process.nextTick(function(){
+ fn(null, user);
+ });
+}
View
22 examples/root.js
@@ -1,22 +0,0 @@
-
-require.paths.unshift(__dirname + '/../support');
-
-/**
- * Module dependencies.
- */
-
-var express = require('express')
- , resource = require('../')
- , app = express.createServer();
-
-app.resource({
- index: function(req, res){
- res.send('index page');
- },
-
- show: function(req, res){
- res.send('item ' + req.params.id);
- }
-});
-
-app.listen(3000);
View
50 examples/user.js
@@ -1,50 +0,0 @@
-/**
- * Module dependencies.
- */
-
-var express = require('express')
- , resource = require('../')
- , app = express.createServer();
-
-var users = ['tobi', 'loki', 'jane'];
-
-var user = {
- index: function(req, res){
- switch (req.format) {
- case 'json':
- res.send(users);
- break;
- default:
- res.contentType('txt');
- res.send(users.join(', '));
- }
- },
-
- show: function(req, res){
- var user = users[req.params.user];
- res.send(user);
- },
-
- edit: function(req, res){
- res.send('editing ' + req.params.user);
- },
-
- destroy: function(req, res){
- delete users[req.params.user];
- res.send('removed ' + req.params.user);
- },
-
- login: function(req, res){
- res.send('logged in ' + req.params.user);
- },
-
- logout: function(req, res){
- res.send('logged out');
- }
-};
-
-var userResource = app.resource('users', user);
-userResource.map('get', 'login', user.login); // relative path accesses element (/users/1/login)
-userResource.map('get', '/logout', user.logout); // absolute path accesses collection (/users/logout)
-
-app.listen(3000);
View
37 index.js
@@ -1,7 +1,7 @@
/*!
* Express - Resource
- * Copyright(c) 2010-2011 TJ Holowaychuk <tj@vision-media.ca>
+ * Copyright(c) 2010-2012 TJ Holowaychuk <tj@vision-media.ca>
* Copyright(c) 2011 Daniel Gasienica <daniel@gasienica.ch>
* MIT Licensed
*/
@@ -11,7 +11,10 @@
*/
var express = require('express')
+ , methods = require('methods')
+ , debug = require('debug')('express-resource')
, lingo = require('lingo')
+ , app = express.application
, en = lingo.en;
/**
@@ -27,7 +30,13 @@ var orderedActions = [
,'update' // PUT /:id
,'destroy' // DEL /:id
];
-
+
+/**
+ * Expose `Resource`.
+ */
+
+module.exports = Resource;
+
/**
* Initialize a new `Resource` with the given `name` and `actions`.
*
@@ -37,7 +46,7 @@ var orderedActions = [
* @api private
*/
-var Resource = module.exports = function Resource(name, actions, app) {
+function Resource(name, actions, app) {
this.name = name;
this.app = app;
this.routes = {};
@@ -143,15 +152,9 @@ Resource.prototype.map = function(method, path, fn){
// apply the route
this.app[method](route, function(req, res, next){
req.format = req.params.format || req.format || self.format;
- if (req.format) res.contentType(req.format);
+ if (req.format) res.type(req.format);
if ('object' == typeof fn) {
- if (req.format && fn[req.format]) {
- fn[req.format](req, res, next);
- } else if (fn.default) {
- fn.default(req, res, next);
- } else {
- res.send(406);
- }
+ res.format(fn);
} else {
fn(req, res, next);
}
@@ -185,7 +188,12 @@ Resource.prototype.add = function(resource){
for (var key in routes) {
route = routes[key];
delete routes[key];
- app[method](key).remove();
+ if (method == 'del') method = 'delete';
+ app.routes[method].forEach(function(route, i){
+ if (route.path == key) {
+ app.routes[method].splice(i, 1);
+ }
+ })
resource.map(route.method, route.orig, route.fn);
}
}
@@ -231,7 +239,7 @@ Resource.prototype.mapDefaultAction = function(key, fn){
* Setup http verb methods.
*/
-express.router.methods.concat(['del', 'all']).forEach(function(method){
+methods.concat(['del', 'all']).forEach(function(method){
Resource.prototype[method] = function(path, fn){
if ('function' == typeof path
|| 'object' == typeof path) fn = path, path = '';
@@ -249,8 +257,7 @@ express.router.methods.concat(['del', 'all']).forEach(function(method){
* @api public
*/
-express.HTTPServer.prototype.resource =
-express.HTTPSServer.prototype.resource = function(name, actions, opts){
+app.resource = function(name, actions, opts){
var options = actions || {};
if ('object' == typeof name) actions = name, name = null;
if (options.id) actions.id = options.id;
View
15 package.json
@@ -6,16 +6,21 @@
, "contributors": [
{ "name": "Daniel Gasienica", "email": "daniel@gasienica.ch" }
]
- , "dependencies": { "lingo": ">= 0.0.4" }
+ , "dependencies": {
+ "lingo": ">= 0.0.4"
+ , "methods": "0.0.1"
+ , "debug": "*"
+ }
, "devDependencies": {
- "connect": "1.8.x"
- , "express": "2.5.x"
+ "connect": "2.x"
+ , "express": "3.x"
, "ejs": "0.4.x"
- , "expresso": "0.9.x"
, "qs": "0.1.x"
+ , "mocha": "*"
, "should": "*"
+ , "supertest": "0.1.2"
}
, "keywords": ["express", "rest", "resource"]
, "main": "index"
- , "engines": { "node": ">= 0.2.0" }
+ , "engines": { "node": "*" }
}
View
291 test/resource.content-negotiation.test.js
@@ -1,158 +1,159 @@
-/**
- * Module dependencies.
- */
var assert = require('assert')
, express = require('express')
- , should = require('should')
- , Resource = require('../');
+ , request = require('supertest')
+ , batch = require('./support/batch')
+ , Resource = require('..');
-module.exports = {
- 'test content-negotiation via extension': function(){
- var app = express.createServer();
-
- app.resource('pets', require('./fixtures/pets'), { format: 'json' });
-
- assert.response(app,
- { url: '/pets.html' },
- { body: 'Not Acceptable'
- , status : 406 });
-
- assert.response(app,
- { url: '/pets' },
- { body: '["tobi","jane","loki"]' });
-
- assert.response(app,
- { url: '/pets.xml' },
- { body: '<pets><pet>tobi</pet><pet>jane</pet><pet>loki</pet></pets>'
- , headers: { 'Content-Type': 'application/xml' }});
-
- assert.response(app,
- { url: '/pets.json' },
- { body: '["tobi","jane","loki"]'
- , headers: { 'Content-Type': 'application/json; charset=utf-8' }});
-
- assert.response(app,
- { url: '/pets/1.json' },
- { body: '"jane"' });
-
- assert.response(app,
- { url: '/pets/0.xml' },
- { body: '<pet>tobi</pet>' });
+describe('app.resource()', function(){
+ it('should support content-negotiation via extension', function(done){
+ var app = express();
+ var next = batch(done);
- assert.response(app,
- { url: '/pets/0.xml', method: 'DELETE' },
- { body: '<message>pet removed</message>' });
+ app.set('json spaces', 0);
+ app.resource('pets', require('./fixtures/pets'));
- assert.response(app,
- { url: '/pets/0.json', method: 'DELETE' },
- { body: '{"message":"pet removed"}' });
- },
-
- 'test content-negotiation via format method': function(){
- var app = express.createServer();
-
- app.resource('pets', require('./fixtures/pets.format-methods'));
-
- assert.response(app,
- { url: '/pets.xml' },
- { body: '<pets><pet>tobi</pet><pet>jane</pet><pet>loki</pet></pets>'
- , headers: { 'Content-Type': 'application/xml' }});
-
- assert.response(app,
- { url: '/pets.json' },
- { body: '["tobi","jane","loki"]'
- , headers: { 'Content-Type': 'application/json; charset=utf-8' }});
-
- assert.response(app,
- { url: '/pets' },
- { body: 'Unsupported format', status: 406 });
- },
-
- 'test content-negotiation via format method without default': function(){
- var app = express.createServer();
-
- app.resource('pets', require('./fixtures/pets.format-methods-without-default'));
-
- assert.response(app,
- { url: '/pets.xml' },
- { body: '<pets><pet>tobi</pet><pet>jane</pet><pet>loki</pet></pets>'
- , headers: { 'Content-Type': 'application/xml' }});
-
- assert.response(app,
- { url: '/pets.json' },
- { body: '["tobi","jane","loki"]'
- , headers: { 'Content-Type': 'application/json; charset=utf-8' }});
-
- assert.response(app,
- { url: '/pets' },
- { body: 'Not Acceptable', status: 406 });
- },
-
- 'test content-negotiation via map()': function(){
- var app = express.createServer();
-
- app.use(express.bodyParser());
-
- var pets = app.resource('pets')
- , toys = app.resource('toys')
- , toysDB = ["balls", "platforms", "tunnels"];
+ request(app)
+ .get('/pets.html')
+ .expect(406, next());
- toys.get('/types', function(req, res){
- res.send(toysDB);
- });
+ request(app)
+ .get('/pets.json')
+ .expect('["tobi","jane","loki"]', next());
- toys.get('/', {
- json: function(req, res){
- res.send(toysDB);
- }
- });
-
- toys.get({
- json: function(req, res){
- res.send('"' + toysDB[req.params.toy] + '"');
- }
- });
-
- pets.add(toys);
-
- pets.get('/', {
- json: function(req, res){
- res.send({ name: 'tobi' });
- }
- });
-
- assert.response(app,
- { url: '/pets/0/toys/types' },
- { body: '["balls","platforms","tunnels"]' });
+ request(app)
+ .get('/pets.xml')
+ .expect('<pets><pet>tobi</pet><pet>jane</pet><pet>loki</pet></pets>', next());
- assert.response(app,
- { url: '/pets/0/toys/2.json' },
- { body: '"tunnels"' });
+ request(app)
+ .get('/pets/1.json')
+ .expect('"jane"', next());
- assert.response(app,
- { url: '/pets/0/toys.json' },
- { body: '["balls","platforms","tunnels"]' });
-
- assert.response(app,
- { url: '/pets.json' },
- { body: '{"name":"tobi"}' });
-
- assert.response(app,
- { url: '/pets' },
- { status: 406 });
- },
-
- 'test nested content-negotiation': function(){
- var app = express.createServer()
- , pets = ['tobi', 'jane', 'loki'];
+ request(app)
+ .get('/pets/0.xml')
+ .expect('<pet>tobi</pet>', next());
+
+ request(app)
+ .del('/pets/0.xml')
+ .expect('<message>pet removed</message>', next());
+
+ request(app)
+ .del('/pets/0.json')
+ .expect('{"message":"pet removed"}', next());
+ })
+
+ it('should support content-negotiation via method', function(done){
+ var app = express();
+ var next = batch(done);
+ app.set('json spaces', 0);
+ app.resource('pets', require('./fixtures/pets.format-methods'));
- var users = app.resource('users');
- var pets = app.resource('pets', require('./fixtures/pets'));
- users.add(pets);
+ // request(app)
+ // .get('/pets.xml')
+ // .expect('<pets><pet>tobi</pet><pet>jane</pet><pet>loki</pet></pets>', next());
- assert.response(app,
- { url: '/users/1/pets.json' },
- { body: '["tobi","jane","loki"]' });
- }
+ request(app)
+ .get('/pets.json')
+ .expect('["tobi","jane","loki"]', next());
+
+ request(app)
+ .get('/pets')
+ .expect('["tobi","jane","loki"]', next());
+ })
+})
+
+module.exports = {
+ // 'test content-negotiation via extension': function(){
+ // },
+ //
+ // 'test content-negotiation via format method': function(){
+
+ // },
+ //
+ // 'test content-negotiation via format method without default': function(){
+ // var app = express.createServer();
+ //
+ // app.resource('pets', require('./fixtures/pets.format-methods-without-default'));
+ //
+ // assert.response(app,
+ // { url: '/pets.xml' },
+ // { body: '<pets><pet>tobi</pet><pet>jane</pet><pet>loki</pet></pets>'
+ // , headers: { 'Content-Type': 'application/xml' }});
+ //
+ // assert.response(app,
+ // { url: '/pets.json' },
+ // { body: '["tobi","jane","loki"]'
+ // , headers: { 'Content-Type': 'application/json; charset=utf-8' }});
+ //
+ // assert.response(app,
+ // { url: '/pets' },
+ // { body: 'Not Acceptable', status: 406 });
+ // },
+ //
+ // 'test content-negotiation via map()': function(){
+ // var app = express.createServer();
+ //
+ // app.use(express.bodyParser());
+ //
+ // var pets = app.resource('pets')
+ // , toys = app.resource('toys')
+ // , toysDB = ["balls", "platforms", "tunnels"];
+ //
+ // toys.get('/types', function(req, res){
+ // res.send(toysDB);
+ // });
+ //
+ // toys.get('/', {
+ // json: function(req, res){
+ // res.send(toysDB);
+ // }
+ // });
+ //
+ // toys.get({
+ // json: function(req, res){
+ // res.send('"' + toysDB[req.params.toy] + '"');
+ // }
+ // });
+ //
+ // pets.add(toys);
+ //
+ // pets.get('/', {
+ // json: function(req, res){
+ // res.send({ name: 'tobi' });
+ // }
+ // });
+ //
+ // assert.response(app,
+ // { url: '/pets/0/toys/types' },
+ // { body: '["balls","platforms","tunnels"]' });
+ //
+ // assert.response(app,
+ // { url: '/pets/0/toys/2.json' },
+ // { body: '"tunnels"' });
+ //
+ // assert.response(app,
+ // { url: '/pets/0/toys.json' },
+ // { body: '["balls","platforms","tunnels"]' });
+ //
+ // assert.response(app,
+ // { url: '/pets.json' },
+ // { body: '{"name":"tobi"}' });
+ //
+ // assert.response(app,
+ // { url: '/pets' },
+ // { status: 406 });
+ // },
+ //
+ // 'test nested content-negotiation': function(){
+ // var app = express.createServer()
+ // , pets = ['tobi', 'jane', 'loki'];
+ //
+ // var users = app.resource('users');
+ // var pets = app.resource('pets', require('./fixtures/pets'));
+ // users.add(pets);
+ //
+ // assert.response(app,
+ // { url: '/users/1/pets.json' },
+ // { body: '["tobi","jane","loki"]' });
+ // }
};
View
494 test/resource.test.js
@@ -1,332 +1,196 @@
-/**
- * Module dependencies.
- */
var assert = require('assert')
, express = require('express')
- , should = require('should')
- , Resource = require('../');
+ , Resource = require('..')
+ , request = require('supertest')
+ , batch = require('./support/batch');
-module.exports = {
- 'test app.resource()': function(){
- var app = express.createServer();
-
- var ret = app.resource('forums', require('./fixtures/forum'));
- ret.should.be.an.instanceof(Resource);
-
- assert.response(app,
- { url: '/forums' },
- { body: 'forum index' });
-
- assert.response(app,
- { url: '/forums/new' },
- { body: 'new forum' });
-
- assert.response(app,
- { url: '/forums', method: 'POST' },
- { body: 'create forum' });
-
- assert.response(app,
- { url: '/forums/5' },
- { body: 'show forum 5' });
-
- assert.response(app,
- { url: '/forums/5/edit' },
- { body: 'edit forum 5' });
-
- assert.response(app,
- { url: '/forums/5', method: 'PUT' },
- { body: 'update forum 5' });
-
- assert.response(app,
- { url: '/forums/5', method: 'DELETE' },
- { body: 'destroy forum 5' });
- },
-
- 'test top-level app.resource()': function(){
- var app = express.createServer();
-
- var ret = app.resource(require('./fixtures/forum'), { id: 'forum' });
- ret.should.be.an.instanceof(Resource);
-
- assert.response(app,
- { url: '/' },
- { body: 'forum index' });
-
- assert.response(app,
- { url: '/new' },
- { body: 'new forum' });
-
- assert.response(app,
- { url: '/', method: 'POST' },
- { body: 'create forum' });
-
- assert.response(app,
- { url: '/5' },
- { body: 'show forum 5' });
-
- assert.response(app,
- { url: '/5/edit' },
- { body: 'edit forum 5' });
-
- assert.response(app,
- { url: '/5', method: 'PUT' },
- { body: 'update forum 5' });
-
- assert.response(app,
- { url: '/5', method: 'DELETE' },
- { body: 'destroy forum 5' });
- },
-
- 'test app.resource() id option': function(){
- var app = express.createServer();
-
- app.resource('users', {
- id: 'uid',
- show: function(req, res){
- res.send(req.params.uid);
- }
- });
-
- assert.response(app,
- { url: '/users' },
- { status: 404 });
-
- assert.response(app,
- { url: '/users/10' },
- { body: '10' });
- },
-
- 'test fetching a resource object': function(){
- var app = express.createServer();
+describe('app.resource(name)', function(){
+ it('should return a pre-defined resource', function(){
+ var app = express();
app.resource('users', { index: function(){} });
app.resource('users').should.be.an.instanceof(Resource);
app.resource('foo').should.be.an.instanceof(Resource);
- },
-
- 'test http methods': function(){
- var app = express.createServer();
-
- var users = app.resource('users');
+ })
+})
- users.get('/', function(req, res){
- res.send('index');
- }).get('/online', function(req, res){
- res.send('users online');
- });
+describe('app.resource()', function(){
+ it('should map CRUD actions', function(done){
+ var app = express();
+ var next = batch(done);
- users.get(function(req, res){
- res.send(req.params.user);
- }).get('online', function(req, res){
- res.send('no');
- });
-
- assert.response(app,
- { url: '/users/online' },
- { body: 'users online' });
-
- assert.response(app,
- { url: '/users' },
- { body: 'index' });
-
- assert.response(app,
- { url: '/users/0' },
- { body: '0' });
+ var ret = app.resource('forums', require('./fixtures/forum'));
+ ret.should.be.an.instanceof(Resource);
- assert.response(app,
- { url: '/users/0/online' },
- { body: 'no' });
- },
+ request(app)
+ .get('/forums')
+ .expect('forum index', next());
+
+ request(app)
+ .get('/forums/new')
+ .expect('new forum', next());
+
+ request(app)
+ .post('/forums')
+ .expect('create forum', next());
+
+ request(app)
+ .get('/forums/5')
+ .expect('show forum 5', next());
+
+ request(app)
+ .get('/forums/5/edit')
+ .expect('edit forum 5', next());
+
+ request(app)
+ .del('/forums/5')
+ .expect('destroy forum 5', next());
+ })
+
+ it('should support root resources', function(done){
+ var app = express();
+ var next = batch(done);
+ var forum = app.resource(require('./fixtures/forum'));
+ var thread = app.resource('threads', require('./fixtures/thread'));
+ forum.map(thread);
- 'test shallow nesting': function(){
- var app = express.createServer();
-
- var forum = app.resource('forums', require('./fixtures/forum'));
- var thread = app.resource('threads', require('./fixtures/thread'));
- forum.map(thread);
-
- assert.response(app,
- { url: '/forums' },
- { body: 'forum index' });
-
- assert.response(app,
- { url: '/forums/12' },
- { body: 'show forum 12' });
-
- assert.response(app,
- { url: '/forums/12/threads' },
- { body: 'thread index of forum 12' });
-
- assert.response(app,
- { url: '/forums/1/threads/50' },
- { body: 'show thread 50 of forum 1' });
- },
+ request(app)
+ .get('/')
+ .expect('forum index', next());
- 'test deep nesting': function(){
- var app = express.createServer();
-
- var user = app.resource('users', { index: function(req, res){ res.end('users'); } });
- var forum = app.resource('forums', require('./fixtures/forum'));
- var thread = app.resource('threads', require('./fixtures/thread'));
-
- var ret = user.add(forum);
- ret.should.equal(user);
-
- var ret = forum.add(thread);
- ret.should.equal(forum);
-
- assert.response(app,
- { url: '/forums/20' },
- { status: 404 });
-
- assert.response(app,
- { url: '/users' },
- { body: 'users' });
-
- assert.response(app,
- { url: '/users/5/forums' },
- { body: 'forum index' });
-
- assert.response(app,
- { url: '/users/5/forums/12' },
- { body: 'show forum 12' });
-
- assert.response(app,
- { url: '/users/5/forums/12/threads' },
- { body: 'thread index of forum 12' });
-
- assert.response(app,
- { url: '/users/5/forums/1/threads/50' },
- { body: 'show thread 50 of forum 1' });
- },
-
- 'test root nesting': function(){
- var app = express.createServer();
-
- var forum = app.resource(require('./fixtures/forum'));
- var thread = app.resource('threads', require('./fixtures/thread'));
- forum.map(thread);
-
- assert.response(app,
- { url: '/' },
- { body: 'forum index' });
-
- assert.response(app,
- { url: '/12' },
- { body: 'show forum 12' });
-
- assert.response(app,
- { url: '/12/threads' },
- { body: 'thread index of forum 12' });
-
- assert.response(app,
- { url: '/1/threads/50' },
- { body: 'show thread 50 of forum 1' });
- },
-
- 'test shallow auto-loading': function(){
- var app = express.createServer();
- var Forum = require('./fixtures/forum').Forum;
-
- var actions = { show: function(req, res){
- res.end(req.forum.title);
- }};
-
- actions.load = Forum.get;
- var forum = app.resource('forum', actions);
-
- assert.response(app,
- { url: '/forum/12' },
- { body: 'Ferrets' });
- },
+ // request(app)
+ // .get('/12')
+ // .expect('show forum 12', next());
- 'test deep auto-loading': function(){
- var app = express.createServer();
- var Forum = require('./fixtures/forum').Forum
- , Thread = require('./fixtures/thread').Thread;
-
- var actions = { show: function(req, res){
- res.end(req.forum.title + ': ' + req.thread.title);
- }};
-
- var forum = app.resource('forum', { load: Forum.get });
- var threads = app.resource('thread', actions, { load: Thread.get });
-
- forum.add(threads);
-
- assert.response(app,
- { url: '/forum/12/thread/1' },
- { body: 'Ferrets: Tobi rules' });
- },
+ // request(app)
+ // .get('/12/threads')
+ // .expect('thread index of forum 12', next());
- 'test .load(fn)': function(){
- var app = express.createServer();
- var Forum = require('./fixtures/forum').Forum;
-
- var actions = { show: function(req, res){
- res.end(req.forum.title);
- }};
-
- var forum = app.resource('forum', actions);
- forum.load(Forum.get);
-
- assert.response(app,
- { url: '/forum/12' },
- { body: 'Ferrets' });
- },
+ // request(app)
+ // .get('/1/threads/50')
+ // .expect('show thread 50 of forum 1', next());
+ })
- 'test auto-loading no resource': function(){
- var app = express.createServer();
-
- function load(id, fn) { fn(); }
- var actions = { show: function(){
- assert.fail('called show when loader failed');
- }};
-
- app.resource('pets', actions, { load: load });
-
- assert.response(app,
- { url: '/pets/0' },
- { body: 'Not Found', status: 404 });
- },
+ describe('"id" option', function(){
+ it('should allow overriding the default', function(done){
+ var app = express();
+ var next = batch(done);
+
+ app.resource('users', {
+ id: 'uid',
+ show: function(req, res){
+ res.send(req.params.uid);
+ }
+ });
- 'test custom route configuration': function(){
- var app = express.createServer();
- var Forum = require('./fixtures/forum').Forum;
-
- function load(id, fn) { fn(null, "User"); }
- var actions = {
- login: function(req, res){
- res.end('login');
- },
- logout: function(req, res){
- res.end('logout');
- }
- };
-
- var users = app.resource('users', actions, { load: load });
- users.map('get', 'login', actions.login);
- users.map('get', '/logout', actions.logout);
-
- assert.response(app,
- { url: '/users/1/login' },
- { body: 'login' });
-
- assert.response(app,
- { url: '/users/logout' },
- { body: 'logout' });
- },
+ request(app)
+ .get('/users')
+ .expect(404, next());
- 'test several segments': function(){
- var app = express.createServer();
- var cat = app.resource('api/cat', require('./fixtures/cat'));
-
- assert.response(app,
- { url: '/api/cat' },
- { body: 'list of cats' });
-
- assert.response(app,
- { url: '/api/cat/new' },
- { body: 'new cat' });
- }
-};
+ request(app)
+ .get('/users/10')
+ .expect('10', next());
+ })
+ })
+
+ describe('with several segments', function(){
+ it('should work', function(done){
+ var app = express();
+ var next = batch(done);
+ var cat = app.resource('api/cat', require('./fixtures/cat'));
+
+ request(app)
+ .get('/api/cat')
+ .expect('list of cats', next());
+
+ request(app)
+ .get('/api/cat/new')
+ .expect('new cat', next());
+ })
+ })
+
+ it('should allow configuring routes', function(done){
+ var app = express();
+ var next = batch(done);
+ var Forum = require('./fixtures/forum').Forum;
+
+ function load(id, fn) { fn(null, "User"); }
+
+ var actions = {
+ login: function(req, res){
+ res.end('login');
+ },
+ logout: function(req, res){
+ res.end('logout');
+ }
+ };
+
+ var users = app.resource('users', actions, { load: load });
+ users.map('get', 'login', actions.login);
+ users.map('get', '/logout', actions.logout);
+
+ request(app)
+ .get('/users/1/login')
+ .expect('login', next());
+
+ request(app)
+ .get('/users/logout')
+ .expect('logout', next());
+ })
+
+ describe('autoloading', function(){
+ describe('when no resource is found', function(){
+ it('should not invoke the callback', function(done){
+ var app = express();
+
+ function load(id, fn) { fn(); }
+ var actions = { show: function(){
+ assert.fail('called show when loader failed');
+ }};
+
+ app.resource('pets', actions, { load: load });
+
+ request(app)
+ .get('/pets/0')
+ .expect(404, done);
+ })
+ })
+
+ describe('when a resource is found', function(){
+ it('should invoke the callback', function(done){
+ var app = express();
+ var Forum = require('./fixtures/forum').Forum;
+
+ var actions = { show: function(req, res){
+ res.end(req.forum.title);
+ }};
+
+ var forum = app.resource('forum', actions);
+ forum.load(Forum.get);
+
+ request(app)
+ .get('/forum/12')
+ .expect('Ferrets', done);
+ })
+
+ it('should work recursively', function(done){
+ var app = express();
+ var Forum = require('./fixtures/forum').Forum;
+ var Thread = require('./fixtures/thread').Thread;
+
+ var actions = { show: function(req, res){
+ res.end(req.forum.title + ': ' + req.thread.title);
+ }};
+
+ var forum = app.resource('forum', { load: Forum.get });
+ var threads = app.resource('thread', actions, { load: Thread.get });
+
+ forum.add(threads);
+
+ request(app)
+ .get('/forum/12/thread/1')
+ .expect('Ferrets: Tobi rules', done);
+ })
+ })
+ })
+})
View
13 test/support/batch.js
@@ -0,0 +1,13 @@
+
+module.exports = function(done) {
+ var pending = 0;
+ var finished = false;
+ return function(){
+ ++pending;
+ return function(err){
+ if (finished) return;
+ if (err) return finished = true, done(err);
+ --pending || done();
+ }
+ }
+};

0 comments on commit 862e1b9

Please sign in to comment.