2015-01-26 02:15:07 -08:00
|
|
|
|
|
|
|
// test tools
|
|
|
|
var chai = require('chai');
|
|
|
|
var cap = require('chai-as-promised');
|
|
|
|
chai.use(cap);
|
|
|
|
var expect = chai.expect;
|
|
|
|
var bluebird = require('bluebird');
|
|
|
|
var then = require('promise');
|
2015-04-16 11:46:22 -07:00
|
|
|
var spawn = require('child_process').spawn;
|
2015-01-26 05:58:52 -08:00
|
|
|
var stream = require('stream');
|
2015-01-27 07:33:06 -08:00
|
|
|
var resumer = require('resumer');
|
|
|
|
|
2015-01-26 05:58:52 -08:00
|
|
|
var TestServer = require('./server');
|
2015-01-26 02:15:07 -08:00
|
|
|
|
|
|
|
// test subjects
|
|
|
|
var fetch = require('../index.js');
|
2015-01-27 05:11:26 -08:00
|
|
|
var Headers = require('../lib/headers.js');
|
|
|
|
var Response = require('../lib/response.js');
|
2015-06-03 21:12:27 -07:00
|
|
|
var Request = require('../lib/request.js');
|
2015-01-26 02:15:07 -08:00
|
|
|
// test with native promise on node 0.11, and bluebird for node 0.10
|
|
|
|
fetch.Promise = fetch.Promise || bluebird;
|
|
|
|
|
2015-01-26 05:58:52 -08:00
|
|
|
var url, opts, local, base;
|
2015-01-26 02:15:07 -08:00
|
|
|
|
2015-01-27 07:33:06 -08:00
|
|
|
describe('node-fetch', function() {
|
2015-01-26 02:15:07 -08:00
|
|
|
|
2015-01-26 05:28:23 -08:00
|
|
|
before(function(done) {
|
2015-01-26 05:58:52 -08:00
|
|
|
local = new TestServer();
|
|
|
|
base = 'http://' + local.hostname + ':' + local.port;
|
|
|
|
local.start(done);
|
2015-01-26 05:28:23 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
after(function(done) {
|
2015-01-26 05:58:52 -08:00
|
|
|
local.stop(done);
|
2015-01-26 02:15:07 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should return a promise', function() {
|
|
|
|
url = 'http://example.com/';
|
2015-01-26 05:58:52 -08:00
|
|
|
var p = fetch(url);
|
|
|
|
expect(p).to.be.an.instanceof(fetch.Promise);
|
|
|
|
expect(p).to.have.property('then');
|
2015-01-26 02:15:07 -08:00
|
|
|
});
|
|
|
|
|
2015-01-26 05:58:52 -08:00
|
|
|
it('should allow custom promise', function() {
|
2015-01-26 02:15:07 -08:00
|
|
|
url = 'http://example.com/';
|
|
|
|
var old = fetch.Promise;
|
|
|
|
fetch.Promise = then;
|
|
|
|
expect(fetch(url)).to.be.an.instanceof(then);
|
2015-01-27 07:33:06 -08:00
|
|
|
expect(fetch(url)).to.not.be.an.instanceof(bluebird);
|
2015-01-26 02:15:07 -08:00
|
|
|
fetch.Promise = old;
|
|
|
|
});
|
|
|
|
|
2015-01-27 07:33:06 -08:00
|
|
|
it('should throw error when no promise implementation are found', function() {
|
2015-01-26 09:46:32 -08:00
|
|
|
url = 'http://example.com/';
|
|
|
|
var old = fetch.Promise;
|
|
|
|
fetch.Promise = undefined;
|
|
|
|
expect(function() {
|
|
|
|
fetch(url)
|
|
|
|
}).to.throw(Error);
|
|
|
|
fetch.Promise = old;
|
|
|
|
});
|
|
|
|
|
2015-06-03 21:12:27 -07:00
|
|
|
it('should expose Headers, Response and Request constructors', function() {
|
2015-05-03 01:37:58 -07:00
|
|
|
expect(fetch.Headers).to.equal(Headers);
|
|
|
|
expect(fetch.Response).to.equal(Response);
|
2015-06-03 21:12:27 -07:00
|
|
|
expect(fetch.Request).to.equal(Request);
|
2015-05-03 01:37:58 -07:00
|
|
|
});
|
|
|
|
|
2015-01-26 05:58:52 -08:00
|
|
|
it('should reject with error if url is protocol relative', function() {
|
|
|
|
url = '//example.com/';
|
|
|
|
return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should reject with error if url is relative path', function() {
|
|
|
|
url = '/some/path';
|
2015-01-26 02:15:07 -08:00
|
|
|
return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should reject with error if protocol is unsupported', function() {
|
|
|
|
url = 'ftp://example.com/';
|
|
|
|
return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
2015-01-26 09:46:32 -08:00
|
|
|
it('should reject with error on network failure', function() {
|
|
|
|
url = 'http://localhost:50000/';
|
|
|
|
return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
2015-01-27 05:11:26 -08:00
|
|
|
it('should resolve into response', function() {
|
2015-01-26 05:58:52 -08:00
|
|
|
url = base + '/hello';
|
2015-01-26 02:15:07 -08:00
|
|
|
return fetch(url).then(function(res) {
|
2015-01-27 05:11:26 -08:00
|
|
|
expect(res).to.be.an.instanceof(Response);
|
|
|
|
expect(res.headers).to.be.an.instanceof(Headers);
|
|
|
|
expect(res.body).to.be.an.instanceof(stream.Transform);
|
|
|
|
expect(res.bodyUsed).to.be.false;
|
2015-01-27 07:33:06 -08:00
|
|
|
|
|
|
|
expect(res.url).to.equal(url);
|
2015-01-27 20:17:12 -08:00
|
|
|
expect(res.ok).to.be.true;
|
2015-01-27 07:33:06 -08:00
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
expect(res.statusText).to.equal('OK');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should accept plain text response', function() {
|
|
|
|
url = base + '/plain';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(res.bodyUsed).to.be.true;
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.equal('text');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should accept html response (like plain text)', function() {
|
|
|
|
url = base + '/html';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/html');
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(res.bodyUsed).to.be.true;
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.equal('<html></html>');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should accept json response', function() {
|
|
|
|
url = base + '/json';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('application/json');
|
|
|
|
return res.json().then(function(result) {
|
|
|
|
expect(res.bodyUsed).to.be.true;
|
|
|
|
expect(result).to.be.an('object');
|
|
|
|
expect(result).to.deep.equal({ name: 'value' });
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should send request with custom headers', function() {
|
|
|
|
url = base + '/inspect';
|
|
|
|
opts = {
|
|
|
|
headers: { 'x-custom-header': 'abc' }
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.headers['x-custom-header']).to.equal('abc');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-04-22 08:36:11 -07:00
|
|
|
it('should accept headers instance', function() {
|
|
|
|
url = base + '/inspect';
|
|
|
|
opts = {
|
|
|
|
headers: new Headers({ 'x-custom-header': 'abc' })
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.headers['x-custom-header']).to.equal('abc');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 07:33:06 -08:00
|
|
|
it('should follow redirect code 301', function() {
|
|
|
|
url = base + '/redirect/301';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.url).to.equal(base + '/inspect');
|
|
|
|
expect(res.status).to.equal(200);
|
2015-01-27 21:10:33 -08:00
|
|
|
expect(res.ok).to.be.true;
|
2015-01-27 07:33:06 -08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should follow redirect code 302', function() {
|
|
|
|
url = base + '/redirect/302';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.url).to.equal(base + '/inspect');
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should follow redirect code 303', function() {
|
|
|
|
url = base + '/redirect/303';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.url).to.equal(base + '/inspect');
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should follow redirect code 307', function() {
|
|
|
|
url = base + '/redirect/307';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.url).to.equal(base + '/inspect');
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should follow redirect code 308', function() {
|
|
|
|
url = base + '/redirect/308';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.url).to.equal(base + '/inspect');
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should follow redirect chain', function() {
|
|
|
|
url = base + '/redirect/chain';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.url).to.equal(base + '/inspect');
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 09:00:53 -08:00
|
|
|
it('should obey maximum redirect', function() {
|
2015-01-27 07:33:06 -08:00
|
|
|
url = base + '/redirect/chain';
|
|
|
|
opts = {
|
|
|
|
follow: 1
|
2015-01-27 09:00:53 -08:00
|
|
|
}
|
2015-01-27 07:33:06 -08:00
|
|
|
return expect(fetch(url, opts)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
2015-03-19 09:22:23 -07:00
|
|
|
it('should allow not following redirect', function() {
|
|
|
|
url = base + '/redirect/301';
|
|
|
|
opts = {
|
|
|
|
follow: 0
|
|
|
|
}
|
|
|
|
return expect(fetch(url, opts)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
2015-04-22 08:36:11 -07:00
|
|
|
it('should follow redirect code 301 and keep existing headers', function() {
|
|
|
|
url = base + '/redirect/301';
|
|
|
|
opts = {
|
|
|
|
headers: new Headers({ 'x-custom-header': 'abc' })
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
expect(res.url).to.equal(base + '/inspect');
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.headers['x-custom-header']).to.equal('abc');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 09:00:53 -08:00
|
|
|
it('should reject broken redirect', function() {
|
|
|
|
url = base + '/error/redirect';
|
|
|
|
return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle client-error response', function() {
|
|
|
|
url = base + '/error/400';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
expect(res.status).to.equal(400);
|
|
|
|
expect(res.statusText).to.equal('Bad Request');
|
2015-01-27 20:17:12 -08:00
|
|
|
expect(res.ok).to.be.false;
|
2015-01-27 09:00:53 -08:00
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(res.bodyUsed).to.be.true;
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.equal('client error');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle server-error response', function() {
|
|
|
|
url = base + '/error/500';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
expect(res.status).to.equal(500);
|
|
|
|
expect(res.statusText).to.equal('Internal Server Error');
|
2015-01-27 20:17:12 -08:00
|
|
|
expect(res.ok).to.be.false;
|
2015-01-27 09:00:53 -08:00
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(res.bodyUsed).to.be.true;
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.equal('server error');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle network-error response', function() {
|
|
|
|
url = base + '/error/reset';
|
|
|
|
return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
2015-01-27 21:01:10 -08:00
|
|
|
it('should reject invalid json response', function() {
|
|
|
|
url = base + '/error/json';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('application/json');
|
|
|
|
return expect(res.json()).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should handle empty response', function() {
|
|
|
|
url = base + '/empty';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.status).to.equal(204);
|
|
|
|
expect(res.statusText).to.equal('No Content');
|
|
|
|
expect(res.ok).to.be.true;
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.be.empty;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 07:33:06 -08:00
|
|
|
it('should decompress gzip response', function() {
|
|
|
|
url = base + '/gzip';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.equal('hello world');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should decompress deflate response', function() {
|
|
|
|
url = base + '/deflate';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.equal('hello world');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 21:01:10 -08:00
|
|
|
it('should skip decompression if unsupported', function() {
|
|
|
|
url = base + '/sdch';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.equal('fake sdch string');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 07:33:06 -08:00
|
|
|
it('should allow disabling auto decompression', function() {
|
|
|
|
url = base + '/gzip';
|
|
|
|
opts = {
|
|
|
|
compress: false
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.be.a('string');
|
|
|
|
expect(result).to.not.equal('hello world');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow custom timeout', function() {
|
2015-04-16 22:26:55 -07:00
|
|
|
this.timeout(500);
|
2015-01-27 07:33:06 -08:00
|
|
|
url = base + '/timeout';
|
|
|
|
opts = {
|
|
|
|
timeout: 100
|
|
|
|
};
|
|
|
|
return expect(fetch(url, opts)).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
|
2015-04-16 22:26:55 -07:00
|
|
|
it('should allow custom timeout on response body', function() {
|
|
|
|
this.timeout(500);
|
|
|
|
url = base + '/slow';
|
|
|
|
opts = {
|
|
|
|
timeout: 100
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
expect(res.ok).to.be.true;
|
|
|
|
return expect(res.text()).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should clear internal timeout on fetch response', function (done) {
|
|
|
|
this.timeout(1000);
|
|
|
|
spawn('node', ['-e', 'require("./")("' + base + '/hello", { timeout: 5000 })'])
|
|
|
|
.on('exit', function () {
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should clear internal timeout on fetch redirect', function (done) {
|
|
|
|
this.timeout(1000);
|
|
|
|
spawn('node', ['-e', 'require("./")("' + base + '/redirect/301", { timeout: 5000 })'])
|
|
|
|
.on('exit', function () {
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should clear internal timeout on fetch error', function (done) {
|
|
|
|
this.timeout(1000);
|
|
|
|
spawn('node', ['-e', 'require("./")("' + base + '/error/reset", { timeout: 5000 })'])
|
|
|
|
.on('exit', function () {
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 07:33:06 -08:00
|
|
|
it('should allow POST request', function() {
|
|
|
|
url = base + '/inspect';
|
|
|
|
opts = {
|
|
|
|
method: 'POST'
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.method).to.equal('POST');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow POST request with string body', function() {
|
|
|
|
url = base + '/inspect';
|
|
|
|
opts = {
|
|
|
|
method: 'POST'
|
|
|
|
, body: 'a=1'
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.method).to.equal('POST');
|
|
|
|
expect(res.body).to.equal('a=1');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow POST request with readable stream as body', function() {
|
|
|
|
url = base + '/inspect';
|
|
|
|
opts = {
|
|
|
|
method: 'POST'
|
|
|
|
, body: resumer().queue('a=1').end()
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.method).to.equal('POST');
|
|
|
|
expect(res.body).to.equal('a=1');
|
2015-01-26 02:15:07 -08:00
|
|
|
});
|
|
|
|
});
|
2015-01-26 05:58:52 -08:00
|
|
|
|
2015-01-27 09:00:53 -08:00
|
|
|
it('should allow PUT request', function() {
|
|
|
|
url = base + '/inspect';
|
|
|
|
opts = {
|
|
|
|
method: 'PUT'
|
|
|
|
, body: 'a=1'
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.method).to.equal('PUT');
|
|
|
|
expect(res.body).to.equal('a=1');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow DELETE request', function() {
|
|
|
|
url = base + '/inspect';
|
|
|
|
opts = {
|
|
|
|
method: 'DELETE'
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.method).to.equal('DELETE');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 21:01:10 -08:00
|
|
|
it('should allow PATCH request', function() {
|
|
|
|
url = base + '/inspect';
|
|
|
|
opts = {
|
|
|
|
method: 'PATCH'
|
|
|
|
, body: 'a=1'
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
return res.json();
|
|
|
|
}).then(function(res) {
|
|
|
|
expect(res.method).to.equal('PATCH');
|
|
|
|
expect(res.body).to.equal('a=1');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 09:00:53 -08:00
|
|
|
it('should allow HEAD request', function() {
|
|
|
|
url = base + '/hello';
|
|
|
|
opts = {
|
|
|
|
method: 'HEAD'
|
|
|
|
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
expect(res.statusText).to.equal('OK');
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
expect(res.body).to.be.an.instanceof(stream.Transform);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should reject decoding body twice', function() {
|
|
|
|
url = base + '/plain';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(res.bodyUsed).to.be.true;
|
|
|
|
return expect(res.text()).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-28 06:56:25 -08:00
|
|
|
it('should support maximum response size, multiple chunk', function() {
|
|
|
|
url = base + '/size/chunk';
|
2015-01-27 09:00:53 -08:00
|
|
|
opts = {
|
2015-01-28 06:56:25 -08:00
|
|
|
size: 5
|
2015-01-27 09:00:53 -08:00
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
return expect(res.text()).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-28 06:56:25 -08:00
|
|
|
it('should support maximum response size, single chunk', function() {
|
|
|
|
url = base + '/size/long';
|
|
|
|
opts = {
|
|
|
|
size: 5
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
expect(res.headers.get('content-type')).to.equal('text/plain');
|
|
|
|
return expect(res.text()).to.eventually.be.rejectedWith(Error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should support encoding decode, xml dtd detect', function() {
|
|
|
|
url = base + '/encoding/euc-jp';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.equal('<?xml version="1.0" encoding="EUC-JP"?><title>日本語</title>');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should support encoding decode, content-type detect', function() {
|
2015-01-27 09:00:53 -08:00
|
|
|
url = base + '/encoding/shift-jis';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.equal('<div>日本語</div>');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should support encoding decode, html5 detect', function() {
|
|
|
|
url = base + '/encoding/gbk';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.equal('<meta charset="gbk"><div>中文</div>');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should support encoding decode, html4 detect', function() {
|
|
|
|
url = base + '/encoding/gb2312';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.equal('<meta http-equiv="Content-Type" content="text/html; charset=gb2312"><div>中文</div>');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 21:01:10 -08:00
|
|
|
it('should default to utf8 encoding', function() {
|
|
|
|
url = base + '/encoding/utf8';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
expect(res.headers.get('content-type')).to.be.null;
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.equal('中文');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-03-23 21:31:04 -07:00
|
|
|
it('should support uncommon content-type order, charset in front', function() {
|
|
|
|
url = base + '/encoding/order1';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.equal('中文');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should support uncommon content-type order, end with qs', function() {
|
|
|
|
url = base + '/encoding/order2';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
return res.text().then(function(result) {
|
|
|
|
expect(result).to.equal('中文');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 21:01:10 -08:00
|
|
|
it('should allow piping response body as stream', function(done) {
|
|
|
|
url = base + '/hello';
|
|
|
|
fetch(url).then(function(res) {
|
|
|
|
expect(res.body).to.be.an.instanceof(stream.Transform);
|
|
|
|
res.body.on('data', function(chunk) {
|
|
|
|
if (chunk === null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
expect(chunk.toString()).to.equal('world');
|
|
|
|
});
|
|
|
|
res.body.on('end', function() {
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 09:00:53 -08:00
|
|
|
it('should allow get all responses of a header', function() {
|
|
|
|
url = base + '/cookie';
|
|
|
|
return fetch(url).then(function(res) {
|
2015-01-27 21:01:10 -08:00
|
|
|
expect(res.headers.get('set-cookie')).to.equal('a=1');
|
|
|
|
expect(res.headers.get('Set-Cookie')).to.equal('a=1');
|
2015-01-27 09:00:53 -08:00
|
|
|
expect(res.headers.getAll('set-cookie')).to.deep.equal(['a=1', 'b=1']);
|
2015-01-27 21:01:10 -08:00
|
|
|
expect(res.headers.getAll('Set-Cookie')).to.deep.equal(['a=1', 'b=1']);
|
2015-01-27 09:00:53 -08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow deleting header', function() {
|
|
|
|
url = base + '/cookie';
|
|
|
|
return fetch(url).then(function(res) {
|
|
|
|
res.headers.delete('set-cookie');
|
|
|
|
expect(res.headers.get('set-cookie')).to.be.null;
|
|
|
|
expect(res.headers.getAll('set-cookie')).to.be.empty;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-04-28 21:15:08 -07:00
|
|
|
it('should ignore unsupported attributes while reading headers', function() {
|
2015-03-19 08:38:27 -07:00
|
|
|
var FakeHeader = function() {};
|
2015-05-03 21:05:06 -07:00
|
|
|
// prototypes are ignored
|
|
|
|
FakeHeader.prototype.z = 'fake';
|
2015-04-28 21:15:08 -07:00
|
|
|
|
2015-03-19 08:38:27 -07:00
|
|
|
var res = new FakeHeader;
|
2015-05-03 21:05:06 -07:00
|
|
|
// valid
|
2015-03-19 08:38:27 -07:00
|
|
|
res.a = 'string';
|
2015-04-28 21:15:08 -07:00
|
|
|
res.b = ['1','2'];
|
|
|
|
res.c = '';
|
|
|
|
res.d = [];
|
2015-05-03 21:05:06 -07:00
|
|
|
// common mistakes, normalized
|
|
|
|
res.e = 1;
|
|
|
|
res.f = [1, 2];
|
|
|
|
// invalid, ignored
|
|
|
|
res.g = { a:1 };
|
|
|
|
res.h = undefined;
|
|
|
|
res.i = null;
|
|
|
|
res.j = NaN;
|
|
|
|
res.k = true;
|
|
|
|
res.l = false;
|
|
|
|
|
|
|
|
var h1 = new Headers(res);
|
|
|
|
|
|
|
|
expect(h1._headers['a']).to.include('string');
|
|
|
|
expect(h1._headers['b']).to.include('1');
|
|
|
|
expect(h1._headers['b']).to.include('2');
|
|
|
|
expect(h1._headers['c']).to.include('');
|
|
|
|
expect(h1._headers['d']).to.be.undefined;
|
|
|
|
|
|
|
|
expect(h1._headers['e']).to.include('1');
|
|
|
|
expect(h1._headers['f']).to.include('1');
|
|
|
|
expect(h1._headers['f']).to.include('2');
|
|
|
|
|
|
|
|
expect(h1._headers['g']).to.be.undefined;
|
|
|
|
expect(h1._headers['h']).to.be.undefined;
|
|
|
|
expect(h1._headers['i']).to.be.undefined;
|
|
|
|
expect(h1._headers['j']).to.be.undefined;
|
|
|
|
expect(h1._headers['k']).to.be.undefined;
|
|
|
|
expect(h1._headers['l']).to.be.undefined;
|
|
|
|
|
|
|
|
expect(h1._headers['z']).to.be.undefined;
|
2015-03-19 08:38:27 -07:00
|
|
|
});
|
|
|
|
|
2015-04-22 08:36:11 -07:00
|
|
|
it('should wrap headers', function() {
|
|
|
|
var h1 = new Headers({
|
|
|
|
a: '1'
|
|
|
|
});
|
|
|
|
|
|
|
|
var h2 = new Headers(h1);
|
|
|
|
h2.set('b', '1');
|
|
|
|
|
|
|
|
var h3 = new Headers(h2);
|
|
|
|
h3.append('a', '2');
|
|
|
|
|
|
|
|
expect(h1._headers['a']).to.include('1');
|
|
|
|
expect(h1._headers['a']).to.not.include('2');
|
|
|
|
expect(h1._headers['b']).to.not.include('1');
|
|
|
|
|
|
|
|
expect(h2._headers['a']).to.include('1');
|
|
|
|
expect(h2._headers['a']).to.not.include('2');
|
|
|
|
expect(h2._headers['b']).to.include('1');
|
|
|
|
|
|
|
|
expect(h3._headers['a']).to.include('1');
|
|
|
|
expect(h3._headers['a']).to.include('2');
|
|
|
|
expect(h3._headers['b']).to.include('1');
|
|
|
|
});
|
|
|
|
|
2015-06-03 21:12:27 -07:00
|
|
|
it('should support fetch with Request instance', function() {
|
|
|
|
url = base + '/hello';
|
|
|
|
var req = new Request(url);
|
|
|
|
return fetch(req).then(function(res) {
|
|
|
|
expect(res.url).to.equal(url);
|
|
|
|
expect(res.ok).to.be.true;
|
|
|
|
expect(res.status).to.equal(200);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-01-27 09:00:53 -08:00
|
|
|
it('should support https request', function() {
|
|
|
|
this.timeout(5000);
|
|
|
|
url = 'https://github.com/';
|
|
|
|
opts = {
|
|
|
|
method: 'HEAD'
|
|
|
|
};
|
|
|
|
return fetch(url, opts).then(function(res) {
|
|
|
|
expect(res.status).to.equal(200);
|
2015-01-27 15:41:48 -08:00
|
|
|
expect(res.ok).to.be.true;
|
2015-01-27 09:00:53 -08:00
|
|
|
});
|
|
|
|
});
|
2015-04-22 08:36:11 -07:00
|
|
|
|
2015-01-26 02:15:07 -08:00
|
|
|
});
|