Skip to content
This repository was archived by the owner on Dec 21, 2021. It is now read-only.

Commit 4d328cb

Browse files
committed
fix(utils): Prevent extra condition call in until. Add until tests.
1 parent 91ac81b commit 4d328cb

File tree

2 files changed

+73
-19
lines changed

2 files changed

+73
-19
lines changed

src/utils/index.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -503,19 +503,20 @@ export async function until(condition: MaybeAsync<() => boolean>, timeOutMs = 10
503503
if (timeOutMs > 0) {
504504
setTimeout(() => { timeout = true }, timeOutMs)
505505
}
506-
507506
// Promise wrapped condition function works for normal functions just the same as Promises
508-
let wasDone = await Promise.resolve().then(condition)
509-
while (!wasDone) {
510-
if (timeout) {
511-
if (failedMsgFn) {
512-
err.message += ` ${failedMsgFn()}`
513-
}
514-
throw err
507+
let wasDone
508+
while (!wasDone && !timeout) { // eslint-disable-line no-await-in-loop
509+
wasDone = await Promise.resolve().then(condition) // eslint-disable-line no-await-in-loop
510+
if (!wasDone && !timeout) {
511+
await sleep(pollingIntervalMs) // eslint-disable-line no-await-in-loop
515512
}
516513

517-
await sleep(pollingIntervalMs) // eslint-disable-line no-await-in-loop
518-
wasDone = await Promise.resolve().then(condition) // eslint-disable-line no-await-in-loop
514+
}
515+
if (timeout) {
516+
if (failedMsgFn) {
517+
err.message += ` ${failedMsgFn()}`
518+
}
519+
throw err
519520
}
520521
return wasDone
521522
}

test/unit/utils.test.ts

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import Debug from 'debug'
33
import express, { Application } from 'express'
44

55
import authFetch from '../../src/rest/authFetch'
6-
import { uuid, getEndpointUrl } from '../../src/utils'
6+
import * as utils from '../../src/utils'
7+
import { describeRepeats } from '../utils'
78
import { Server } from 'http'
89

910
const debug = Debug('StreamrClient::test::utils')
@@ -12,7 +13,7 @@ interface TestResponse {
1213
test: string
1314
}
1415

15-
describe('utils', () => {
16+
describeRepeats('utils', () => {
1617
let session: any
1718
let expressApp: Application
1819
let server: Server
@@ -81,20 +82,72 @@ describe('utils', () => {
8182

8283
describe('uuid', () => {
8384
it('generates different ids', () => {
84-
expect(uuid('test')).not.toEqual(uuid('test'))
85+
expect(utils.uuid('test')).not.toEqual(utils.uuid('test'))
8586
})
8687
it('includes text', () => {
87-
expect(uuid('test')).toContain('test')
88+
expect(utils.uuid('test')).toContain('test')
8889
})
8990
it('increments', () => {
90-
const uid = uuid('test') // generate new text to ensure count starts at 1
91-
expect(uuid(uid) < uuid(uid)).toBeTruthy()
91+
const uid = utils.uuid('test') // generate new text to ensure count starts at 1
92+
expect(utils.uuid(uid) < utils.uuid(uid)).toBeTruthy()
9293
})
9394
})
9495

9596
describe('getEndpointUrl', () => {
96-
const streamId = 'x/y'
97-
const url = getEndpointUrl('http://example.com', 'abc', streamId, 'def')
98-
expect(url.toLowerCase()).toBe('http://example.com/abc/x%2fy/def')
97+
it('works', () => {
98+
const streamId = 'x/y'
99+
const url = utils.getEndpointUrl('http://example.com', 'abc', streamId, 'def')
100+
expect(url.toLowerCase()).toBe('http://example.com/abc/x%2fy/def')
101+
})
102+
})
103+
104+
describe('until', () => {
105+
it('works with sync true', async () => {
106+
const condition = jest.fn(() => true)
107+
await utils.until(condition)
108+
expect(condition).toHaveBeenCalledTimes(1)
109+
})
110+
111+
it('works with async true', async () => {
112+
const condition = jest.fn(async () => true)
113+
await utils.until(condition)
114+
expect(condition).toHaveBeenCalledTimes(1)
115+
})
116+
117+
it('works with sync false -> true', async () => {
118+
let calls = 0
119+
const condition = jest.fn(() => {
120+
calls += 1
121+
return calls > 1
122+
})
123+
await utils.until(condition)
124+
expect(condition).toHaveBeenCalledTimes(2)
125+
})
126+
127+
it('works with sync false -> true', async () => {
128+
let calls = 0
129+
const condition = jest.fn(async () => {
130+
calls += 1
131+
return calls > 1
132+
})
133+
await utils.until(condition)
134+
expect(condition).toHaveBeenCalledTimes(2)
135+
})
136+
137+
it('can time out', async () => {
138+
const condition = jest.fn(() => false)
139+
await expect(async () => {
140+
await utils.until(condition, 100)
141+
}).rejects.toThrow('Timeout')
142+
expect(condition).toHaveBeenCalled()
143+
})
144+
145+
it('can set interval', async () => {
146+
const condition = jest.fn(() => false)
147+
await expect(async () => {
148+
await utils.until(condition, 100, 20)
149+
}).rejects.toThrow('Timeout')
150+
expect(condition).toHaveBeenCalledTimes(5) // exactly 5
151+
})
99152
})
100153
})

0 commit comments

Comments
 (0)