prettier import { expect } from 'chai' ; import { map , tap , mergeMap , take } from 'rxjs/operators' ; import { TestScheduler } from 'rxjs/testing' ; import { of , Observable , identity } from 'rxjs' ; import { observableMatcher } from '../helpers/observableMatcher' ; const addDrama = ( x ) => x + '!' ; test describe ( 'map' , ( ) => { let testScheduler ; beforeEach ( ( ) => { testScheduler = new TestScheduler ( observableMatcher ) ; } ) ; it ( 'should map multiple values' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' --1--2--3--|' ) ; const e1subs = '  ^----------!' ; const expected = '--x--y--z--|' ; const result = e1 . pipe ( map ( ( x ) => 10 * + x ) ) ; expectObservable ( result ) . toBe ( expected , { x : 10 , y : 20 , z : 30 } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should map one value' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const values = { x : 42 } ; const e1 = cold ( ' --x--|' , values ) ; const e1subs = '  ^----!' ; const expected = '--y--|' ; const result = e1 . pipe ( map ( addDrama ) ) ; expectObservable ( result ) . toBe ( expected , { y : '42!' } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should map multiple values' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' --1--2--3--|' ) ; const e1subs = '  ^----------!' ; const expected = '--x--y--z--|' ; const result = e1 . pipe ( map ( addDrama ) ) ; expectObservable ( result ) . toBe ( expected , { x : '1!' , y : '2!' , z : '3!' } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should propagate errors from map function' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const values = { x : 42 } ; const e1 = cold ( ' --x--|' , values ) ; const e1subs = '  ^-!   ' ; const expected = '--#   ' ; const result = e1 . pipe ( map ( ( x ) => { throw 'too bad' ; } ) ) ; expectObservable ( result ) . toBe ( expected , null , 'too bad' ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should propagate errors from observable that emits only errors' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' #   ' ) ; const e1subs = '  (^!)' ; const expected = '#   ' ; const result = e1 . pipe ( map ( identity ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should propagate errors from observable that emit values' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const values = { a : 1 , b : 2 } ; const e1 = cold ( ' --a--b--#' , values , 'too bad' ) ; const e1subs = '  ^-------!' ; const expected = '--x--y--#' ; const result = e1 . pipe ( map ( addDrama ) ) ; expectObservable ( result ) . toBe ( expected , { x : '1!' , y : '2!' } , 'too bad' ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should not map an empty observable' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' |   ' ) ; const e1subs = '  (^!)' ; const expected = '|   ' ; let invoked = 0 ; const result = e1 . pipe ( map ( ( x ) => { invoked ++ ; return x ; } ) , tap ( { complete ( ) { expect ( invoked ) . to . equal ( 0 ) ; } , } ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should allow unsubscribing explicitly and early' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' --1--2--3--|' ) ; const e1subs = '  ^-----!     ' ; const expected = '--x--y-     ' ; const unsub = '   ------!     ' ; const result = e1 . pipe ( map ( addDrama ) ) ; expectObservable ( result , unsub ) . toBe ( expected , { x : '1!' , y : '2!' } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should map with index' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '-5-^-4--3---2----1--|' ) ; const e1subs = '   ^----------------!' ; const expected = ' --a--b---c----d--|' ; const values = { a : 5 , b : 14 , c : 23 , d : 32 } ; let invoked = 0 ; const result = e1 . pipe ( map ( ( x , index ) => { invoked ++ ; return parseInt ( x ) + 1 + index * 10 ; } ) , tap ( { complete ( ) { expect ( invoked ) . to . equal ( 4 ) ; } , } ) ) ; expectObservable ( result ) . toBe ( expected , values ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should map with index until completed' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '-5-^-4--3---2----1--|' ) ; const e1subs = '   ^----------------!' ; const expected = ' --a--b---c----d--|' ; const values = { a : 5 , b : 14 , c : 23 , d : 32 } ; let invoked = 0 ; const result = e1 . pipe ( map ( ( x , index ) => { invoked ++ ; return parseInt ( x ) + 1 + index * 10 ; } ) , tap ( { complete ( ) { expect ( invoked ) . to . equal ( 4 ) ; } , } ) ) ; expectObservable ( result ) . toBe ( expected , values ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should map with index until an error occurs' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '-5-^-4--3---2----1--#' , undefined , 'too bad' ) ; const e1subs = '   ^----------------!' ; const expected = ' --a--b---c----d--#' ; const values = { a : 5 , b : 14 , c : 23 , d : 32 } ; let invoked = 0 ; const result = e1 . pipe ( map ( ( x , index ) => { invoked ++ ; return parseInt ( x ) + 1 + index * 10 ; } ) , tap ( { error ( ) { expect ( invoked ) . to . equal ( 4 ) ; } , } ) ) ; expectObservable ( result ) . toBe ( expected , values , 'too bad' ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should map using a custom thisArg' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '-5-^-4--3---2----1--|' ) ; const e1subs = '   ^----------------!' ; const expected = ' --a--b---c----d--|' ; const values = { a : 46 , b : 55 , c : 64 , d : 73 } ; const foo = { value : 42 , } ; const result = e1 . pipe ( map ( function ( this , x , index ) { expect ( this ) . to . equal ( foo ) ; return parseInt ( x ) + foo . value + index * 10 ; } , foo ) ) ; expectObservable ( result ) . toBe ( expected , values ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should map twice' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '-0----1-^-2---3--4-5--6--7-8-|' ) ; const e1subs = '        ^--------------------!' ; const expected = '      --a---b--c-d--e--f-g-|' ; const values = { a : 2 , b : 3 , c : 4 , d : 5 , e : 6 , f : 7 , g : 8 } ; let invoked1 = 0 ; let invoked2 = 0 ; const result = e1 . pipe ( map ( ( x ) => { invoked1 ++ ; return parseInt ( x ) * 2 ; } ) , map ( ( x ) => { invoked2 ++ ; return x / 2 ; } ) , tap ( { complete ( ) { expect ( invoked1 ) . to . equal ( 7 ) ; expect ( invoked2 ) . to . equal ( 7 ) ; } , } ) ) ; expectObservable ( result ) . toBe ( expected , values ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should do multiple maps using a custom thisArg' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --1--2--3--4--|' ) ; const e1subs = '  ^-------------!' ; const expected = '--a--b--c--d--|' ; const values = { a : 11 , b : 14 , c : 17 , d : 20 } ; class Filterer { selector1 = ( x ) => parseInt ( x ) + 2 ; selector2 = ( x ) => parseInt ( x ) * 3 ; } const filterer = new Filterer ( ) ; const result = e1 . pipe ( map ( function ( this , x ) { return this . selector1 ( x ) ; } , filterer ) , map ( function ( this , x ) { return this . selector2 ( x ) ; } , filterer ) , map ( function ( this , x ) { return this . selector1 ( x ) ; } , filterer ) ) ; expectObservable ( result ) . toBe ( expected , values ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should not break unsubscription chain when unsubscribed explicitly' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' --1--2--3--|' ) ; const e1subs = '  ^-----!     ' ; const expected = '--x--y-     ' ; const unsub = '   ------!     ' ; const result = e1 . pipe ( mergeMap ( ( x ) => of ( x ) ) , map ( addDrama ) , mergeMap ( ( x ) => of ( x ) ) ) ; expectObservable ( result , unsub ) . toBe ( expected , { x : '1!' , y : '2!' } ) ; 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 ( map ( identity ) , take ( 3 ) ) . subscribe ( ( ) => { } ) ; expect ( sideEffects ) . to . deep . equal ( [ 0 , 1 , 2 ] ) ; } ) ; } ) ;