From 7b2b4acbb6066160405c4f2f0bfe0d0b52652b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Sun, 28 Feb 2021 22:40:04 +0100 Subject: [PATCH] fix: add unit test for addon-retry --- src/lib/addons/addon.js | 39 +++++++------------- src/lib/addons/addon.test.js | 70 ++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 src/lib/addons/addon.test.js diff --git a/src/lib/addons/addon.js b/src/lib/addons/addon.js index 04c9285f66..499c5c8ec2 100644 --- a/src/lib/addons/addon.js +++ b/src/lib/addons/addon.js @@ -28,36 +28,21 @@ class Addon { async fetchRetry(url, options = {}, retries = 1, backoff = 300) { const retryCodes = [408, 500, 502, 503, 504, 522, 524]; + let res; try { - const res = await fetch(url, options); - if (res.ok) { - return res; - } - if (retries > 0 && retryCodes.includes(res.status)) { - setTimeout(() => { - return this.fetchRetry( - url, - options, - retries - 1, - backoff * 2, - ); - }, backoff); - } - return res; + res = await fetch(url, options); } catch (error) { - this.logger.warn(error); - if (retries > 0) { - setTimeout(() => { - return this.fetchRetry( - url, - options, - retries - 1, - backoff * 2, - ); - }, backoff); - } - return { status: 500 }; + res = { status: 500, ok: false }; } + if (res.ok) { + return res; + } + if (retries > 0 && retryCodes.includes(res.status)) { + setTimeout(() => { + return this.fetchRetry(url, options, retries - 1, backoff * 2); + }, backoff); + } + return res; } } diff --git a/src/lib/addons/addon.test.js b/src/lib/addons/addon.test.js new file mode 100644 index 0000000000..b9694be25f --- /dev/null +++ b/src/lib/addons/addon.test.js @@ -0,0 +1,70 @@ +const test = require('ava'); +const proxyquire = require('proxyquire'); +const lolex = require('lolex'); +const fetchMock = require('fetch-mock').sandbox(); +const noLogger = require('../../test/fixtures/no-logger'); + +const Addon = proxyquire('./addon', { 'node-fetch': fetchMock }); + +test.beforeEach(() => { + fetchMock.restore(); + fetchMock.reset(); +}); + +const definition = { + name: 'test', + displayName: 'test', + description: 'hello', +}; + +test.serial('Retries if fetch throws', async t => { + const url = 'https://test.some.com'; + const clock = lolex.install(); + const addon = new Addon(definition, { + getLogger: noLogger, + }); + fetchMock + .once( + { + name: 'rejection', + type: 'POST', + url: `begin:${url}`, + }, + () => { + throw new Error('Network error'); + }, + ) + .mock( + { + name: 'acceptance', + type: 'POST', + url: `begin:${url}`, + }, + 201, + ); + await addon.fetchRetry(url); + clock.tick(1000); + t.true(fetchMock.done()); +}); + +test.serial('does not crash even if fetch throws', async t => { + const url = 'https://test.some.com'; + const clock = lolex.install(); + const addon = new Addon(definition, { + getLogger: noLogger, + }); + fetchMock.mock( + { + name: 'rejection', + type: 'POST', + url: `begin:${url}`, + }, + () => { + throw new Error('Network error'); + }, + ); + await addon.fetchRetry(url); + clock.tick(1000); + t.true(fetchMock.done()); + t.is(fetchMock.calls().length, 2); +});