From 838071247d986a3f706392640ea299ec37f67073 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Mon, 10 Oct 2016 11:50:04 -0700 Subject: [PATCH] Convert all files to ES2015 (#182) Elements of this commit come from #140 by @gwicke. --- package.json | 5 +- src/body.js | 412 +++++++++++++-------------- src/fetch-error.js | 4 +- src/index.js | 109 +++---- src/request.js | 112 ++++---- src/response.js | 69 +++-- test/server.js | 588 +++++++++++++++++++------------------- test/test.js | 691 ++++++++++++++++++++++----------------------- 8 files changed, 986 insertions(+), 1004 deletions(-) diff --git a/package.json b/package.json index 7014d43..1552704 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "babel -d lib src", "prepublish": "npm run build", - "test": "mocha --compilers js:babel-register test/test.js", + "test": "mocha --compilers js:babel-polyfill --compilers js:babel-register test/test.js", "report": "cross-env BABEL_ENV=test nyc --reporter lcov --reporter text mocha -R spec test/test.js", "coverage": "cross-env BABEL_ENV=test nyc --reporter lcovonly mocha -R spec test/test.js && cat ./coverage/lcov.info | coveralls" }, @@ -29,6 +29,7 @@ "babel-cli": "^6.16.0", "babel-plugin-istanbul": "^2.0.1", "babel-plugin-transform-runtime": "^6.15.0", + "babel-polyfill": "^6.16.0", "babel-preset-es2015": "^6.16.0", "babel-register": "^6.16.3", "bluebird": "^3.3.4", @@ -44,6 +45,7 @@ "resumer": "0.0.0" }, "dependencies": { + "babel-runtime": "^6.11.6", "encoding": "^0.1.11", "is-stream": "^1.0.1" }, @@ -67,6 +69,7 @@ "src/*.js" ], "require": [ + "babel-polyfill", "babel-register" ], "sourceMap": false, diff --git a/src/body.js b/src/body.js index e7bbe1d..ab76421 100644 --- a/src/body.js +++ b/src/body.js @@ -5,12 +5,17 @@ * Body interface provides common methods for Request and Response */ -var convert = require('encoding').convert; -var bodyStream = require('is-stream'); -var PassThrough = require('stream').PassThrough; -var FetchError = require('./fetch-error'); +import {convert} from 'encoding'; +import bodyStream from 'is-stream'; +import {PassThrough} from 'stream'; +import FetchError from './fetch-error.js'; -module.exports = Body; +const DISTURBED = Symbol('disturbed'); +const BYTES = Symbol('bytes'); +const RAW = Symbol('raw'); +const ABORT = Symbol('abort'); +const CONVERT = Symbol('convert'); +const DECODE = Symbol('decode'); /** * Body class @@ -19,221 +24,210 @@ module.exports = Body; * @param Object opts Response options * @return Void */ -function Body(body, opts) { +export default class Body { + constructor(body, { + size = 0, + timeout = 0 + } = {}) { + this.body = body; + this[DISTURBED] = false; + this.size = size; + this[BYTES] = 0; + this.timeout = timeout; + this[RAW] = []; + this[ABORT] = false; + } - opts = opts || {}; + get bodyUsed() { + return this[DISTURBED]; + } - this.body = body; - this.bodyUsed = false; - this.size = opts.size || 0; - this.timeout = opts.timeout || 0; - this._raw = []; - this._abort = false; + /** + * Decode response as json + * + * @return Promise + */ + json() { + // for 204 No Content response, buffer will be empty, parsing it will throw error + if (this.status === 204) { + return Body.Promise.resolve({}); + } + + return this[DECODE]().then(buffer => JSON.parse(buffer.toString())); + } + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return this[DECODE]().then(buffer => buffer.toString()); + } + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return this[DECODE](); + } + + /** + * Decode buffers into utf-8 string + * + * @return Promise + */ + [DECODE]() { + if (this[DISTURBED]) { + return Body.Promise.reject(new Error(`body used already for: ${this.url}`)); + } + + this[DISTURBED] = true; + this[BYTES] = 0; + this[ABORT] = false; + this[RAW] = []; + + return new Body.Promise((resolve, reject) => { + let resTimeout; + + // body is string + if (typeof this.body === 'string') { + this[BYTES] = this.body.length; + this[RAW] = [new Buffer(this.body)]; + return resolve(this[CONVERT]()); + } + + // body is buffer + if (this.body instanceof Buffer) { + this[BYTES] = this.body.length; + this[RAW] = [this.body]; + return resolve(this[CONVERT]()); + } + + // allow timeout on slow response body + if (this.timeout) { + resTimeout = setTimeout(() => { + this[ABORT] = true; + reject(new FetchError('response timeout at ' + this.url + ' over limit: ' + this.timeout, 'body-timeout')); + }, this.timeout); + } + + // handle stream error, such as incorrect content-encoding + this.body.on('error', err => { + reject(new FetchError('invalid response body at: ' + this.url + ' reason: ' + err.message, 'system', err)); + }); + + // body is stream + this.body.on('data', chunk => { + if (this[ABORT] || chunk === null) { + return; + } + + if (this.size && this[BYTES] + chunk.length > this.size) { + this[ABORT] = true; + reject(new FetchError(`content size at ${this.url} over limit: ${this.size}`, 'max-size')); + return; + } + + this[BYTES] += chunk.length; + this[RAW].push(chunk); + }); + + this.body.on('end', () => { + if (this[ABORT]) { + return; + } + + clearTimeout(resTimeout); + resolve(this[CONVERT]()); + }); + }); + } + + /** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param String encoding Target encoding + * @return String + */ + [CONVERT](encoding = 'utf-8') { + const ct = this.headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + // skip encoding detection altogether if not html/xml/plain text + if (!/text\/html|text\/plain|\+xml|\/xml/i.test(ct)) { + return Buffer.concat(this[RAW]); + } + + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + if (!res && this[RAW].length > 0) { + for (let i = 0; i < this[RAW].length; i++) { + str += this[RAW][i].toString() + if (str.length > 1024) { + break; + } + } + str = str.substr(0, 1024); + } + + // html5 + if (!res && str) { + res = / self.size) { - self._abort = true; - reject(new FetchError('content size at ' + self.url + ' over limit: ' + self.size, 'max-size')); - return; - } - - self._bytes += chunk.length; - self._raw.push(chunk); - }); - - self.body.on('end', function() { - if (self._abort) { - return; - } - - clearTimeout(resTimeout); - resolve(self._convert()); - }); - }); - -}; - -/** - * Detect buffer encoding and convert to target encoding - * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding - * - * @param String encoding Target encoding - * @return String - */ -Body.prototype._convert = function(encoding) { - - encoding = encoding || 'utf-8'; - - var ct = this.headers.get('content-type'); - var charset = 'utf-8'; - var res, str; - - // header - if (ct) { - // skip encoding detection altogether if not html/xml/plain text - if (!/text\/html|text\/plain|\+xml|\/xml/i.test(ct)) { - return Buffer.concat(this._raw); - } - - res = /charset=([^;]*)/i.exec(ct); - } - - // no charset in content type, peek at response body for at most 1024 bytes - if (!res && this._raw.length > 0) { - for (var i = 0; i < this._raw.length; i++) { - str += this._raw[i].toString() - if (str.length > 1024) { - break; - } - } - str = str.substr(0, 1024); - } - - // html5 - if (!res && str) { - res = / { // build request object - var options = new Request(url, opts); + const options = new Request(url, opts); if (!options.protocol || !options.hostname) { throw new Error('only absolute urls are supported'); @@ -58,15 +46,10 @@ function Fetch(url, opts) { throw new Error('only http(s) protocols are supported'); } - var send; - if (options.protocol === 'https:') { - send = https.request; - } else { - send = http.request; - } + const send = (options.protocol === 'https:' ? https : http).request; // normalize headers - var headers = new Headers(options.headers); + const headers = new Headers(options.headers); if (options.compress) { headers.set('accept-encoding', 'gzip,deflate'); @@ -86,7 +69,7 @@ function Fetch(url, opts) { // detect form data input from form-data module, this hack avoid the need to pass multipart header manually if (!headers.has('content-type') && options.body && typeof options.body.getBoundary === 'function') { - headers.set('content-type', 'multipart/form-data; boundary=' + options.body.getBoundary()); + headers.set('content-type', `multipart/form-data; boundary=${options.body.getBoundary()}`); } // bring node-fetch closer to browser behavior by setting content-length automatically @@ -116,40 +99,40 @@ function Fetch(url, opts) { } // send request - var req = send(options); - var reqTimeout; + const req = send(options); + let reqTimeout; if (options.timeout) { - req.once('socket', function(socket) { - reqTimeout = setTimeout(function() { + req.once('socket', socket => { + reqTimeout = setTimeout(() => { req.abort(); - reject(new FetchError('network timeout at: ' + options.url, 'request-timeout')); + reject(new FetchError(`network timeout at: ${options.url}`, 'request-timeout')); }, options.timeout); }); } - req.on('error', function(err) { + req.on('error', err => { clearTimeout(reqTimeout); - reject(new FetchError('request to ' + options.url + ' failed, reason: ' + err.message, 'system', err)); + reject(new FetchError(`request to ${options.url} failed, reason: ${err.message}`, 'system', err)); }); - req.on('response', function(res) { + req.on('response', res => { clearTimeout(reqTimeout); // handle redirect - if (self.isRedirect(res.statusCode) && options.redirect !== 'manual') { + if (fetch.isRedirect(res.statusCode) && options.redirect !== 'manual') { if (options.redirect === 'error') { - reject(new FetchError('redirect mode is set to error: ' + options.url, 'no-redirect')); + reject(new FetchError(`redirect mode is set to error: ${options.url}`, 'no-redirect')); return; } if (options.counter >= options.follow) { - reject(new FetchError('maximum redirect reached at: ' + options.url, 'max-redirect')); + reject(new FetchError(`maximum redirect reached at: ${options.url}`, 'max-redirect')); return; } if (!res.headers.location) { - reject(new FetchError('redirect location header missing at: ' + options.url, 'invalid-redirect')); + reject(new FetchError(`redirect location header missing at: ${options.url}`, 'invalid-redirect')); return; } @@ -164,19 +147,19 @@ function Fetch(url, opts) { options.counter++; - resolve(Fetch(resolve_url(options.url, res.headers.location), options)); + resolve(fetch(resolve_url(options.url, res.headers.location), options)); return; } // normalize location header for manual redirect mode - var headers = new Headers(res.headers); + const headers = new Headers(res.headers); if (options.redirect === 'manual' && headers.has('location')) { headers.set('location', resolve_url(options.url, headers.get('location'))); } // prepare response - var body = res.pipe(new stream.PassThrough()); - var response_options = { + let body = res.pipe(new PassThrough()); + const response_options = { url: options.url , status: res.statusCode , statusText: res.statusMessage @@ -186,7 +169,7 @@ function Fetch(url, opts) { }; // response object - var output; + let output; // in following scenarios we ignore compression support // 1. compression support is disabled @@ -201,7 +184,7 @@ function Fetch(url, opts) { } // otherwise, check for gzip or deflate - var name = headers.get('content-encoding'); + let name = headers.get('content-encoding'); // for gzip if (name == 'gzip' || name == 'x-gzip') { @@ -214,8 +197,8 @@ function Fetch(url, opts) { } else if (name == 'deflate' || name == 'x-deflate') { // handle the infamous raw deflate response from old servers // a hack for old IIS and Apache servers - var raw = res.pipe(new stream.PassThrough()); - raw.once('data', function(chunk) { + const raw = res.pipe(new PassThrough()); + raw.once('data', chunk => { // see http://stackoverflow.com/questions/37519828 if ((chunk[0] & 0x0F) === 0x08) { body = body.pipe(zlib.createInflate()); @@ -254,18 +237,18 @@ function Fetch(url, opts) { }; +module.exports = fetch; + /** * Redirect code matching * * @param Number code Status code * @return Boolean */ -Fetch.prototype.isRedirect = function(code) { - return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; -} +fetch.isRedirect = code => code === 301 || code === 302 || code === 303 || code === 307 || code === 308; // expose Promise -Fetch.Promise = global.Promise; -Fetch.Response = Response; -Fetch.Headers = Headers; -Fetch.Request = Request; +fetch.Promise = global.Promise; +fetch.Response = Response; +fetch.Headers = Headers; +fetch.Request = Request; diff --git a/src/request.js b/src/request.js index ec80635..1508d67 100644 --- a/src/request.js +++ b/src/request.js @@ -5,11 +5,9 @@ * Request class contains server only options */ -var parse_url = require('url').parse; -import Headers from './headers'; -var Body = require('./body'); - -module.exports = Request; +import { parse as parse_url } from 'url'; +import Headers from './headers.js'; +import Body, { clone } from './body'; /** * Request class @@ -18,58 +16,62 @@ module.exports = Request; * @param Object init Custom options * @return Void */ -function Request(input, init) { - var url, url_parsed; +export default class Request extends Body { + constructor(input, init = {}) { + let url, url_parsed; - // normalize input - if (!(input instanceof Request)) { - url = input; - url_parsed = parse_url(url); - input = {}; - } else { - url = input.url; - url_parsed = parse_url(url); + // normalize input + if (!(input instanceof Request)) { + url = input; + url_parsed = parse_url(url); + input = {}; + } else { + url = input.url; + url_parsed = parse_url(url); + } + + super(init.body || clone(input), { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + // fetch spec options + this.method = init.method || input.method || 'GET'; + this.redirect = init.redirect || input.redirect || 'follow'; + this.headers = new Headers(init.headers || input.headers || {}); + this.url = url; + + // server only options + this.follow = init.follow !== undefined ? + init.follow : input.follow !== undefined ? + input.follow : 20; + this.compress = init.compress !== undefined ? + init.compress : input.compress !== undefined ? + input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + + // server request options + this.protocol = url_parsed.protocol; + this.hostname = url_parsed.hostname; + this.port = url_parsed.port; + this.path = url_parsed.path; + this.auth = url_parsed.auth; } - // normalize init - init = init || {}; + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } - // fetch spec options - this.method = init.method || input.method || 'GET'; - this.redirect = init.redirect || input.redirect || 'follow'; - this.headers = new Headers(init.headers || input.headers || {}); - this.url = url; - - // server only options - this.follow = init.follow !== undefined ? - init.follow : input.follow !== undefined ? - input.follow : 20; - this.compress = init.compress !== undefined ? - init.compress : input.compress !== undefined ? - input.compress : true; - this.counter = init.counter || input.counter || 0; - this.agent = init.agent || input.agent; - - Body.call(this, init.body || this._clone(input), { - timeout: init.timeout || input.timeout || 0, - size: init.size || input.size || 0 - }); - - // server request options - this.protocol = url_parsed.protocol; - this.hostname = url_parsed.hostname; - this.port = url_parsed.port; - this.path = url_parsed.path; - this.auth = url_parsed.auth; + /** + * Tag used by `Object.prototype.toString()`. + */ + get [Symbol.toStringTag]() { + return 'Request'; + } } - -Request.prototype = Object.create(Body.prototype); - -/** - * Clone this request - * - * @return Request - */ -Request.prototype.clone = function() { - return new Request(this); -}; diff --git a/src/response.js b/src/response.js index b079bd0..fb53a78 100644 --- a/src/response.js +++ b/src/response.js @@ -5,11 +5,9 @@ * Response class provides content decoding */ -var http = require('http'); -import Headers from './headers'; -var Body = require('./body'); - -module.exports = Response; +import { STATUS_CODES } from 'http'; +import Headers from './headers.js'; +import Body, { clone } from './body'; /** * Response class @@ -18,33 +16,44 @@ module.exports = Response; * @param Object opts Response options * @return Void */ -function Response(body, opts) { +export default class Response extends Body { + constructor(body, opts = {}) { + super(body, opts); - opts = opts || {}; + this.url = opts.url; + this.status = opts.status || 200; + this.statusText = opts.statusText || STATUS_CODES[this.status]; + this.headers = new Headers(opts.headers); + } - this.url = opts.url; - this.status = opts.status || 200; - this.statusText = opts.statusText || http.STATUS_CODES[this.status]; - this.headers = new Headers(opts.headers); - this.ok = this.status >= 200 && this.status < 300; + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this.status >= 200 && this.status < 300; + } - Body.call(this, body, opts); + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url + , status: this.status + , statusText: this.statusText + , headers: this.headers + , ok: this.ok + }); + + } + + /** + * Tag used by `Object.prototype.toString()`. + */ + get [Symbol.toStringTag]() { + return 'Response'; + } } - -Response.prototype = Object.create(Body.prototype); - -/** - * Clone this response - * - * @return Response - */ -Response.prototype.clone = function() { - return new Response(this._clone(this), { - url: this.url - , status: this.status - , statusText: this.statusText - , headers: this.headers - , ok: this.ok - }); -}; diff --git a/test/server.js b/test/server.js index 08e582d..5a75b29 100644 --- a/test/server.js +++ b/test/server.js @@ -1,337 +1,331 @@ +import 'babel-polyfill'; +import * as http from 'http'; +import { parse } from 'url'; +import * as zlib from 'zlib'; +import * as stream from 'stream'; +import { convert } from 'encoding'; +import { multipart as Multipart } from 'parted'; -var http = require('http'); -var parse = require('url').parse; -var zlib = require('zlib'); -var stream = require('stream'); -var convert = require('encoding').convert; -var Multipart = require('parted').multipart; - -module.exports = TestServer; - -function TestServer() { - this.server = http.createServer(this.router); - this.port = 30001; - this.hostname = 'localhost'; - this.server.on('error', function(err) { - console.log(err.stack); - }); - this.server.on('connection', function(socket) { - socket.setTimeout(1500); - }); -} - -TestServer.prototype.start = function(cb) { - this.server.listen(this.port, this.hostname, cb); -} - -TestServer.prototype.stop = function(cb) { - this.server.close(cb); -} - -TestServer.prototype.router = function(req, res) { - - var p = parse(req.url).pathname; - - if (p === '/hello') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.end('world'); - } - - if (p === '/plain') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.end('text'); - } - - if (p === '/options') { - res.statusCode = 200; - res.setHeader('Allow', 'GET, HEAD, OPTIONS'); - res.end('hello world'); - } - - if (p === '/html') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/html'); - res.end(''); - } - - if (p === '/json') { - res.statusCode = 200; - res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify({ - name: 'value' - })); - } - - if (p === '/gzip') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.setHeader('Content-Encoding', 'gzip'); - zlib.gzip('hello world', function(err, buffer) { - res.end(buffer); +export default class TestServer { + constructor() { + this.server = http.createServer(this.router); + this.port = 30001; + this.hostname = 'localhost'; + this.server.on('error', function(err) { + console.log(err.stack); + }); + this.server.on('connection', function(socket) { + socket.setTimeout(1500); }); } - if (p === '/deflate') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.setHeader('Content-Encoding', 'deflate'); - zlib.deflate('hello world', function(err, buffer) { - res.end(buffer); - }); + start(cb) { + this.server.listen(this.port, this.hostname, cb); } - if (p === '/deflate-raw') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.setHeader('Content-Encoding', 'deflate'); - zlib.deflateRaw('hello world', function(err, buffer) { - res.end(buffer); - }); + stop(cb) { + this.server.close(cb); } - if (p === '/sdch') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.setHeader('Content-Encoding', 'sdch'); - res.end('fake sdch string'); - } + router(req, res) { + let p = parse(req.url).pathname; - if (p === '/invalid-content-encoding') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.setHeader('Content-Encoding', 'gzip'); - res.end('fake gzip string'); - } + if (p === '/hello') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('world'); + } - if (p === '/timeout') { - setTimeout(function() { + if (p === '/plain') { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('text'); - }, 1000); - } + } - if (p === '/slow') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.write('test'); - setTimeout(function() { - res.end('test'); - }, 1000); - } + if (p === '/options') { + res.statusCode = 200; + res.setHeader('Allow', 'GET, HEAD, OPTIONS'); + res.end('hello world'); + } - if (p === '/cookie') { - res.statusCode = 200; - res.setHeader('Set-Cookie', ['a=1', 'b=1']); - res.end('cookie'); - } + if (p === '/html') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/html'); + res.end(''); + } - if (p === '/size/chunk') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - setTimeout(function() { + if (p === '/json') { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify({ + name: 'value' + })); + } + + if (p === '/gzip') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Encoding', 'gzip'); + zlib.gzip('hello world', function(err, buffer) { + res.end(buffer); + }); + } + + if (p === '/deflate') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Encoding', 'deflate'); + zlib.deflate('hello world', function(err, buffer) { + res.end(buffer); + }); + } + + if (p === '/deflate-raw') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Encoding', 'deflate'); + zlib.deflateRaw('hello world', function(err, buffer) { + res.end(buffer); + }); + } + + if (p === '/sdch') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Encoding', 'sdch'); + res.end('fake sdch string'); + } + + if (p === '/invalid-content-encoding') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Encoding', 'gzip'); + res.end('fake gzip string'); + } + + if (p === '/timeout') { + setTimeout(function() { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('text'); + }, 1000); + } + + if (p === '/slow') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); res.write('test'); - }, 50); - setTimeout(function() { - res.end('test'); - }, 100); - } - - if (p === '/size/long') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain'); - res.end('testtest'); - } - - if (p === '/encoding/gbk') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/html'); - res.end(convert('
中文
', 'gbk')); - } - - if (p === '/encoding/gb2312') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/html'); - res.end(convert('
中文
', 'gb2312')); - } - - if (p === '/encoding/shift-jis') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/html; charset=Shift-JIS'); - res.end(convert('
日本語
', 'Shift_JIS')); - } - - if (p === '/encoding/euc-jp') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/xml'); - res.end(convert('日本語', 'EUC-JP')); - } - - if (p === '/encoding/utf8') { - res.statusCode = 200; - res.end('中文'); - } - - if (p === '/encoding/order1') { - res.statusCode = 200; - res.setHeader('Content-Type', 'charset=gbk; text/plain'); - res.end(convert('中文', 'gbk')); - } - - if (p === '/encoding/order2') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/plain; charset=gbk; qs=1'); - res.end(convert('中文', 'gbk')); - } - - if (p === '/encoding/chunked') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/html'); - res.setHeader('Transfer-Encoding', 'chunked'); - var padding = 'a'; - for (var i = 0; i < 10; i++) { - res.write(padding); + setTimeout(function() { + res.end('test'); + }, 1000); } - res.end(convert('
日本語
', 'Shift_JIS')); - } - if (p === '/encoding/invalid') { - res.statusCode = 200; - res.setHeader('Content-Type', 'text/html'); - res.setHeader('Transfer-Encoding', 'chunked'); - // because node v0.12 doesn't have str.repeat - var padding = new Array(120 + 1).join('a'); - for (var i = 0; i < 10; i++) { - res.write(padding); + if (p === '/cookie') { + res.statusCode = 200; + res.setHeader('Set-Cookie', ['a=1', 'b=1']); + res.end('cookie'); } - res.end(convert('中文', 'gbk')); - } - if (p === '/redirect/301') { - res.statusCode = 301; - res.setHeader('Location', '/inspect'); - res.end(); - } + if (p === '/size/chunk') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + setTimeout(function() { + res.write('test'); + }, 50); + setTimeout(function() { + res.end('test'); + }, 100); + } - if (p === '/redirect/302') { - res.statusCode = 302; - res.setHeader('Location', '/inspect'); - res.end(); - } + if (p === '/size/long') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('testtest'); + } - if (p === '/redirect/303') { - res.statusCode = 303; - res.setHeader('Location', '/inspect'); - res.end(); - } + if (p === '/encoding/gbk') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/html'); + res.end(convert('
中文
', 'gbk')); + } - if (p === '/redirect/307') { - res.statusCode = 307; - res.setHeader('Location', '/inspect'); - res.end(); - } + if (p === '/encoding/gb2312') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/html'); + res.end(convert('
中文
', 'gb2312')); + } - if (p === '/redirect/308') { - res.statusCode = 308; - res.setHeader('Location', '/inspect'); - res.end(); - } + if (p === '/encoding/shift-jis') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/html; charset=Shift-JIS'); + res.end(convert('
日本語
', 'Shift_JIS')); + } - if (p === '/redirect/chain') { - res.statusCode = 301; - res.setHeader('Location', '/redirect/301'); - res.end(); - } + if (p === '/encoding/euc-jp') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/xml'); + res.end(convert('日本語', 'EUC-JP')); + } - if (p === '/error/redirect') { - res.statusCode = 301; - //res.setHeader('Location', '/inspect'); - res.end(); - } + if (p === '/encoding/utf8') { + res.statusCode = 200; + res.end('中文'); + } - if (p === '/error/400') { - res.statusCode = 400; - res.setHeader('Content-Type', 'text/plain'); - res.end('client error'); - } + if (p === '/encoding/order1') { + res.statusCode = 200; + res.setHeader('Content-Type', 'charset=gbk; text/plain'); + res.end(convert('中文', 'gbk')); + } - if (p === '/error/404') { - res.statusCode = 404; - res.setHeader('Content-Encoding', 'gzip'); - res.end(); - } + if (p === '/encoding/order2') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain; charset=gbk; qs=1'); + res.end(convert('中文', 'gbk')); + } - if (p === '/error/500') { - res.statusCode = 500; - res.setHeader('Content-Type', 'text/plain'); - res.end('server error'); - } + if (p === '/encoding/chunked') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/html'); + res.setHeader('Transfer-Encoding', 'chunked'); + const padding = 'a'; + res.write(padding.repeat(10)); + res.end(convert('
日本語
', 'Shift_JIS')); + } - if (p === '/error/reset') { - res.destroy(); - } + if (p === '/encoding/invalid') { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/html'); + res.setHeader('Transfer-Encoding', 'chunked'); + const padding = 'a'.repeat(120); + res.write(padding.repeat(10)); + res.end(convert('中文', 'gbk')); + } - if (p === '/error/json') { - res.statusCode = 200; - res.setHeader('Content-Type', 'application/json'); - res.end('invalid json'); - } + if (p === '/redirect/301') { + res.statusCode = 301; + res.setHeader('Location', '/inspect'); + res.end(); + } - if (p === '/no-content') { - res.statusCode = 204; - res.end(); - } + if (p === '/redirect/302') { + res.statusCode = 302; + res.setHeader('Location', '/inspect'); + res.end(); + } - if (p === '/no-content/gzip') { - res.statusCode = 204; - res.setHeader('Content-Encoding', 'gzip'); - res.end(); - } + if (p === '/redirect/303') { + res.statusCode = 303; + res.setHeader('Location', '/inspect'); + res.end(); + } - if (p === '/not-modified') { - res.statusCode = 304; - res.end(); - } + if (p === '/redirect/307') { + res.statusCode = 307; + res.setHeader('Location', '/inspect'); + res.end(); + } - if (p === '/not-modified/gzip') { - res.statusCode = 304; - res.setHeader('Content-Encoding', 'gzip'); - res.end(); - } + if (p === '/redirect/308') { + res.statusCode = 308; + res.setHeader('Location', '/inspect'); + res.end(); + } - if (p === '/inspect') { - res.statusCode = 200; - res.setHeader('Content-Type', 'application/json'); - var body = ''; - req.on('data', function(c) { body += c }); - req.on('end', function() { - res.end(JSON.stringify({ - method: req.method, - url: req.url, - headers: req.headers, - body: body - })); - }); - } + if (p === '/redirect/chain') { + res.statusCode = 301; + res.setHeader('Location', '/redirect/301'); + res.end(); + } - if (p === '/multipart') { - res.statusCode = 200; - res.setHeader('Content-Type', 'application/json'); - var parser = new Multipart(req.headers['content-type']); - var body = ''; - parser.on('part', function(field, part) { - body += field + '=' + part; - }); - parser.on('end', function() { - res.end(JSON.stringify({ - method: req.method, - url: req.url, - headers: req.headers, - body: body - })); - }); - req.pipe(parser); + if (p === '/error/redirect') { + res.statusCode = 301; + //res.setHeader('Location', '/inspect'); + res.end(); + } + + if (p === '/error/400') { + res.statusCode = 400; + res.setHeader('Content-Type', 'text/plain'); + res.end('client error'); + } + + if (p === '/error/404') { + res.statusCode = 404; + res.setHeader('Content-Encoding', 'gzip'); + res.end(); + } + + if (p === '/error/500') { + res.statusCode = 500; + res.setHeader('Content-Type', 'text/plain'); + res.end('server error'); + } + + if (p === '/error/reset') { + res.destroy(); + } + + if (p === '/error/json') { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end('invalid json'); + } + + if (p === '/no-content') { + res.statusCode = 204; + res.end(); + } + + if (p === '/no-content/gzip') { + res.statusCode = 204; + res.setHeader('Content-Encoding', 'gzip'); + res.end(); + } + + if (p === '/not-modified') { + res.statusCode = 304; + res.end(); + } + + if (p === '/not-modified/gzip') { + res.statusCode = 304; + res.setHeader('Content-Encoding', 'gzip'); + res.end(); + } + + if (p === '/inspect') { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + let body = ''; + req.on('data', function(c) { body += c }); + req.on('end', function() { + res.end(JSON.stringify({ + method: req.method, + url: req.url, + headers: req.headers, + body + })); + }); + } + + if (p === '/multipart') { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + const parser = new Multipart(req.headers['content-type']); + let body = ''; + parser.on('part', function(field, part) { + body += field + '=' + part; + }); + parser.on('end', function() { + res.end(JSON.stringify({ + method: req.method, + url: req.url, + headers: req.headers, + body: body + })); + }); + req.pipe(parser); + } } } diff --git a/test/test.js b/test/test.js index b593407..a1ea39a 100644 --- a/test/test.js +++ b/test/test.js @@ -1,54 +1,55 @@ // 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'); -var spawn = require('child_process').spawn; -var stream = require('stream'); -var resumer = require('resumer'); -var FormData = require('form-data'); -var http = require('http'); -var fs = require('fs'); +import chai from 'chai'; +import cap from 'chai-as-promised'; +import bluebird from 'bluebird'; +import then from 'promise'; +import {spawn} from 'child_process'; +import * as stream from 'stream'; +import resumer from 'resumer'; +import FormData from 'form-data'; +import * as http from 'http'; +import * as fs from 'fs'; -var TestServer = require('./server'); +chai.use(cap); +const expect = chai.expect; + +import TestServer from './server'; // test subjects -var fetch = require('../src/index.js'); +import fetch from '../src/index.js'; import Headers from '../src/headers.js'; -var Response = require('../src/response.js'); -var Request = require('../src/request.js'); -var Body = require('../src/body.js'); -var FetchError = require('../src/fetch-error.js'); +import Response from '../src/response.js'; +import Request from '../src/request.js'; +import Body from '../src/body.js'; +import FetchError from '../src/fetch-error.js'; // test with native promise on node 0.11, and bluebird for node 0.10 fetch.Promise = fetch.Promise || bluebird; -var url, opts, local, base; +let url, opts, local, base; -describe('node-fetch', function() { +describe('node-fetch', () => { - before(function(done) { + before(done => { local = new TestServer(); base = 'http://' + local.hostname + ':' + local.port; local.start(done); }); - after(function(done) { + after(done => { local.stop(done); }); it('should return a promise', function() { url = 'http://example.com/'; - var p = fetch(url); + const p = fetch(url); expect(p).to.be.an.instanceof(fetch.Promise); expect(p).to.have.property('then'); }); it('should allow custom promise', function() { url = 'http://example.com/'; - var old = fetch.Promise; + const old = fetch.Promise; fetch.Promise = then; expect(fetch(url)).to.be.an.instanceof(then); expect(fetch(url)).to.not.be.an.instanceof(bluebird); @@ -57,9 +58,9 @@ describe('node-fetch', function() { it('should throw error when no promise implementation are found', function() { url = 'http://example.com/'; - var old = fetch.Promise; + const old = fetch.Promise; fetch.Promise = undefined; - expect(function() { + expect(() => { fetch(url) }).to.throw(Error); fetch.Promise = old; @@ -94,8 +95,8 @@ describe('node-fetch', function() { }); it('should resolve into response', function() { - url = base + '/hello'; - return fetch(url).then(function(res) { + url = `${base}/hello`; + return fetch(url).then(res => { expect(res).to.be.an.instanceof(Response); expect(res.headers).to.be.an.instanceof(Headers); expect(res.body).to.be.an.instanceof(stream.Transform); @@ -109,10 +110,10 @@ describe('node-fetch', function() { }); it('should accept plain text response', function() { - url = base + '/plain'; - return fetch(url).then(function(res) { + url = `${base}/plain`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); - return res.text().then(function(result) { + return res.text().then(result => { expect(res.bodyUsed).to.be.true; expect(result).to.be.a('string'); expect(result).to.equal('text'); @@ -121,10 +122,10 @@ describe('node-fetch', function() { }); it('should accept html response (like plain text)', function() { - url = base + '/html'; - return fetch(url).then(function(res) { + url = `${base}/html`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/html'); - return res.text().then(function(result) { + return res.text().then(result => { expect(res.bodyUsed).to.be.true; expect(result).to.be.a('string'); expect(result).to.equal(''); @@ -133,10 +134,10 @@ describe('node-fetch', function() { }); it('should accept json response', function() { - url = base + '/json'; - return fetch(url).then(function(res) { + url = `${base}/json`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('application/json'); - return res.json().then(function(result) { + return res.json().then(result => { expect(res.bodyUsed).to.be.true; expect(result).to.be.an('object'); expect(result).to.deep.equal({ name: 'value' }); @@ -145,102 +146,102 @@ describe('node-fetch', function() { }); it('should send request with custom headers', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { headers: { 'x-custom-header': 'abc' } }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.headers['x-custom-header']).to.equal('abc'); }); }); it('should accept headers instance', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { headers: new Headers({ 'x-custom-header': 'abc' }) }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.headers['x-custom-header']).to.equal('abc'); }); }); it('should accept custom host header', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { headers: { host: 'example.com' } }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.headers['host']).to.equal('example.com'); }); }); it('should follow redirect code 301', function() { - url = base + '/redirect/301'; - return fetch(url).then(function(res) { - expect(res.url).to.equal(base + '/inspect'); + url = `${base}/redirect/301`; + return fetch(url).then(res => { + expect(res.url).to.equal(`${base}/inspect`); expect(res.status).to.equal(200); expect(res.ok).to.be.true; }); }); it('should follow redirect code 302', function() { - url = base + '/redirect/302'; - return fetch(url).then(function(res) { - expect(res.url).to.equal(base + '/inspect'); + url = `${base}/redirect/302`; + return fetch(url).then(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'); + url = `${base}/redirect/303`; + return fetch(url).then(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'); + url = `${base}/redirect/307`; + return fetch(url).then(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'); + url = `${base}/redirect/308`; + return fetch(url).then(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'); + url = `${base}/redirect/chain`; + return fetch(url).then(res => { + expect(res.url).to.equal(`${base}/inspect`); expect(res.status).to.equal(200); }); }); it('should follow POST request redirect code 301 with GET', function() { - url = base + '/redirect/301'; + url = `${base}/redirect/301`; opts = { method: 'POST' , body: 'a=1' }; - return fetch(url, opts).then(function(res) { - expect(res.url).to.equal(base + '/inspect'); + return fetch(url, opts).then(res => { + expect(res.url).to.equal(`${base}/inspect`); expect(res.status).to.equal(200); - return res.json().then(function(result) { + return res.json().then(result => { expect(result.method).to.equal('GET'); expect(result.body).to.equal(''); }); @@ -248,15 +249,15 @@ describe('node-fetch', function() { }); it('should follow POST request redirect code 302 with GET', function() { - url = base + '/redirect/302'; + url = `${base}/redirect/302`; opts = { method: 'POST' , body: 'a=1' }; - return fetch(url, opts).then(function(res) { - expect(res.url).to.equal(base + '/inspect'); + return fetch(url, opts).then(res => { + expect(res.url).to.equal(`${base}/inspect`); expect(res.status).to.equal(200); - return res.json().then(function(result) { + return res.json().then(result => { expect(result.method).to.equal('GET'); expect(result.body).to.equal(''); }); @@ -264,15 +265,15 @@ describe('node-fetch', function() { }); it('should follow redirect code 303 with GET', function() { - url = base + '/redirect/303'; + url = `${base}/redirect/303`; opts = { method: 'PUT' , body: 'a=1' }; - return fetch(url, opts).then(function(res) { - expect(res.url).to.equal(base + '/inspect'); + return fetch(url, opts).then(res => { + expect(res.url).to.equal(`${base}/inspect`); expect(res.status).to.equal(200); - return res.json().then(function(result) { + return res.json().then(result => { expect(result.method).to.equal('GET'); expect(result.body).to.equal(''); }); @@ -280,7 +281,7 @@ describe('node-fetch', function() { }); it('should obey maximum redirect, reject case', function() { - url = base + '/redirect/chain'; + url = `${base}/redirect/chain`; opts = { follow: 1 } @@ -290,18 +291,18 @@ describe('node-fetch', function() { }); it('should obey redirect chain, resolve case', function() { - url = base + '/redirect/chain'; + url = `${base}/redirect/chain`; opts = { follow: 2 } - return fetch(url, opts).then(function(res) { - expect(res.url).to.equal(base + '/inspect'); + return fetch(url, opts).then(res => { + expect(res.url).to.equal(`${base}/inspect`); expect(res.status).to.equal(200); }); }); it('should allow not following redirect', function() { - url = base + '/redirect/301'; + url = `${base}/redirect/301`; opts = { follow: 0 } @@ -311,19 +312,19 @@ describe('node-fetch', function() { }); it('should support redirect mode, manual flag', function() { - url = base + '/redirect/301'; + url = `${base}/redirect/301`; opts = { redirect: 'manual' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.url).to.equal(url); expect(res.status).to.equal(301); - expect(res.headers.get('location')).to.equal(base + '/inspect'); + expect(res.headers.get('location')).to.equal(`${base}/inspect`); }); }); it('should support redirect mode, error flag', function() { - url = base + '/redirect/301'; + url = `${base}/redirect/301`; opts = { redirect: 'error' }; @@ -333,11 +334,11 @@ describe('node-fetch', function() { }); it('should support redirect mode, manual flag when there is no redirect', function() { - url = base + '/hello'; + url = `${base}/hello`; opts = { redirect: 'manual' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.url).to.equal(url); expect(res.status).to.equal(200); expect(res.headers.get('location')).to.be.null; @@ -345,31 +346,31 @@ describe('node-fetch', function() { }); it('should follow redirect code 301 and keep existing headers', function() { - url = base + '/redirect/301'; + 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 fetch(url, opts).then(res => { + expect(res.url).to.equal(`${base}/inspect`); return res.json(); - }).then(function(res) { + }).then(res => { expect(res.headers['x-custom-header']).to.equal('abc'); }); }); it('should reject broken redirect', function() { - url = base + '/error/redirect'; + url = `${base}/error/redirect`; return expect(fetch(url)).to.eventually.be.rejected .and.be.an.instanceOf(FetchError) .and.have.property('type', 'invalid-redirect'); }); it('should not reject broken redirect under manual redirect', function() { - url = base + '/error/redirect'; + url = `${base}/error/redirect`; opts = { redirect: 'manual' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.url).to.equal(url); expect(res.status).to.equal(301); expect(res.headers.get('location')).to.be.null; @@ -377,13 +378,13 @@ describe('node-fetch', function() { }); it('should handle client-error response', function() { - url = base + '/error/400'; - return fetch(url).then(function(res) { + url = `${base}/error/400`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); expect(res.status).to.equal(400); expect(res.statusText).to.equal('Bad Request'); expect(res.ok).to.be.false; - return res.text().then(function(result) { + return res.text().then(result => { expect(res.bodyUsed).to.be.true; expect(result).to.be.a('string'); expect(result).to.equal('client error'); @@ -392,13 +393,13 @@ describe('node-fetch', function() { }); it('should handle server-error response', function() { - url = base + '/error/500'; - return fetch(url).then(function(res) { + url = `${base}/error/500`; + return fetch(url).then(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'); expect(res.ok).to.be.false; - return res.text().then(function(result) { + return res.text().then(result => { expect(res.bodyUsed).to.be.true; expect(result).to.be.a('string'); expect(result).to.equal('server error'); @@ -407,7 +408,7 @@ describe('node-fetch', function() { }); it('should handle network-error response', function() { - url = base + '/error/reset'; + url = `${base}/error/reset`; return expect(fetch(url)).to.eventually.be.rejected .and.be.an.instanceOf(FetchError) .and.have.property('code', 'ECONNRESET'); @@ -421,20 +422,20 @@ describe('node-fetch', function() { }); it('should reject invalid json response', function() { - url = base + '/error/json'; - return fetch(url).then(function(res) { + url = `${base}/error/json`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('application/json'); return expect(res.json()).to.eventually.be.rejectedWith(Error); }); }); it('should handle no content response', function() { - url = base + '/no-content'; - return fetch(url).then(function(res) { + url = `${base}/no-content`; + return fetch(url).then(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) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.be.empty; }); @@ -442,9 +443,9 @@ describe('node-fetch', function() { }); it('should return empty object on no-content response', function() { - url = base + '/no-content'; - return fetch(url).then(function(res) { - return res.json().then(function(result) { + url = `${base}/no-content`; + return fetch(url).then(res => { + return res.json().then(result => { expect(result).to.be.an('object'); expect(result).to.be.empty; }); @@ -452,13 +453,13 @@ describe('node-fetch', function() { }); it('should handle no content response with gzip encoding', function() { - url = base + '/no-content/gzip'; - return fetch(url).then(function(res) { + url = `${base}/no-content/gzip`; + return fetch(url).then(res => { expect(res.status).to.equal(204); expect(res.statusText).to.equal('No Content'); expect(res.headers.get('content-encoding')).to.equal('gzip'); expect(res.ok).to.be.true; - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.be.empty; }); @@ -466,12 +467,12 @@ describe('node-fetch', function() { }); it('should handle not modified response', function() { - url = base + '/not-modified'; - return fetch(url).then(function(res) { + url = `${base}/not-modified`; + return fetch(url).then(res => { expect(res.status).to.equal(304); expect(res.statusText).to.equal('Not Modified'); expect(res.ok).to.be.false; - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.be.empty; }); @@ -479,13 +480,13 @@ describe('node-fetch', function() { }); it('should handle not modified response with gzip encoding', function() { - url = base + '/not-modified/gzip'; - return fetch(url).then(function(res) { + url = `${base}/not-modified/gzip`; + return fetch(url).then(res => { expect(res.status).to.equal(304); expect(res.statusText).to.equal('Not Modified'); expect(res.headers.get('content-encoding')).to.equal('gzip'); expect(res.ok).to.be.false; - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.be.empty; }); @@ -493,10 +494,10 @@ describe('node-fetch', function() { }); it('should decompress gzip response', function() { - url = base + '/gzip'; - return fetch(url).then(function(res) { + url = `${base}/gzip`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.equal('hello world'); }); @@ -504,10 +505,10 @@ describe('node-fetch', function() { }); it('should decompress deflate response', function() { - url = base + '/deflate'; - return fetch(url).then(function(res) { + url = `${base}/deflate`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.equal('hello world'); }); @@ -515,10 +516,10 @@ describe('node-fetch', function() { }); it('should decompress deflate raw response from old apache server', function() { - url = base + '/deflate-raw'; - return fetch(url).then(function(res) { + url = `${base}/deflate-raw`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.equal('hello world'); }); @@ -526,10 +527,10 @@ describe('node-fetch', function() { }); it('should skip decompression if unsupported', function() { - url = base + '/sdch'; - return fetch(url).then(function(res) { + url = `${base}/sdch`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.equal('fake sdch string'); }); @@ -537,8 +538,8 @@ describe('node-fetch', function() { }); it('should reject if response compression is invalid', function() { - url = base + '/invalid-content-encoding'; - return fetch(url).then(function(res) { + url = `${base}/invalid-content-encoding`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); return expect(res.text()).to.eventually.be.rejected .and.be.an.instanceOf(FetchError) @@ -547,13 +548,13 @@ describe('node-fetch', function() { }); it('should allow disabling auto decompression', function() { - url = base + '/gzip'; + url = `${base}/gzip`; opts = { compress: false }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.be.a('string'); expect(result).to.not.equal('hello world'); }); @@ -562,7 +563,7 @@ describe('node-fetch', function() { it('should allow custom timeout', function() { this.timeout(500); - url = base + '/timeout'; + url = `${base}/timeout`; opts = { timeout: 100 }; @@ -573,11 +574,11 @@ describe('node-fetch', function() { it('should allow custom timeout on response body', function() { this.timeout(500); - url = base + '/slow'; + url = `${base}/slow`; opts = { timeout: 100 }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.ok).to.be.true; return expect(res.text()).to.eventually.be.rejected .and.be.an.instanceOf(FetchError) @@ -587,36 +588,36 @@ describe('node-fetch', function() { it('should clear internal timeout on fetch response', function (done) { this.timeout(1000); - spawn('node', ['-e', 'require("./")("' + base + '/hello", { timeout: 5000 })']) - .on('exit', function () { + spawn('node', ['-e', `require('./')('${base}/hello', { timeout: 5000 })`]) + .on('exit', () => { 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 () { + spawn('node', ['-e', `require('./')('${base}/redirect/301', { timeout: 5000 })`]) + .on('exit', () => { 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 () { + spawn('node', ['-e', `require('./')('${base}/error/reset', { timeout: 5000 })`]) + .on('exit', () => { done(); }); }); it('should allow POST request', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'POST' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.headers['transfer-encoding']).to.be.undefined; expect(res.headers['content-length']).to.equal('0'); @@ -624,14 +625,14 @@ describe('node-fetch', function() { }); it('should allow POST request with string body', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'POST' , body: 'a=1' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.body).to.equal('a=1'); expect(res.headers['transfer-encoding']).to.be.undefined; @@ -640,14 +641,14 @@ describe('node-fetch', function() { }); it('should allow POST request with buffer body', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'POST' , body: new Buffer('a=1', 'utf-8') }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.body).to.equal('a=1'); expect(res.headers['transfer-encoding']).to.equal('chunked'); @@ -656,17 +657,17 @@ describe('node-fetch', function() { }); it('should allow POST request with readable stream as body', function() { - var body = resumer().queue('a=1').end(); + let body = resumer().queue('a=1').end(); body = body.pipe(new stream.PassThrough()); - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'POST' - , body: body + , body }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.body).to.equal('a=1'); expect(res.headers['transfer-encoding']).to.equal('chunked'); @@ -675,17 +676,17 @@ describe('node-fetch', function() { }); it('should allow POST request with form-data as body', function() { - var form = new FormData(); + const form = new FormData(); form.append('a','1'); - url = base + '/multipart'; + url = `${base}/multipart`; opts = { method: 'POST' , body: form }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.headers['content-type']).to.contain('multipart/form-data'); expect(res.headers['content-length']).to.be.a('string'); @@ -694,18 +695,18 @@ describe('node-fetch', function() { }); it('should allow POST request with form-data using stream as body', function() { - var form = new FormData(); + const form = new FormData(); form.append('my_field', fs.createReadStream('test/dummy.txt')); - url = base + '/multipart'; + url = `${base}/multipart`; opts = { method: 'POST' , body: form }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.headers['content-type']).to.contain('multipart/form-data'); expect(res.headers['content-length']).to.be.undefined; @@ -714,21 +715,21 @@ describe('node-fetch', function() { }); it('should allow POST request with form-data as body and custom headers', function() { - var form = new FormData(); + const form = new FormData(); form.append('a','1'); - var headers = form.getHeaders(); + const headers = form.getHeaders(); headers['b'] = '2'; - url = base + '/multipart'; + url = `${base}/multipart`; opts = { method: 'POST' , body: form - , headers: headers + , headers }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.headers['content-type']).to.contain('multipart/form-data'); expect(res.headers['content-length']).to.be.a('string'); @@ -738,55 +739,55 @@ describe('node-fetch', function() { }); it('should allow POST request with object body', function() { - url = base + '/inspect'; + url = `${base}/inspect`; // note that fetch simply calls tostring on an object opts = { method: 'POST' , body: { a:1 } }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.body).to.equal('[object Object]'); }); }); it('should allow PUT request', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'PUT' , body: 'a=1' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('PUT'); expect(res.body).to.equal('a=1'); }); }); it('should allow DELETE request', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'DELETE' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('DELETE'); }); }); it('should allow POST request with string body', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'POST' , body: 'a=1' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('POST'); expect(res.body).to.equal('a=1'); expect(res.headers['transfer-encoding']).to.be.undefined; @@ -795,14 +796,14 @@ describe('node-fetch', function() { }); it('should allow DELETE request with string body', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'DELETE' , body: 'a=1' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('DELETE'); expect(res.body).to.equal('a=1'); expect(res.headers['transfer-encoding']).to.be.undefined; @@ -811,55 +812,55 @@ describe('node-fetch', function() { }); it('should allow PATCH request', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { method: 'PATCH' , body: 'a=1' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.method).to.equal('PATCH'); expect(res.body).to.equal('a=1'); }); }); it('should allow HEAD request', function() { - url = base + '/hello'; + url = `${base}/hello`; opts = { method: 'HEAD' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(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); return res.text(); - }).then(function(text) { + }).then(text => { expect(text).to.equal(''); }); }); it('should allow HEAD request with content-encoding header', function() { - url = base + '/error/404'; + url = `${base}/error/404`; opts = { method: 'HEAD' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.status).to.equal(404); expect(res.headers.get('content-encoding')).to.equal('gzip'); return res.text(); - }).then(function(text) { + }).then(text => { expect(text).to.equal(''); }); }); it('should allow OPTIONS request', function() { - url = base + '/options'; + url = `${base}/options`; opts = { method: 'OPTIONS' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.status).to.equal(200); expect(res.statusText).to.equal('OK'); expect(res.headers.get('allow')).to.equal('GET, HEAD, OPTIONS'); @@ -868,10 +869,10 @@ describe('node-fetch', function() { }); it('should reject decoding body twice', function() { - url = base + '/plain'; - return fetch(url).then(function(res) { + url = `${base}/plain`; + return fetch(url).then(res => { expect(res.headers.get('content-type')).to.equal('text/plain'); - return res.text().then(function(result) { + return res.text().then(result => { expect(res.bodyUsed).to.be.true; return expect(res.text()).to.eventually.be.rejectedWith(Error); }); @@ -879,11 +880,11 @@ describe('node-fetch', function() { }); it('should support maximum response size, multiple chunk', function() { - url = base + '/size/chunk'; + url = `${base}/size/chunk`; opts = { size: 5 }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.status).to.equal(200); expect(res.headers.get('content-type')).to.equal('text/plain'); return expect(res.text()).to.eventually.be.rejected @@ -893,11 +894,11 @@ describe('node-fetch', function() { }); it('should support maximum response size, single chunk', function() { - url = base + '/size/long'; + url = `${base}/size/long`; opts = { size: 5 }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.status).to.equal(200); expect(res.headers.get('content-type')).to.equal('text/plain'); return expect(res.text()).to.eventually.be.rejected @@ -907,142 +908,140 @@ describe('node-fetch', function() { }); it('should support encoding decode, xml dtd detect', function() { - url = base + '/encoding/euc-jp'; - return fetch(url).then(function(res) { + url = `${base}/encoding/euc-jp`; + return fetch(url).then(res => { expect(res.status).to.equal(200); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.equal('日本語'); }); }); }); it('should support encoding decode, content-type detect', function() { - url = base + '/encoding/shift-jis'; - return fetch(url).then(function(res) { + url = `${base}/encoding/shift-jis`; + return fetch(url).then(res => { expect(res.status).to.equal(200); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.equal('
日本語
'); }); }); }); it('should support encoding decode, html5 detect', function() { - url = base + '/encoding/gbk'; - return fetch(url).then(function(res) { + url = `${base}/encoding/gbk`; + return fetch(url).then(res => { expect(res.status).to.equal(200); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.equal('
中文
'); }); }); }); it('should support encoding decode, html4 detect', function() { - url = base + '/encoding/gb2312'; - return fetch(url).then(function(res) { + url = `${base}/encoding/gb2312`; + return fetch(url).then(res => { expect(res.status).to.equal(200); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.equal('
中文
'); }); }); }); it('should default to utf8 encoding', function() { - url = base + '/encoding/utf8'; - return fetch(url).then(function(res) { + url = `${base}/encoding/utf8`; + return fetch(url).then(res => { expect(res.status).to.equal(200); expect(res.headers.get('content-type')).to.be.null; - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.equal('中文'); }); }); }); it('should support uncommon content-type order, charset in front', function() { - url = base + '/encoding/order1'; - return fetch(url).then(function(res) { + url = `${base}/encoding/order1`; + return fetch(url).then(res => { expect(res.status).to.equal(200); - return res.text().then(function(result) { + return res.text().then(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) { + url = `${base}/encoding/order2`; + return fetch(url).then(res => { expect(res.status).to.equal(200); - return res.text().then(function(result) { + return res.text().then(result => { expect(result).to.equal('中文'); }); }); }); it('should support chunked encoding, html4 detect', function() { - url = base + '/encoding/chunked'; - return fetch(url).then(function(res) { + url = `${base}/encoding/chunked`; + return fetch(url).then(res => { expect(res.status).to.equal(200); - // because node v0.12 doesn't have str.repeat - var padding = new Array(10 + 1).join('a'); - return res.text().then(function(result) { - expect(result).to.equal(padding + '
日本語
'); + const padding = 'a'.repeat(10); + return res.text().then(result => { + expect(result).to.equal(`${padding}
日本語
`); }); }); }); it('should only do encoding detection up to 1024 bytes', function() { - url = base + '/encoding/invalid'; - return fetch(url).then(function(res) { + url = `${base}/encoding/invalid`; + return fetch(url).then(res => { expect(res.status).to.equal(200); - // because node v0.12 doesn't have str.repeat - var padding = new Array(1200 + 1).join('a'); - return res.text().then(function(result) { - expect(result).to.not.equal(padding + '中文'); + const padding = 'a'.repeat(1200); + return res.text().then(result => { + expect(result).to.not.equal(`${padding}中文`); }); }); }); it('should allow piping response body as stream', function(done) { - url = base + '/hello'; - fetch(url).then(function(res) { + url = `${base}/hello`; + fetch(url).then(res => { expect(res.body).to.be.an.instanceof(stream.Transform); - res.body.on('data', function(chunk) { + res.body.on('data', chunk => { if (chunk === null) { return; } expect(chunk.toString()).to.equal('world'); }); - res.body.on('end', function() { + res.body.on('end', () => { done(); }); }); }); it('should allow cloning a response, and use both as stream', function(done) { - url = base + '/hello'; - return fetch(url).then(function(res) { - var counter = 0; - var r1 = res.clone(); + url = `${base}/hello`; + return fetch(url).then(res => { + let counter = 0; + const r1 = res.clone(); expect(res.body).to.be.an.instanceof(stream.Transform); expect(r1.body).to.be.an.instanceof(stream.Transform); - res.body.on('data', function(chunk) { + res.body.on('data', chunk => { if (chunk === null) { return; } expect(chunk.toString()).to.equal('world'); }); - res.body.on('end', function() { + res.body.on('end', () => { counter++; if (counter == 2) { done(); } }); - r1.body.on('data', function(chunk) { + r1.body.on('data', chunk => { if (chunk === null) { return; } expect(chunk.toString()).to.equal('world'); }); - r1.body.on('end', function() { + r1.body.on('end', () => { counter++; if (counter == 2) { done(); @@ -1052,10 +1051,10 @@ describe('node-fetch', function() { }); it('should allow cloning a json response and log it as text response', function() { - url = base + '/json'; - return fetch(url).then(function(res) { - var r1 = res.clone(); - return fetch.Promise.all([res.json(), r1.text()]).then(function(results) { + url = `${base}/json`; + return fetch(url).then(res => { + const r1 = res.clone(); + return fetch.Promise.all([res.json(), r1.text()]).then(results => { expect(results[0]).to.deep.equal({name: 'value'}); expect(results[1]).to.equal('{"name":"value"}'); }); @@ -1063,12 +1062,12 @@ describe('node-fetch', function() { }); it('should allow cloning a json response, and then log it as text response', function() { - url = base + '/json'; - return fetch(url).then(function(res) { - var r1 = res.clone(); - return res.json().then(function(result) { + url = `${base}/json`; + return fetch(url).then(res => { + const r1 = res.clone(); + return res.json().then(result => { expect(result).to.deep.equal({name: 'value'}); - return r1.text().then(function(result) { + return r1.text().then(result => { expect(result).to.equal('{"name":"value"}'); }); }); @@ -1076,12 +1075,12 @@ describe('node-fetch', function() { }); it('should allow cloning a json response, first log as text response, then return json object', function() { - url = base + '/json'; - return fetch(url).then(function(res) { - var r1 = res.clone(); - return r1.text().then(function(result) { + url = `${base}/json`; + return fetch(url).then(res => { + const r1 = res.clone(); + return r1.text().then(result => { expect(result).to.equal('{"name":"value"}'); - return res.json().then(function(result) { + return res.json().then(result => { expect(result).to.deep.equal({name: 'value'}); }); }); @@ -1089,19 +1088,19 @@ describe('node-fetch', function() { }); it('should not allow cloning a response after its been used', function() { - url = base + '/hello'; - return fetch(url).then(function(res) { - return res.text().then(function(result) { - expect(function() { - var r1 = res.clone(); + url = `${base}/hello`; + return fetch(url).then(res => + res.text().then(result => { + expect(() => { + res.clone(); }).to.throw(Error); - }); - }) + }) + ); }); it('should allow get all responses of a header', function() { - url = base + '/cookie'; - return fetch(url).then(function(res) { + url = `${base}/cookie`; + return fetch(url).then(res => { expect(res.headers.get('set-cookie')).to.equal('a=1'); expect(res.headers.get('Set-Cookie')).to.equal('a=1'); expect(res.headers.getAll('set-cookie')).to.deep.equal(['a=1', 'b=1']); @@ -1110,19 +1109,19 @@ describe('node-fetch', function() { }); it('should allow iterating through all headers', function() { - var headers = new Headers({ + const headers = new Headers({ a: 1 , b: [2, 3] , c: [4] }); expect(headers).to.have.property('forEach'); - var result = []; - headers.forEach(function(val, key) { + const result = []; + headers.forEach((val, key) => { result.push([key, val]); }); - var expected = [ + const expected = [ ["a", "1"] , ["b", "2"] , ["b", "3"] @@ -1132,7 +1131,7 @@ describe('node-fetch', function() { }); it('should allow iterating through all headers', function() { - var headers = new Headers({ + const headers = new Headers({ a: 1 , b: [2, 3] , c: [4] @@ -1142,7 +1141,7 @@ describe('node-fetch', function() { expect(headers).to.have.property('values'); expect(headers).to.have.property('entries'); - var result, expected; + let result, expected; result = []; for (let [key, val] of headers) { @@ -1191,8 +1190,8 @@ describe('node-fetch', function() { }); it('should allow deleting header', function() { - url = base + '/cookie'; - return fetch(url).then(function(res) { + url = `${base}/cookie`; + return fetch(url).then(res => { res.headers.delete('set-cookie'); expect(res.headers.get('set-cookie')).to.be.null; expect(res.headers.getAll('set-cookie')).to.be.empty; @@ -1200,25 +1199,25 @@ describe('node-fetch', function() { }); it('should send request with connection keep-alive if agent is provided', function() { - url = base + '/inspect'; + url = `${base}/inspect`; opts = { agent: new http.Agent({ keepAlive: true }) }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { return res.json(); - }).then(function(res) { + }).then(res => { expect(res.headers['connection']).to.equal('keep-alive'); }); }); it('should ignore unsupported attributes while reading headers', function() { - var FakeHeader = function() {}; + const FakeHeader = () => {}; // prototypes are ignored FakeHeader.prototype.z = 'fake'; - var res = new FakeHeader; + const res = new FakeHeader; // valid res.a = 'string'; res.b = ['1','2']; @@ -1236,8 +1235,8 @@ describe('node-fetch', function() { res.l = false; res.m = new Buffer('test'); - var h1 = new Headers(res); - var h1Raw = h1.raw(); + const h1 = new Headers(res); + const h1Raw = h1.raw(); expect(h1Raw['a']).to.include('string'); expect(h1Raw['b']).to.include('1'); @@ -1261,18 +1260,18 @@ describe('node-fetch', function() { }); it('should wrap headers', function() { - var h1 = new Headers({ + const h1 = new Headers({ a: '1' }); - var h1Raw = h1.raw(); + const h1Raw = h1.raw(); - var h2 = new Headers(h1); + const h2 = new Headers(h1); h2.set('b', '1'); - var h2Raw = h2.raw(); + const h2Raw = h2.raw(); - var h3 = new Headers(h2); + const h3 = new Headers(h2); h3.append('a', '2'); - var h3Raw = h3.raw(); + const h3Raw = h3.raw(); expect(h1Raw['a']).to.include('1'); expect(h1Raw['a']).to.not.include('2'); @@ -1287,9 +1286,9 @@ describe('node-fetch', function() { }); it('should support fetch with Request instance', function() { - url = base + '/hello'; - var req = new Request(url); - return fetch(req).then(function(res) { + url = `${base}/hello`; + const req = new Request(url); + return fetch(req).then(res => { expect(res.url).to.equal(url); expect(res.ok).to.be.true; expect(res.status).to.equal(200); @@ -1297,17 +1296,17 @@ describe('node-fetch', function() { }); it('should support wrapping Request instance', function() { - url = base + '/hello'; + url = `${base}/hello`; - var form = new FormData(); + const form = new FormData(); form.append('a', '1'); - var r1 = new Request(url, { + const r1 = new Request(url, { method: 'POST' , follow: 1 , body: form }); - var r2 = new Request(r1, { + const r2 = new Request(r1, { follow: 2 }); @@ -1322,8 +1321,8 @@ describe('node-fetch', function() { }); it('should support overwrite Request instance', function() { - url = base + '/inspect'; - var req = new Request(url, { + url = `${base}/inspect`; + const req = new Request(url, { method: 'POST' , headers: { a: '1' @@ -1334,25 +1333,25 @@ describe('node-fetch', function() { , headers: { a: '2' } - }).then(function(res) { + }).then(res => { return res.json(); - }).then(function(body) { + }).then(body => { expect(body.method).to.equal('GET'); expect(body.headers.a).to.equal('2'); }); }); it('should support empty options in Response constructor', function() { - var body = resumer().queue('a=1').end(); + let body = resumer().queue('a=1').end(); body = body.pipe(new stream.PassThrough()); - var res = new Response(body); - return res.text().then(function(result) { + const res = new Response(body); + return res.text().then(result => { expect(result).to.equal('a=1'); }); }); it('should support parsing headers in Response constructor', function() { - var res = new Response(null, { + const res = new Response(null, { headers: { a: '1' } @@ -1361,30 +1360,30 @@ describe('node-fetch', function() { }); it('should support text() method in Response constructor', function() { - var res = new Response('a=1'); - return res.text().then(function(result) { + const res = new Response('a=1'); + return res.text().then(result => { expect(result).to.equal('a=1'); }); }); it('should support json() method in Response constructor', function() { - var res = new Response('{"a":1}'); - return res.json().then(function(result) { + const res = new Response('{"a":1}'); + return res.json().then(result => { expect(result.a).to.equal(1); }); }); it('should support buffer() method in Response constructor', function() { - var res = new Response('a=1'); - return res.buffer().then(function(result) { + const res = new Response('a=1'); + return res.buffer().then(result => { expect(result.toString()).to.equal('a=1'); }); }); it('should support clone() method in Response constructor', function() { - var body = resumer().queue('a=1').end(); + let body = resumer().queue('a=1').end(); body = body.pipe(new stream.PassThrough()); - var res = new Response(body, { + const res = new Response(body, { headers: { a: '1' } @@ -1392,7 +1391,7 @@ describe('node-fetch', function() { , status: 346 , statusText: 'production' }); - var cl = res.clone(); + const cl = res.clone(); expect(cl.headers.get('a')).to.equal('1'); expect(cl.url).to.equal(base); expect(cl.status).to.equal(346); @@ -1400,42 +1399,42 @@ describe('node-fetch', function() { expect(cl.ok).to.be.false; // clone body shouldn't be the same body expect(cl.body).to.not.equal(body); - return cl.text().then(function(result) { + return cl.text().then(result => { expect(result).to.equal('a=1'); }); }); it('should support stream as body in Response constructor', function() { - var body = resumer().queue('a=1').end(); + let body = resumer().queue('a=1').end(); body = body.pipe(new stream.PassThrough()); - var res = new Response(body); - return res.text().then(function(result) { + const res = new Response(body); + return res.text().then(result => { expect(result).to.equal('a=1'); }); }); it('should support string as body in Response constructor', function() { - var res = new Response('a=1'); - return res.text().then(function(result) { + const res = new Response('a=1'); + return res.text().then(result => { expect(result).to.equal('a=1'); }); }); it('should support buffer as body in Response constructor', function() { - var res = new Response(new Buffer('a=1')); - return res.text().then(function(result) { + const res = new Response(new Buffer('a=1')); + return res.text().then(result => { expect(result).to.equal('a=1'); }); }); it('should default to 200 as status code', function() { - var res = new Response(null); + const res = new Response(null); expect(res.status).to.equal(200); }); it('should support parsing headers in Request constructor', function() { url = base; - var req = new Request(url, { + const req = new Request(url, { headers: { a: '1' } @@ -1446,50 +1445,50 @@ describe('node-fetch', function() { it('should support text() method in Request constructor', function() { url = base; - var req = new Request(url, { + const req = new Request(url, { body: 'a=1' }); expect(req.url).to.equal(url); - return req.text().then(function(result) { + return req.text().then(result => { expect(result).to.equal('a=1'); }); }); it('should support json() method in Request constructor', function() { url = base; - var req = new Request(url, { + const req = new Request(url, { body: '{"a":1}' }); expect(req.url).to.equal(url); - return req.json().then(function(result) { + return req.json().then(result => { expect(result.a).to.equal(1); }); }); it('should support buffer() method in Request constructor', function() { url = base; - var req = new Request(url, { + const req = new Request(url, { body: 'a=1' }); expect(req.url).to.equal(url); - return req.buffer().then(function(result) { + return req.buffer().then(result => { expect(result.toString()).to.equal('a=1'); }); }); it('should support arbitrary url in Request constructor', function() { url = 'anything'; - var req = new Request(url); + const req = new Request(url); expect(req.url).to.equal('anything'); }); it('should support clone() method in Request constructor', function() { url = base; - var body = resumer().queue('a=1').end(); + let body = resumer().queue('a=1').end(); body = body.pipe(new stream.PassThrough()); - var agent = new http.Agent(); - var req = new Request(url, { - body: body + const agent = new http.Agent(); + const req = new Request(url, { + body , method: 'POST' , redirect: 'manual' , headers: { @@ -1497,9 +1496,9 @@ describe('node-fetch', function() { } , follow: 3 , compress: false - , agent: agent + , agent }); - var cl = req.clone(); + const cl = req.clone(); expect(cl.url).to.equal(url); expect(cl.method).to.equal('POST'); expect(cl.redirect).to.equal('manual'); @@ -1511,24 +1510,24 @@ describe('node-fetch', function() { expect(cl.agent).to.equal(agent); // clone body shouldn't be the same body expect(cl.body).to.not.equal(body); - return fetch.Promise.all([cl.text(), req.text()]).then(function(results) { + return fetch.Promise.all([cl.text(), req.text()]).then(results => { expect(results[0]).to.equal('a=1'); expect(results[1]).to.equal('a=1'); }); }); it('should support text(), json() and buffer() method in Body constructor', function() { - var body = new Body('a=1'); + const body = new Body('a=1'); expect(body).to.have.property('text'); expect(body).to.have.property('json'); expect(body).to.have.property('buffer'); }); it('should create custom FetchError', function() { - var systemError = new Error('system'); + const systemError = new Error('system'); systemError.code = 'ESOMEERROR'; - var err = new FetchError('test message', 'test-error', systemError); + const err = new FetchError('test message', 'test-error', systemError); expect(err).to.be.an.instanceof(Error); expect(err).to.be.an.instanceof(FetchError); expect(err.name).to.equal('FetchError'); @@ -1544,7 +1543,7 @@ describe('node-fetch', function() { opts = { method: 'HEAD' }; - return fetch(url, opts).then(function(res) { + return fetch(url, opts).then(res => { expect(res.status).to.equal(200); expect(res.ok).to.be.true; });