1
- import { ReflectiveInjector } from '@angular/core' ;
1
+ import { ReflectiveInjector , InjectionToken } from '@angular/core' ;
2
2
import { TestBed } from '@angular/core/testing' ;
3
3
import { hot } from 'jasmine-marbles' ;
4
4
import {
@@ -10,12 +10,16 @@ import {
10
10
ReducerManagerDispatcher ,
11
11
UPDATE ,
12
12
REDUCER_FACTORY ,
13
+ ActionReducer ,
14
+ Action ,
13
15
} from '../' ;
16
+ import { StoreConfig } from '../src/store_module' ;
14
17
import {
15
18
counterReducer ,
16
19
INCREMENT ,
17
20
DECREMENT ,
18
21
RESET ,
22
+ counterReducer2 ,
19
23
} from './fixtures/counter' ;
20
24
import Spy = jasmine . Spy ;
21
25
import any = jasmine . any ;
@@ -33,15 +37,18 @@ describe('ngRx Store', () => {
33
37
let store : Store < TestAppSchema > ;
34
38
let dispatcher : ActionsSubject ;
35
39
36
- function setup ( initialState : any = { counter1 : 0 , counter2 : 1 } ) {
40
+ function setup (
41
+ initialState : any = { counter1 : 0 , counter2 : 1 } ,
42
+ metaReducers : any = [ ]
43
+ ) {
37
44
const reducers = {
38
45
counter1 : counterReducer ,
39
46
counter2 : counterReducer ,
40
47
counter3 : counterReducer ,
41
48
} ;
42
49
43
50
TestBed . configureTestingModule ( {
44
- imports : [ StoreModule . forRoot ( reducers , { initialState } ) ] ,
51
+ imports : [ StoreModule . forRoot ( reducers , { initialState, metaReducers } ) ] ,
45
52
} ) ;
46
53
47
54
store = TestBed . get ( Store ) ;
@@ -471,4 +478,235 @@ describe('ngRx Store', () => {
471
478
mockStore . dispatch ( action ) ;
472
479
} ) ;
473
480
} ) ;
481
+
482
+ describe ( 'Meta Reducers' , ( ) => {
483
+ let metaReducerContainer : any ;
484
+ let metaReducerSpy1 : Spy ;
485
+ let metaReducerSpy2 : Spy ;
486
+
487
+ beforeEach ( ( ) => {
488
+ metaReducerContainer = ( function ( ) {
489
+ function metaReducer1 ( reducer : ActionReducer < any , any > ) {
490
+ return function ( state : any , action : Action ) {
491
+ return reducer ( state , action ) ;
492
+ } ;
493
+ }
494
+
495
+ function metaReducer2 ( reducer : ActionReducer < any , any > ) {
496
+ return function ( state : any , action : Action ) {
497
+ return reducer ( state , action ) ;
498
+ } ;
499
+ }
500
+
501
+ return {
502
+ metaReducer1 : metaReducer1 ,
503
+ metaReducer2 : metaReducer2 ,
504
+ } ;
505
+ } ) ( ) ;
506
+
507
+ metaReducerSpy1 = spyOn (
508
+ metaReducerContainer ,
509
+ 'metaReducer1'
510
+ ) . and . callThrough ( ) ;
511
+
512
+ metaReducerSpy2 = spyOn (
513
+ metaReducerContainer ,
514
+ 'metaReducer2'
515
+ ) . and . callThrough ( ) ;
516
+ } ) ;
517
+
518
+ it ( 'should create a meta reducer for root and call it through' , ( ) => {
519
+ setup ( { } , [ metaReducerContainer . metaReducer1 ] ) ;
520
+ const action = { type : INCREMENT } ;
521
+ store . dispatch ( action ) ;
522
+ expect ( metaReducerSpy1 ) . toHaveBeenCalled ( ) ;
523
+ } ) ;
524
+
525
+ it ( 'should call two meta reducers' , ( ) => {
526
+ setup ( { } , [
527
+ metaReducerContainer . metaReducer1 ,
528
+ metaReducerContainer . metaReducer2 ,
529
+ ] ) ;
530
+ const action = { type : INCREMENT } ;
531
+ store . dispatch ( action ) ;
532
+
533
+ expect ( metaReducerSpy1 ) . toHaveBeenCalled ( ) ;
534
+ expect ( metaReducerSpy2 ) . toHaveBeenCalled ( ) ;
535
+ } ) ;
536
+
537
+ it ( 'should create a meta reducer for feature and call it with the expected reducer' , ( ) => {
538
+ TestBed . configureTestingModule ( {
539
+ imports : [
540
+ StoreModule . forRoot ( { } ) ,
541
+ StoreModule . forFeature ( 'counter1' , counterReducer , {
542
+ metaReducers : [ metaReducerContainer . metaReducer1 ] ,
543
+ } ) ,
544
+ StoreModule . forFeature ( 'counter2' , counterReducer2 , {
545
+ metaReducers : [ metaReducerContainer . metaReducer2 ] ,
546
+ } ) ,
547
+ ] ,
548
+ } ) ;
549
+ const mockStore = TestBed . get ( Store ) ;
550
+ const action = { type : INCREMENT } ;
551
+ mockStore . dispatch ( action ) ;
552
+
553
+ expect ( metaReducerSpy1 ) . toHaveBeenCalledWith ( counterReducer ) ;
554
+ expect ( metaReducerSpy2 ) . toHaveBeenCalledWith ( counterReducer2 ) ;
555
+ } ) ;
556
+ } ) ;
557
+
558
+ describe ( 'Feature config token' , ( ) => {
559
+ let FEATURE_CONFIG_TOKEN : InjectionToken < StoreConfig < any , any > > ;
560
+ let FEATURE_CONFIG2_TOKEN : InjectionToken < StoreConfig < any , any > > ;
561
+
562
+ beforeEach ( ( ) => {
563
+ FEATURE_CONFIG_TOKEN = new InjectionToken ( 'Feature Config' ) ;
564
+ FEATURE_CONFIG2_TOKEN = new InjectionToken ( 'Feature Config2' ) ;
565
+ } ) ;
566
+
567
+ it ( 'should initial state with value' , ( done : DoneFn ) => {
568
+ const initialState = { counter1 : 1 } ;
569
+ const featureKey = 'counter' ;
570
+
571
+ TestBed . configureTestingModule ( {
572
+ imports : [
573
+ StoreModule . forRoot ( { } ) ,
574
+ StoreModule . forFeature (
575
+ featureKey ,
576
+ counterReducer ,
577
+ FEATURE_CONFIG_TOKEN
578
+ ) ,
579
+ ] ,
580
+ providers : [
581
+ {
582
+ provide : FEATURE_CONFIG_TOKEN ,
583
+ useValue : { initialState : initialState } ,
584
+ } ,
585
+ ] ,
586
+ } ) ;
587
+
588
+ const mockStore = TestBed . get ( Store ) ;
589
+
590
+ mockStore . pipe ( take ( 1 ) ) . subscribe ( {
591
+ next ( val : any ) {
592
+ expect ( val [ featureKey ] ) . toEqual ( initialState ) ;
593
+ } ,
594
+ error : done ,
595
+ complete : done ,
596
+ } ) ;
597
+ } ) ;
598
+
599
+ it ( 'should initial state with value for multi features' , ( done : DoneFn ) => {
600
+ const initialState = 1 ;
601
+ const initialState2 = 2 ;
602
+ const initialState3 = 3 ;
603
+ const featureKey = 'counter' ;
604
+ const featureKey2 = 'counter2' ;
605
+ const featureKey3 = 'counter3' ;
606
+
607
+ TestBed . configureTestingModule ( {
608
+ imports : [
609
+ StoreModule . forRoot ( { } ) ,
610
+ StoreModule . forFeature (
611
+ featureKey ,
612
+ counterReducer ,
613
+ FEATURE_CONFIG_TOKEN
614
+ ) ,
615
+ StoreModule . forFeature (
616
+ featureKey2 ,
617
+ counterReducer ,
618
+ FEATURE_CONFIG2_TOKEN
619
+ ) ,
620
+ StoreModule . forFeature ( featureKey3 , counterReducer , {
621
+ initialState : initialState3 ,
622
+ } ) ,
623
+ ] ,
624
+ providers : [
625
+ {
626
+ provide : FEATURE_CONFIG_TOKEN ,
627
+ useValue : { initialState : initialState } ,
628
+ } ,
629
+ {
630
+ provide : FEATURE_CONFIG2_TOKEN ,
631
+ useValue : { initialState : initialState2 } ,
632
+ } ,
633
+ ] ,
634
+ } ) ;
635
+
636
+ const mockStore = TestBed . get ( Store ) ;
637
+
638
+ mockStore . pipe ( take ( 1 ) ) . subscribe ( {
639
+ next ( val : any ) {
640
+ expect ( val [ featureKey ] ) . toEqual ( initialState ) ;
641
+ expect ( val [ featureKey2 ] ) . toEqual ( initialState2 ) ;
642
+ expect ( val [ featureKey3 ] ) . toEqual ( initialState3 ) ;
643
+ } ,
644
+ error : done ,
645
+ complete : done ,
646
+ } ) ;
647
+ } ) ;
648
+
649
+ it ( 'should create a meta reducer with config injection token and call it with the expected reducer' , ( ) => {
650
+ const metaReducerContainer = ( function ( ) {
651
+ function metaReducer1 ( reducer : ActionReducer < any , any > ) {
652
+ return function ( state : any , action : Action ) {
653
+ return reducer ( state , action ) ;
654
+ } ;
655
+ }
656
+
657
+ function metaReducer2 ( reducer : ActionReducer < any , any > ) {
658
+ return function ( state : any , action : Action ) {
659
+ return reducer ( state , action ) ;
660
+ } ;
661
+ }
662
+
663
+ return {
664
+ metaReducer1 : metaReducer1 ,
665
+ metaReducer2 : metaReducer2 ,
666
+ } ;
667
+ } ) ( ) ;
668
+
669
+ const metaReducerSpy1 = spyOn (
670
+ metaReducerContainer ,
671
+ 'metaReducer1'
672
+ ) . and . callThrough ( ) ;
673
+
674
+ const metaReducerSpy2 = spyOn (
675
+ metaReducerContainer ,
676
+ 'metaReducer2'
677
+ ) . and . callThrough ( ) ;
678
+
679
+ TestBed . configureTestingModule ( {
680
+ imports : [
681
+ StoreModule . forRoot ( { } ) ,
682
+ StoreModule . forFeature (
683
+ 'counter1' ,
684
+ counterReducer ,
685
+ FEATURE_CONFIG_TOKEN
686
+ ) ,
687
+ StoreModule . forFeature (
688
+ 'counter2' ,
689
+ counterReducer2 ,
690
+ FEATURE_CONFIG2_TOKEN
691
+ ) ,
692
+ ] ,
693
+ providers : [
694
+ {
695
+ provide : FEATURE_CONFIG_TOKEN ,
696
+ useValue : { metaReducers : [ metaReducerContainer . metaReducer1 ] } ,
697
+ } ,
698
+ {
699
+ provide : FEATURE_CONFIG2_TOKEN ,
700
+ useValue : { metaReducers : [ metaReducerContainer . metaReducer2 ] } ,
701
+ } ,
702
+ ] ,
703
+ } ) ;
704
+ const mockStore = TestBed . get ( Store ) ;
705
+ const action = { type : INCREMENT } ;
706
+ mockStore . dispatch ( action ) ;
707
+
708
+ expect ( metaReducerSpy1 ) . toHaveBeenCalledWith ( counterReducer ) ;
709
+ expect ( metaReducerSpy2 ) . toHaveBeenCalledWith ( counterReducer2 ) ;
710
+ } ) ;
711
+ } ) ;
474
712
} ) ;
0 commit comments