test_runner: add TestContext.prototype.waitFor() · nodejs/node@697a851 · GitHub
Skip to content

Commit 697a851

Browse files
cjihrigaduh95
authored andcommitted
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: #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>
1 parent a8a0603 commit 697a851

3 files changed

Lines changed: 206 additions & 1 deletion

File tree

doc/api/test.md

Lines changed: 21 additions & 0 deletions

lib/internal/test_runner/test.js

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const {
88
ArrayPrototypeSplice,
99
ArrayPrototypeUnshift,
1010
ArrayPrototypeUnshiftApply,
11+
Error,
1112
FunctionPrototype,
1213
MathMax,
1314
Number,
@@ -58,11 +59,16 @@ const {
5859
const { isPromise } = require('internal/util/types');
5960
const {
6061
validateAbortSignal,
62+
validateFunction,
6163
validateNumber,
64+
validateObject,
6265
validateOneOf,
6366
validateUint32,
6467
} = require('internal/validators');
65-
const { setTimeout } = require('timers');
68+
const {
69+
clearTimeout,
70+
setTimeout,
71+
} = require('timers');
6672
const { TIMEOUT_MAX } = require('internal/timers');
6773
const { fileURLToPath } = require('internal/url');
6874
const { availableParallelism } = require('os');
@@ -340,6 +346,60 @@ class TestContext {
340346
loc: getCallerLocation(),
341347
});
342348
}
349+
350+
waitFor(condition, options = kEmptyObject) {
351+
validateFunction(condition, 'condition');
352+
validateObject(options, 'options');
353+
354+
const {
355+
interval = 50,
356+
timeout = 1000,
357+
} = options;
358+
359+
validateNumber(interval, 'options.interval', 0, TIMEOUT_MAX);
360+
validateNumber(timeout, 'options.timeout', 0, TIMEOUT_MAX);
361+
362+
const { promise, resolve, reject } = PromiseWithResolvers();
363+
const noError = Symbol();
364+
let cause = noError;
365+
let pollerId;
366+
let timeoutId;
367+
const done = (err, result) => {
368+
clearTimeout(pollerId);
369+
clearTimeout(timeoutId);
370+
371+
if (err === noError) {
372+
resolve(result);
373+
} else {
374+
reject(err);
375+
}
376+
};
377+
378+
timeoutId = setTimeout(() => {
379+
// eslint-disable-next-line no-restricted-syntax
380+
const err = new Error('waitFor() timed out');
381+
382+
if (cause !== noError) {
383+
err.cause = cause;
384+
}
385+
386+
done(err);
387+
}, timeout);
388+
389+
const poller = async () => {
390+
try {
391+
const result = await condition();
392+
393+
done(noError, result);
394+
} catch (err) {
395+
cause = err;
396+
pollerId = setTimeout(poller, interval);
397+
}
398+
};
399+
400+
poller();
401+
return promise;
402+
}
343403
}
344404

345405
class SuiteContext {
Lines changed: 124 additions & 0 deletions

0 commit comments

Comments
 (0)