UNPKG

@augment-vir/assert

Version:

A collection of assertions for test and production code alike.

88 lines (87 loc) 3.14 kB
import { ensureError, ensureErrorAndPrependMessage, wait, } from '@augment-vir/core'; import { convertDuration } from '@date-vir/duration'; export const defaultWaitUntilOptions = { interval: { milliseconds: 100, }, timeout: { seconds: 10, }, }; const notSetSymbol = Symbol('not set'); export async function executeWaitUntil(assert, rawArgs, requireSynchronousResult) { const { callback, extraAssertionArgs, failureMessage, options } = parseWaitUntilArgs(rawArgs); const timeout = convertDuration(options.timeout, { milliseconds: true }).milliseconds; const interval = convertDuration(options.interval, { milliseconds: true }); let lastCallbackOutput = notSetSymbol; let lastError = undefined; async function checkCondition() { try { lastCallbackOutput = requireSynchronousResult ? callback() : await callback(); assert(lastCallbackOutput, ...extraAssertionArgs); } catch (error) { lastCallbackOutput = notSetSymbol; lastError = ensureError(error); } } const startTime = Date.now(); while (lastCallbackOutput === notSetSymbol) { await checkCondition(); await wait(interval); if (Date.now() - startTime >= timeout) { const message = failureMessage ? `${failureMessage}: ` : ''; const preMessage = `${message}Timeout of '${timeout}' milliseconds exceeded waiting for callback value to match expectations`; throw ensureErrorAndPrependMessage(lastError, preMessage); } } return lastCallbackOutput; } export function createWaitUntil(assert, requireSynchronousResult = false) { return ((...rawArgs) => { return executeWaitUntil(assert, rawArgs, requireSynchronousResult); }); } export function parseWaitUntilArgs(rawArgs) { const args = { extraAssertionArgs: [], options: undefined, failureMessage: undefined, }; rawArgs.toReversed().forEach((arg) => { if (args.callback) { args.extraAssertionArgs.push(arg); } else if (typeof arg === 'function') { args.callback = arg; } else if (typeof arg === 'string') { args.failureMessage = arg; } else if (typeof arg === 'object') { args.options = arg; } else if (arg === undefined) { /** Skip an undefined arg. */ return; } else { throw new TypeError(`Unexpected waitUntil arg: ${JSON.stringify(arg)}`); } }); if (!args.callback) { throw new TypeError('Missing waitUntil callback.'); } return { callback: args.callback, options: parseWaitUntilOptions(args.options), extraAssertionArgs: args.extraAssertionArgs.toReversed(), failureMessage: args.failureMessage, }; } export function parseWaitUntilOptions(rawOptions) { return { interval: rawOptions?.interval || defaultWaitUntilOptions.interval, timeout: rawOptions?.timeout || defaultWaitUntilOptions.timeout, }; }