@@ -19,6 +19,15 @@ function counterWithBug(state = 0, action) {
1919 }
2020}
2121
22+ function counterWithAnotherBug ( state = 0 , action ) {
23+ switch ( action . type ) {
24+ case 'INCREMENT' : return mistake + 1 ; // eslint-disable-line no-undef
25+ case 'DECREMENT' : return state - 1 ;
26+ case 'SET_UNDEFINED' : return undefined ;
27+ default : return state ;
28+ }
29+ }
30+
2231function doubleCounter ( state = 0 , action ) {
2332 switch ( action . type ) {
2433 case 'INCREMENT' : return state + 2 ;
@@ -295,6 +304,166 @@ describe('instrument', () => {
295304 expect ( monitoredLiftedStore . getState ( ) . computedStates ) . toBe ( savedComputedStates ) ;
296305 } ) ;
297306
307+ describe ( 'maxAge option' , ( ) => {
308+ let configuredStore ;
309+ let configuredLiftedStore ;
310+
311+ beforeEach ( ( ) => {
312+ configuredStore = createStore ( counter , instrument ( undefined , { maxAge : 3 } ) ) ;
313+ configuredLiftedStore = configuredStore . liftedStore ;
314+ } ) ;
315+
316+ it ( 'should auto-commit earliest non-@@INIT action when maxAge is reached' , ( ) => {
317+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
318+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
319+ let liftedStoreState = configuredLiftedStore . getState ( ) ;
320+
321+ expect ( configuredStore . getState ( ) ) . toBe ( 2 ) ;
322+ expect ( Object . keys ( liftedStoreState . actionsById ) . length ) . toBe ( 3 ) ;
323+ expect ( liftedStoreState . committedState ) . toBe ( undefined ) ;
324+ expect ( liftedStoreState . stagedActionIds ) . toInclude ( 1 ) ;
325+
326+ // Trigger auto-commit.
327+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
328+ liftedStoreState = configuredLiftedStore . getState ( ) ;
329+
330+ expect ( configuredStore . getState ( ) ) . toBe ( 3 ) ;
331+ expect ( Object . keys ( liftedStoreState . actionsById ) . length ) . toBe ( 3 ) ;
332+ expect ( liftedStoreState . stagedActionIds ) . toExclude ( 1 ) ;
333+ expect ( liftedStoreState . computedStates [ 0 ] . state ) . toBe ( 1 ) ;
334+ expect ( liftedStoreState . committedState ) . toBe ( 1 ) ;
335+ expect ( liftedStoreState . currentStateIndex ) . toBe ( 2 ) ;
336+ } ) ;
337+
338+ it ( 'should remove skipped actions once committed' , ( ) => {
339+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
340+ configuredLiftedStore . dispatch ( ActionCreators . toggleAction ( 1 ) ) ;
341+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
342+ expect ( configuredLiftedStore . getState ( ) . skippedActionIds ) . toInclude ( 1 ) ;
343+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
344+ expect ( configuredLiftedStore . getState ( ) . skippedActionIds ) . toExclude ( 1 ) ;
345+ } ) ;
346+
347+ it ( 'should not auto-commit errors' , ( ) => {
348+ let spy = spyOn ( console , 'error' ) ;
349+
350+ let storeWithBug = createStore ( counterWithBug , instrument ( undefined , { maxAge : 3 } ) ) ;
351+ let liftedStoreWithBug = storeWithBug . liftedStore ;
352+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
353+ storeWithBug . dispatch ( { type : 'INCREMENT' } ) ;
354+ expect ( liftedStoreWithBug . getState ( ) . stagedActionIds . length ) . toBe ( 3 ) ;
355+
356+ storeWithBug . dispatch ( { type : 'INCREMENT' } ) ;
357+ expect ( liftedStoreWithBug . getState ( ) . stagedActionIds . length ) . toBe ( 4 ) ;
358+
359+ spy . restore ( ) ;
360+ } ) ;
361+
362+ it ( 'should auto-commit actions after hot reload fixes error' , ( ) => {
363+ let spy = spyOn ( console , 'error' ) ;
364+
365+ let storeWithBug = createStore ( counterWithBug , instrument ( undefined , { maxAge : 3 } ) ) ;
366+ let liftedStoreWithBug = storeWithBug . liftedStore ;
367+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
368+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
369+ storeWithBug . dispatch ( { type : 'INCREMENT' } ) ;
370+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
371+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
372+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
373+ expect ( liftedStoreWithBug . getState ( ) . stagedActionIds . length ) . toBe ( 7 ) ;
374+
375+ // Auto-commit 2 actions by "fixing" reducer bug, but introducing another.
376+ storeWithBug . replaceReducer ( counterWithAnotherBug ) ;
377+ expect ( liftedStoreWithBug . getState ( ) . stagedActionIds . length ) . toBe ( 5 ) ;
378+
379+ // Auto-commit 2 more actions by "fixing" other reducer bug.
380+ storeWithBug . replaceReducer ( counter ) ;
381+ expect ( liftedStoreWithBug . getState ( ) . stagedActionIds . length ) . toBe ( 3 ) ;
382+
383+ spy . restore ( ) ;
384+ } ) ;
385+
386+ it ( 'should update currentStateIndex when auto-committing' , ( ) => {
387+ let liftedStoreState ;
388+ let currentComputedState ;
389+
390+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
391+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
392+ liftedStoreState = configuredLiftedStore . getState ( ) ;
393+ expect ( liftedStoreState . currentStateIndex ) . toBe ( 2 ) ;
394+
395+ // currentStateIndex should stay at 2 as actions are committed.
396+ configuredStore . dispatch ( { type : 'INCREMENT' } ) ;
397+ liftedStoreState = configuredLiftedStore . getState ( ) ;
398+ currentComputedState = liftedStoreState . computedStates [ liftedStoreState . currentStateIndex ] ;
399+ expect ( liftedStoreState . currentStateIndex ) . toBe ( 2 ) ;
400+ expect ( currentComputedState . state ) . toBe ( 3 ) ;
401+ } ) ;
402+
403+ it ( 'should continue to increment currentStateIndex while error blocks commit' , ( ) => {
404+ let spy = spyOn ( console , 'error' ) ;
405+
406+ let storeWithBug = createStore ( counterWithBug , instrument ( undefined , { maxAge : 3 } ) ) ;
407+ let liftedStoreWithBug = storeWithBug . liftedStore ;
408+
409+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
410+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
411+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
412+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
413+
414+ let liftedStoreState = liftedStoreWithBug . getState ( ) ;
415+ let currentComputedState = liftedStoreState . computedStates [ liftedStoreState . currentStateIndex ] ;
416+ expect ( liftedStoreState . currentStateIndex ) . toBe ( 4 ) ;
417+ expect ( currentComputedState . state ) . toBe ( 0 ) ;
418+ expect ( currentComputedState . error ) . toExist ( ) ;
419+
420+ spy . restore ( ) ;
421+ } ) ;
422+
423+ it ( 'should adjust currentStateIndex correctly when multiple actions are committed' , ( ) => {
424+ let spy = spyOn ( console , 'error' ) ;
425+
426+ let storeWithBug = createStore ( counterWithBug , instrument ( undefined , { maxAge : 3 } ) ) ;
427+ let liftedStoreWithBug = storeWithBug . liftedStore ;
428+
429+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
430+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
431+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
432+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
433+
434+ // Auto-commit 2 actions by "fixing" reducer bug.
435+ storeWithBug . replaceReducer ( counter ) ;
436+ let liftedStoreState = liftedStoreWithBug . getState ( ) ;
437+ let currentComputedState = liftedStoreState . computedStates [ liftedStoreState . currentStateIndex ] ;
438+ expect ( liftedStoreState . currentStateIndex ) . toBe ( 2 ) ;
439+ expect ( currentComputedState . state ) . toBe ( - 4 ) ;
440+
441+ spy . restore ( ) ;
442+ } ) ;
443+
444+ it ( 'should not allow currentStateIndex to drop below 0' , ( ) => {
445+ let spy = spyOn ( console , 'error' ) ;
446+
447+ let storeWithBug = createStore ( counterWithBug , instrument ( undefined , { maxAge : 3 } ) ) ;
448+ let liftedStoreWithBug = storeWithBug . liftedStore ;
449+
450+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
451+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
452+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
453+ storeWithBug . dispatch ( { type : 'DECREMENT' } ) ;
454+ liftedStoreWithBug . dispatch ( ActionCreators . jumpToState ( 1 ) ) ;
455+
456+ // Auto-commit 2 actions by "fixing" reducer bug.
457+ storeWithBug . replaceReducer ( counter ) ;
458+ let liftedStoreState = liftedStoreWithBug . getState ( ) ;
459+ let currentComputedState = liftedStoreState . computedStates [ liftedStoreState . currentStateIndex ] ;
460+ expect ( liftedStoreState . currentStateIndex ) . toBe ( 0 ) ;
461+ expect ( currentComputedState . state ) . toBe ( - 2 ) ;
462+
463+ spy . restore ( ) ;
464+ } ) ;
465+ } ) ;
466+
298467 describe ( 'Import State' , ( ) => {
299468 let monitoredStore ;
300469 let monitoredLiftedStore ;
0 commit comments