prettier import { expect } from 'chai' ; import { findIndex , mergeMap , delay } from 'rxjs/operators' ; import { TestScheduler } from 'rxjs/testing' ; import { observableMatcher } from '../helpers/observableMatcher' ; import { of , Observable } from 'rxjs' ; test describe ( 'findIndex' , ( ) => { let testScheduler ; beforeEach ( ( ) => { testScheduler = new TestScheduler ( observableMatcher ) ; } ) ; function truePredicate ( x ) { return true ; } it ( 'should return matching element from source emits single element' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const values = { a : 3 , b : 9 , c : 15 , d : 20 } ; const e1 = hot ( '  ---a--b--c--d---|' , values ) ; const e1subs = '  ^--------!       ' ; const expected = '---------(x|)    ' ; const predicate = function ( x ) { return x % 5 === 0 ; } ; expectObservable ( e1 . pipe ( findIndex ( predicate ) ) ) . toBe ( expected , { x : 2 } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should not emit if source does not emit' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  -' ) ; const e1subs = '  ^' ; const expected = '-' ; expectObservable ( e1 . pipe ( findIndex ( truePredicate ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should return negative index if source is empty to match predicate' , ( ) => { testScheduler . run ( ( { cold , expectObservable , expectSubscriptions } ) => { const e1 = cold ( ' |   ' ) ; const e1subs = '  (^!)' ; const expected = '(x|)' ; const result = e1 . pipe ( findIndex ( truePredicate ) ) ; expectObservable ( result ) . toBe ( expected , { x : - 1 } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should return index of element from source emits single element' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--|' , { a : 1 } ) ; const e1subs = '  ^-!   ' ; const expected = '--(x|)' ; const predicate = function ( value ) { return value === 1 ; } ; expectObservable ( e1 . pipe ( findIndex ( predicate ) ) ) . toBe ( expected , { x : 0 } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should return index of matching element from source emits multiple elements' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b---c-|' , { b : 7 } ) ; const e1subs = '  ^----!      ' ; const expected = '-----(x|)   ' ; const predicate = function ( value ) { return value === 7 ; } ; expectObservable ( e1 . pipe ( findIndex ( predicate ) ) ) . toBe ( expected , { x : 1 } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should work with a custom thisArg' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const sourceValues = { b : 7 } ; const e1 = hot ( '  --a--b---c-|' , sourceValues ) ; const e1subs = '  ^----!      ' ; const expected = '-----(x|)   ' ; const predicate = function ( this , value ) { return value === this . b ; } ; const result = e1 . pipe ( findIndex ( predicate , sourceValues ) ) ; expectObservable ( result ) . toBe ( expected , { x : 1 } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should return negative index if element does not match with predicate' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b--c--|   ' ) ; const e1subs = '  ^----------!   ' ; const expected = '-----------(x|)' ; const predicate = function ( value ) { return value === 'z' ; } ; expectObservable ( e1 . pipe ( findIndex ( predicate ) ) ) . toBe ( expected , { x : - 1 } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should allow unsubscribing early and explicitly' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b--c--|' ) ; const e1subs = '  ^-----!     ' ; const expected = '-------     ' ; const unsub = '   ------!     ' ; const result = e1 . pipe ( findIndex ( ( value ) => value === 'z' ) ) ; expectObservable ( result , 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--|' ) ; const e1subs = '  ^-----!     ' ; const expected = '-------     ' ; const unsub = '   ------!     ' ; const result = e1 . pipe ( mergeMap ( ( x ) => of ( x ) ) , findIndex ( ( value ) => value === 'z' ) , mergeMap ( ( x ) => of ( x ) ) ) ; expectObservable ( result , unsub ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should unsubscribe when the predicate is matched' , ( ) => { testScheduler . run ( ( { hot , time , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b---c-|' ) ; const e1subs = '  ^----!      ' ; const t = time ( '    --|       ' ) ; const expected = '-------(x|) ' ; const result = e1 . pipe ( findIndex ( ( value ) => value === 'b' ) , delay ( t ) ) ; expectObservable ( result ) . toBe ( expected , { x : 1 } ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should raise if source raise error while element does not match with predicate' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b--#' ) ; const e1subs = '  ^-------!' ; const expected = '--------#' ; const predicate = function ( value ) { return value === 'z' ; } ; expectObservable ( e1 . pipe ( findIndex ( predicate ) ) ) . toBe ( expected ) ; expectSubscriptions ( e1 . subscriptions ) . toBe ( e1subs ) ; } ) ; } ) ; it ( 'should raise error if predicate throws error' , ( ) => { testScheduler . run ( ( { hot , expectObservable , expectSubscriptions } ) => { const e1 = hot ( '  --a--b--c--|' ) ; const e1subs = '  ^-!         ' ; const expected = '--#         ' ; const predicate = function ( value ) { throw 'error' ; } ; expectObservable ( e1 . pipe ( findIndex ( predicate ) ) ) . 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 ( findIndex ( ( value ) => value === 2 ) ) . subscribe ( ( ) => { } ) ; expect ( sideEffects ) . to . deep . equal ( [ 0 , 1 , 2 ] ) ; } ) ; } ) ;