From 1c85c5293ebbcd4be2cddeeddf890981df369dd3 Mon Sep 17 00:00:00 2001 From: Wil Wilsman Date: Thu, 17 Mar 2022 15:09:23 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20sdk-utils=20waitForPercyIdle?= =?UTF-8?q?=20helper=20(#831)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/sdk-utils/src/index.js | 2 ++ packages/sdk-utils/src/percy-idle.js | 13 +++++++++++++ packages/sdk-utils/test/index.test.js | 21 +++++++++++++++++++++ packages/sdk-utils/test/server.js | 3 ++- 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 packages/sdk-utils/src/percy-idle.js diff --git a/packages/sdk-utils/src/index.js b/packages/sdk-utils/src/index.js index 460cc9ade..b77e496f9 100644 --- a/packages/sdk-utils/src/index.js +++ b/packages/sdk-utils/src/index.js @@ -2,6 +2,7 @@ import logger from '@percy/logger'; import percy from './percy-info'; import request from './request'; import isPercyEnabled from './percy-enabled'; +import waitForPercyIdle from './percy-idle'; import fetchPercyDOM from './percy-dom'; import postSnapshot from './post-snapshot'; @@ -13,6 +14,7 @@ export { percy, request, isPercyEnabled, + waitForPercyIdle, fetchPercyDOM, postSnapshot }; diff --git a/packages/sdk-utils/src/percy-idle.js b/packages/sdk-utils/src/percy-idle.js new file mode 100644 index 000000000..e4fb88cff --- /dev/null +++ b/packages/sdk-utils/src/percy-idle.js @@ -0,0 +1,13 @@ +import request from './request'; + +const RETRY_ERROR_CODES = ['ECONNRESET', 'ETIMEDOUT']; + +export async function waitForPercyIdle() { + try { + return !!(await request('/percy/idle')); + } catch (e) { + return RETRY_ERROR_CODES.includes(e.code) && waitForPercyIdle(); + } +} + +export default waitForPercyIdle; diff --git a/packages/sdk-utils/test/index.test.js b/packages/sdk-utils/test/index.test.js index 60f4593e2..9bfcfc05d 100644 --- a/packages/sdk-utils/test/index.test.js +++ b/packages/sdk-utils/test/index.test.js @@ -126,6 +126,27 @@ describe('SDK Utils', () => { }); }); + describe('waitForPercyIdle()', () => { + let { waitForPercyIdle } = utils; + + it('gets idle state from the CLI API idle endpoint', async () => { + await expectAsync(waitForPercyIdle()).toBeResolvedTo(true); + await expectAsync(helpers.getRequests()).toBeResolvedTo([['/percy/idle']]); + }); + + it('polls the CLI API idle endpoint on timeout', async () => { + spyOn(utils.request, 'fetch').and.callFake((...args) => { + return utils.request.fetch.calls.count() > 2 + ? utils.request.fetch.and.originalFn(...args) + // eslint-disable-next-line prefer-promise-reject-errors + : Promise.reject({ code: 'ETIMEDOUT' }); + }); + + await expectAsync(waitForPercyIdle()).toBeResolvedTo(true); + expect(utils.request.fetch).toHaveBeenCalledTimes(3); + }); + }); + describe('fetchPercyDOM()', () => { let { fetchPercyDOM } = utils; diff --git a/packages/sdk-utils/test/server.js b/packages/sdk-utils/test/server.js index 6729904f5..eadfc7110 100644 --- a/packages/sdk-utils/test/server.js +++ b/packages/sdk-utils/test/server.js @@ -50,7 +50,8 @@ function context() { { success: true, config: { snapshot: { widths: [1280] } } })], '/percy/config': ({ body }) => [200, 'application/json', ( { success: true, config: body })], - '/percy/snapshot': () => [200, 'application/json', { success: true }] + '/percy/snapshot': () => [200, 'application/json', { success: true }], + '/percy/idle': () => [200, 'application/json', { success: true }] }, 5338); ctx.server.route((req, res, next) => {