From 5d37245ec00ed98861d64bcec114860f2a97265b Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Thu, 9 May 2019 10:17:55 -0700 Subject: [PATCH 1/4] Remove timeout factory, use jest fake timers for testing --- .../__test__/browserDatafileManager.spec.ts | 13 +- .../httpPollingDatafileManager.spec.ts | 116 ++++++++++-------- .../__test__/nodeDatafileManager.spec.ts | 16 ++- .../__test__/testTimeoutFactory.ts | 37 ------ .../datafile-manager/__test__/testUtils.ts | 11 ++ .../datafile-manager/src/datafileManager.ts | 3 - .../src/httpPollingDatafileManager.ts | 17 +-- .../datafile-manager/src/timeoutFactory.ts | 28 ----- 8 files changed, 94 insertions(+), 147 deletions(-) delete mode 100644 packages/datafile-manager/__test__/testTimeoutFactory.ts create mode 100644 packages/datafile-manager/__test__/testUtils.ts delete mode 100644 packages/datafile-manager/src/timeoutFactory.ts diff --git a/packages/datafile-manager/__test__/browserDatafileManager.spec.ts b/packages/datafile-manager/__test__/browserDatafileManager.spec.ts index 5f2b2492f..d5f38c74c 100644 --- a/packages/datafile-manager/__test__/browserDatafileManager.spec.ts +++ b/packages/datafile-manager/__test__/browserDatafileManager.spec.ts @@ -17,19 +17,18 @@ import BrowserDatafileManager from '../src/browserDatafileManager' import * as browserRequest from '../src/browserRequest' import { Headers, AbortableRequest } from '../src/http' -import TestTimeoutFactory from './testTimeoutFactory' +import { advanceTimersByTime, getTimerCount } from './testUtils'; describe('browserDatafileManager', () => { - const testTimeoutFactory: TestTimeoutFactory = new TestTimeoutFactory() - let makeGetRequestSpy: jest.SpyInstance beforeEach(() => { + jest.useFakeTimers() makeGetRequestSpy = jest.spyOn(browserRequest, 'makeGetRequest') }) afterEach(() => { jest.restoreAllMocks() - testTimeoutFactory.cleanup() + jest.clearAllTimers() }) it('calls makeGetRequest when started', async () => { @@ -69,11 +68,10 @@ describe('browserDatafileManager', () => { const manager = new BrowserDatafileManager({ sdkKey: '1234', autoUpdate: true, - timeoutFactory: testTimeoutFactory, }) manager.start() await manager.onReady() - testTimeoutFactory.timeoutFns[0]() + await advanceTimersByTime(300000) expect(makeGetRequestSpy).toBeCalledTimes(2) expect(makeGetRequestSpy.mock.calls[1][0]).toBe('https://cdn.optimizely.com/datafiles/1234.json') expect(makeGetRequestSpy.mock.calls[1][1]).toEqual({ @@ -96,12 +94,11 @@ describe('browserDatafileManager', () => { }) const manager = new BrowserDatafileManager({ sdkKey: '1234', - timeoutFactory: testTimeoutFactory, }) manager.start() await manager.onReady() // Should not set a timeout for a later update - expect(testTimeoutFactory.timeoutFns.length).toBe(0) + expect(getTimerCount()).toBe(0) await manager.stop() }) diff --git a/packages/datafile-manager/__test__/httpPollingDatafileManager.spec.ts b/packages/datafile-manager/__test__/httpPollingDatafileManager.spec.ts index 00dc8d468..669bb5c78 100644 --- a/packages/datafile-manager/__test__/httpPollingDatafileManager.spec.ts +++ b/packages/datafile-manager/__test__/httpPollingDatafileManager.spec.ts @@ -17,7 +17,7 @@ import HTTPPollingDatafileManager from '../src/httpPollingDatafileManager' import { Headers, AbortableRequest, Response } from '../src/http' import { DatafileManagerConfig } from '../src/datafileManager'; -import TestTimeoutFactory from './testTimeoutFactory' +import { advanceTimersByTime, getTimerCount } from './testUtils' jest.mock('../src/backoffController', () => { return jest.fn().mockImplementation(() => { @@ -59,29 +59,23 @@ class TestDatafileManager extends HTTPPollingDatafileManager { } describe('httpPollingDatafileManager', () => { - const testTimeoutFactory: TestTimeoutFactory = new TestTimeoutFactory() - - function createTestManager(config: DatafileManagerConfig): TestDatafileManager { - return new TestDatafileManager({ - ...config, - timeoutFactory: testTimeoutFactory - }) - } + beforeEach(() => { + jest.useFakeTimers() + }) let manager: TestDatafileManager afterEach(async () => { - testTimeoutFactory.cleanup() - if (manager) { manager.stop() } jest.clearAllMocks() jest.restoreAllMocks() + jest.clearAllTimers() }) describe('when constructed with sdkKey and datafile and autoUpdate: true,', () => { beforeEach(() => { - manager = createTestManager({ datafile: { foo: 'abcd' }, sdkKey: '123', autoUpdate: true }) + manager = new TestDatafileManager({ datafile: { foo: 'abcd' }, sdkKey: '123', autoUpdate: true }) }) it('returns the passed datafile from get', () => { @@ -118,7 +112,9 @@ describe('httpPollingDatafileManager', () => { }) expect(manager.get()).toEqual({ foo: 'bar' }) updateFn.mockReset() - testTimeoutFactory.timeoutFns[0]() + + await advanceTimersByTime(300000) + expect(manager.responsePromises.length).toBe(2) await manager.responsePromises[1] expect(updateFn).toBeCalledTimes(1) @@ -131,7 +127,7 @@ describe('httpPollingDatafileManager', () => { describe('when constructed with sdkKey and datafile and autoUpdate: false,', () => { beforeEach(() => { - manager = createTestManager({ datafile: { foo: 'abcd' }, sdkKey: '123', autoUpdate: false }) + manager = new TestDatafileManager({ datafile: { foo: 'abcd' }, sdkKey: '123', autoUpdate: false }) }) it('returns the passed datafile from get', () => { @@ -160,13 +156,13 @@ describe('httpPollingDatafileManager', () => { datafile: { foo: 'bar' } }) expect(manager.get()).toEqual({ foo: 'bar' }) - expect(testTimeoutFactory.timeoutFns.length).toBe(0) + expect(getTimerCount()).toBe(0) }) }) describe('when constructed with sdkKey and autoUpdate: true', () => { beforeEach(() => { - manager = createTestManager({ sdkKey: '123', updateInterval: 1000, autoUpdate: true }) + manager = new TestDatafileManager({ sdkKey: '123', updateInterval: 1000, autoUpdate: true }) }) describe('initial state', () => { @@ -215,22 +211,32 @@ describe('httpPollingDatafileManager', () => { ) manager.start() await manager.onReady() - testTimeoutFactory.timeoutFns[0]() + await advanceTimersByTime(1000) + expect(manager.responsePromises.length).toBe(2) await manager.responsePromises[1] expect(manager.get()).toEqual({ foo: 'bar' }) }) describe('live updates', () => { - it('passes the update interval to its timeoutFactory setTimeout method', () => { - manager.queuedResponses.push({ - statusCode: 200, - body: '{"foo3": "bar3"}', - headers: {}, - }) - const setTimeoutSpy: jest.SpyInstance<() => void, [() => void, number]> = jest.spyOn(testTimeoutFactory, 'setTimeout') + it('sets a timeout to update again after the update interval', async () => { + manager.queuedResponses.push( + { + statusCode: 200, + body: '{"foo3": "bar3"}', + headers: {}, + }, + { + statusCode: 200, + body: '{"foo4": "bar4"}', + headers: {}, + }, + ) + const makeGetRequestSpy = jest.spyOn(manager, 'makeGetRequest') manager.start() - expect(setTimeoutSpy).toBeCalledTimes(1) - expect(setTimeoutSpy.mock.calls[0][1]).toBe(1000) + expect(makeGetRequestSpy).toBeCalledTimes(1) + await manager.responsePromises[0] + await advanceTimersByTime(1000) + expect(makeGetRequestSpy).toBeCalledTimes(2) }) it('emits update events after live updates', async () => { @@ -260,7 +266,7 @@ describe('httpPollingDatafileManager', () => { expect(manager.get()).toEqual({ foo: 'bar' }) expect(updateFn).toBeCalledTimes(0) - testTimeoutFactory.timeoutFns[0]() + await advanceTimersByTime(1000) await manager.responsePromises[1] expect(updateFn).toBeCalledTimes(1) expect(updateFn.mock.calls[0][0]).toEqual({ datafile: { foo2: 'bar2' } }) @@ -268,7 +274,7 @@ describe('httpPollingDatafileManager', () => { updateFn.mockReset() - testTimeoutFactory.timeoutFns[1]() + await advanceTimersByTime(1000) await manager.responsePromises[2] expect(updateFn).toBeCalledTimes(1) expect(updateFn.mock.calls[0][0]).toEqual({ datafile: { foo3: 'bar3' } }) @@ -285,13 +291,11 @@ describe('httpPollingDatafileManager', () => { abort() {}, responsePromise, }) - const setTimeoutSpy = jest.spyOn(testTimeoutFactory, 'setTimeout') manager.start() - expect(setTimeoutSpy).toBeCalledTimes(1) expect(makeGetRequestSpy).toBeCalledTimes(1) - testTimeoutFactory.timeoutFns[0]() + await advanceTimersByTime(1000) expect(makeGetRequestSpy).toBeCalledTimes(1) resolveResponsePromise!({ @@ -301,7 +305,6 @@ describe('httpPollingDatafileManager', () => { }) await responsePromise expect(makeGetRequestSpy).toBeCalledTimes(2) - expect(setTimeoutSpy).toBeCalledTimes(2) }) }) @@ -317,10 +320,9 @@ describe('httpPollingDatafileManager', () => { manager.start() await manager.onReady() - expect(testTimeoutFactory.timeoutFns.length).toBe(1) - expect(testTimeoutFactory.cancelFns.length).toBe(1) + expect(getTimerCount()).toBe(1) manager.stop() - expect(testTimeoutFactory.cancelFns[0]).toBeCalledTimes(1) + expect(getTimerCount()).toBe(0) }) it('cancels reactions to a pending fetch when stop is called', async () => { @@ -340,7 +342,9 @@ describe('httpPollingDatafileManager', () => { manager.start() await manager.onReady() expect(manager.get()).toEqual({ foo: 'bar' }) - testTimeoutFactory.timeoutFns[0]() + + advanceTimersByTime(1000) + expect(manager.responsePromises.length).toBe(2) manager.stop() await manager.responsePromises[1] @@ -383,9 +387,9 @@ describe('httpPollingDatafileManager', () => { expect(manager.responsePromises.length).toBe(1) await manager.responsePromises[0] // Not ready yet due to first request failed, but should have queued a live update - expect(testTimeoutFactory.timeoutFns.length).toBe(1) + expect(getTimerCount()).toBe(1) // Trigger the update, should fetch the next response which should succeed, then we get ready - testTimeoutFactory.timeoutFns[0]() + advanceTimersByTime(1000) await manager.onReady() expect(manager.get()).toEqual({ foo: 'bar' }) }) @@ -416,7 +420,7 @@ describe('httpPollingDatafileManager', () => { // First response promise was for the initial 200 response expect(manager.responsePromises.length).toBe(1) // Trigger the queued update - testTimeoutFactory.timeoutFns[0]() + advanceTimersByTime(1000) // Second response promise is for the 304 response expect(manager.responsePromises.length).toBe(2) await manager.responsePromises[1] @@ -443,7 +447,7 @@ describe('httpPollingDatafileManager', () => { manager.start() await manager.onReady() const makeGetRequestSpy = jest.spyOn(manager, 'makeGetRequest') - testTimeoutFactory.timeoutFns[0]() + advanceTimersByTime(1000) expect(makeGetRequestSpy).toBeCalledTimes(1) const firstCall = makeGetRequestSpy.mock.calls[0] const headers = firstCall[1] @@ -458,7 +462,9 @@ describe('httpPollingDatafileManager', () => { const BackoffControllerMock = (BackoffController as unknown) as jest.Mock const getDelayMock = BackoffControllerMock.mock.results[0].value.getDelay getDelayMock.mockImplementationOnce(() => 5432) - const setTimeoutSpy = jest.spyOn(testTimeoutFactory, 'setTimeout') + + const makeGetRequestSpy = jest.spyOn(manager, 'makeGetRequest') + manager.queuedResponses.push( { statusCode: 404, @@ -468,8 +474,15 @@ describe('httpPollingDatafileManager', () => { ) manager.start() await manager.responsePromises[0] - expect(setTimeoutSpy).toBeCalledTimes(1) - expect(setTimeoutSpy.mock.calls[0][1]).toBe(5432) + expect(makeGetRequestSpy).toBeCalledTimes(1) + + // Should not make another request after 1 second because the error should have triggered backoff + advanceTimersByTime(1000) + expect(makeGetRequestSpy).toBeCalledTimes(1) + + // But after another 5 seconds, another request should be made + advanceTimersByTime(5000) + expect(makeGetRequestSpy).toBeCalledTimes(2) }) it('calls countError on the backoff controller when a non-success status code response is received', async () => { @@ -531,7 +544,7 @@ describe('httpPollingDatafileManager', () => { describe('when constructed with sdkKey and autoUpdate: false', () => { beforeEach(() => { - manager = createTestManager({ sdkKey: '123', autoUpdate: false }) + manager = new TestDatafileManager({ sdkKey: '123', autoUpdate: false }) }) it('after being started, fetches the datafile and resolves onReady', async () => { @@ -555,7 +568,7 @@ describe('httpPollingDatafileManager', () => { manager.on('update', updateFn) manager.start() await manager.onReady() - expect(testTimeoutFactory.timeoutFns.length).toBe(0) + expect(getTimerCount()).toBe(0) }) // TODO: figure out what's wrong with this test @@ -579,7 +592,7 @@ describe('httpPollingDatafileManager', () => { describe('when constructed with sdkKey and a valid urlTemplate', () => { beforeEach(() => { - manager = createTestManager({ + manager = new TestDatafileManager({ sdkKey: '456', updateInterval: 1000, urlTemplate: 'https://localhost:5556/datafiles/%s', @@ -602,22 +615,23 @@ describe('httpPollingDatafileManager', () => { describe('when constructed with an update interval below the minimum', () => { beforeEach(() => { - manager = createTestManager({ sdkKey: '123', updateInterval: 500, autoUpdate: true }) + manager = new TestDatafileManager({ sdkKey: '123', updateInterval: 500, autoUpdate: true }) }) it('uses the default update interval', async () => { + const makeGetRequestSpy = jest.spyOn(manager, 'makeGetRequest') + manager.queuedResponses.push({ statusCode: 200, body: '{"foo3": "bar3"}', headers: {}, }) - const setTimeoutSpy: jest.SpyInstance<() => void, [() => void, number]> = jest.spyOn(testTimeoutFactory, 'setTimeout') - manager.start() await manager.onReady() - expect(setTimeoutSpy).toBeCalledTimes(1) - expect(setTimeoutSpy.mock.calls[0][1]).toBe(300000) + expect(makeGetRequestSpy).toBeCalledTimes(1) + await advanceTimersByTime(300000) + expect(makeGetRequestSpy).toBeCalledTimes(2) }) }) }) diff --git a/packages/datafile-manager/__test__/nodeDatafileManager.spec.ts b/packages/datafile-manager/__test__/nodeDatafileManager.spec.ts index 2f561cf2f..636e0d91f 100644 --- a/packages/datafile-manager/__test__/nodeDatafileManager.spec.ts +++ b/packages/datafile-manager/__test__/nodeDatafileManager.spec.ts @@ -17,19 +17,19 @@ import NodeDatafileManager from '../src/nodeDatafileManager' import * as nodeRequest from '../src/nodeRequest' import { Headers, AbortableRequest } from '../src/http' -import TestTimeoutFactory from './testTimeoutFactory' +import { advanceTimersByTime, getTimerCount } from './testUtils'; describe('nodeDatafileManager', () => { - const testTimeoutFactory: TestTimeoutFactory = new TestTimeoutFactory() - let makeGetRequestSpy: jest.SpyInstance beforeEach(() => { + jest.useFakeTimers() makeGetRequestSpy = jest.spyOn(nodeRequest, 'makeGetRequest') }) afterEach(() => { + jest.clearAllMocks() jest.restoreAllMocks() - testTimeoutFactory.cleanup() + jest.clearAllTimers() }) it('calls nodeEnvironment.makeGetRequest when started', async () => { @@ -69,11 +69,10 @@ describe('nodeDatafileManager', () => { const manager = new NodeDatafileManager({ sdkKey: '1234', autoUpdate: true, - timeoutFactory: testTimeoutFactory, }) manager.start() await manager.onReady() - testTimeoutFactory.timeoutFns[0]() + await advanceTimersByTime(300000) expect(makeGetRequestSpy).toBeCalledTimes(2) expect(makeGetRequestSpy.mock.calls[1][0]).toBe('https://cdn.optimizely.com/datafiles/1234.json') expect(makeGetRequestSpy.mock.calls[1][1]).toEqual({ @@ -96,13 +95,12 @@ describe('nodeDatafileManager', () => { }) const manager = new NodeDatafileManager({ sdkKey: '1234', - timeoutFactory: testTimeoutFactory, }) manager.start() await manager.onReady() // Should set a timeout for a later update - expect(testTimeoutFactory.timeoutFns.length).toBe(1) - testTimeoutFactory.timeoutFns[0]() + expect(getTimerCount()).toBe(1) + await advanceTimersByTime(300000) expect(makeGetRequestSpy).toBeCalledTimes(2) await manager.stop() diff --git a/packages/datafile-manager/__test__/testTimeoutFactory.ts b/packages/datafile-manager/__test__/testTimeoutFactory.ts deleted file mode 100644 index 7b1db3667..000000000 --- a/packages/datafile-manager/__test__/testTimeoutFactory.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { TimeoutFactory } from '../src/timeoutFactory' - -export default class TestTimeoutFactory implements TimeoutFactory { - timeoutFns: Array<() => void> = [] - - cancelFns: Array<() => void> = [] - - setTimeout(onTimeout: () => void, timeout: number): () => void { - const cancelFn = jest.fn() - this.timeoutFns.push(() => { - onTimeout() - }) - this.cancelFns.push(cancelFn) - return cancelFn - } - - cleanup() { - this.timeoutFns = [] - this.cancelFns = [] - } -} diff --git a/packages/datafile-manager/__test__/testUtils.ts b/packages/datafile-manager/__test__/testUtils.ts new file mode 100644 index 000000000..aae4ee6e7 --- /dev/null +++ b/packages/datafile-manager/__test__/testUtils.ts @@ -0,0 +1,11 @@ +export function advanceTimersByTime(waitMs: number): Promise { + const timeoutPromise: Promise = new Promise(res => setTimeout(res, waitMs)) + jest.advanceTimersByTime(waitMs) + return timeoutPromise +} + +export function getTimerCount(): number { + // Type definition for jest doesn't include this, but it exists + // https://jestjs.io/docs/en/jest-object#jestgettimercount + return (jest as any).getTimerCount() +} diff --git a/packages/datafile-manager/src/datafileManager.ts b/packages/datafile-manager/src/datafileManager.ts index a1bb737e5..b4210e99d 100644 --- a/packages/datafile-manager/src/datafileManager.ts +++ b/packages/datafile-manager/src/datafileManager.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { TimeoutFactory } from "./timeoutFactory"; - export interface DatafileUpdate { datafile: object } @@ -41,7 +39,6 @@ export interface DatafileManagerConfig { autoUpdate?: boolean datafile?: object sdkKey: string - timeoutFactory?: TimeoutFactory, updateInterval?: number urlTemplate?: string } diff --git a/packages/datafile-manager/src/httpPollingDatafileManager.ts b/packages/datafile-manager/src/httpPollingDatafileManager.ts index 62f4387aa..79420f903 100644 --- a/packages/datafile-manager/src/httpPollingDatafileManager.ts +++ b/packages/datafile-manager/src/httpPollingDatafileManager.ts @@ -20,7 +20,6 @@ import { DatafileManager, DatafileManagerConfig, DatafileUpdate } from './datafi import EventEmitter from './eventEmitter' import { AbortableRequest, Response, Headers } from './http'; import { DEFAULT_UPDATE_INTERVAL, MIN_UPDATE_INTERVAL, DEFAULT_URL_TEMPLATE } from './config' -import { TimeoutFactory, DEFAULT_TIMEOUT_FACTORY } from './timeoutFactory' import BackoffController from './backoffController'; const logger = getLogger('DatafileManager') @@ -61,7 +60,7 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana private readonly updateInterval: number - private cancelTimeout: (() => void) | null + private currentTimeout: any private isStarted: boolean @@ -69,8 +68,6 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana private datafileUrl: string - private timeoutFactory: TimeoutFactory - private currentRequest: AbortableRequest | null private backoffController: BackoffController @@ -90,7 +87,6 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana datafile, autoUpdate = false, sdkKey, - timeoutFactory = DEFAULT_TIMEOUT_FACTORY, updateInterval = DEFAULT_UPDATE_INTERVAL, urlTemplate = DEFAULT_URL_TEMPLATE, } = configWithDefaultsApplied @@ -114,7 +110,6 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana this.datafileUrl = sprintf(urlTemplate, sdkKey) - this.timeoutFactory = timeoutFactory this.emitter = new EventEmitter() this.autoUpdate = autoUpdate if (isValidUpdateInterval(updateInterval)) { @@ -123,7 +118,7 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana logger.warn('Invalid updateInterval %s, defaulting to %s', updateInterval, DEFAULT_UPDATE_INTERVAL) this.updateInterval = DEFAULT_UPDATE_INTERVAL } - this.cancelTimeout = null + this.currentTimeout = null this.currentRequest = null this.backoffController = new BackoffController() this.syncOnCurrentRequestComplete = false @@ -145,9 +140,9 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana stop(): Promise { logger.debug('Datafile manager stopped') this.isStarted = false - if (this.cancelTimeout) { - this.cancelTimeout() - this.cancelTimeout = null + if (this.currentTimeout) { + clearTimeout(this.currentTimeout) + this.currentTimeout = null } this.emitter.removeAllListeners() @@ -272,7 +267,7 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana const currentBackoffDelay = this.backoffController.getDelay() const nextUpdateDelay = Math.max(currentBackoffDelay, this.updateInterval) logger.debug('Scheduling sync in %s ms', nextUpdateDelay) - this.cancelTimeout = this.timeoutFactory.setTimeout(() => { + this.currentTimeout = setTimeout(() => { if (this.currentRequest) { this.syncOnCurrentRequestComplete = true } else { diff --git a/packages/datafile-manager/src/timeoutFactory.ts b/packages/datafile-manager/src/timeoutFactory.ts deleted file mode 100644 index a9dff614f..000000000 --- a/packages/datafile-manager/src/timeoutFactory.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export interface TimeoutFactory { - setTimeout(onTimeout: () => void, timeout: number): () => void -} - -export const DEFAULT_TIMEOUT_FACTORY: TimeoutFactory = { - setTimeout(onTimeout: () => void, timeout: number) { - const timeoutId = setTimeout(onTimeout, timeout) - return () => { - clearTimeout(timeoutId) - } - } -} From 674cd9ec1efbc57861b5b5ff9511f4d3424d3bff Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Thu, 9 May 2019 11:01:38 -0700 Subject: [PATCH 2/4] Remove clearAllMocks --- packages/datafile-manager/__test__/nodeDatafileManager.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/datafile-manager/__test__/nodeDatafileManager.spec.ts b/packages/datafile-manager/__test__/nodeDatafileManager.spec.ts index 636e0d91f..1d90d6677 100644 --- a/packages/datafile-manager/__test__/nodeDatafileManager.spec.ts +++ b/packages/datafile-manager/__test__/nodeDatafileManager.spec.ts @@ -27,7 +27,6 @@ describe('nodeDatafileManager', () => { }) afterEach(() => { - jest.clearAllMocks() jest.restoreAllMocks() jest.clearAllTimers() }) From da378b3574df8443686576af784f7ea9f867ae39 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Thu, 9 May 2019 11:31:32 -0700 Subject: [PATCH 3/4] License header on new file --- packages/datafile-manager/__test__/testUtils.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/datafile-manager/__test__/testUtils.ts b/packages/datafile-manager/__test__/testUtils.ts index aae4ee6e7..9d58c593b 100644 --- a/packages/datafile-manager/__test__/testUtils.ts +++ b/packages/datafile-manager/__test__/testUtils.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export function advanceTimersByTime(waitMs: number): Promise { const timeoutPromise: Promise = new Promise(res => setTimeout(res, waitMs)) jest.advanceTimersByTime(waitMs) From 620628a33844a6e331e1b0fed535eb9d7ce65789 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Fri, 10 May 2019 09:48:10 -0700 Subject: [PATCH 4/4] Add changelog entry --- packages/datafile-manager/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/datafile-manager/CHANGELOG.md b/packages/datafile-manager/CHANGELOG.md index 21c21274c..a7a9c5cbd 100644 --- a/packages/datafile-manager/CHANGELOG.md +++ b/packages/datafile-manager/CHANGELOG.md @@ -12,6 +12,7 @@ Changes that have landed but are not yet released. - Updated polling behavior: - Start update interval timer immediately after request - When update interval timer fires during request, wait until request completes, then immediately start next request +- Remove `timeoutFactory` property from `HTTPPollingDatafileManager` constructor argument object ## [0.2.0] - April 9, 2019