1import { CommandError } from './errors'; 2 3/** Await for a given duration of milliseconds. */ 4export function delayAsync(timeout: number): Promise<void> { 5 return new Promise((resolve) => setTimeout(resolve, timeout)); 6} 7 8/** Wait for a given action to return a truthy value. */ 9export async function waitForActionAsync<T>({ 10 action, 11 interval = 100, 12 maxWaitTime = 20000, 13}: { 14 action: () => T | Promise<T>; 15 interval?: number; 16 maxWaitTime?: number; 17}): Promise<T> { 18 let complete: T; 19 const start = Date.now(); 20 do { 21 const actionStartTime = Date.now(); 22 complete = await action(); 23 24 const actionTimeElapsed = Date.now() - actionStartTime; 25 const remainingDelayInterval = interval - actionTimeElapsed; 26 if (remainingDelayInterval > 0) { 27 await delayAsync(remainingDelayInterval); 28 } 29 if (Date.now() - start > maxWaitTime) { 30 break; 31 } 32 } while (!complete); 33 34 return complete; 35} 36 37/** Resolves a given function or rejects if the provided timeout is passed. */ 38export function resolveWithTimeout<T>( 39 action: () => Promise<T>, 40 { 41 timeout, 42 errorMessage, 43 }: { 44 /** Duration in milliseconds to wait before asserting a timeout. */ 45 timeout: number; 46 /** Optional error message to use in the assertion. */ 47 errorMessage?: string; 48 } 49): Promise<T> { 50 return new Promise((resolve, reject) => { 51 setTimeout(() => { 52 reject(new CommandError('TIMEOUT', errorMessage)); 53 }, timeout); 54 action().then(resolve, reject); 55 }); 56} 57