diff --git a/README.md b/README.md index 978462e..f63ab94 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Adds retry functionality to the `Fetch` API. -It wraps [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) and retries requests that fail due to network issues. It can also be configured to retry requests on specific HTTP status codes. +It wraps any `Fetch` API package (eg: [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch), [cross-fetch](https://github.com/lquixada/cross-fetch), [isomorphic-unfetch](https://github.com/developit/unfetch) and etc.) and retries requests that fail due to network issues. It can also be configured to retry requests on specific HTTP status codes. [![Build Status](https://travis-ci.org/jonbern/fetch-retry.svg?branch=master)](https://travis-ci.org/jonbern/fetch-retry) @@ -18,7 +18,8 @@ npm install fetch-retry --save These properties are optional, and when omitted will default to 3 retries, a 1000ms retry delay, and to retry only on network errors. ```javascript -var fetch = require('fetch-retry'); +var originalFetch = require('isomorphic-fetch'); +var fetch = require('fetch-retry')(originalFetch); ``` ```javascript diff --git a/index.d.ts b/index.d.ts index 575a01d..b59ddf4 100644 --- a/index.d.ts +++ b/index.d.ts @@ -17,6 +17,6 @@ declare module 'fetch-retry' { retryOn?: number[] | RequestRetryOnFunction; } - function fetch(url: String, options?: IRequestInitWithRetry): Promise; - export = fetch; -} + function fetchBuilder(fetch: (url: String, options?: RequestInit) => Promise): ((url: String, options?: IRequestInitWithRetry) => Promise); + export = fetchBuilder; +} \ No newline at end of file diff --git a/index.js b/index.js index 301add3..ad920f2 100644 --- a/index.js +++ b/index.js @@ -1,81 +1,86 @@ 'use strict'; -require('isomorphic-fetch'); require('es6-promise').polyfill(); -module.exports = function(url, options) { - var retries = 3; - var retryDelay = 1000; - var retryOn = []; +module.exports = function (fetch) { + if (typeof fetch !== 'function') { + throw new ArgumentError('fetch must be a function'); + } + + return function fetchRetry(url, options) { + var retries = 3; + var retryDelay = 1000; + var retryOn = []; - if (options && options.retries !== undefined) { - if (isPositiveInteger(options.retries)) { - retries = options.retries; - } else { - throw new ArgumentError('retries must be a positive integer'); + if (options && options.retries !== undefined) { + if (isPositiveInteger(options.retries)) { + retries = options.retries; + } else { + throw new ArgumentError('retries must be a positive integer'); + } } - } - if (options && options.retryDelay !== undefined) { - if (isPositiveInteger(options.retryDelay) || (typeof options.retryDelay === 'function')) { - retryDelay = options.retryDelay; - } else { - throw new ArgumentError('retryDelay must be a positive integer or a function returning a positive integer'); + if (options && options.retryDelay !== undefined) { + if (isPositiveInteger(options.retryDelay) || (typeof options.retryDelay === 'function')) { + retryDelay = options.retryDelay; + } else { + throw new ArgumentError('retryDelay must be a positive integer or a function returning a positive integer'); + } } - } - if (options && options.retryOn) { - if (Array.isArray(options.retryOn) || (typeof options.retryOn === 'function')) { - retryOn = options.retryOn; - } else { - throw new ArgumentError('retryOn property expects an array or function'); + if (options && options.retryOn) { + if (Array.isArray(options.retryOn) || (typeof options.retryOn === 'function')) { + retryOn = options.retryOn; + } else { + throw new ArgumentError('retryOn property expects an array or function'); + } } - } - return new Promise(function(resolve, reject) { - var wrappedFetch = function(attempt) { - fetch(url, options) - .then(function(response) { - if (Array.isArray(retryOn) && retryOn.indexOf(response.status) === -1) { - resolve(response); - } else if (typeof retryOn === 'function') { - if (retryOn(attempt, null, response)) { - retry(attempt, null, response); - } else { + return new Promise(function (resolve, reject) { + var wrappedFetch = function (attempt) { + fetch(url, options) + .then(function (response) { + if (Array.isArray(retryOn) && retryOn.indexOf(response.status) === -1) { resolve(response); - } - } else { - if (attempt < retries) { - retry(attempt, null, response); + } else if (typeof retryOn === 'function') { + if (retryOn(attempt, null, response)) { + retry(attempt, null, response); + } else { + resolve(response); + } } else { - resolve(response); + if (attempt < retries) { + retry(attempt, null, response); + } else { + resolve(response); + } } - } - }) - .catch(function(error) { - if (typeof retryOn === 'function') { - if (retryOn(attempt, error, null)) { + }) + .catch(function (error) { + if (typeof retryOn === 'function') { + if (retryOn(attempt, error, null)) { + retry(attempt, error, null); + } else { + reject(error); + } + } else if (attempt < retries) { retry(attempt, error, null); } else { reject(error); } - } else if (attempt < retries) { - retry(attempt, error, null); - } else { - reject(error); - } - }); - }; + }); + }; - function retry(attempt, error, response) { - var delay = (typeof retryDelay === 'function') ? - retryDelay(attempt, error, response) : retryDelay; - setTimeout(function() { - wrappedFetch(++attempt); - }, delay); - } + function retry(attempt, error, response) { + var delay = (typeof retryDelay === 'function') ? + retryDelay(attempt, error, response) : retryDelay; + setTimeout(function () { + wrappedFetch(++attempt); + }, delay); + } - wrappedFetch(0); - }); + wrappedFetch(0); + }); + }; }; function isPositiveInteger(value) { diff --git a/package-lock.json b/package-lock.json index e21b830..ef90128 100644 --- a/package-lock.json +++ b/package-lock.json @@ -648,6 +648,7 @@ "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, "requires": { "iconv-lite": "~0.4.13" } @@ -943,16 +944,6 @@ "flat-cache": "^2.0.1" } }, - "fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - } - }, "finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -1176,9 +1167,13 @@ } }, "iconv-lite": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.16.tgz", - "integrity": "sha1-Zd477rOeKWDWfwSfFjT/y83pAUs=" + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } }, "ignore": { "version": "4.0.6", @@ -1272,12 +1267,6 @@ "is-extglob": "^2.1.1" } }, - "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true - }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -1287,7 +1276,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "isarray": { "version": "0.0.1", @@ -1305,6 +1295,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "dev": true, "requires": { "node-fetch": "^1.0.1", "whatwg-fetch": ">=0.10.0" @@ -1650,12 +1641,6 @@ "supports-color": "5.4.0" } }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1723,9 +1708,10 @@ } }, "node-fetch": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", - "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, "requires": { "encoding": "^0.1.11", "is-stream": "^1.0.1" @@ -2014,17 +2000,6 @@ "ipaddr.js": "1.9.0" } }, - "proxyquire": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "requires": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -2659,9 +2634,10 @@ "dev": true }, "whatwg-fetch": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", - "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", + "dev": true }, "which": { "version": "1.3.1", diff --git a/package.json b/package.json index 8d28b19..0aed3be 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,7 @@ "author": "Jon K. Bernhardsen", "license": "MIT", "dependencies": { - "es6-promise": "^4.2.8", - "isomorphic-fetch": "^2.2.1" + "es6-promise": "^4.2.8" }, "devDependencies": { "body-parser": "^1.19.0", @@ -29,9 +28,9 @@ "eslint": "^6.2.2", "expectations": "^0.7.1", "express": "^4.17.1", + "isomorphic-fetch": "^2.2.1", "mocha": "^5.2.0", "nyc": "^14.1.1", - "proxyquire": "^2.1.3", "sinon": "^6.3.5" } } diff --git a/test/integration/index.js b/test/integration/index.js index ddcb1bb..948e6c1 100644 --- a/test/integration/index.js +++ b/test/integration/index.js @@ -4,7 +4,8 @@ const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); chai.should(); const childProcess = require('child_process'); -const fetchRetry = require('../../'); +const fetch = require('isomorphic-fetch'); +const fetchRetry = require('../../')(fetch); describe('fetch-retry integration tests', () => { diff --git a/test/unit/index.js b/test/unit/index.js index 680b22d..5a3c9cf 100644 --- a/test/unit/index.js +++ b/test/unit/index.js @@ -1,12 +1,28 @@ 'use strict'; -require('isomorphic-fetch'); -var proxyquire = require('proxyquire').noPreserveCache(); +var fetchBuilder = require('../../'); var sinon = require('sinon'); var expect = require('expectations'); var Promise = require('es6-promise'); -describe('fetch-retry', function() { +describe('fetchBuilder', function () { + it('should accept fetch function as argument', function () { + expect(function () { + fetchBuilder(); + }).toThrow({ + name: 'ArgumentError', + message: 'fetch must be a function' + }); + }); + + it('should return fetchRetry function', function () { + expect(typeof fetchBuilder(function () { })).toBe('function'); + }); +}); + +describe('fetch-retry', function () { + + var fetch; var fetchRetry; var deferred1; @@ -20,55 +36,51 @@ describe('fetch-retry', function() { var clock; var delay; - beforeEach(function() { + beforeEach(function () { delay = 1000; clock = sinon.useFakeTimers(); }); - afterEach(function() { + afterEach(function () { clock.restore(); }); - beforeEach(function() { + beforeEach(function () { deferred1 = defer(); deferred2 = defer(); deferred3 = defer(); deferred4 = defer(); - global.fetch = sinon.stub(); + fetch = sinon.stub(); fetch.onCall(0).returns(deferred1.promise); fetch.onCall(1).returns(deferred2.promise); fetch.onCall(2).returns(deferred3.promise); fetch.onCall(3).returns(deferred4.promise); - var stubs = { - 'isomorphic-fetch': fetch - }; - - fetchRetry = proxyquire('../../', stubs); + fetchRetry = fetchBuilder(fetch); }); - describe('#url', function() { + describe('#url', function () { var expectedUrl = 'http://some-url.com'; - beforeEach(function() { + beforeEach(function () { fetchRetry(expectedUrl); }); - it('passes #url to fetch', function() { + it('passes #url to fetch', function () { expect(fetch.getCall(0).args[0]).toBe(expectedUrl); }); }); - describe('#options', function() { + describe('#options', function () { - describe('when #options is provided', function() { + describe('when #options is provided', function () { var options; - beforeEach(function() { + beforeEach(function () { options = { retries: 3, whatever: 'something' @@ -77,14 +89,14 @@ describe('fetch-retry', function() { fetchRetry('http://someUrl', options); }); - it('passes options to fetch', function() { + it('passes options to fetch', function () { expect(fetch.getCall(0).args[1]).toEqual(options); }); describe('when #options.retryOn is not an array or function', () => { it('throws exception', () => { - expect(function() { + expect(function () { options.retryOn = 503; fetchRetry('http://someUrl', options); }).toThrow({ @@ -97,15 +109,15 @@ describe('fetch-retry', function() { }); - describe('when #options is undefined or null', function() { + describe('when #options is undefined or null', function () { - [undefined, null].forEach(function(testCase) { + [undefined, null].forEach(function (testCase) { - beforeEach(function() { + beforeEach(function () { fetchRetry('http://someUrl', testCase); }); - it('does not pass through options to fetch', function() { + it('does not pass through options to fetch', function () { expect(fetch.getCall(0).args[1]).toEqual(undefined); }); @@ -115,11 +127,11 @@ describe('fetch-retry', function() { }); - describe('#options.retries', function() { + describe('#options.retries', function () { - describe('when #options.retries=3 (default)', function() { + describe('when #options.retries=3 (default)', function () { - beforeEach(function() { + beforeEach(function () { thenCallback = sinon.spy(); catchCallback = sinon.spy(); @@ -128,19 +140,19 @@ describe('fetch-retry', function() { .catch(catchCallback); }); - describe('when first call is a success', function() { + describe('when first call is a success', function () { - beforeEach(function() { + beforeEach(function () { deferred1.resolve({ status: 200 }); }); - describe('when resolved', function() { + describe('when resolved', function () { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('calls fetch once', function() { + it('calls fetch once', function () { expect(fetch.callCount).toBe(1); }); @@ -148,26 +160,26 @@ describe('fetch-retry', function() { }); - describe('when first call is a failure', function() { + describe('when first call is a failure', function () { - beforeEach(function() { + beforeEach(function () { deferred1.reject(); }); - describe('when second call is a success', function() { + describe('when second call is a success', function () { - beforeEach(function() { + beforeEach(function () { clock.tick(delay); deferred2.resolve({ status: 200 }); }); - describe('when resolved', function() { + describe('when resolved', function () { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('calls fetch twice', function() { + it('calls fetch twice', function () { expect(fetch.callCount).toBe(2); }); @@ -175,27 +187,27 @@ describe('fetch-retry', function() { }); - describe('when second call is a failure', function() { + describe('when second call is a failure', function () { - beforeEach(function() { + beforeEach(function () { deferred2.reject(); clock.tick(delay); }); - describe('when third call is a success', function() { + describe('when third call is a success', function () { - beforeEach(function() { + beforeEach(function () { deferred3.resolve({ status: 200 }); clock.tick(delay); }); - describe('when resolved', function() { + describe('when resolved', function () { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('calls fetch three times', function() { + it('calls fetch three times', function () { expect(fetch.callCount).toBe(3); }); @@ -203,27 +215,27 @@ describe('fetch-retry', function() { }); - describe('when third call is a failure', function() { + describe('when third call is a failure', function () { - beforeEach(function() { + beforeEach(function () { deferred3.reject(); clock.tick(delay); }); - describe('when fourth call is a success', function() { + describe('when fourth call is a success', function () { - beforeEach(function() { + beforeEach(function () { deferred4.resolve({ status: 200 }); clock.tick(delay); }); - describe('when resolved', function() { + describe('when resolved', function () { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('calls fetch four times', function() { + it('calls fetch four times', function () { expect(fetch.callCount).toBe(4); }); @@ -231,20 +243,20 @@ describe('fetch-retry', function() { }); - describe('when fourth call is a failure', function() { + describe('when fourth call is a failure', function () { - beforeEach(function() { + beforeEach(function () { deferred4.reject(); clock.tick(delay); }); - describe('when rejected', function() { + describe('when rejected', function () { - it('invokes the catch callback', function() { + it('invokes the catch callback', function () { expect(catchCallback.called).toBe(true); }); - it('does not call fetch again', function() { + it('does not call fetch again', function () { expect(fetch.callCount).toBe(4); }); @@ -260,9 +272,9 @@ describe('fetch-retry', function() { }); - describe('when #options.retries=1', function() { + describe('when #options.retries=1', function () { - beforeEach(function() { + beforeEach(function () { thenCallback = sinon.spy(); catchCallback = sinon.spy(); @@ -271,19 +283,19 @@ describe('fetch-retry', function() { .catch(catchCallback); }); - describe('when first call is a success', function() { + describe('when first call is a success', function () { - beforeEach(function() { + beforeEach(function () { deferred1.resolve({ status: 200 }); }); - describe('when resolved', function() { + describe('when resolved', function () { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('calls fetch once', function() { + it('calls fetch once', function () { expect(fetch.callCount).toBe(1); }); @@ -291,27 +303,27 @@ describe('fetch-retry', function() { }); - describe('when first call is a failure', function() { + describe('when first call is a failure', function () { - beforeEach(function() { + beforeEach(function () { deferred1.reject(); clock.tick(delay); }); - describe('when second call is a success', function() { + describe('when second call is a success', function () { - beforeEach(function() { + beforeEach(function () { deferred2.resolve({ status: 200 }); clock.tick(delay); }); - describe('when resolved', function() { + describe('when resolved', function () { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('calls fetch twice', function() { + it('calls fetch twice', function () { expect(fetch.callCount).toBe(2); }); @@ -319,20 +331,20 @@ describe('fetch-retry', function() { }); - describe('when second call is a failure', function() { + describe('when second call is a failure', function () { - beforeEach(function() { + beforeEach(function () { deferred2.reject(); clock.tick(delay); }); - describe('when rejected', function() { + describe('when rejected', function () { - it('invokes the catch callback', function() { + it('invokes the catch callback', function () { expect(catchCallback.called).toBe(true); }); - it('does not call fetch again', function() { + it('does not call fetch again', function () { expect(fetch.callCount).toBe(2); }); @@ -344,9 +356,9 @@ describe('fetch-retry', function() { }); - describe('when #options.retries=0', function() { + describe('when #options.retries=0', function () { - beforeEach(function() { + beforeEach(function () { thenCallback = sinon.spy(); catchCallback = sinon.spy(); @@ -355,19 +367,19 @@ describe('fetch-retry', function() { .catch(catchCallback); }); - describe('when first call is a success', function() { + describe('when first call is a success', function () { - beforeEach(function() { + beforeEach(function () { deferred1.resolve({ status: 200 }); }); - describe('when resolved', function() { + describe('when resolved', function () { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('calls fetch once', function() { + it('calls fetch once', function () { expect(fetch.callCount).toBe(1); }); @@ -375,15 +387,15 @@ describe('fetch-retry', function() { }); - describe('when first call is a failure', function() { + describe('when first call is a failure', function () { - beforeEach(function() { + beforeEach(function () { deferred1.reject(); }); describe('when rejected', () => { - it('invokes the catch callback', function() { + it('invokes the catch callback', function () { expect(catchCallback.called).toBe(true); }); @@ -413,14 +425,14 @@ describe('fetch-retry', function() { }); - describe('#options.retryDelay', function() { + describe('#options.retryDelay', function () { - describe('when #options.retryDelay is a number', function() { + describe('when #options.retryDelay is a number', function () { var options; var retryDelay; - beforeEach(function() { + beforeEach(function () { retryDelay = 5000; options = { retryDelay: retryDelay @@ -432,31 +444,31 @@ describe('fetch-retry', function() { .then(thenCallback); }); - describe('when first call is unsuccessful', function() { + describe('when first call is unsuccessful', function () { - beforeEach(function() { + beforeEach(function () { deferred1.reject(); }); - describe('after specified time', function() { + describe('after specified time', function () { - beforeEach(function() { + beforeEach(function () { clock.tick(retryDelay); }); - it('invokes fetch again', function() { + it('invokes fetch again', function () { expect(fetch.callCount).toBe(2); }); }); - describe('after less than specified time', function() { + describe('after less than specified time', function () { - beforeEach(function() { + beforeEach(function () { clock.tick(1000); }); - it('does not invoke fetch again', function() { + it('does not invoke fetch again', function () { expect(fetch.callCount).toBe(1); }); @@ -466,12 +478,12 @@ describe('fetch-retry', function() { }); - describe('when #options.retryDelay is 0', function() { + describe('when #options.retryDelay is 0', function () { var options; var retryDelay; - beforeEach(function() { + beforeEach(function () { retryDelay = 0; options = { retryDelay: retryDelay @@ -483,19 +495,19 @@ describe('fetch-retry', function() { .then(thenCallback); }); - describe('when first call is unsuccessful', function() { + describe('when first call is unsuccessful', function () { - beforeEach(function() { + beforeEach(function () { deferred1.reject(); }); - describe('after one event loop tick', function() { + describe('after one event loop tick', function () { - beforeEach(function() { + beforeEach(function () { clock.tick(0); }); - it('invokes fetch again', function() { + it('invokes fetch again', function () { expect(fetch.callCount).toBe(2); }); @@ -523,12 +535,12 @@ describe('fetch-retry', function() { }); - describe('when #options.retryDelay is a function', function() { + describe('when #options.retryDelay is a function', function () { var options; var retryDelay; - beforeEach(function() { + beforeEach(function () { retryDelay = sinon.stub().returns(5000); options = { retryDelay: retryDelay @@ -540,20 +552,20 @@ describe('fetch-retry', function() { .then(thenCallback); }); - describe('when first call is unsuccessful', function() { + describe('when first call is unsuccessful', function () { - beforeEach(function() { + beforeEach(function () { deferred1.reject(new Error('first error')); }); - describe('when the second call is a success', function() { + describe('when the second call is a success', function () { - beforeEach(function() { + beforeEach(function () { deferred2.resolve({ status: 200 }); clock.tick(5000); }); - it('invokes the retryDelay function', function() { + it('invokes the retryDelay function', function () { expect(retryDelay.called).toBe(true); expect(retryDelay.lastCall.args[0]).toEqual(0); expect(retryDelay.lastCall.args[1].message).toEqual('first error'); @@ -562,21 +574,21 @@ describe('fetch-retry', function() { }); - describe('when second call is a failure', function() { + describe('when second call is a failure', function () { - beforeEach(function() { + beforeEach(function () { deferred2.reject(new Error('second error')); clock.tick(5000); }); - describe('when the third call is a success', function() { + describe('when the third call is a success', function () { - beforeEach(function() { + beforeEach(function () { deferred3.resolve({ status: 200 }); clock.tick(5000); }); - it('invokes the retryDelay function again', function() { + it('invokes the retryDelay function again', function () { expect(retryDelay.callCount).toBe(2); expect(retryDelay.lastCall.args[0]).toEqual(1); expect(retryDelay.lastCall.args[1].message).toEqual('second error'); @@ -599,7 +611,7 @@ describe('fetch-retry', function() { var options; var retryOn; - beforeEach(function() { + beforeEach(function () { retryOn = [503, 404]; options = { retryOn: retryOn @@ -616,7 +628,7 @@ describe('fetch-retry', function() { describe('when first fetch is resolved with status code specified in retryOn array', () => { beforeEach(() => { - deferred1.resolve({status: 503}); + deferred1.resolve({ status: 503 }); }); describe('after specified delay', () => { @@ -632,16 +644,16 @@ describe('fetch-retry', function() { describe('when second fetch resolves with a different status code', () => { beforeEach(() => { - deferred2.resolve({status: 200}); + deferred2.resolve({ status: 200 }); }); describe('when resolved', () => { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('has called fetch twice', function() { + it('has called fetch twice', function () { expect(fetch.callCount).toBe(2); }); @@ -655,12 +667,12 @@ describe('fetch-retry', function() { }); - describe('when #options.retryOn is a function', function() { + describe('when #options.retryOn is a function', function () { var options; var retryOn; - beforeEach(function() { + beforeEach(function () { retryOn = sinon.stub(); options = { retryOn: retryOn @@ -674,18 +686,18 @@ describe('fetch-retry', function() { .catch((catchCallback)); }); - describe('when first attempt is rejected due to network error', function() { + describe('when first attempt is rejected due to network error', function () { describe('when #retryOn() returns true', () => { - beforeEach(function() { + beforeEach(function () { retryOn.returns(true); deferred1.reject(new Error('first error')); }); - describe('when rejected', function() { + describe('when rejected', function () { - it('invokes #retryOn function with an error', function() { + it('invokes #retryOn function with an error', function () { expect(retryOn.called).toBe(true); expect(retryOn.lastCall.args.length).toBe(3); expect(retryOn.lastCall.args[0]).toBe(0); @@ -693,26 +705,26 @@ describe('fetch-retry', function() { expect(retryOn.lastCall.args[2]).toBe(null); }); - describe('after specified time', function() { + describe('after specified time', function () { - beforeEach(function() { + beforeEach(function () { clock.tick(delay); }); - it('invokes fetch again', function() { + it('invokes fetch again', function () { expect(fetch.callCount).toBe(2); }); - describe('when the second call is unsuccessful', function() { + describe('when the second call is unsuccessful', function () { - beforeEach(function() { + beforeEach(function () { deferred2.reject(new Error('second error')); clock.tick(delay); }); - describe('when rejected', function() { + describe('when rejected', function () { - it('invokes the #retryOn function twice', function() { + it('invokes the #retryOn function twice', function () { expect(retryOn.callCount).toBe(2); expect(retryOn.lastCall.args[0]).toBe(1); }); @@ -729,14 +741,14 @@ describe('fetch-retry', function() { describe('when #retryOn() returns false', () => { - beforeEach(function() { + beforeEach(function () { retryOn.returns(false); deferred1.reject(new Error('first error')); }); - describe('when rejected', function() { + describe('when rejected', function () { - it('invokes #retryOn function with an error', function() { + it('invokes #retryOn function with an error', function () { expect(retryOn.called).toBe(true); expect(retryOn.lastCall.args.length).toBe(3); expect(retryOn.lastCall.args[0]).toBe(0); @@ -744,17 +756,17 @@ describe('fetch-retry', function() { expect(retryOn.lastCall.args[2]).toBe(null); }); - describe('after specified time', function() { + describe('after specified time', function () { - beforeEach(function() { + beforeEach(function () { clock.tick(delay); }); - it('invokes the catch callback', function() { + it('invokes the catch callback', function () { expect(catchCallback.called).toBe(true); }); - it('does not call fetch again', function() { + it('does not call fetch again', function () { expect(fetch.callCount).toBe(1); }); @@ -766,33 +778,33 @@ describe('fetch-retry', function() { }); - describe('when first attempt is resolved', function() { + describe('when first attempt is resolved', function () { describe('when #retryOn() returns true', () => { - beforeEach(function() { + beforeEach(function () { retryOn.returns(true); deferred1.resolve({ status: 200 }); }); describe('after specified delay', () => { - beforeEach(function() { + beforeEach(function () { clock.tick(delay); }); - it('calls fetch again', function() { + it('calls fetch again', function () { expect(fetch.callCount).toBe(2); }); describe('when second call is resolved', () => { - beforeEach(function() { + beforeEach(function () { deferred2.resolve({ status: 200 }); clock.tick(delay); }); - it('invokes the #retryOn function with the response', function() { + it('invokes the #retryOn function with the response', function () { expect(retryOn.called).toBe(true); expect(retryOn.lastCall.args.length).toBe(3); expect(retryOn.lastCall.args[0]).toBe(0); @@ -808,18 +820,18 @@ describe('fetch-retry', function() { describe('when #retryOn() returns false', () => { - beforeEach(function() { + beforeEach(function () { retryOn.returns(false); deferred1.resolve({ status: 502 }); }); describe('when resolved', () => { - it('invokes the then callback', function() { + it('invokes the then callback', function () { expect(thenCallback.called).toBe(true); }); - it('calls fetch 1 time only', function() { + it('calls fetch 1 time only', function () { expect(fetch.callCount).toBe(1); }); @@ -831,14 +843,14 @@ describe('fetch-retry', function() { }); - describe('when #options.retryOn is not an array or function', function() { + describe('when #options.retryOn is not an array or function', function () { var options; describe('when #options.retryOn is not an array or function', () => { it('throws exception', () => { - expect(function() { + expect(function () { options.retryOn = 503; fetchRetry('http://someUrl', options); }).toThrow({ @@ -857,7 +869,7 @@ describe('fetch-retry', function() { function defer() { var resolve, reject; - var promise = new Promise(function() { + var promise = new Promise(function () { resolve = arguments[0]; reject = arguments[1]; });