-
Notifications
You must be signed in to change notification settings - Fork 30.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test_runner: add TestContext.prototype.waitFor()
This commit adds a waitFor() method to the TestContext class in the test runner. As the name implies, this method allows tests to more easily wait for things to happen.
- Loading branch information
Showing
3 changed files
with
223 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
'use strict'; | ||
require('../common'); | ||
const { test } = require('node:test'); | ||
|
||
test('throws if condition is not a function', (t) => { | ||
t.assert.throws(() => { | ||
t.waitFor(5); | ||
}, { | ||
code: 'ERR_INVALID_ARG_TYPE', | ||
message: /The "condition" argument must be of type function/, | ||
}); | ||
}); | ||
|
||
test('throws if options is not an object', (t) => { | ||
t.assert.throws(() => { | ||
t.waitFor(() => {}, null); | ||
}, { | ||
code: 'ERR_INVALID_ARG_TYPE', | ||
message: /The "options" argument must be of type object/, | ||
}); | ||
}); | ||
|
||
test('throws if options.interval is not a number', (t) => { | ||
t.assert.throws(() => { | ||
t.waitFor(() => {}, { interval: 'foo' }); | ||
}, { | ||
code: 'ERR_INVALID_ARG_TYPE', | ||
message: /The "options\.interval" property must be of type number/, | ||
}); | ||
}); | ||
|
||
test('throws if options.timeout is not a number', (t) => { | ||
t.assert.throws(() => { | ||
t.waitFor(() => {}, { timeout: 'foo' }); | ||
}, { | ||
code: 'ERR_INVALID_ARG_TYPE', | ||
message: /The "options\.timeout" property must be of type number/, | ||
}); | ||
}); | ||
|
||
test('throws if options.abortOnError is not a boolean', (t) => { | ||
t.assert.throws(() => { | ||
t.waitFor(() => {}, { abortOnError: 'foo' }); | ||
}, { | ||
code: 'ERR_INVALID_ARG_TYPE', | ||
message: /The "options\.abortOnError" property must be of type boolean/, | ||
}); | ||
}); | ||
|
||
test('rejects if an error is thrown and abortOnError is set', async (t) => { | ||
const err = new Error('boom'); | ||
|
||
await t.assert.rejects(async () => { | ||
await t.waitFor(() => { | ||
throw err; | ||
}, { abortOnError: true }); | ||
}, err); | ||
}); | ||
|
||
test('rejects if a promise rejects and abortOnError is set', async (t) => { | ||
const err = new Error('boom'); | ||
|
||
await t.assert.rejects(async () => { | ||
await t.waitFor(() => { | ||
return new Promise((_, reject) => { | ||
reject(err); | ||
}); | ||
}, { abortOnError: true }); | ||
}, err); | ||
}); | ||
|
||
test('returns the result of the condition function', async (t) => { | ||
const result = await t.waitFor(() => { | ||
return 42; | ||
}); | ||
|
||
t.assert.strictEqual(result, 42); | ||
}); | ||
|
||
test('returns the result of an async condition function', async (t) => { | ||
const result = await t.waitFor(async () => { | ||
return 84; | ||
}); | ||
|
||
t.assert.strictEqual(result, 84); | ||
}); | ||
|
||
test('errors if the condition times out', async (t) => { | ||
await t.assert.rejects(async () => { | ||
await t.waitFor(() => { | ||
return new Promise(() => {}); | ||
}, { | ||
interval: 60_000, | ||
timeout: 1, | ||
}); | ||
}, { | ||
message: /waitFor\(\) timed out/, | ||
}); | ||
}); | ||
|
||
test('polls until the condition returns successfully', async (t) => { | ||
let count = 0; | ||
const result = await t.waitFor(() => { | ||
++count; | ||
if (count < 4) { | ||
throw new Error('resource is not ready yet'); | ||
} | ||
|
||
return 'success'; | ||
}, { | ||
interval: 1, | ||
timeout: 60_000, | ||
}); | ||
|
||
t.assert.strictEqual(result, 'success'); | ||
t.assert.strictEqual(count, 4); | ||
}); | ||
|
||
test('sets last failure as error cause on timeouts', async (t) => { | ||
const error = new Error('boom'); | ||
await t.assert.rejects(async () => { | ||
await t.waitFor(() => { | ||
return new Promise((_, reject) => { | ||
reject(error); | ||
}); | ||
}); | ||
}, (err) => { | ||
t.assert.match(err.message, /timed out/); | ||
t.assert.strictEqual(err.cause, error); | ||
return true; | ||
}); | ||
}); |