node-fetch/test/test.js

455 lines
12 KiB
JavaScript
Raw Normal View History

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-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-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-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');
});
});
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);
});
});
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 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);
});
});
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-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 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');
});
});
});
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() {
url = base + '/timeout';
opts = {
timeout: 100
};
return expect(fetch(url, opts)).to.eventually.be.rejectedWith(Error);
});
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');
});
});
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);
});
});
});
it('should support maximum response size', function() {
url = base + '/long';
opts = {
size: 1
};
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, conte-type detect', function() {
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>');
});
});
});
it('should allow get all responses of a header', function() {
url = base + '/cookie';
return fetch(url).then(function(res) {
expect(res.headers.getAll('set-cookie')).to.deep.equal(['a=1', 'b=1']);
});
});
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;
});
});
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);
expect(res.ok).to.be.true;
2015-01-27 09:00:53 -08:00
});
});
2015-01-26 02:15:07 -08:00
});