Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Tests and implementation for middleware + formats + nesting together.

  • Loading branch information...
commit 0f2abab0d247be627ae39632fd35ea4d314b1d73 1 parent d4b0c9c
authored January 03, 2012
33  index.js
@@ -140,30 +140,19 @@ Resource.prototype.map = function(method, path, fn){
140 140
     , fn: fn
141 141
   };
142 142
 
143  
-  // apply Array of middleware
144  
-  if (fn instanceof Array) {
145  
-    // TODO: Make arrays of middleware also work with formats
146  
-    this.app[method](route, fn);
147  
-  }
148  
-  else {
149  
-    // apply the route
150  
-    this.app[method](route, function(req, res, next){
151  
-      req.format = req.params.format || req.format || self.format;
152  
-      if (req.format) res.contentType(req.format);
153  
-      if ('object' == typeof fn) {
154  
-        if (req.format && fn[req.format]) {
155  
-          fn[req.format](req, res, next);
156  
-        } else if (fn.default) {
157  
-          fn.default(req, res, next);
158  
-        } else {
159  
-          res.send(406);
160  
-        }
161  
-      } else {
162  
-        fn(req, res, next);
163  
-      }
164  
-    });  
  143
+  function extract_format(req, res, next) {
  144
+    req.format = req.params.format || req.format || self.format;
  145
+    if (req.format) res.contentType(req.format);
  146
+    next();
165 147
   }
166 148
 
  149
+  // ensure fn is an array of functions and inject req.format
  150
+  if (!(fn instanceof Array)) fn = [fn];
  151
+  fn.unshift(extract_format);
  152
+  
  153
+  // apply the route
  154
+  this.app[method](route, fn);
  155
+
167 156
   return this;
168 157
 };
169 158
 
17  test/fixtures/cat.js
@@ -14,6 +14,19 @@ exports.filter = function(req, res, next) {
14 14
 
15 15
 exports.edit = [
16 16
   exports.filter,
17  
-  function(req, res, next) {
  17
+  function(req, res) {
18 18
     res.send('usertype: ' + req.usertype);
19  
-  }];
  19
+  }
  20
+];
  21
+
  22
+exports.show = [
  23
+  exports.filter,
  24
+  function(req, res) {
  25
+    if ('json' === req.format) {
  26
+      res.send(JSON.stringify({usertype: req.usertype}));
  27
+    }
  28
+    else {
  29
+      res.send('usertype: ' + req.usertype);
  30
+    }
  31
+  }
  32
+];
43  test/fixtures/forum.middleware.js
... ...
@@ -0,0 +1,43 @@
  1
+
  2
+
  3
+function middleware(req, res, next) {
  4
+  req.user = 'middleware user';
  5
+  next();
  6
+}
  7
+
  8
+exports.index = function(req, res){
  9
+  res.send('forum index');
  10
+};
  11
+
  12
+exports.new = function(req, res){
  13
+  res.send('new forum');
  14
+};
  15
+
  16
+exports.create = function(req, res){
  17
+  res.send('create forum');
  18
+};
  19
+
  20
+exports.show = [
  21
+  middleware,
  22
+  function(req, res){
  23
+    res.send('show forum ' + req.params.forum);
  24
+  }
  25
+];
  26
+
  27
+exports.edit = function(req, res){
  28
+  res.send('edit forum ' + req.params.forum);
  29
+};
  30
+
  31
+exports.update = function(req, res){
  32
+  res.send('update forum ' + req.params.forum);
  33
+};
  34
+
  35
+exports.destroy = function(req, res){
  36
+  res.send('destroy forum ' + req.params.forum);
  37
+};
  38
+
  39
+exports.load = function(id, fn){
  40
+  process.nextTick(function(){
  41
+    fn(null, { title: 'Ferrets' });
  42
+  });
  43
+};
53  test/fixtures/thread.middleware.js
... ...
@@ -0,0 +1,53 @@
  1
+
  2
+
  3
