1 |
|
2 |
|
3 | var chai = require('chai');
|
4 | var cap = require('chai-as-promised');
|
5 | chai.use(cap);
|
6 | var expect = chai.expect;
|
7 | var bluebird = require('bluebird');
|
8 | var then = require('promise');
|
9 | var spawn = require('child_process').spawn;
|
10 | var stream = require('stream');
|
11 | var resumer = require('resumer');
|
12 |
|
13 | var TestServer = require('./server');
|
14 |
|
15 |
|
16 | var fetch = require('../index.js');
|
17 | var Headers = require('../lib/headers.js');
|
18 | var Response = require('../lib/response.js');
|
19 | var Request = require('../lib/request.js');
|
20 |
|
21 | fetch.Promise = fetch.Promise || bluebird;
|
22 |
|
23 | var url, opts, local, base;
|
24 |
|
25 | describe('node-fetch', function() {
|
26 |
|
27 | before(function(done) {
|
28 | local = new TestServer();
|
29 | base = 'http://' + local.hostname + ':' + local.port;
|
30 | local.start(done);
|
31 | });
|
32 |
|
33 | after(function(done) {
|
34 | local.stop(done);
|
35 | });
|
36 |
|
37 | it('should return a promise', function() {
|
38 | url = 'http://example.com/';
|
39 | var p = fetch(url);
|
40 | expect(p).to.be.an.instanceof(fetch.Promise);
|
41 | expect(p).to.have.property('then');
|
42 | });
|
43 |
|
44 | it('should allow custom promise', function() {
|
45 | url = 'http://example.com/';
|
46 | var old = fetch.Promise;
|
47 | fetch.Promise = then;
|
48 | expect(fetch(url)).to.be.an.instanceof(then);
|
49 | expect(fetch(url)).to.not.be.an.instanceof(bluebird);
|
50 | fetch.Promise = old;
|
51 | });
|
52 |
|
53 | it('should throw error when no promise implementation are found', function() {
|
54 | url = 'http://example.com/';
|
55 | var old = fetch.Promise;
|
56 | fetch.Promise = undefined;
|
57 | expect(function() {
|
58 | fetch(url)
|
59 | }).to.throw(Error);
|
60 | fetch.Promise = old;
|
61 | });
|
62 |
|
63 | it('should expose Headers, Response and Request constructors', function() {
|
64 | expect(fetch.Headers).to.equal(Headers);
|
65 | expect(fetch.Response).to.equal(Response);
|
66 | expect(fetch.Request).to.equal(Request);
|
67 | });
|
68 |
|
69 | it('should reject with error if url is protocol relative', function() {
|
70 | url = '//example.com/';
|
71 | return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
72 | });
|
73 |
|
74 | it('should reject with error if url is relative path', function() {
|
75 | url = '/some/path';
|
76 | return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
77 | });
|
78 |
|
79 | it('should reject with error if protocol is unsupported', function() {
|
80 | url = 'ftp://example.com/';
|
81 | return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
82 | });
|
83 |
|
84 | it('should reject with error on network failure', function() {
|
85 | url = 'http://localhost:50000/';
|
86 | return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
87 | });
|
88 |
|
89 | it('should resolve into response', function() {
|
90 | url = base + '/hello';
|
91 | return fetch(url).then(function(res) {
|
92 | expect(res).to.be.an.instanceof(Response);
|
93 | expect(res.headers).to.be.an.instanceof(Headers);
|
94 | expect(res.body).to.be.an.instanceof(stream.Transform);
|
95 | expect(res.bodyUsed).to.be.false;
|
96 |
|
97 | expect(res.url).to.equal(url);
|
98 | expect(res.ok).to.be.true;
|
99 | expect(res.status).to.equal(200);
|
100 | expect(res.statusText).to.equal('OK');
|
101 | });
|
102 | });
|
103 |
|
104 | it('should accept plain text response', function() {
|
105 | url = base + '/plain';
|
106 | return fetch(url).then(function(res) {
|
107 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
108 | return res.text().then(function(result) {
|
109 | expect(res.bodyUsed).to.be.true;
|
110 | expect(result).to.be.a('string');
|
111 | expect(result).to.equal('text');
|
112 | });
|
113 | });
|
114 | });
|
115 |
|
116 | it('should accept html response (like plain text)', function() {
|
117 | url = base + '/html';
|
118 | return fetch(url).then(function(res) {
|
119 | expect(res.headers.get('content-type')).to.equal('text/html');
|
120 | return res.text().then(function(result) {
|
121 | expect(res.bodyUsed).to.be.true;
|
122 | expect(result).to.be.a('string');
|
123 | expect(result).to.equal('<html></html>');
|
124 | });
|
125 | });
|
126 | });
|
127 |
|
128 | it('should accept json response', function() {
|
129 | url = base + '/json';
|
130 | return fetch(url).then(function(res) {
|
131 | expect(res.headers.get('content-type')).to.equal('application/json');
|
132 | return res.json().then(function(result) {
|
133 | expect(res.bodyUsed).to.be.true;
|
134 | expect(result).to.be.an('object');
|
135 | expect(result).to.deep.equal({ name: 'value' });
|
136 | });
|
137 | });
|
138 | });
|
139 |
|
140 | it('should send request with custom headers', function() {
|
141 | url = base + '/inspect';
|
142 | opts = {
|
143 | headers: { 'x-custom-header': 'abc' }
|
144 | };
|
145 | return fetch(url, opts).then(function(res) {
|
146 | return res.json();
|
147 | }).then(function(res) {
|
148 | expect(res.headers['x-custom-header']).to.equal('abc');
|
149 | });
|
150 | });
|
151 |
|
152 | it('should accept headers instance', function() {
|
153 | url = base + '/inspect';
|
154 | opts = {
|
155 | headers: new Headers({ 'x-custom-header': 'abc' })
|
156 | };
|
157 | return fetch(url, opts).then(function(res) {
|
158 | return res.json();
|
159 | }).then(function(res) {
|
160 | expect(res.headers['x-custom-header']).to.equal('abc');
|
161 | });
|
162 | });
|
163 |
|
164 | it('should accept custom host header', function() {
|
165 | url = base + '/inspect';
|
166 | opts = {
|
167 | headers: {
|
168 | host: 'example.com'
|
169 | }
|
170 | };
|
171 | return fetch(url, opts).then(function(res) {
|
172 | return res.json();
|
173 | }).then(function(res) {
|
174 | expect(res.headers['host']).to.equal('example.com');
|
175 | });
|
176 | });
|
177 |
|
178 | it('should follow redirect code 301', function() {
|
179 | url = base + '/redirect/301';
|
180 | return fetch(url).then(function(res) {
|
181 | expect(res.url).to.equal(base + '/inspect');
|
182 | expect(res.status).to.equal(200);
|
183 | expect(res.ok).to.be.true;
|
184 | });
|
185 | });
|
186 |
|
187 | it('should follow redirect code 302', function() {
|
188 | url = base + '/redirect/302';
|
189 | return fetch(url).then(function(res) {
|
190 | expect(res.url).to.equal(base + '/inspect');
|
191 | expect(res.status).to.equal(200);
|
192 | });
|
193 | });
|
194 |
|
195 | it('should follow redirect code 303', function() {
|
196 | url = base + '/redirect/303';
|
197 | return fetch(url).then(function(res) {
|
198 | expect(res.url).to.equal(base + '/inspect');
|
199 | expect(res.status).to.equal(200);
|
200 | });
|
201 | });
|
202 |
|
203 | it('should follow redirect code 307', function() {
|
204 | url = base + '/redirect/307';
|
205 | return fetch(url).then(function(res) {
|
206 | expect(res.url).to.equal(base + '/inspect');
|
207 | expect(res.status).to.equal(200);
|
208 | });
|
209 | });
|
210 |
|
211 | it('should follow redirect code 308', function() {
|
212 | url = base + '/redirect/308';
|
213 | return fetch(url).then(function(res) {
|
214 | expect(res.url).to.equal(base + '/inspect');
|
215 | expect(res.status).to.equal(200);
|
216 | });
|
217 | });
|
218 |
|
219 | it('should follow redirect chain', function() {
|
220 | url = base + '/redirect/chain';
|
221 | return fetch(url).then(function(res) {
|
222 | expect(res.url).to.equal(base + '/inspect');
|
223 | expect(res.status).to.equal(200);
|
224 | });
|
225 | });
|
226 |
|
227 | it('should obey maximum redirect', function() {
|
228 | url = base + '/redirect/chain';
|
229 | opts = {
|
230 | follow: 1
|
231 | }
|
232 | return expect(fetch(url, opts)).to.eventually.be.rejectedWith(Error);
|
233 | });
|
234 |
|
235 | it('should allow not following redirect', function() {
|
236 | url = base + '/redirect/301';
|
237 | opts = {
|
238 | follow: 0
|
239 | }
|
240 | return expect(fetch(url, opts)).to.eventually.be.rejectedWith(Error);
|
241 | });
|
242 |
|
243 | it('should follow redirect code 301 and keep existing headers', function() {
|
244 | url = base + '/redirect/301';
|
245 | opts = {
|
246 | headers: new Headers({ 'x-custom-header': 'abc' })
|
247 | };
|
248 | return fetch(url, opts).then(function(res) {
|
249 | expect(res.url).to.equal(base + '/inspect');
|
250 | return res.json();
|
251 | }).then(function(res) {
|
252 | expect(res.headers['x-custom-header']).to.equal('abc');
|
253 | });
|
254 | });
|
255 |
|
256 | it('should reject broken redirect', function() {
|
257 | url = base + '/error/redirect';
|
258 | return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
259 | });
|
260 |
|
261 | it('should handle client-error response', function() {
|
262 | url = base + '/error/400';
|
263 | return fetch(url).then(function(res) {
|
264 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
265 | expect(res.status).to.equal(400);
|
266 | expect(res.statusText).to.equal('Bad Request');
|
267 | expect(res.ok).to.be.false;
|
268 | return res.text().then(function(result) {
|
269 | expect(res.bodyUsed).to.be.true;
|
270 | expect(result).to.be.a('string');
|
271 | expect(result).to.equal('client error');
|
272 | });
|
273 | });
|
274 | });
|
275 |
|
276 | it('should handle server-error response', function() {
|
277 | url = base + '/error/500';
|
278 | return fetch(url).then(function(res) {
|
279 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
280 | expect(res.status).to.equal(500);
|
281 | expect(res.statusText).to.equal('Internal Server Error');
|
282 | expect(res.ok).to.be.false;
|
283 | return res.text().then(function(result) {
|
284 | expect(res.bodyUsed).to.be.true;
|
285 | expect(result).to.be.a('string');
|
286 | expect(result).to.equal('server error');
|
287 | });
|
288 | });
|
289 | });
|
290 |
|
291 | it('should handle network-error response', function() {
|
292 | url = base + '/error/reset';
|
293 | return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
294 | });
|
295 |
|
296 | it('should reject invalid json response', function() {
|
297 | url = base + '/error/json';
|
298 | return fetch(url).then(function(res) {
|
299 | expect(res.headers.get('content-type')).to.equal('application/json');
|
300 | return expect(res.json()).to.eventually.be.rejectedWith(Error);
|
301 | });
|
302 | });
|
303 |
|
304 | it('should handle empty response', function() {
|
305 | url = base + '/empty';
|
306 | return fetch(url).then(function(res) {
|
307 | expect(res.status).to.equal(204);
|
308 | expect(res.statusText).to.equal('No Content');
|
309 | expect(res.ok).to.be.true;
|
310 | return res.text().then(function(result) {
|
311 | expect(result).to.be.a('string');
|
312 | expect(result).to.be.empty;
|
313 | });
|
314 | });
|
315 | });
|
316 |
|
317 | it('should decompress gzip response', function() {
|
318 | url = base + '/gzip';
|
319 | return fetch(url).then(function(res) {
|
320 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
321 | return res.text().then(function(result) {
|
322 | expect(result).to.be.a('string');
|
323 | expect(result).to.equal('hello world');
|
324 | });
|
325 | });
|
326 | });
|
327 |
|
328 | it('should decompress deflate response', function() {
|
329 | url = base + '/deflate';
|
330 | return fetch(url).then(function(res) {
|
331 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
332 | return res.text().then(function(result) {
|
333 | expect(result).to.be.a('string');
|
334 | expect(result).to.equal('hello world');
|
335 | });
|
336 | });
|
337 | });
|
338 |
|
339 | it('should skip decompression if unsupported', function() {
|
340 | url = base + '/sdch';
|
341 | return fetch(url).then(function(res) {
|
342 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
343 | return res.text().then(function(result) {
|
344 | expect(result).to.be.a('string');
|
345 | expect(result).to.equal('fake sdch string');
|
346 | });
|
347 | });
|
348 | });
|
349 |
|
350 | it('should allow disabling auto decompression', function() {
|
351 | url = base + '/gzip';
|
352 | opts = {
|
353 | compress: false
|
354 | };
|
355 | return fetch(url, opts).then(function(res) {
|
356 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
357 | return res.text().then(function(result) {
|
358 | expect(result).to.be.a('string');
|
359 | expect(result).to.not.equal('hello world');
|
360 | });
|
361 | });
|
362 | });
|
363 |
|
364 | it('should allow custom timeout', function() {
|
365 | this.timeout(500);
|
366 | url = base + '/timeout';
|
367 | opts = {
|
368 | timeout: 100
|
369 | };
|
370 | return expect(fetch(url, opts)).to.eventually.be.rejectedWith(Error);
|
371 | });
|
372 |
|
373 | it('should allow custom timeout on response body', function() {
|
374 | this.timeout(500);
|
375 | url = base + '/slow';
|
376 | opts = {
|
377 | timeout: 100
|
378 | };
|
379 | return fetch(url, opts).then(function(res) {
|
380 | expect(res.ok).to.be.true;
|
381 | return expect(res.text()).to.eventually.be.rejectedWith(Error);
|
382 | });
|
383 | });
|
384 |
|
385 | it('should clear internal timeout on fetch response', function (done) {
|
386 | this.timeout(1000);
|
387 | spawn('node', ['-e', 'require("./")("' + base + '/hello", { timeout: 5000 })'])
|
388 | .on('exit', function () {
|
389 | done();
|
390 | });
|
391 | });
|
392 |
|
393 | it('should clear internal timeout on fetch redirect', function (done) {
|
394 | this.timeout(1000);
|
395 | spawn('node', ['-e', 'require("./")("' + base + '/redirect/301", { timeout: 5000 })'])
|
396 | .on('exit', function () {
|
397 | done();
|
398 | });
|
399 | });
|
400 |
|
401 | it('should clear internal timeout on fetch error', function (done) {
|
402 | this.timeout(1000);
|
403 | spawn('node', ['-e', 'require("./")("' + base + '/error/reset", { timeout: 5000 })'])
|
404 | .on('exit', function () {
|
405 | done();
|
406 | });
|
407 | });
|
408 |
|
409 | it('should allow POST request', function() {
|
410 | url = base + '/inspect';
|
411 | opts = {
|
412 | method: 'POST'
|
413 | };
|
414 | return fetch(url, opts).then(function(res) {
|
415 | return res.json();
|
416 | }).then(function(res) {
|
417 | expect(res.method).to.equal('POST');
|
418 | });
|
419 | });
|
420 |
|
421 | it('should allow POST request with string body', function() {
|
422 | url = base + '/inspect';
|
423 | opts = {
|
424 | method: 'POST'
|
425 | , body: 'a=1'
|
426 | };
|
427 | return fetch(url, opts).then(function(res) {
|
428 | return res.json();
|
429 | }).then(function(res) {
|
430 | expect(res.method).to.equal('POST');
|
431 | expect(res.body).to.equal('a=1');
|
432 | });
|
433 | });
|
434 |
|
435 | it('should allow POST request with readable stream as body', function() {
|
436 | url = base + '/inspect';
|
437 | opts = {
|
438 | method: 'POST'
|
439 | , body: resumer().queue('a=1').end()
|
440 | };
|
441 | return fetch(url, opts).then(function(res) {
|
442 | return res.json();
|
443 | }).then(function(res) {
|
444 | expect(res.method).to.equal('POST');
|
445 | expect(res.body).to.equal('a=1');
|
446 | });
|
447 | });
|
448 |
|
449 | it('should allow PUT request', function() {
|
450 | url = base + '/inspect';
|
451 | opts = {
|
452 | method: 'PUT'
|
453 | , body: 'a=1'
|
454 | };
|
455 | return fetch(url, opts).then(function(res) {
|
456 | return res.json();
|
457 | }).then(function(res) {
|
458 | expect(res.method).to.equal('PUT');
|
459 | expect(res.body).to.equal('a=1');
|
460 | });
|
461 | });
|
462 |
|
463 | it('should allow DELETE request', function() {
|
464 | url = base + '/inspect';
|
465 | opts = {
|
466 | method: 'DELETE'
|
467 | };
|
468 | return fetch(url, opts).then(function(res) {
|
469 | return res.json();
|
470 | }).then(function(res) {
|
471 | expect(res.method).to.equal('DELETE');
|
472 | });
|
473 | });
|
474 |
|
475 | it('should allow PATCH request', function() {
|
476 | url = base + '/inspect';
|
477 | opts = {
|
478 | method: 'PATCH'
|
479 | , body: 'a=1'
|
480 | };
|
481 | return fetch(url, opts).then(function(res) {
|
482 | return res.json();
|
483 | }).then(function(res) {
|
484 | expect(res.method).to.equal('PATCH');
|
485 | expect(res.body).to.equal('a=1');
|
486 | });
|
487 | });
|
488 |
|
489 | it('should allow HEAD request', function() {
|
490 | url = base + '/hello';
|
491 | opts = {
|
492 | method: 'HEAD'
|
493 | };
|
494 | return fetch(url, opts).then(function(res) {
|
495 | expect(res.status).to.equal(200);
|
496 | expect(res.statusText).to.equal('OK');
|
497 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
498 | expect(res.body).to.be.an.instanceof(stream.Transform);
|
499 | });
|
500 | });
|
501 |
|
502 | it('should reject decoding body twice', function() {
|
503 | url = base + '/plain';
|
504 | return fetch(url).then(function(res) {
|
505 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
506 | return res.text().then(function(result) {
|
507 | expect(res.bodyUsed).to.be.true;
|
508 | return expect(res.text()).to.eventually.be.rejectedWith(Error);
|
509 | });
|
510 | });
|
511 | });
|
512 |
|
513 | it('should support maximum response size, multiple chunk', function() {
|
514 | url = base + '/size/chunk';
|
515 | opts = {
|
516 | size: 5
|
517 | };
|
518 | return fetch(url, opts).then(function(res) {
|
519 | expect(res.status).to.equal(200);
|
520 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
521 | return expect(res.text()).to.eventually.be.rejectedWith(Error);
|
522 | });
|
523 | });
|
524 |
|
525 | it('should support maximum response size, single chunk', function() {
|
526 | url = base + '/size/long';
|
527 | opts = {
|
528 | size: 5
|
529 | };
|
530 | return fetch(url, opts).then(function(res) {
|
531 | expect(res.status).to.equal(200);
|
532 | expect(res.headers.get('content-type')).to.equal('text/plain');
|
533 | return expect(res.text()).to.eventually.be.rejectedWith(Error);
|
534 | });
|
535 | });
|
536 |
|
537 | it('should support encoding decode, xml dtd detect', function() {
|
538 | url = base + '/encoding/euc-jp';
|
539 | return fetch(url).then(function(res) {
|
540 | expect(res.status).to.equal(200);
|
541 | return res.text().then(function(result) {
|
542 | expect(result).to.equal('<?xml version="1.0" encoding="EUC-JP"?><title>日本語</title>');
|
543 | });
|
544 | });
|
545 | });
|
546 |
|
547 | it('should support encoding decode, content-type detect', function() {
|
548 | url = base + '/encoding/shift-jis';
|
549 | return fetch(url).then(function(res) {
|
550 | expect(res.status).to.equal(200);
|
551 | return res.text().then(function(result) {
|
552 | expect(result).to.equal('<div>日本語</div>');
|
553 | });
|
554 | });
|
555 | });
|
556 |
|
557 | it('should support encoding decode, html5 detect', function() {
|
558 | url = base + '/encoding/gbk';
|
559 | return fetch(url).then(function(res) {
|
560 | expect(res.status).to.equal(200);
|
561 | return res.text().then(function(result) {
|
562 | expect(result).to.equal('<meta charset="gbk"><div>中文</div>');
|
563 | });
|
564 | });
|
565 | });
|
566 |
|
567 | it('should support encoding decode, html4 detect', function() {
|
568 | url = base + '/encoding/gb2312';
|
569 | return fetch(url).then(function(res) {
|
570 | expect(res.status).to.equal(200);
|
571 | return res.text().then(function(result) {
|
572 | expect(result).to.equal('<meta http-equiv="Content-Type" content="text/html; charset=gb2312"><div>中文</div>');
|
573 | });
|
574 | });
|
575 | });
|
576 |
|
577 | it('should default to utf8 encoding', function() {
|
578 | url = base + '/encoding/utf8';
|
579 | return fetch(url).then(function(res) {
|
580 | expect(res.status).to.equal(200);
|
581 | expect(res.headers.get('content-type')).to.be.null;
|
582 | return res.text().then(function(result) {
|
583 | expect(result).to.equal('中文');
|
584 | });
|
585 | });
|
586 | });
|
587 |
|
588 | it('should support uncommon content-type order, charset in front', function() {
|
589 | url = base + '/encoding/order1';
|
590 | return fetch(url).then(function(res) {
|
591 | expect(res.status).to.equal(200);
|
592 | return res.text().then(function(result) {
|
593 | expect(result).to.equal('中文');
|
594 | });
|
595 | });
|
596 | });
|
597 |
|
598 | it('should support uncommon content-type order, end with qs', function() {
|
599 | url = base + '/encoding/order2';
|
600 | return fetch(url).then(function(res) {
|
601 | expect(res.status).to.equal(200);
|
602 | return res.text().then(function(result) {
|
603 | expect(result).to.equal('中文');
|
604 | });
|
605 | });
|
606 | });
|
607 |
|
608 | it('should allow piping response body as stream', function(done) {
|
609 | url = base + '/hello';
|
610 | fetch(url).then(function(res) {
|
611 | expect(res.body).to.be.an.instanceof(stream.Transform);
|
612 | res.body.on('data', function(chunk) {
|
613 | if (chunk === null) {
|
614 | return;
|
615 | }
|
616 | expect(chunk.toString()).to.equal('world');
|
617 | });
|
618 | res.body.on('end', function() {
|
619 | done();
|
620 | });
|
621 | });
|
622 | });
|
623 |
|
624 | it('should allow get all responses of a header', function() {
|
625 | url = base + '/cookie';
|
626 | return fetch(url).then(function(res) {
|
627 | expect(res.headers.get('set-cookie')).to.equal('a=1');
|
628 | expect(res.headers.get('Set-Cookie')).to.equal('a=1');
|
629 | expect(res.headers.getAll('set-cookie')).to.deep.equal(['a=1', 'b=1']);
|
630 | expect(res.headers.getAll('Set-Cookie')).to.deep.equal(['a=1', 'b=1']);
|
631 | });
|
632 | });
|
633 |
|
634 | it('should allow deleting header', function() {
|
635 | url = base + '/cookie';
|
636 | return fetch(url).then(function(res) {
|
637 | res.headers.delete('set-cookie');
|
638 | expect(res.headers.get('set-cookie')).to.be.null;
|
639 | expect(res.headers.getAll('set-cookie')).to.be.empty;
|
640 | });
|
641 | });
|
642 |
|
643 | it('should ignore unsupported attributes while reading headers', function() {
|
644 | var FakeHeader = function() {};
|
645 |
|
646 | FakeHeader.prototype.z = 'fake';
|
647 |
|
648 | var res = new FakeHeader;
|
649 |
|
650 | res.a = 'string';
|
651 | res.b = ['1','2'];
|
652 | res.c = '';
|
653 | res.d = [];
|
654 |
|
655 | res.e = 1;
|
656 | res.f = [1, 2];
|
657 |
|
658 | res.g = { a:1 };
|
659 | res.h = undefined;
|
660 | res.i = null;
|
661 | res.j = NaN;
|
662 | res.k = true;
|
663 | res.l = false;
|
664 |
|
665 | var h1 = new Headers(res);
|
666 |
|
667 | expect(h1._headers['a']).to.include('string');
|
668 | expect(h1._headers['b']).to.include('1');
|
669 | expect(h1._headers['b']).to.include('2');
|
670 | expect(h1._headers['c']).to.include('');
|
671 | expect(h1._headers['d']).to.be.undefined;
|
672 |
|
673 | expect(h1._headers['e']).to.include('1');
|
674 | expect(h1._headers['f']).to.include('1');
|
675 | expect(h1._headers['f']).to.include('2');
|
676 |
|
677 | expect(h1._headers['g']).to.be.undefined;
|
678 | expect(h1._headers['h']).to.be.undefined;
|
679 | expect(h1._headers['i']).to.be.undefined;
|
680 | expect(h1._headers['j']).to.be.undefined;
|
681 | expect(h1._headers['k']).to.be.undefined;
|
682 | expect(h1._headers['l']).to.be.undefined;
|
683 |
|
684 | expect(h1._headers['z']).to.be.undefined;
|
685 | });
|
686 |
|
687 | it('should wrap headers', function() {
|
688 | var h1 = new Headers({
|
689 | a: '1'
|
690 | });
|
691 |
|
692 | var h2 = new Headers(h1);
|
693 | h2.set('b', '1');
|
694 |
|
695 | var h3 = new Headers(h2);
|
696 | h3.append('a', '2');
|
697 |
|
698 | expect(h1._headers['a']).to.include('1');
|
699 | expect(h1._headers['a']).to.not.include('2');
|
700 | expect(h1._headers['b']).to.not.include('1');
|
701 |
|
702 | expect(h2._headers['a']).to.include('1');
|
703 | expect(h2._headers['a']).to.not.include('2');
|
704 | expect(h2._headers['b']).to.include('1');
|
705 |
|
706 | expect(h3._headers['a']).to.include('1');
|
707 | expect(h3._headers['a']).to.include('2');
|
708 | expect(h3._headers['b']).to.include('1');
|
709 | });
|
710 |
|
711 | it('should support fetch with Request instance', function() {
|
712 | url = base + '/hello';
|
713 | var req = new Request(url);
|
714 | return fetch(req).then(function(res) {
|
715 | expect(res.url).to.equal(url);
|
716 | expect(res.ok).to.be.true;
|
717 | expect(res.status).to.equal(200);
|
718 | });
|
719 | });
|
720 |
|
721 | it('should support wrapping Request instance', function() {
|
722 | url = base + '/hello';
|
723 | var r1 = new Request(url, {
|
724 | method: 'POST'
|
725 | , follow: 1
|
726 | });
|
727 | var r2 = new Request(r1, {
|
728 | follow: 2
|
729 | })
|
730 | expect(r2.url).to.equal(url);
|
731 | expect(r2.method).to.equal('POST');
|
732 | expect(r1.follow).to.equal(1);
|
733 | expect(r2.follow).to.equal(2);
|
734 | });
|
735 |
|
736 | it('should support overwrite Request instance', function() {
|
737 | url = base + '/inspect';
|
738 | var req = new Request(url, {
|
739 | method: 'POST'
|
740 | , headers: {
|
741 | a: '1'
|
742 | }
|
743 | });
|
744 | return fetch(req, {
|
745 | method: 'GET'
|
746 | , headers: {
|
747 | a: '2'
|
748 | }
|
749 | }).then(function(res) {
|
750 | return res.json();
|
751 | }).then(function(body) {
|
752 | expect(body.method).to.equal('GET');
|
753 | expect(body.headers.a).to.equal('2');
|
754 | });
|
755 | });
|
756 |
|
757 | it('should support https request', function() {
|
758 | this.timeout(5000);
|
759 | url = 'https://github.com/';
|
760 | opts = {
|
761 | method: 'HEAD'
|
762 | };
|
763 | return fetch(url, opts).then(function(res) {
|
764 | expect(res.status).to.equal(200);
|
765 | expect(res.ok).to.be.true;
|
766 | });
|
767 | });
|
768 |
|
769 | });
|