prettier import { TestScheduler } from 'rxjs/testing' ; import { last , mergeMap } from 'rxjs/operators' ; import { EmptyError , of , from , Observable } from 'rxjs' ; import { observableMatcher } from '../helpers/observableMatcher' ; test describe ( 'last' , ( ) => { let testScheduler ; beforeEach ( ( ) => { testScheduler = new TestScheduler ( observableMatcher ) ; } ) ; it ( 'should take the last value of an observable' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a----b--c--|   ' ) ; const e1subs = '  ^------------!   ' ; const expected = '-------------(c|)' ; expectObservable ( e1 . pipe ( last ( ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should error on nothing sent but completed' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a--^----|' ) ; const e1subs = '     ^----!' ; const expected = '   -----#' ; expectObservable ( e1 . pipe ( last ( ) ) ) . toBe ( expected , null , new EmptyError ( ) ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should error on empty' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' |   ' ) ; const e1subs = '  (^!)' ; const expected = '#   ' ; expectObservable ( e1 . pipe ( last ( ) ) ) . toBe ( expected , null , new EmptyError ( ) ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should go on forever on never' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' -' ) ; const e1subs = '  ^' ; const expected = '-' ; expectObservable ( e1 . pipe ( last ( ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should allow undefined as a default value' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  -----a--a---a-|   ' ) ; const e1subs = '  ^-------------!   ' ; const expected = '--------------(U|)' ; expectObservable ( e1 . pipe ( last ( ( value ) => value === 'b' , undefined ) ) ) . toBe ( expected , { U : undefined } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should return last element matches with predicate' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b--a--b--|   ' ) ; const e1subs = '  ^-------------!   ' ; const expected = '--------------(b|)' ; expectObservable ( e1 . pipe ( last ( ( value ) => value === 'b' ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should allow unsubscribing explicitly and early' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b--c--d--|' ) ; const e1subs = '  ^------!       ' ; const expected = '--------       ' ; const unsub = '   -------!       ' ; expectObservable ( e1 . pipe ( last ( ) ) , unsub ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should not break unsubscription chains when result is unsubscribed explicitly' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b--c--d--|' ) ; const e1subs = '  ^------!       ' ; const expected = '--------       ' ; const unsub = '   -------!       ' ; const result = e1 . pipe ( mergeMap ( ( x ) => of ( x ) ) , last ( ) , mergeMap ( ( x ) => of ( x ) ) ) ; expectObservable ( result , unsub ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should return a default value if no element found' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' |   ' ) ; const e1subs = '  (^!)' ; const expected = '(a|)' ; expectObservable ( e1 . pipe ( last ( null , 'a' ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should not return default value if an element is found' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a---^---b---c---d---|   ' ) ; const e1subs = '      ^---------------!   ' ; const expected = '    ----------------(d|)' ; expectObservable ( e1 . pipe ( last ( null , 'x' ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should raise error when predicate throws' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a--^---b---c---d---e--|' ) ; const e1subs = '     ^-------!           ' ; const expected = '   --------#           ' ; const predicate = function ( x ) { if ( x === 'c' ) { throw 'error' ; } else { return false ; } } ; expectObservable ( e1 . pipe ( last ( predicate ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should support type guards without breaking previous behavior' , ( ) => { { interface Bar { bar ? : string ; } interface Baz { baz ? : number ; } class Foo implements Bar , Baz { constructor ( public bar = 'name' , public baz = 42 ) { } } const isBar = ( x ) : x is Bar => x && ( x as Bar ) . bar !== undefined ; const isBaz = ( x ) : x is Baz => x && ( x as Baz ) . baz !== undefined ; const foo = new Foo ( ) ; of ( foo ) . pipe ( last ( ) ) . subscribe ( ( x ) => x . baz ) ; of ( foo ) . pipe ( last ( ( foo ) => foo . bar === 'name' ) ) . subscribe ( ( x ) => x . baz ) ; of ( foo ) . pipe ( last ( isBar ) ) . subscribe ( ( x ) => x . bar ) ; const foobar = new Foo ( ) ; of ( foobar ) . pipe ( last ( ) ) . subscribe ( ( x ) => x . bar ) ; of ( foobar ) . pipe ( last ( ( foobar ) => foobar . bar === 'name' ) ) . subscribe ( ( x ) => x . bar ) ; of ( foobar ) . pipe ( last ( isBaz ) ) . subscribe ( ( x ) => x . baz ) ; const barish = { bar : 'quack' , baz : 42 } ; of ( barish ) . pipe ( last ( ) ) . subscribe ( ( x ) => x . baz ) ; of ( barish ) . pipe ( last ( ( x ) => x . bar === 'quack' ) ) . subscribe ( ( x ) => x . bar ) ; of ( barish ) . pipe ( last ( isBar ) ) . subscribe ( ( x ) => x . bar ) ; } { const xs = from ( [ 1 , 'aaa' , 3 , 'bb' ] ) ; const isString = ( x ) : x is string => typeof x === 'string' ; xs . pipe ( last ( ) ) . subscribe ( ( x ) => x ) ; xs . pipe ( last ( null ) ) . subscribe ( ( x ) => x ) ; xs . pipe ( last ( undefined ) ) . subscribe ( ( x ) => x ) ; xs . pipe ( last ( isString ) ) . subscribe ( ( s ) => s . length ) ; xs . pipe ( last ( ( x ) => typeof x === 'string' ) ) . subscribe ( ( x ) => x ) ; } } ) ; } ) ;