+function middleware(req, res, next) {
  4
+  req.role = 'thread owner';
  5
+  next();
  6
+}
  7
+
  8
+exports.index = function(req, res){
  9
+  res.send('thread index of forum ' + req.params.forum);
  10
+};
  11
+
  12
+exports.new = function(req, res){
  13
+  res.send('new thread');
  14
+};
  15
+
  16
+exports.create = function(req, res){
  17
+  res.send('create thread');
  18
+};
  19
+
  20
+exports.show = [
  21
+  middleware,
  22
+  function(req, res){
  23
+    if (req.format === 'json') {
  24
+      res.send(JSON.stringify({
  25
+        thread: req.params.thread,
  26
+        forum: req.params.forum,
  27
+        user: req.user,           // Should not be populated because middleware should only run for the final route
  28
+        role: req.role
  29
+      }));
  30
+    }
  31
+    else {
  32
+      res.send('show thread ' + req.params.thread + ' of forum ' + req.params.forum + ' for ' + req.user + ', ' + req.role);
  33
+    }
  34
+  }
  35
+];
  36
+
  37
+exports.edit = function(req, res){
  38
+  res.send('edit thread ' + req.params.thread + ' of forum ' + req.params.forum);
  39
+};
  40
+
  41
+exports.update = function(req, res){
  42
+  res.send('update thread ' + req.params.thread + ' of forum ' + req.params.forum);
  43
+};
  44
+
  45
+exports.destroy = function(req, res){
  46
+  res.send('destroy thread ' + req.params.thread + ' of forum ' + req.params.forum);
  47
+};
  48
+
  49
+exports.load = function(id, fn){
  50
+  process.nextTick(function(){
  51
+    fn(null, { title: 'Tobi rules' });
  52
+  });
  53
+};
109  test/resource.content-negotiation.test.js
@@ -48,101 +48,7 @@ module.exports = {
48 48
       { url: '/pets/0.json', method: 'DELETE' },
49 49
       { body: '{"message":"pet removed"}' });
50 50
   },
