import 'mocha' ; import { expect } from 'chai' ; import { sleep , SchedulerType , SchedulerCallbackType } from '@/infrastructure/Threading/AsyncSleep' ; describe ( 'AsyncSleep' , ( ) => { describe ( 'sleep' , ( ) => { it ( 'fulfills after delay' , async ( ) => { const delayInMs = 10 ; const scheduler = new SchedulerMock ( ) ; const promise = sleep ( delayInMs , scheduler . mock ) ; const promiseState = watchPromiseState ( promise ) ; scheduler . tickNext ( delayInMs ) ; await flushPromiseResolutionQueue ( ) ; const actual = promiseState . isFulfilled ( ) ; expect ( actual ) . to . equal ( true ) ; } ) ; it ( 'pending before delay' , async ( ) => { const delayInMs = 10 ; const scheduler = new SchedulerMock ( ) ; const promise = sleep ( delayInMs , scheduler . mock ) ; const promiseState = watchPromiseState ( promise ) ; scheduler . tickNext ( delayInMs / 5 ) ; await flushPromiseResolutionQueue ( ) ; const actual = promiseState . isPending ( ) ; expect ( actual ) . to . equal ( true ) ; } ) ; } ) ; } ) ; function flushPromiseResolutionQueue ( ) { return Promise . resolve ( ) ; } class SchedulerMock { public readonly mock : SchedulerType ; private currentTime = 0 ; private scheduledActions = new Array < { time : number ; action : SchedulerCallbackType ; } > ( ) ; constructor ( ) { this . mock = ( callback , ms ) => { this . scheduledActions . push ( { time : this . currentTime + ms , action : callback } ) ; } ; } public tickNext ( ms ) { const newTime = this . currentTime + ms ; const dueActions = this . scheduledActions . filter ( ( action ) => newTime >= action . time ) ; for ( const action of dueActions ) { action . action ( ) ; } this . scheduledActions = this . scheduledActions . filter ( ( action ) => ! dueActions . includes ( action ) ) ; } } function watchPromiseState < T > ( promise ) { let isPending = true ; let isRejected = false ; let isFulfilled = false ; promise . then ( ( ) => { isFulfilled = true ; isPending = false ; } , ( ) => { isRejected = true ; isPending = false ; } ) ; return { isFulfilled : ( ) => isFulfilled , isPending : ( ) => isPending , isRejected : ( ) => isRejected , } ; }