123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- 'use strict';
- const chai = require('chai');
- const chaiAsPromised = require('chai-as-promised');
- chai.use(chaiAsPromised);
- chai.should();
- const childProcess = require('child_process');
- const fetch = require('node-fetch');
- const fetchRetry = require('../../')(fetch);
- describe('fetch-retry integration tests', () => {
- const baseUrl = 'http://localhost:3000/mock';
- before(() => {
- const process = childProcess.fork('./test/integration/mock-api/index.js');
- process.on('error', err => {
- console.log(err);
- });
- });
- after(() => {
- return fetchRetry(baseUrl + '/stop', {
- method: 'POST'
- });
- });
- const setupResponses = (responses) => {
- return fetchRetry(baseUrl, {
- method: 'POST',
- body: JSON.stringify(responses),
- headers: {
- 'content-type': 'application/json'
- }
- });
- };
- const getCallCount = () => {
- return fetchRetry(`${baseUrl}/calls`)
- .then(response => {
- return response.text();
- })
- .then(text => {
- return Number.parseInt(text);
- });
- };
- [
- ['with url string', (baseUrl, init) => fetchRetry(baseUrl, init)],
- ['with URL type', (baseUrl, init) => {
- const url = new URL(baseUrl);
- return fetchRetry(url, init);
- }],
- ['with Request argument', (baseUrl, init) => {
- const request = new fetch.Request(baseUrl);
- return fetchRetry(request, init);
- }],
- ].forEach(([usagePatternDescription, fetchInvocation]) => {
- describe(usagePatternDescription, () => {
- [200, 503, 404].forEach(statusCode => {
- describe('when endpoint returns ' + statusCode, () => {
-
- before(() => {
- return setupResponses([statusCode]);
- });
-
- it('does not retry request', () => {
- return fetchInvocation(baseUrl)
- .then(getCallCount)
- .should.eventually.equal(1);
- });
-
- });
-
- });
-
- describe('when configured to retry on a specific HTTP code', () => {
-
- describe('and it never succeeds', () => {
-
- const retryOn = [503];
-
- beforeEach(() => {
- return setupResponses([503, 503, 503, 503]);
- });
-
- it('retries the request #retries times', () => {
- const init = {
- retries: 3,
- retryDelay: 100,
- retryOn
- };
-
- const expectedCallCount = init.retries + 1;
-
- return fetchInvocation(baseUrl, init)
- .then(getCallCount)
- .should.eventually.equal(expectedCallCount);
- });
-
- it('eventually resolves the promise with the response of the last request', () => {
- const init = {
- retries: 3,
- retryDelay: 100,
- retryOn
- };
-
- const expectedResponse = {
- status: 503,
- ok: false
- };
-
- return fetchInvocation(baseUrl, init)
- .then(response => {
- return {
- status: response.status,
- ok: response.ok
- };
- })
- .should.become(expectedResponse);
- });
-
- });
-
- describe('and it eventually succeeds', () => {
-
- const retryOnStatus = 503;
- const responses = [503, 503, 200];
- const requestsToRetry = responses
- .filter(response => response === retryOnStatus)
- .length;
-
- beforeEach(() => {
- return setupResponses(responses);
- });
-
- it('retries the request up to #retries times', () => {
- const init = {
- retries: 3,
- retryDelay: 100,
- retryOn: [retryOnStatus]
- };
-
- const expectedCallCount = requestsToRetry + 1;
-
- return fetchInvocation(baseUrl, init)
- .then(getCallCount)
- .should.eventually.equal(expectedCallCount);
- });
-
- it('eventually resolves the promise with the received response of the last request', () => {
- const init = {
- retries: 3,
- retryDelay: 100,
- retryOn: [retryOnStatus]
- };
-
- const expectedResponse = {
- status: 200,
- ok: true
- };
-
- return fetchInvocation(baseUrl, init)
- .then(response => {
- return {
- status: response.status,
- ok: response.ok
- };
- })
- .should.become(expectedResponse);
- });
-
- });
-
- });
-
- describe('when configured to retry on a set of HTTP codes', () => {
-
- describe('and it never succeeds', () => {
-
- const retryOn = [503, 404];
-
- beforeEach(() => {
- return setupResponses([503, 404, 404, 503]);
- });
-
- it('retries the request #retries times', () => {
- const init = {
- retries: 3,
- retryDelay: 100,
- retryOn
- };
-
- const expectedCallCount = init.retries + 1;
-
- return fetchInvocation(baseUrl, init)
- .then(getCallCount)
- .should.eventually.equal(expectedCallCount);
- });
-
- });
-
- });
-
- });
- });
- });
|