import { CompleteNotification , ErrorNotification , NextNotification , Observable , ObservableNotification , Subscription , } from 'rxjs' ; import { TestScheduler } from 'rxjs/testing' ; import { isEqual } from 'lodash' ; import { getTestScheduler } from './scheduler' ; import { TestObservable } from './test-observables' ; import { mapSymbolsToNotifications } from './map-symbols-to-notifications' ; import { TestMessages } from './types' ; import { unparseMarble } from './marble-unparser' ; export function materializeInnerObservable < T > ( observable , outerFrame ) { const messages = [ ] ; const scheduler = getTestScheduler ( ) ; observable . subscribe ( { next : ( value ) => { messages . push ( { frame : scheduler . frame - outerFrame , notification : { kind : 'N' , value , error : undefined , } as NextNotification < T > , } ) ; } , error : ( error ) => { messages . push ( { frame : scheduler . frame - outerFrame , notification : { kind : 'E' , value : undefined , error , } as ErrorNotification , } ) ; } , complete : ( ) => { messages . push ( { frame : scheduler . frame - outerFrame , notification : { kind : 'C' , value : undefined , error : undefined , } as CompleteNotification , } ) ; } , } ) ; return messages ; } export function toHaveSubscriptionsComparer ( actual , marbles ) { const marblesArray = typeof marbles === 'string' ? [ marbles ] : marbles ; const results = marblesArray . map ( ( marbles ) => TestScheduler . parseMarblesAsSubscriptions ( marbles ) ) ; expect ( results ) . toEqual ( actual . getSubscriptions ( ) ) ; return { pass : true , message : ( ) => '' } ; } export function toBeObservableComparer ( actual , fixture ) { const results = [ ] ; let subscription ; const scheduler = getTestScheduler ( ) ; scheduler . schedule ( ( ) => { subscription = actual . subscribe ( { next : ( x ) => { let value = x ; if ( x instanceof Observable ) { value = materializeInnerObservable ( value , scheduler . frame ) ; } results . push ( { frame : scheduler . frame , notification : { kind : 'N' , value , error : undefined , } as NextNotification < any > , } ) ; } , error : ( error ) => { results . push ( { frame : scheduler . frame , notification : { kind : 'E' , value : undefined , error , } as ErrorNotification , } ) ; } , complete : ( ) => { results . push ( { frame : scheduler . frame , notification : { kind : 'C' , value : undefined , error : undefined , } as CompleteNotification , } ) ; } , } ) ; } ) ; scheduler . flush ( ) ; const expected = TestScheduler . parseMarbles ( fixture . marbles , fixture . values , fixture . error , true , true ) ; try { expect ( results ) . toEqual ( expected ) ; return { pass : true , message : ( ) => '' } ; } catch ( e ) { const mapNotificationToSymbol = buildNotificationToSymbolMapper ( fixture . marbles , expected , isEqual ) ; const receivedMarble = unparseMarble ( results , mapNotificationToSymbol ) ; const message = formatMessage ( fixture . marbles , expected , receivedMarble , results ) ; return { pass : false , message : ( ) => message } ; } } function buildNotificationToSymbolMapper ( expectedMarbles , expectedMessages , equalityFn ) { const symbolsToNotificationsMap = mapSymbolsToNotifications ( expectedMarbles , expectedMessages ) ; return ( notification ) => { const mapped = Object . keys ( symbolsToNotificationsMap ) . find ( ( key ) => equalityFn ( symbolsToNotificationsMap [ key ] , notification ) ) ! ; return mapped || '?' ; } ; } function formatMessage ( expectedMarbles , expectedMessages , receivedMarbles , receivedMessages ) { return `
    Expected: ${ expectedMarbles },
    Received: ${ receivedMarbles },
    
    Expected:
    ${ JSON . stringify ( expectedMessages ) }
    
    Received:
    ${ JSON . stringify ( receivedMessages ) },
  ` ; }