3 var express
= require('../')
4 , request
= require('supertest')
5 , assert
= require('assert');
6 var utils
= require('./support/utils');
8 describe('res', function(){
9 describe('.jsonp(object)', function(){
10 it('should respond with jsonp', function(done
){
13 app
.use(function(req
, res
){
14 res
.jsonp({ count
: 1 });
18 .get('/?callback=something')
19 .expect('Content-Type', 'text/javascript; charset=utf-8')
20 .expect(200, /something\(\{"count":1\}\);/, done
);
23 it('should use first callback parameter with jsonp', function(done
){
26 app
.use(function(req
, res
){
27 res
.jsonp({ count
: 1 });
31 .get('/?callback=something&callback=somethingelse')
32 .expect('Content-Type', 'text/javascript; charset=utf-8')
33 .expect(200, /something\(\{"count":1\}\);/, done
);
36 it('should ignore object callback parameter with jsonp', function(done
){
39 app
.use(function(req
, res
){
40 res
.jsonp({ count
: 1 });
44 .get('/?callback[a]=something')
45 .expect('Content-Type', 'application/json; charset=utf-8')
46 .expect(200, '{"count":1}', done
)
49 it('should allow renaming callback', function(done
){
52 app
.set('jsonp callback name', 'clb');
54 app
.use(function(req
, res
){
55 res
.jsonp({ count
: 1 });
59 .get('/?clb=something')
60 .expect('Content-Type', 'text/javascript; charset=utf-8')
61 .expect(200, /something\(\{"count":1\}\);/, done
);
64 it('should allow []', function(done
){
67 app
.use(function(req
, res
){
68 res
.jsonp({ count
: 1 });
72 .get('/?callback=callbacks[123]')
73 .expect('Content-Type', 'text/javascript; charset=utf-8')
74 .expect(200, /callbacks\[123\]\(\{"count":1\}\);/, done
);
77 it('should disallow arbitrary js', function(done
){
80 app
.use(function(req
, res
){
85 .get('/?callback=foo;bar()')
86 .expect('Content-Type', 'text/javascript; charset=utf-8')
87 .expect(200, /foobar\(\{\}\);/, done
);
90 it('should escape utf whitespace', function(done
){
93 app
.use(function(req
, res
){
94 res
.jsonp({ str
: '\u2028 \u2029 woot' });
98 .get('/?callback=foo')
99 .expect('Content-Type', 'text/javascript; charset=utf-8')
100 .expect(200, /foo\(\{"str":"\\u2028 \\u2029 woot"\}\);/, done
);
103 it('should not escape utf whitespace for json fallback', function(done
){
106 app
.use(function(req
, res
){
107 res
.jsonp({ str
: '\u2028 \u2029 woot' });
112 .expect('Content-Type', 'application/json; charset=utf-8')
113 .expect(200, '{"str":"\u2028 \u2029 woot"}', done
);
116 it('should include security header and prologue', function (done
) {
119 app
.use(function(req
, res
){
120 res
.jsonp({ count
: 1 });
124 .get('/?callback=something')
125 .expect('Content-Type', 'text/javascript; charset=utf-8')
126 .expect('X-Content-Type-Options', 'nosniff')
127 .expect(200, /^\/\*\*\//, done
);
130 it('should not override previous Content-Types with no callback', function(done
){
133 app
.get('/', function(req
, res
){
134 res
.type('application/vnd.example+json');
135 res
.jsonp({ hello
: 'world' });
140 .expect('Content-Type', 'application/vnd.example+json; charset=utf-8')
141 .expect(utils
.shouldNotHaveHeader('X-Content-Type-Options'))
142 .expect(200, '{"hello":"world"}', done
);
145 it('should override previous Content-Types with callback', function(done
){
148 app
.get('/', function(req
, res
){
149 res
.type('application/vnd.example+json');
150 res
.jsonp({ hello
: 'world' });
154 .get('/?callback=cb')
155 .expect('Content-Type', 'text/javascript; charset=utf-8')
156 .expect('X-Content-Type-Options', 'nosniff')
157 .expect(200, /cb\(\{"hello":"world"\}\);$/, done
);
160 describe('when given undefined', function () {
161 it('should invoke callback with no arguments', function (done
) {
164 app
.use(function (req
, res
) {
169 .get('/?callback=cb')
170 .expect('Content-Type', 'text/javascript; charset=utf-8')
171 .expect(200, /cb\(\)/, done
)
175 describe('when given null', function () {
176 it('should invoke callback with null', function (done
) {
179 app
.use(function (req
, res
) {
184 .get('/?callback=cb')
185 .expect('Content-Type', 'text/javascript; charset=utf-8')
186 .expect(200, /cb\(null\)/, done
)
190 describe('when given a string', function () {
191 it('should invoke callback with a string', function (done
) {
194 app
.use(function (req
, res
) {
199 .get('/?callback=cb')
200 .expect('Content-Type', 'text/javascript; charset=utf-8')
201 .expect(200, /cb\("tobi"\)/, done
)
205 describe('when given a number', function () {
206 it('should invoke callback with a number', function (done
) {
209 app
.use(function (req
, res
) {
214 .get('/?callback=cb')
215 .expect('Content-Type', 'text/javascript; charset=utf-8')
216 .expect(200, /cb\(42\)/, done
)
220 describe('when given an array', function () {
221 it('should invoke callback with an array', function (done
) {
224 app
.use(function (req
, res
) {
225 res
.jsonp(['foo', 'bar', 'baz'])
229 .get('/?callback=cb')
230 .expect('Content-Type', 'text/javascript; charset=utf-8')
231 .expect(200, /cb\(\["foo","bar","baz"\]\)/, done
)
235 describe('when given an object', function () {
236 it('should invoke callback with an object', function (done
) {
239 app
.use(function (req
, res
) {
240 res
.jsonp({ name
: 'tobi' })
244 .get('/?callback=cb')
245 .expect('Content-Type', 'text/javascript; charset=utf-8')
246 .expect(200, /cb\(\{"name":"tobi"\}\)/, done
)
250 describe('"json escape" setting', function () {
251 it('should be undefined by default', function () {
253 assert
.strictEqual(app
.get('json escape'), undefined)
256 it('should unicode escape HTML-sniffing characters', function (done
) {
259 app
.enable('json escape')
261 app
.use(function (req
, res
) {
262 res
.jsonp({ '&': '\u2028<script>\u2029' })
266 .get('/?callback=foo')
267 .expect('Content-Type', 'text/javascript; charset=utf-8')
268 .expect(200, /foo\({"\\u0026":"\\u2028\\u003cscript\\u003e\\u2029"}\)/, done
)
271 it('should not break undefined escape', function (done
) {
274 app
.enable('json escape')
276 app
.use(function (req
, res
) {
281 .get('/?callback=cb')
282 .expect('Content-Type', 'text/javascript; charset=utf-8')
283 .expect(200, /cb\(\)/, done
)
287 describe('"json replacer" setting', function(){
288 it('should be passed to JSON.stringify()', function(done
){
291 app
.set('json replacer', function(key
, val
){
292 return key
[0] === '_'
297 app
.use(function(req
, res
){
298 res
.jsonp({ name
: 'tobi', _id
: 12345 });
303 .expect('Content-Type', 'application/json; charset=utf-8')
304 .expect(200, '{"name":"tobi"}', done
)
308 describe('"json spaces" setting', function(){
309 it('should be undefined by default', function(){
311 assert(undefined === app
.get('json spaces'));
314 it('should be passed to JSON.stringify()', function(done
){
317 app
.set('json spaces', 2);
319 app
.use(function(req
, res
){
320 res
.jsonp({ name
: 'tobi', age
: 2 });
325 .expect('Content-Type', 'application/json; charset=utf-8')
326 .expect(200, '{\n "name": "tobi",\n "age": 2\n}', done
)
331 it('should not override previous Content-Types', function(done
){
334 app
.get('/', function(req
, res
){
335 res
.type('application/vnd.example+json');
336 res
.jsonp({ hello
: 'world' });
341 .expect('content-type', 'application/vnd.example+json; charset=utf-8')
342 .expect(200, '{"hello":"world"}', done
)