51  
-  
52  
-  'test content-negotiation via format method': function(){
53  
-    var app = express.createServer();
54  
-  
55  
-    app.resource('pets', require('./fixtures/pets.format-methods'));
56  
-  
57  
-    assert.response(app,
58  
-      { url: '/pets.xml' },
59  
-      { body: '<pets><pet>tobi</pet><pet>jane</pet><pet>loki</pet></pets>'
60  
-      , headers: { 'Content-Type': 'application/xml' }});
61  
-  
62  
-    assert.response(app,
63  
-      { url: '/pets.json' },
64  
-      { body: '["tobi","jane","loki"]'
65  
-      , headers: { 'Content-Type': 'application/json; charset=utf-8' }});
66  
-  
67  
-    assert.response(app,
68  
-      { url: '/pets' },
69  
-      { body: 'Unsupported format', status: 406 });
70  
-  },
71  
-  
72  
-  'test content-negotiation via format method without default': function(){
73  
-    var app = express.createServer();
74  
-  
75  
-    app.resource('pets', require('./fixtures/pets.format-methods-without-default'));
76  
-  
77  
-    assert.response(app,
78  
-      { url: '/pets.xml' },
79  
-      { body: '<pets><pet>tobi</pet><pet>jane</pet><pet>loki</pet></pets>'
80  
-      , headers: { 'Content-Type': 'application/xml' }});
81  
-  
82  
-    assert.response(app,
83  
-      { url: '/pets.json' },
84  
-      { body: '["tobi","jane","loki"]'
85  
-      , headers: { 'Content-Type': 'application/json; charset=utf-8' }});
86  
-  
87  
-    assert.response(app,
88  
-      { url: '/pets' },
89  
-      { body: 'Not Acceptable', status: 406 });
90  
-  },
91  
-  
92  
-  'test content-negotiation via map()': function(){
93  
-    var app = express.createServer();
94  
-  
95  
-    app.use(express.bodyParser());
96  
-  
97  
-    var pets = app.resource('pets')
98  
-      , toys = app.resource('toys')
99  
-      , toysDB = ["balls", "platforms", "tunnels"];
100  
-
101  
-    toys.get('/types', function(req, res){
102  
-      res.send(toysDB);
103  
-    });  
104  
-
105  
-    toys.get('/', {
106  
-      json: function(req, res){
107  
-        res.send(toysDB);
108  
-      }
109  
-    });
110  
-    
111  
-    toys.get({
112  
-      json: function(req, res){
113  
-        res.send('"' + toysDB[req.params.toy] + '"');
114  
-      }
115  
-    });
116  
-  
117  
-    pets.add(toys);
118  
-  
119  
-    pets.get('/', {
120  
-      json: function(req, res){
121  
-        res.send({ name: 'tobi' });
122  
-      }
123  
-    });
124  
-  
125  
-    assert.response(app,
126  
-      { url: '/pets/0/toys/types' },
127  
-      { body: '["balls","platforms","tunnels"]' });
128  
-
129  
-    assert.response(app,
130  
-      { url: '/pets/0/toys/2.json' },
131  
-      { body: '"tunnels"' });
132  
-
133  
-    assert.response(app,
134  
-      { url: '/pets/0/toys.json' },
135  
-      { body: '["balls","platforms","tunnels"]' });
136 51
       
137  
-    assert.response(app,
138  
-      { url: '/pets.json' },
139  
-      { body: '{"name":"tobi"}' });
140  
-      
141  
-    assert.response(app,
142  
-      { url: '/pets' },
143  
-      { status: 406 });
144  
-  },
145  
-  
146 52
   'test nested content-negotiation': function(){
147 53
     var app = express.createServer()
148 54
       , pets = ['tobi', 'jane', 'loki'];
@@ -154,5 +60,20 @@ module.exports = {
154 60
     assert.response(app,
155 61
       { url: '/users/1/pets.json' },
156 62
       { body: '["tobi","jane","loki"]' });
  63
+  },
  64
+
  65
+  'test content-negotiation with middleware': function() {
  66
+    var app = express.createServer();
  67
+
  68
+    var cat = app.resource('api/cat', require('./fixtures/cat'));
  69
+
  70
+    assert.response(app,
  71
+      { url: '/api/cat/1' },
  72
+      { body: 'usertype: cat owner' });
  73
+
  74
+    assert.response(app,
  75
+      { url: '/api/cat/1.json' },
  76
+      { body: '{"usertype":"cat owner"}'
  77
+        , headers: { 'Content-Type': 'application/json' } });
157 78
   }
158 79
 };
25  test/resource.test.js
@@ -337,5 +337,30 @@ module.exports = {
337 337
     assert.response(app,
338 338
       { url: '/api/cat/1/edit' },
339 339
       { body: 'usertype: cat owner' });
  340
+  },
  341
+
  342
+  'test middleware by array with shallow nesting and format': function(){
  343
+    var app = express.createServer();
  344
+
  345
+    var forum = app.resource('forums', require('./fixtures/forum.middleware'));
  346
+    var thread = app.resource('threads', require('./fixtures/thread.middleware'));
  347
+    forum.map(thread);
  348
+
  349
+    assert.response(app,
  350
+      { url: '/forums' },
  351
+      { body: 'forum index' });
  352
+
  353
+    assert.response(app,
  354
+      { url: '/forums/12' },
  355
+      { body: 'show forum 12' });
  356
+
  357
+    assert.response(app,
  358
+      { url: '/forums/12/threads' },
  359
+      { body: 'thread index of forum 12' });
  360
+    
  361
+    assert.response(app,
  362
+      { url: '/forums/1/threads/50.json' },
  363
+      { body: '{"thread":"50","forum":"1","role":"thread owner"}'
  364
+        , headers: { 'Content-Type': 'application/json' } });
340 365
   }
341 366
 };

0 notes on commit 0f2abab

Please sign in to comment.
Something went wrong with that request. Please try again.