prettier import { expect } from 'chai' ; import { Observable , of } from 'rxjs' ; import { switchMapTo , mergeMap , take } from 'rxjs/operators' ; import { TestScheduler } from 'rxjs/testing' ; import { observableMatcher } from '../helpers/observableMatcher' ; test describe ( 'switchMapTo' , ( ) => { let testScheduler ; beforeEach ( ( ) => { testScheduler = new TestScheduler ( observableMatcher ) ; } ) ; it ( 'should map-and-flatten each item to an Observable' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --1-----3--5-------|' ) ; const e1subs = '  ^------------------!' ; const e2 = cold ( '   x-x-x|            ' , { x : 10 } ) ; const expected = '--x-x-x-x-xx-x-x---|' ; const values = { x : 10 } ; const result = e1 . pipe ( switchMapTo ( e2 ) ) ; expectObservable ( result ) . toBe ( expected , values ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should support the deprecated resultSelector' , ( ) => { const results = [ ] ; of ( 1 , 2 , 3 ) . pipe ( switchMapTo ( of ( 4 , 5 , 6 ) , ( a , b , i , ii ) => [ a , b , i , ii ] ) ) . subscribe ( { next ( value ) { results . push ( value ) ; } , error ( err ) { throw err ; } , complete ( ) { expect ( results ) . to . deep . equal ( [ [ 1 , 4 , 0 , 0 ] , [ 1 , 5 , 0 , 1 ] , [ 1 , 6 , 0 , 2 ] , [ 2 , 4 , 1 , 0 ] , [ 2 , 5 , 1 , 1 ] , [ 2 , 6 , 1 , 2 ] , [ 3 , 4 , 2 , 0 ] , [ 3 , 5 , 2 , 1 ] , [ 3 , 6 , 2 , 2 ] , ] ) ; } , } ) ; } ) ; it ( 'should support a void resultSelector (still deprecated)' , ( ) => { const results = [ ] ; of ( 1 , 2 , 3 ) . pipe ( switchMapTo ( of ( 4 , 5 , 6 ) , void 0 ) ) . subscribe ( { next ( value ) { results . push ( value ) ; } , error ( err ) { throw err ; } , complete ( ) { expect ( results ) . to . deep . equal ( [ 4 , 5 , 6 , 4 , 5 , 6 , 4 , 5 , 6 ] ) ; } , } ) ; } ) ; it ( 'should switch a synchronous many outer to a synchronous many inner' , ( done ) => { const a = of ( 1 , 2 , 3 ) ; const expected = [ 'a' , 'b' , 'c' , 'a' , 'b' , 'c' , 'a' , 'b' , 'c' ] ; a . pipe ( switchMapTo ( of ( 'a' , 'b' , 'c' ) ) ) . subscribe ( { next ( x ) { expect ( x ) . to . equal ( expected . shift ( ) ) ; } , complete : done , } ) ; } ) ; it ( 'should unsub inner observables' , ( ) => { let unsubbed = 0 ; of ( 'a' , 'b' ) . pipe ( switchMapTo ( new Observable < string > ( ( subscriber ) => { subscriber . complete ( ) ; return ( ) => { unsubbed ++ ; } ; } ) ) ) . subscribe ( ) ; expect ( unsubbed ) . to . equal ( 2 ) ; } ) ; it ( 'should switch to an inner cold observable' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           --a--b--c--d--e--|          ' ) ; const xsubs = [ '               ---------^---------!                 ' , '               -------------------^----------------!' , ] ; const e1 = hot ( '  ---------x---------x---------|       ' ) ; const e1subs = '  ^----------------------------!       ' ; const expected = '-----------a--b--c---a--b--c--d--e--|' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should switch to an inner cold observable, outer eventually throws' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           --a--b--c--d--e--|' ) ; const xsubs = '   ---------^---------!       ' ; const e1 = hot ( '  ---------x---------#       ' ) ; const e1subs = '  ^------------------!       ' ; const expected = '-----------a--b--c-#       ' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should switch to an inner cold observable, outer is unsubscribed early' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           --a--b--c--d--e--|   ' ) ; const xsubs = [ '               ---------^---------!          ' , '               -------------------^--!       ' , ] ; const e1 = hot ( '  ---------x---------x---------|' ) ; const unsub = '   ----------------------!       ' ; const e1subs = '  ^---------------------!       ' ; const expected = '-----------a--b--c---a-       ' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) , unsub ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should not break unsubscription chains when result is unsubscribed explicitly' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '--a--b--c--d--e--|   ' ) ; const xsubs = [ '               ---------^---------!          ' , '               -------------------^--!       ' , ] ; const e1 = hot ( '  ---------x---------x---------|' ) ; const e1subs = '  ^---------------------!       ' ; const expected = '-----------a--b--c---a-       ' ; const unsub = '   ----------------------!       ' ; const result = e1 . pipe ( mergeMap ( ( x ) => of ( x ) ) , switchMapTo ( x ) , mergeMap ( ( x ) => of ( x ) ) ) ; expectObservable ( result , unsub ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should switch to an inner cold observable, inner never completes' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           --a--b--c--d--e-          ' ) ; const xsubs = [ '               ---------^---------!               ' , '               -------------------^               ' , ] ; const e1 = hot ( '  ---------x---------y---------|     ' ) ; const e1subs = '  ^----------------------------!     ' ; const expected = '-----------a--b--c---a--b--c--d--e-' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should handle a synchronous switch to the inner observable' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           --a--b--c--d--e--|   ' ) ; const xsubs = [ '               ---------(^!)                 ' , '               ---------^----------------!   ' ] ; const e1 = hot ( '  ---------(xx)----------------|' ) ; const e1subs = '  ^----------------------------!' ; const expected = '-----------a--b--c--d--e-----|' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should switch to an inner cold observable, inner raises an error' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           --a--b--#            ' ) ; const xsubs = '   ---------^-------!            ' ; const e1 = hot ( '  ---------x---------x---------|' ) ; const e1subs = '  ^----------------!            ' ; const expected = '-----------a--b--#            ' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should switch an inner hot observable' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const x = hot ( '   --p-o-o-p---a--b--c--d-|      ' ) ; const xsubs = [ '               ---------^---------!          ' , '               -------------------^---!      ' ] ; const e1 = hot ( '  ---------x---------x---------|' ) ; const e1subs = '  ^----------------------------!' ; const expected = '------------a--b--c--d-------|' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should switch to an inner empty' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           |                    ' ) ; const xsubs = [ '               ---------(^!)                 ' , '               -------------------(^!)       ' , ] ; const e1 = hot ( '  ---------x---------x---------|' ) ; const e1subs = '  ^----------------------------!' ; const expected = '-----------------------------|' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should switch to an inner never' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           -                    ' ) ; const xsubs = [ '               ---------^---------!          ' , '               -------------------^          ' , ] ; const e1 = hot ( '  ---------x---------x---------|' ) ; const e1subs = '  ^----------------------------!' ; const expected = '------------------------------' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should switch to an inner that just raises an error' , ( ) => { testScheduler . run ( ( { hot , cold , expectObservable , expectSubscriptions } ) => { const x = cold ( '           #                    ' ) ; const xsubs = '   ---------(^!)                 ' ; const e1 = hot ( '  ---------x---------x---------|' ) ; const e1subs = '  ^--------!                    ' ; const expected = '---------#                    ' ; expectObservable ( e1 . pipe ( switchMapTo ( x ) ) ) . toBe ( expected ) ; expectSubscriptions ( x . subscriptions ) . toBe ( xsubs ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should handle an empty outer' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' |   ' ) ; const e1subs = '  (^!)' ; const expected = '|   ' ; expectObservable ( e1 . pipe ( switchMapTo ( of ( 'foo' ) ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should handle a never outer' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' -' ) ; const e1subs = '  ^' ; const expected = '-' ; expectObservable ( e1 . pipe ( switchMapTo ( of ( 'foo' ) ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should handle an outer that just raises and error' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' #   ' ) ; const e1subs = '  (^!)' ; const expected = '#   ' ; expectObservable ( e1 . pipe ( switchMapTo ( of ( 'foo' ) ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; 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 ( switchMapTo ( of ( 0 ) ) , take ( 3 ) ) . subscribe ( ( ) => { } ) ; expect ( sideEffects ) . to . deep . equal ( [ 0 , 1 , 2 ] ) ; } ) ; } ) ;