prettier import { expect } from 'chai' ; import { takeWhile , tap , mergeMap } from 'rxjs/operators' ; import { of , Observable , from } from 'rxjs' ; import { TestScheduler } from 'rxjs/testing' ; import { observableMatcher } from '../helpers/observableMatcher' ; test describe ( 'takeWhile' , ( ) => { let testScheduler ; beforeEach ( ( ) => { testScheduler = new TestScheduler ( observableMatcher ) ; } ) ; it ( 'should take all elements until predicate is false' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '-1-^2--3--4--5--6--|' ) ; const e1subs = '   ^------!         ' ; const expected = ' -2--3--|         ' ; const result = e1 . pipe ( takeWhile ( ( v ) => + v < 4 ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should take all elements with predicate returns true' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-------------!' ; const expected = '  --b--c--d--e--|' ; const result = e1 . pipe ( takeWhile ( ( ) => true ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should take all elements with truthy predicate' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-------------!' ; const expected = '  --b--c--d--e--|' ; const result = e1 . pipe ( takeWhile ( < any > ( ( ) => { return { } ; } ) ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should skip all elements with predicate returns false' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-!            ' ; const expected = '  --|            ' ; const result = e1 . pipe ( takeWhile ( ( ) => false ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should skip all elements with falsy predicate' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-!            ' ; const expected = '  --|            ' ; const result = e1 . pipe ( takeWhile ( ( ) => null as any ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should take all elements until predicate return false' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-------!      ' ; const expected = '  --b--c--|      ' ; function predicate ( value ) { return value !== 'd' ; } const result = e1 . pipe ( takeWhile ( predicate ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should take all elements up to and including the element that made the predicate return false' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-------!      ' ; const expected = '  --b--c--(d|)   ' ; function predicate ( value ) { return value !== 'd' ; } const inclusive = true ; const result = e1 . pipe ( takeWhile ( predicate , inclusive ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should take elements with predicate when source does not complete' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--' ) ; const e1subs = '    ^-------------' ; const expected = '  --b--c--d--e--' ; const result = e1 . pipe ( takeWhile ( ( ) => true ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should not complete when source never completes' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' -' ) ; const e1subs = '  ^' ; const expected = '-' ; const result = e1 . pipe ( takeWhile ( ( ) => true ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should complete when source does not emit' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^------------|' ) ; const e1subs = '    ^------------!' ; const expected = '  -------------|' ; const result = e1 . pipe ( takeWhile ( ( ) => true ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should complete when source is empty' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' |   ' ) ; const e1subs = '  (^!)' ; const expected = '|   ' ; const result = e1 . pipe ( takeWhile ( ( ) => true ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should pass element index to predicate' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-------!      ' ; const expected = '  --b--c--|      ' ; function predicate ( value , index ) { return index < 2 ; } const result = e1 . pipe ( takeWhile ( predicate ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should raise error when source raises error' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--#' ) ; const e1subs = '    ^-------------!' ; const expected = '  --b--c--d--e--#' ; const result = e1 . pipe ( takeWhile ( ( ) => true ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should raise error when source throws' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' #   ' ) ; const e1subs = '  (^!)' ; const expected = '#   ' ; const result = e1 . pipe ( takeWhile ( ( ) => true ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should invoke predicate until return false' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-------!      ' ; const expected = '  --b--c--|      ' ; let invoked = 0 ; function predicate ( value ) { invoked ++ ; return value !== 'd' ; } const result = e1 . pipe ( takeWhile ( predicate ) , tap ( { complete : ( ) => { expect ( invoked ) . to . equal ( 3 ) ; } , } ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should raise error if predicate throws' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const e1subs = '    ^-!            ' ; const expected = '  --#            ' ; function predicate ( value ) { throw 'error' ; } const result = e1 . pipe ( takeWhile ( < any > predicate ) ) ; expectObservable ( result ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should take elements until unsubscribed' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const unsub = '     -----!         ' ; const e1subs = '    ^----!         ' ; const expected = '  --b---         ' ; function predicate ( value ) { return value !== 'd' ; } const result = e1 . pipe ( takeWhile ( predicate ) ) ; expectObservable ( result , unsub ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should not break unsubscription chain when unsubscribed explicitly' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '--a-^-b--c--d--e--|' ) ; const unsub = '     -----!         ' ; const e1subs = '    ^----!         ' ; const expected = '  --b---         ' ; function predicate ( value ) { return value !== 'd' ; } const result = e1 . pipe ( mergeMap ( ( x ) => of ( x ) ) , takeWhile ( predicate ) , mergeMap ( ( x ) => of ( x ) ) ) ; expectObservable ( result , unsub ) . 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 && ( < Bar > x ) . bar !== undefined ; const foo = new Foo ( ) ; of ( foo ) . pipe ( takeWhile ( ( foo ) => foo . baz === 42 ) ) . subscribe ( ( x ) => x . baz ) ; of ( foo ) . pipe ( takeWhile ( isBar ) ) . subscribe ( ( x ) => x . bar ) ; const foobar = new Foo ( ) ; of ( foobar ) . pipe ( takeWhile ( ( foobar ) => foobar . bar === 'name' ) ) . subscribe ( ( x ) => x . bar ) ; of ( foobar ) . pipe ( takeWhile ( isBar ) ) . subscribe ( ( x ) => x . bar ) ; const barish = { bar : 'quack' , baz : 42 } ; of ( barish ) . pipe ( takeWhile ( ( x ) => x . bar === 'quack' ) ) . subscribe ( ( x ) => x . bar ) ; of ( barish ) . pipe ( takeWhile ( isBar ) ) . subscribe ( ( bar ) => bar . bar ) ; } { const xs = from ( [ 1 , 'aaa' , 3 , 'bb' ] ) ; const isString = ( x ) : x is string => typeof x === 'string' ; xs . pipe ( takeWhile ( isString ) ) . subscribe ( ( s ) => s . length ) ; xs . pipe ( takeWhile ( ( x ) => typeof x === 'number' ) ) . subscribe ( ( x ) => x ) ; xs . pipe ( takeWhile ( ( x , i ) => typeof x === 'number' && x > i ) ) . subscribe ( ( x ) => x ) ; } } ) ; 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 ( takeWhile ( ( value ) => value < 2 ) ) . subscribe ( ( ) => { } ) ; expect ( sideEffects ) . to . deep . equal ( [ 0 , 1 , 2 ] ) ; } ) ; } ) ;