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){
14 app.use(function(req, res){
20 .expect(200, '', done);
24 describe('.send(null)', function(){
25 it('should set body to ""', function(done){
28 app.use(function(req, res){
34 .expect('Content-Length', '0')
35 .expect(200, '', done);
39 describe('.send(undefined)', function(){
40 it('should set body to ""', function(done){
43 app.use(function(req, res){
49 .expect(200, '', done);
53 describe('.send(code)', function(){
54 it('should set .statusCode', function(done){
57 app.use(function(req, res){
68 describe('.send(code, body)', function(){
69 it('should set .statusCode and body', function(done){
72 app.use(function(req, res){
73 res.send(201, 'Created :)');
83 describe('.send(body, code)', function(){
84 it('should be supported for backwards compat', function(done){
87 app.use(function(req, res){
88 res.send('Bad!', 400);
98 describe('.send(code, number)', function(){
99 it('should send number as json', function(done){
102 app.use(function(req, res){
103 res.send(200, 0.123);
108 .expect('Content-Type', 'application/json; charset=utf-8')
109 .expect(200, '0.123', done);
113 describe('.send(String)', function(){
114 it('should send as html', function(done){
117 app.use(function(req, res){
118 res.send('<p>hey</p>');
123 .expect('Content-Type', 'text/html; charset=utf-8')
124 .expect(200, '<p>hey</p>', done);
127 it('should set ETag', function (done) {
130 app.use(function (req, res) {
131 var str = Array(1000).join('-');
137 .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"')
141 it('should not override Content-Type', function(done){
144 app.use(function(req, res){
145 res.set('Content-Type', 'text/plain').send('hey');
150 .expect('Content-Type', 'text/plain; charset=utf-8')
151 .expect(200, 'hey', done);
154 it('should override charset in Content-Type', function(done){
157 app.use(function(req, res){
158 res.set('Content-Type', 'text/plain; charset=iso-8859-1').send('hey');
163 .expect('Content-Type', 'text/plain; charset=utf-8')
164 .expect(200, 'hey', done);
167 it('should keep charset in Content-Type for Buffers', function(done){
170 app.use(function(req, res){
171 res.set('Content-Type', 'text/plain; charset=iso-8859-1').send(Buffer.from('hi'))
176 .expect('Content-Type', 'text/plain; charset=iso-8859-1')
177 .expect(200, 'hi', done);
181 describe('.send(Buffer)', function(){
182 it('should send as octet-stream', function(done){
185 app.use(function(req, res){
186 res.send(Buffer.from('hello'))
192 .expect('Content-Type', 'application/octet-stream')
193 .expect(shouldHaveBody(Buffer.from('hello')))
197 it('should set ETag', function (done) {
200 app.use(function (req, res) {
201 res.send(Buffer.alloc(999, '-'))
206 .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"')
210 it('should not override Content-Type', function(done){
213 app.use(function(req, res){
214 res.set('Content-Type', 'text/plain').send(Buffer.from('hey'))
219 .expect('Content-Type', 'text/plain; charset=utf-8')
220 .expect(200, 'hey', done);
223 it('should not override ETag', function (done) {
226 app.use(function (req, res) {
227 res.type('text/plain').set('ETag', '"foo"').send(Buffer.from('hey'))
232 .expect('ETag', '"foo"')
233 .expect(200, 'hey', done)
237 describe('.send(Object)', function(){
238 it('should send as application/json', function(done){
241 app.use(function(req, res){
242 res.send({ name: 'tobi' });
247 .expect('Content-Type', 'application/json; charset=utf-8')
248 .expect(200, '{"name":"tobi"}', done)
252 describe('when the request method is HEAD', function(){
253 it('should ignore the body', function(done){
256 app.use(function(req, res){
263 .expect(shouldNotHaveBody())
268 describe('when .statusCode is 204', function(){
269 it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
272 app.use(function(req, res){
273 res.status(204).set('Transfer-Encoding', 'chunked').send('foo');
278 .expect(utils.shouldNotHaveHeader('Content-Type'))
279 .expect(utils.shouldNotHaveHeader('Content-Length'))
280 .expect(utils.shouldNotHaveHeader('Transfer-Encoding'))
281 .expect(204, '', done);
285 describe('when .statusCode is 304', function(){
286 it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
289 app.use(function(req, res){
290 res.status(304).set('Transfer-Encoding', 'chunked').send('foo');
295 .expect(utils.shouldNotHaveHeader('Content-Type'))
296 .expect(utils.shouldNotHaveHeader('Content-Length'))
297 .expect(utils.shouldNotHaveHeader('Transfer-Encoding'))
298 .expect(304, '', done);
302 it('should always check regardless of length', function(done){
306 app.use(function(req, res, next){
307 res.set('ETag', etag);
313 .set('If-None-Match', etag)
317 it('should respond with 304 Not Modified when fresh', function(done){
321 app.use(function(req, res){
322 var str = Array(1000).join('-');
323 res.set('ETag', etag);
329 .set('If-None-Match', etag)
333 it('should not perform freshness check unless 2xx or 304', function(done){
337 app.use(function(req, res, next){
339 res.set('ETag', etag);
345 .set('If-None-Match', etag)
350 it('should not support jsonp callbacks', function(done){
353 app.use(function(req, res){
354 res.send({ foo: 'bar' });
358 .get('/?callback=foo')
359 .expect('{"foo":"bar"}', done);
362 it('should be chainable', function (done) {
365 app.use(function (req, res) {
366 assert.equal(res.send('hey'), res)
371 .expect(200, 'hey', done)
374 describe('"etag" setting', function () {
375 describe('when enabled', function () {
376 it('should send ETag', function (done) {
379 app.use(function (req, res) {
380 res.send('kajdslfkasdf');
387 .expect('ETag', 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"')
391 methods.forEach(function (method) {
392 if (method === 'connect') return;
394 it('should send ETag in response to ' + method.toUpperCase() + ' request', function (done) {
397 app[method]('/', function (req, res) {
398 res.send('kajdslfkasdf');
403 .expect('ETag', 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"')
408 it('should send ETag for empty string response', function (done) {
411 app.use(function (req, res) {
419 .expect('ETag', 'W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"')
423 it('should send ETag for long response', function (done) {
426 app.use(function (req, res) {
427 var str = Array(1000).join('-');
435 .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"')
439 it('should not override ETag when manually set', function (done) {
442 app.use(function (req, res) {
443 res.set('etag', '"asdf"');
451 .expect('ETag', '"asdf"')
455 it('should not send ETag for res.send()', function (done) {
458 app.use(function (req, res) {
466 .expect(utils.shouldNotHaveHeader('ETag'))
471 describe('when disabled', function () {
472 it('should send no ETag', function (done) {
475 app.use(function (req, res) {
476 var str = Array(1000).join('-');
484 .expect(utils.shouldNotHaveHeader('ETag'))
488 it('should send ETag when manually set', function (done) {
493 app.use(function (req, res) {
494 res.set('etag', '"asdf"');
500 .expect('ETag', '"asdf"')
505 describe('when "strong"', function () {
506 it('should send strong ETag', function (done) {
509 app.set('etag', 'strong');
511 app.use(function (req, res) {
512 res.send('hello, world!');
517 .expect('ETag', '"d-HwnTDHB9U/PRbFMN1z1wps51lqk"')
522 describe('when "weak"', function () {
523 it('should send weak ETag', function (done) {
526 app.set('etag', 'weak');
528 app.use(function (req, res) {
529 res.send('hello, world!');
534 .expect('ETag', 'W/"d-HwnTDHB9U/PRbFMN1z1wps51lqk"')
539 describe('when a function', function () {
540 it('should send custom ETag', function (done) {
543 app.set('etag', function (body, encoding) {
544 var chunk = !Buffer.isBuffer(body)
545 ? Buffer.from(body, encoding)
547 chunk.toString().should.equal('hello, world!');
551 app.use(function (req, res) {
552 res.send('hello, world!');
557 .expect('ETag', '"custom"')
561 it('should not send falsy ETag', function (done) {
564 app.set('etag', function (body, encoding) {
568 app.use(function (req, res) {
569 res.send('hello, world!');
574 .expect(utils.shouldNotHaveHeader('ETag'))
581 function shouldHaveBody (buf) {
582 return function (res) {
583 var body = !Buffer.isBuffer(res.body)
584 ? Buffer.from(res.text)
586 assert.ok(body, 'response has body')
587 assert.strictEqual(body.toString('hex'), buf.toString('hex'))
591 function shouldNotHaveBody () {
592 return function (res) {
593 assert.ok(res.text === '' || res.text === undefined)