import { createEvents } from '../' ; describe ( 'createEvents(eventDefs, prevState, action)' , ( ) => { [ { title : 'event definition is an empty array' , eventDefs : [ ] , expected : [ ] , } , { title : 'event definition returns undefined' , eventDefs : [ ( ) => { } ] , expected : [ ] , } , { title : 'event definition returns null' , eventDefs : [ ( ) => null ] , expected : [ ] , } , { title : 'event definition is undefined' , eventDefs : [ undefined ] , expected : [ ] , } , { title : 'event definition returns an empty array' , eventDefs : [ ( ) => [ ] ] , expected : [ ] , } , { title : 'event definition returns a string' , eventDefs : [ ( ) => 'str' ] , expected : [ 'str' ] , } , { title : 'event definition returns a number' , eventDefs : [ ( ) => 123 ] , expected : [ 123 ] , } , { title : 'event definition returns a POJO' , eventDefs : [ ( ) => ( { event : 'pageview' , route : '/login' } ) ] , expected : [ { event : 'pageview' , route : '/login' } ] , } , { title : 'event definition uses data from action' , eventDefs : [ action => ( { route : action . payload } ) ] , action : { type : 'ROUTE_CHANGED' , payload : '/home' } , expected : [ { route : '/home' } ] , } , { title : 'event definition uses data from prevState' , eventDefs : [ ( _ , prevState ) => ( { something : prevState . whatever } ) ] , prevState : { whatever : 'kent beck' } , expected : [ { something : 'kent beck' } ] , } , { title : 'event definition uses data from prevState & action' , eventDefs : [ ( action , prevState ) => ( { referrer : prevState . route , route : action . payload , } ) , ] , prevState : { route : '/' } , action : { payload : '/checkout' } , expected : [ { referrer : '/' , route : '/checkout' } ] , } , { title : 'event definition returns an array of events' , eventDefs : [ ( ) => [ { hitType : 'pageview' } , { hitType : 'event' } , { hitType : 'timing' } , ] , ] , expected : [ { hitType : 'pageview' } , { hitType : 'event' } , { hitType : 'timing' } , ] , } , { title : 'event definition returns an array of events, with some nulls' , eventDefs : [ ( ) => [ { hitType : 'pageview' } , null , { hitType : 'timing' } , null ] , ] , expected : [ { hitType : 'pageview' } , { hitType : 'timing' } ] , } , { title : 'event definition uses previous state' , eventDefs : [ ( action , prevState , nextState ) => ( { hitType : 'event' , numActions : nextState . numActions , } ) , ] , nextState : { numActions : 3 } , expected : [ { hitType : 'event' , numActions : 3 , } , ] , } , { title : 'event definition returns a Promise' , eventDefs : [ ( ) => Promise . resolve ( ) ] , expected : [ Promise . resolve ( ) ] , } , { title : 'multiple event definitions for an action - simple' , eventDefs : [ action => ( { hitType : 'pageview' , paramA : action . payload } ) , ( action , prevState ) => ( { hitType : 'event' , paramA : action . payload , paramB : prevState . someProperty , } ) , ] , action : { type : 'WHATEVER' , payload : 'something' } , prevState : { someProperty : 'someValue' } , expected : [ { hitType : 'pageview' , paramA : 'something' } , { hitType : 'event' , paramA : 'something' , paramB : 'someValue' } , ] , } , { title : 'multiple event definitions for an action - multiple events' , eventDefs : [ action => ( { hitType : 'pageview' , paramA : action . payload } ) , ( ) => [ { hitType : 'event' } , { hitType : 'timing' } ] , ] , action : { type : 'WHATEVER' , payload : 'something' } , expected : [ { hitType : 'pageview' , paramA : 'something' } , { hitType : 'event' } , { hitType : 'timing' } , ] , } , { title : 'multiple event definitions for an action - async events' , eventDefs : [ action => ( { hitType : 'pageview' , paramA : action . payload } ) , ( ) => Promise . resolve ( ) , ] , action : { type : 'WHATEVER' , payload : 'something' } , expected : [ { hitType : 'pageview' , paramA : 'something' } , Promise . resolve ( ) , ] , } , ] . forEach ( ( scenario , index ) => { const { title , eventDefs , prevState , nextState , action , expected , } = scenario ; test ( `${ index + 1 }. ${ title }` || 'no title' , ( ) => { if ( title === undefined || expected === undefined ) { throw new Error ( 'tests require title, eventDefs, and expected keys' ) ; } const events = createEvents ( eventDefs , prevState || { } , action || { } , nextState || { } ) ; expect ( events ) . toEqual ( expected ) ; } ) ; } ) ; } ) ;