nodejs/test/parallel/test-runner-wait-for.js
Colin Ihrig 0e7ec5e7a1
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.

PR-URL: https://github.com/nodejs/node/pull/56595
Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
2025-01-16 02:32:37 +00:00

125 lines
2.9 KiB
JavaScript

'use strict';
require('../common');
const { suite, test } = require('node:test');
suite('input validation', () => {
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('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;
});
});
test('limits polling if condition takes longer than interval', async (t) => {
let count = 0;
function condition() {
count++;
return new Promise((resolve) => {
setTimeout(() => {
resolve('success');
}, 200);
});
}
const result = await t.waitFor(condition, {
interval: 1,
timeout: 60_000,
});
t.assert.strictEqual(result, 'success');
t.assert.strictEqual(count, 1);
});