prettier import { expect } from 'chai' ; import { timeoutWith , mergeMap , take } from 'rxjs/operators' ; import { TestScheduler } from 'rxjs/testing' ; import { of , Observable , EMPTY } from 'rxjs' ; import { observableMatcher } from '../helpers/observableMatcher' ; test describe ( 'timeoutWith operator' , ( ) => { let rxTestScheduler ; beforeEach ( ( ) => { rxTestScheduler = new TestScheduler ( observableMatcher ) ; } ) ; it ( 'should timeout after a specified period then subscribe to the passed observable' , ( ) => { rxTestScheduler . run ( ( { cold , time , expectObservable , expectSubscriptions } ) => { const source = cold ( '  -------a--b--|' ) ; const sourceSubs = '   ^----!        ' ; const t = time ( '       -----|' ) ; const switchTo = cold ( '     x-y-z-|  ' ) ; const switchToSubs = ' -----^-----!  ' ; const expected = '     -----x-y-z-|  ' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should timeout at a specified date then subscribe to the passed observable' , ( ) => { rxTestScheduler . run ( ( { cold , time , expectObservable , expectSubscriptions } ) => { const source = cold ( '  -' ) ; const sourceSubs = '   ^---------!           ' ; const t = time ( '       ----------|' ) ; const switchTo = cold ( '          --x--y--z--|' ) ; const switchToSubs = ' ----------^----------!' ; const expected = '     ------------x--y--z--|' ; const result = source . pipe ( timeoutWith ( new Date ( t ) , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should timeout after a specified period between emit then subscribe to the passed observable when source emits' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '  ---a---b------c---|' ) ; const t = time ( '             ----|       ' ) ; const sourceSubs = '  ^----------!       ' ; const switchTo = cold ( '          -x-y-|  ' ) ; const switchToSubs = '-----------^----!  ' ; const expected = '    ---a---b----x-y-|  ' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should allow unsubscribing explicitly and early' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '  ---a---b-----c----|' ) ; const t = time ( '             ----|       ' ) ; const sourceSubs = '  ^----------!       ' ; const switchTo = cold ( '          -x---y| ' ) ; const switchToSubs = '-----------^--!    ' ; const expected = '    ---a---b----x--    ' ; const unsub = '       --------------!    ' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result , unsub ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should not break unsubscription chain when unsubscribed explicitly' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '  ---a---b-----c----|' ) ; const t = time ( '      ----|              ' ) ; const sourceSubs = '  ^----------!       ' ; const switchTo = cold ( '          -x---y| ' ) ; const switchToSubs = '-----------^--!    ' ; const expected = '    ---a---b----x--    ' ; const unsub = '       --------------!    ' ; const result = source . pipe ( mergeMap ( ( x ) => of ( x ) ) , timeoutWith ( t , switchTo , rxTestScheduler ) , mergeMap ( ( x ) => of ( x ) ) ) ; expectObservable ( result , unsub ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should not subscribe to withObservable after explicit unsubscription' , ( ) => { rxTestScheduler . run ( ( { cold , time , expectObservable , expectSubscriptions } ) => { const source = cold ( '---a------b------' ) ; const t = time ( '     -----|           ' ) ; const sourceSubs = ' ^----!           ' ; const switchTo = cold ( '   i---j---|   ' ) ; const expected = '   ---a--           ' ; const unsub = '      -----!           ' ; const result = source . pipe ( mergeMap ( ( x ) => of ( x ) ) , timeoutWith ( t , switchTo , rxTestScheduler ) , mergeMap ( ( x ) => of ( x ) ) ) ; expectObservable ( result , unsub ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( [ ] ) ; } ) ; } ) ; it ( 'should timeout after a specified period then subscribe to the passed observable when source is empty' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '  -------------|      ' ) ; const t = time ( '      ----------|         ' ) ; const sourceSubs = '  ^---------!         ' ; const switchTo = cold ( '         ----x----|' ) ; const switchToSubs = '----------^--------!' ; const expected = '    --------------x----|' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should timeout after a specified period between emit then never completes if other source does not complete' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '  --a--b--------c--d--|' ) ; const t = time ( '           ----|           ' ) ; const sourceSubs = '  ^--------!           ' ; const switchTo = cold ( '        ------------' ) ; const switchToSubs = '---------^-----------' ; const expected = '    --a--b---------------' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should timeout after a specified period then subscribe to the passed observable when source raises error after timeout' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '  -------------#      ' ) ; const t = time ( '      ----------|         ' ) ; const sourceSubs = '  ^---------!         ' ; const switchTo = cold ( '         ----x----|' ) ; const switchToSubs = '----------^--------!' ; const expected = '    --------------x----|' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should timeout after a specified period between emit then never completes if other source emits but not complete' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '  -------------|      ' ) ; const t = time ( '      -----------|        ' ) ; const sourceSubs = '  ^----------!        ' ; const switchTo = cold ( '          ----x----' ) ; const switchToSubs = '-----------^--------' ; const expected = '    ---------------x----' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( switchToSubs ) ; } ) ; } ) ; it ( 'should not timeout if source completes within timeout period' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '  -----|        ' ) ; const t = time ( '      ----------|   ' ) ; const sourceSubs = '  ^----!        ' ; const switchTo = cold ( '    ----x----' ) ; const expected = '    -----|        ' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( [ ] ) ; } ) ; } ) ; it ( 'should not timeout if source raises error within timeout period' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '-----#              ' ) ; const t = time ( '    ----------|         ' ) ; const sourceSubs = '^----!              ' ; const switchTo = cold ( '       ----x----|' ) ; const expected = '  -----#              ' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( [ ] ) ; } ) ; } ) ; it ( 'should not timeout if source emits within timeout period' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '   --a--b--c--d--e--|' ) ; const t = time ( '       -----|            ' ) ; const sourceSubs = '   ^----------------!' ; const switchTo = cold ( '----x----|        ' ) ; const expected = '     --a--b--c--d--e--|' ; const result = source . pipe ( timeoutWith ( t , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( [ ] ) ; } ) ; } ) ; it ( 'should not timeout if source completes within specified Date' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '--a--b--c--d--e--|   ' ) ; const t = time ( '    --------------------|' ) ; const sourceSubs = '^----------------!   ' ; const switchTo = cold ( '--x--|            ' ) ; const expected = '  --a--b--c--d--e--|   ' ; const result = source . pipe ( timeoutWith ( new Date ( t ) , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( [ ] ) ; } ) ; } ) ; it ( 'should not timeout if source raises error within specified Date' , ( ) => { rxTestScheduler . run ( ( { hot , cold , time , expectObservable , expectSubscriptions } ) => { const source = hot ( '---a---#           ' ) ; const t = time ( '       ----------|     ' ) ; const sourceSubs = '^------!           ' ; const switchTo = cold ( '          --x--|' ) ; const expected = '  ---a---#           ' ; const result = source . pipe ( timeoutWith ( new Date ( t ) , switchTo , rxTestScheduler ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( source . subscriptions ) . toBe ( sourceSubs ) ; expectSubscriptions ( switchTo . subscriptions ) . toBe ( [ ] ) ; } ) ; } ) ; it ( 'should stop listening to a synchronous observable when unsubscribed' , ( ) => { const sideEffects = [ ] ; const synchronousObservable = new Observable < number > ( subscriber => { for ( let i = 0 ; ! subscriber . closed && i < 10 ; i ++ ) { sideEffects . push ( i ) ; subscriber . next ( i ) ; } } ) ; synchronousObservable . pipe ( timeoutWith ( 0 , EMPTY ) , take ( 3 ) ) . subscribe ( ( ) => { } ) ; expect ( sideEffects ) . to . deep . equal ( [ 0 , 1 , 2 ] ) ; } ) ; } ) ;