Skip to content

Commit e900737

Browse files
feat(time): Add Interval class (#5792)
Creates our own version of an Interval, similar to how we have our own Timeout --- <!--- REMINDER: Ensure that your PR meets the guidelines in CONTRIBUTING.md --> License: I confirm that my contribution is made under the terms of the Apache 2.0 license. Signed-off-by: nkomonen-amazon <[email protected]>
1 parent 87831ea commit e900737

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

packages/core/src/shared/utilities/timeoutUtils.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,34 @@ export class Timeout {
184184
}
185185
}
186186

187+
export class Interval {
188+
private _setCompleted: (() => void) | undefined
189+
private _nextCompletion: Promise<void>
190+
private ref: NodeJS.Timer | number | undefined
191+
192+
constructor(intervalMillis: number, onCompletion: () => Promise<void>) {
193+
this._nextCompletion = new Promise<void>((resolve) => {
194+
this._setCompleted = () => resolve()
195+
})
196+
this.ref = globals.clock.setInterval(async () => {
197+
await onCompletion()
198+
this._setCompleted!()
199+
this._nextCompletion = new Promise<void>((resolve) => {
200+
this._setCompleted = () => resolve()
201+
})
202+
}, intervalMillis)
203+
}
204+
205+
/** Allows to wait for the next interval to finish running */
206+
public async nextCompletion() {
207+
await this._nextCompletion
208+
}
209+
210+
public dispose() {
211+
globals.clock.clearInterval(this.ref)
212+
}
213+
}
214+
187215
interface WaitUntilOptions {
188216
/** Timeout in ms (default: 5000) */
189217
readonly timeout?: number

packages/core/src/test/shared/utilities/timeoutUtils.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,29 @@ import * as FakeTimers from '@sinonjs/fake-timers'
88
import * as timeoutUtils from '../../../shared/utilities/timeoutUtils'
99
import { installFakeClock, tickPromise } from '../../../test/testUtil'
1010
import { sleep } from '../../../shared/utilities/timeoutUtils'
11+
import { SinonStub, SinonSandbox, createSandbox } from 'sinon'
1112

1213
// We export this describe() so it can be used in the web tests as well
1314
export const timeoutUtilsDescribe = describe('timeoutUtils', async function () {
1415
let clock: FakeTimers.InstalledClock
16+
let sandbox: SinonSandbox
1517

1618
before(function () {
1719
clock = installFakeClock()
1820
})
1921

22+
beforeEach(function () {
23+
sandbox = createSandbox()
24+
})
25+
2026
after(function () {
2127
clock.uninstall()
2228
})
2329

2430
afterEach(function () {
2531
clock.reset()
2632
this.timer?.dispose()
33+
sandbox.restore()
2734
})
2835

2936
describe('Timeout', async function () {
@@ -192,6 +199,53 @@ export const timeoutUtilsDescribe = describe('timeoutUtils', async function () {
192199
})
193200
})
194201

202+
describe('Interval', async function () {
203+
let interval: timeoutUtils.Interval
204+
let onCompletionStub: SinonStub
205+
206+
beforeEach(async function () {
207+
onCompletionStub = sandbox.stub()
208+
interval = new timeoutUtils.Interval(1000, onCompletionStub)
209+
})
210+
211+
afterEach(async function () {
212+
interval?.dispose()
213+
})
214+
215+
it('Executes the callback on an interval', async function () {
216+
await clock.tickAsync(999)
217+
assert.strictEqual(onCompletionStub.callCount, 0)
218+
await clock.tickAsync(1)
219+
assert.strictEqual(onCompletionStub.callCount, 1)
220+
221+
await clock.tickAsync(500)
222+
assert.strictEqual(onCompletionStub.callCount, 1)
223+
await clock.tickAsync(500)
224+
assert.strictEqual(onCompletionStub.callCount, 2)
225+
226+
await clock.tickAsync(1000)
227+
assert.strictEqual(onCompletionStub.callCount, 3)
228+
})
229+
230+
it('allows to wait for next completion', async function () {
231+
clock.uninstall()
232+
233+
let curr = 'Did Not Change'
234+
235+
const realInterval = new timeoutUtils.Interval(50, async () => {
236+
await sleep(50)
237+
curr = 'Did Change'
238+
})
239+
240+
const withoutWait = curr
241+
await realInterval.nextCompletion()
242+
const withWait = curr
243+
244+
assert.strictEqual(withoutWait, 'Did Not Change')
245+
assert.strictEqual(withWait, 'Did Change')
246+
})
247+
})
248+
195249
describe('waitUntil', async function () {
196250
const testSettings = {
197251
callCounter: 0,

0 commit comments

Comments
 (0)