build: update example dependencies
[express.git] / test / res.send.js
blobb836b5e4dcb40c421b297b678a46f56795677dd3
2 var assert = require('assert')
3 var Buffer = require('safe-buffer').Buffer
4 var express = require('..');
5 var methods = require('methods');
6 var request = require('supertest');
7 var utils = require('./support/utils');
9 describe('res', function(){
10   describe('.send()', function(){
11     it('should set body to ""', function(done){
12       var app = express();
14       app.use(function(req, res){
15         res.send();
16       });
18       request(app)
19       .get('/')
20       .expect(200, '', done);
21     })
22   })
24   describe('.send(null)', function(){
25     it('should set body to ""', function(done){
26       var app = express();
28       app.use(function(req, res){
29         res.send(null);
30       });
32       request(app)
33       .get('/')
34       .expect('Content-Length', '0')
35       .expect(200, '', done);
36     })
37   })
39   describe('.send(undefined)', function(){
40     it('should set body to ""', function(done){
41       var app = express();
43       app.use(function(req, res){
44         res.send(undefined);
45       });
47       request(app)
48       .get('/')
49       .expect(200, '', done);
50     })
51   })
53   describe('.send(code)', function(){
54     it('should set .statusCode', function(done){
55       var app = express();
57       app.use(function(req, res){
58         res.send(201)
59       });
61       request(app)
62       .get('/')
63       .expect('Created')
64       .expect(201, done);
65     })
66   })
68   describe('.send(code, body)', function(){
69     it('should set .statusCode and body', function(done){
70       var app = express();
72       app.use(function(req, res){
73         res.send(201, 'Created :)');
74       });
76       request(app)
77       .get('/')
78       .expect('Created :)')
79       .expect(201, done);
80     })
81   })
83   describe('.send(body, code)', function(){
84     it('should be supported for backwards compat', function(done){
85       var app = express();
87       app.use(function(req, res){
88         res.send('Bad!', 400);
89       });
91       request(app)
92       .get('/')
93       .expect('Bad!')
94       .expect(400, done);
95     })
96   })
98   describe('.send(code, number)', function(){
99     it('should send number as json', function(done){
100       var app = express();
102       app.use(function(req, res){
103         res.send(200, 0.123);
104       });
106       request(app)
107       .get('/')
108       .expect('Content-Type', 'application/json; charset=utf-8')
109       .expect(200, '0.123', done);
110     })
111   })
113   describe('.send(String)', function(){
114     it('should send as html', function(done){
115       var app = express();
117       app.use(function(req, res){
118         res.send('<p>hey</p>');
119       });
121       request(app)
122       .get('/')
123       .expect('Content-Type', 'text/html; charset=utf-8')
124       .expect(200, '<p>hey</p>', done);
125     })
127     it('should set ETag', function (done) {
128       var app = express();
130       app.use(function (req, res) {
131         var str = Array(1000).join('-');
132         res.send(str);
133       });
135       request(app)
136       .get('/')
137       .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"')
138       .expect(200, done);
139     })
141     it('should not override Content-Type', function(done){
142       var app = express();
144       app.use(function(req, res){
145         res.set('Content-Type', 'text/plain').send('hey');
146       });
148       request(app)
149       .get('/')
150       .expect('Content-Type', 'text/plain; charset=utf-8')
151       .expect(200, 'hey', done);
152     })
154     it('should override charset in Content-Type', function(done){
155       var app = express();
157       app.use(function(req, res){
158         res.set('Content-Type', 'text/plain; charset=iso-8859-1').send('hey');
159       });
161       request(app)
162       .get('/')
163       .expect('Content-Type', 'text/plain; charset=utf-8')
164       .expect(200, 'hey', done);
165     })
167     it('should keep charset in Content-Type for Buffers', function(done){
168       var app = express();
170       app.use(function(req, res){
171         res.set('Content-Type', 'text/plain; charset=iso-8859-1').send(Buffer.from('hi'))
172       });
174       request(app)
175       .get('/')
176       .expect('Content-Type', 'text/plain; charset=iso-8859-1')
177       .expect(200, 'hi', done);
178     })
179   })
181   describe('.send(Buffer)', function(){
182     it('should send as octet-stream', function(done){
183       var app = express();
185       app.use(function(req, res){
186         res.send(Buffer.from('hello'))
187       });
189       request(app)
190       .get('/')
191       .expect(200)
192       .expect('Content-Type', 'application/octet-stream')
193       .expect(shouldHaveBody(Buffer.from('hello')))
194       .end(done)
195     })
197     it('should set ETag', function (done) {
198       var app = express();
200       app.use(function (req, res) {
201         res.send(Buffer.alloc(999, '-'))
202       });
204       request(app)
205       .get('/')
206       .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"')
207       .expect(200, done);
208     })
210     it('should not override Content-Type', function(done){
211       var app = express();
213       app.use(function(req, res){
214         res.set('Content-Type', 'text/plain').send(Buffer.from('hey'))
215       });
217       request(app)
218       .get('/')
219       .expect('Content-Type', 'text/plain; charset=utf-8')
220       .expect(200, 'hey', done);
221     })
223     it('should not override ETag', function (done) {
224       var app = express()
226       app.use(function (req, res) {
227         res.type('text/plain').set('ETag', '"foo"').send(Buffer.from('hey'))
228       })
230       request(app)
231       .get('/')
232       .expect('ETag', '"foo"')
233       .expect(200, 'hey', done)
234     })
235   })
237   describe('.send(Object)', function(){
238     it('should send as application/json', function(done){
239       var app = express();
241       app.use(function(req, res){
242         res.send({ name: 'tobi' });
243       });
245       request(app)
246       .get('/')
247       .expect('Content-Type', 'application/json; charset=utf-8')
248       .expect(200, '{"name":"tobi"}', done)
249     })
250   })
252   describe('when the request method is HEAD', function(){
253     it('should ignore the body', function(done){
254       var app = express();
256       app.use(function(req, res){
257         res.send('yay');
258       });
260       request(app)
261       .head('/')
262       .expect(200)
263       .expect(shouldNotHaveBody())
264       .end(done)
265     })
266   })
268   describe('when .statusCode is 204', function(){
269     it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
270       var app = express();
272       app.use(function(req, res){
273         res.status(204).set('Transfer-Encoding', 'chunked').send('foo');
274       });
276       request(app)
277       .get('/')
278       .expect(utils.shouldNotHaveHeader('Content-Type'))
279       .expect(utils.shouldNotHaveHeader('Content-Length'))
280       .expect(utils.shouldNotHaveHeader('Transfer-Encoding'))
281       .expect(204, '', done);
282     })
283   })
285   describe('when .statusCode is 304', function(){
286     it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
287       var app = express();
289       app.use(function(req, res){
290         res.status(304).set('Transfer-Encoding', 'chunked').send('foo');
291       });
293       request(app)
294       .get('/')
295       .expect(utils.shouldNotHaveHeader('Content-Type'))
296       .expect(utils.shouldNotHaveHeader('Content-Length'))
297       .expect(utils.shouldNotHaveHeader('Transfer-Encoding'))
298       .expect(304, '', done);
299     })
300   })
302   it('should always check regardless of length', function(done){
303     var app = express();
304     var etag = '"asdf"';
306     app.use(function(req, res, next){
307       res.set('ETag', etag);
308       res.send('hey');
309     });
311     request(app)
312     .get('/')
313     .set('If-None-Match', etag)
314     .expect(304, done);
315   })
317   it('should respond with 304 Not Modified when fresh', function(done){
318     var app = express();
319     var etag = '"asdf"';
321     app.use(function(req, res){
322       var str = Array(1000).join('-');
323       res.set('ETag', etag);
324       res.send(str);
325     });
327     request(app)
328     .get('/')
329     .set('If-None-Match', etag)
330     .expect(304, done);
331   })
333   it('should not perform freshness check unless 2xx or 304', function(done){
334     var app = express();
335     var etag = '"asdf"';
337     app.use(function(req, res, next){
338       res.status(500);
339       res.set('ETag', etag);
340       res.send('hey');
341     });
343     request(app)
344     .get('/')
345     .set('If-None-Match', etag)
346     .expect('hey')
347     .expect(500, done);
348   })
350   it('should not support jsonp callbacks', function(done){
351     var app = express();
353     app.use(function(req, res){
354       res.send({ foo: 'bar' });
355     });
357     request(app)
358     .get('/?callback=foo')
359     .expect('{"foo":"bar"}', done);
360   })
362   it('should be chainable', function (done) {
363     var app = express()
365     app.use(function (req, res) {
366       assert.equal(res.send('hey'), res)
367     })
369     request(app)
370     .get('/')
371     .expect(200, 'hey', done)
372   })
374   describe('"etag" setting', function () {
375     describe('when enabled', function () {
376       it('should send ETag', function (done) {
377         var app = express();
379         app.use(function (req, res) {
380           res.send('kajdslfkasdf');
381         });
383         app.enable('etag');
385         request(app)
386         .get('/')
387         .expect('ETag', 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"')
388         .expect(200, done);
389       });
391       methods.forEach(function (method) {
392         if (method === 'connect') return;
394         it('should send ETag in response to ' + method.toUpperCase() + ' request', function (done) {
395           var app = express();
397           app[method]('/', function (req, res) {
398             res.send('kajdslfkasdf');
399           });
401           request(app)
402           [method]('/')
403           .expect('ETag', 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"')
404           .expect(200, done);
405         })
406       });
408       it('should send ETag for empty string response', function (done) {
409         var app = express();
411         app.use(function (req, res) {
412           res.send('');
413         });
415         app.enable('etag');
417         request(app)
418         .get('/')
419         .expect('ETag', 'W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"')
420         .expect(200, done);
421       })
423       it('should send ETag for long response', function (done) {
424         var app = express();
426         app.use(function (req, res) {
427           var str = Array(1000).join('-');
428           res.send(str);
429         });
431         app.enable('etag');
433         request(app)
434         .get('/')
435         .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"')
436         .expect(200, done);
437       });
439       it('should not override ETag when manually set', function (done) {
440         var app = express();
442         app.use(function (req, res) {
443           res.set('etag', '"asdf"');
444           res.send(200);
445         });
447         app.enable('etag');
449         request(app)
450         .get('/')
451         .expect('ETag', '"asdf"')
452         .expect(200, done);
453       });
455       it('should not send ETag for res.send()', function (done) {
456         var app = express();
458         app.use(function (req, res) {
459           res.send();
460         });
462         app.enable('etag');
464         request(app)
465         .get('/')
466         .expect(utils.shouldNotHaveHeader('ETag'))
467         .expect(200, done);
468       })
469     });
471     describe('when disabled', function () {
472       it('should send no ETag', function (done) {
473         var app = express();
475         app.use(function (req, res) {
476           var str = Array(1000).join('-');
477           res.send(str);
478         });
480         app.disable('etag');
482         request(app)
483         .get('/')
484         .expect(utils.shouldNotHaveHeader('ETag'))
485         .expect(200, done);
486       });
488       it('should send ETag when manually set', function (done) {
489         var app = express();
491         app.disable('etag');
493         app.use(function (req, res) {
494           res.set('etag', '"asdf"');
495           res.send(200);
496         });
498         request(app)
499         .get('/')
500         .expect('ETag', '"asdf"')
501         .expect(200, done);
502       });
503     });
505     describe('when "strong"', function () {
506       it('should send strong ETag', function (done) {
507         var app = express();
509         app.set('etag', 'strong');
511         app.use(function (req, res) {
512           res.send('hello, world!');
513         });
515         request(app)
516         .get('/')
517         .expect('ETag', '"d-HwnTDHB9U/PRbFMN1z1wps51lqk"')
518         .expect(200, done);
519       })
520     })
522     describe('when "weak"', function () {
523       it('should send weak ETag', function (done) {
524         var app = express();
526         app.set('etag', 'weak');
528         app.use(function (req, res) {
529           res.send('hello, world!');
530         });
532         request(app)
533         .get('/')
534         .expect('ETag', 'W/"d-HwnTDHB9U/PRbFMN1z1wps51lqk"')
535         .expect(200, done)
536       })
537     })
539     describe('when a function', function () {
540       it('should send custom ETag', function (done) {
541         var app = express();
543         app.set('etag', function (body, encoding) {
544           var chunk = !Buffer.isBuffer(body)
545             ? Buffer.from(body, encoding)
546             : body;
547           chunk.toString().should.equal('hello, world!');
548           return '"custom"';
549         });
551         app.use(function (req, res) {
552           res.send('hello, world!');
553         });
555         request(app)
556         .get('/')
557         .expect('ETag', '"custom"')
558         .expect(200, done);
559       })
561       it('should not send falsy ETag', function (done) {
562         var app = express();
564         app.set('etag', function (body, encoding) {
565           return undefined;
566         });
568         app.use(function (req, res) {
569           res.send('hello, world!');
570         });
572         request(app)
573         .get('/')
574         .expect(utils.shouldNotHaveHeader('ETag'))
575         .expect(200, done);
576       })
577     })
578   })
581 function shouldHaveBody (buf) {
582   return function (res) {
583     var body = !Buffer.isBuffer(res.body)
584       ? Buffer.from(res.text)
585       : res.body
586     assert.ok(body, 'response has body')
587     assert.strictEqual(body.toString('hex'), buf.toString('hex'))
588   }
591 function shouldNotHaveBody () {
592   return function (res) {
593     assert.ok(res.text === '' || res.text === undefined)
594   }