11import { Injector } from '@angular/core' ;
22import {
33 Action ,
4- StoreModule ,
4+ props ,
55 ScannedActionsSubject ,
66 ActionsSubject ,
7+ createAction ,
78} from '@ngrx/store' ;
89import { Actions , ofType } from '../' ;
910import { map , toArray , switchMap } from 'rxjs/operators' ;
@@ -25,16 +26,12 @@ describe('Actions', function() {
2526 type : 'SUBTRACT' ;
2627 }
2728
28- function reducer ( state : number = 0 , action : Action ) {
29- switch ( action . type ) {
30- case ADD :
31- return state + 1 ;
32- case SUBTRACT :
33- return state - 1 ;
34- default :
35- return state ;
36- }
37- }
29+ const square = createAction ( 'SQUARE' ) ;
30+ const multiply = createAction ( 'MULTYPLY' , props < { by : number } > ( ) ) ;
31+ const divide = createAction ( 'DIVIDE' , props < { by : number } > ( ) ) ;
32+
33+ // Class-based Action types
34+ const actions = [ ADD , ADD , SUBTRACT , ADD , SUBTRACT ] ;
3835
3936 beforeEach ( function ( ) {
4037 const injector = Injector . create ( [
@@ -69,12 +66,12 @@ describe('Actions', function() {
6966 } ) ;
7067
7168 actions . forEach ( action => dispatcher . next ( action ) ) ;
69+ dispatcher . complete ( ) ;
7270 } ) ;
7371
74- const actions = [ ADD , ADD , SUBTRACT , ADD , SUBTRACT ] ;
75- const expected = actions . filter ( type => type === ADD ) ;
72+ it ( 'should filter out actions' , ( ) => {
73+ const expected = actions . filter ( type => type === ADD ) ;
7674
77- it ( 'should let you filter out actions' , function ( ) {
7875 actions$
7976 . pipe (
8077 ofType ( ADD ) ,
@@ -83,15 +80,17 @@ describe('Actions', function() {
8380 )
8481 . subscribe ( {
8582 next ( actual ) {
86- expect ( actual ) . toEqual ( expected as any [ ] ) ;
83+ expect ( actual ) . toEqual ( expected ) ;
8784 } ,
8885 } ) ;
8986
9087 actions . forEach ( action => dispatcher . next ( { type : action } ) ) ;
9188 dispatcher . complete ( ) ;
9289 } ) ;
9390
94- it ( 'should let you filter out actions and ofType can take an explicit type argument' , function ( ) {
91+ it ( 'should filter out actions and ofType can take an explicit type argument' , ( ) => {
92+ const expected = actions . filter ( type => type === ADD ) ;
93+
9594 actions$
9695 . pipe (
9796 ofType < AddAction > ( ADD ) ,
@@ -100,11 +99,192 @@ describe('Actions', function() {
10099 )
101100 . subscribe ( {
102101 next ( actual ) {
103- expect ( actual ) . toEqual ( expected as any [ ] ) ;
102+ expect ( actual ) . toEqual ( expected ) ;
103+ } ,
104+ } ) ;
105+
106+ actions . forEach ( action => dispatcher . next ( { type : action } ) ) ;
107+ dispatcher . complete ( ) ;
108+ } ) ;
109+
110+ it ( 'should let you filter out multiple action types with explicit type argument' , ( ) => {
111+ const expected = actions . filter ( type => type === ADD || type === SUBTRACT ) ;
112+
113+ actions$
114+ . pipe (
115+ ofType < AddAction | SubtractAction > ( ADD , SUBTRACT ) ,
116+ map ( update => update . type ) ,
117+ toArray ( )
118+ )
119+ . subscribe ( {
120+ next ( actual ) {
121+ expect ( actual ) . toEqual ( expected ) ;
122+ } ,
123+ } ) ;
124+
125+ actions . forEach ( action => dispatcher . next ( { type : action } ) ) ;
126+ dispatcher . complete ( ) ;
127+ } ) ;
128+
129+ it ( 'should filter out actions by action creator' , ( ) => {
130+ actions$
131+ . pipe (
132+ ofType ( square ) ,
133+ map ( update => update . type ) ,
134+ toArray ( )
135+ )
136+ . subscribe ( {
137+ next ( actual ) {
138+ expect ( actual ) . toEqual ( [ 'SQUARE' ] ) ;
139+ } ,
140+ } ) ;
141+
142+ [ ...actions , square . type ] . forEach ( action =>
143+ dispatcher . next ( { type : action } )
144+ ) ;
145+ dispatcher . complete ( ) ;
146+ } ) ;
147+
148+ it ( 'should infer the type for the action when it is filter by action creator with property' , ( ) => {
149+ const MULTYPLY_BY = 5 ;
150+
151+ actions$
152+ . pipe (
153+ ofType ( multiply ) ,
154+ map ( update => update . by ) ,
155+ toArray ( )
156+ )
157+ . subscribe ( {
158+ next ( actual ) {
159+ expect ( actual ) . toEqual ( [ MULTYPLY_BY ] ) ;
104160 } ,
105161 } ) ;
106162
163+ // Unrelated Actions
107164 actions . forEach ( action => dispatcher . next ( { type : action } ) ) ;
165+ // Action under test
166+ dispatcher . next ( multiply ( { by : MULTYPLY_BY } ) ) ;
167+ dispatcher . complete ( ) ;
168+ } ) ;
169+
170+ it ( 'should infer the type for the action when it is filter by action creator' , ( ) => {
171+ // Types are not provided for generic Actions
172+ const untypedActions$ : Actions = actions$ ;
173+ const MULTYPLY_BY = 5 ;
174+
175+ untypedActions$
176+ . pipe (
177+ ofType ( multiply ) ,
178+ // Type is infered, even though untypedActions$ is Actions<Action>
179+ map ( update => update . by ) ,
180+ toArray ( )
181+ )
182+ . subscribe ( {
183+ next ( actual ) {
184+ expect ( actual ) . toEqual ( [ MULTYPLY_BY ] ) ;
185+ } ,
186+ } ) ;
187+
188+ // Unrelated Actions
189+ actions . forEach ( action => dispatcher . next ( { type : action } ) ) ;
190+ // Action under test
191+ dispatcher . next ( multiply ( { by : MULTYPLY_BY } ) ) ;
192+ dispatcher . complete ( ) ;
193+ } ) ;
194+
195+ it ( 'should filter out multiple actions by action creator' , ( ) => {
196+ const DIVIDE_BY = 3 ;
197+ const MULTYPLY_BY = 5 ;
198+ const expected = [ DIVIDE_BY , MULTYPLY_BY ] ;
199+
200+ actions$
201+ . pipe (
202+ ofType ( divide , multiply ) ,
203+ // Both have 'by' property
204+ map ( update => update . by ) ,
205+ toArray ( )
206+ )
207+ . subscribe ( {
208+ next ( actual ) {
209+ expect ( actual ) . toEqual ( expected ) ;
210+ } ,
211+ } ) ;
212+
213+ // Unrelated Actions
214+ actions . forEach ( action => dispatcher . next ( { type : action } ) ) ;
215+ // Actions under test, in specific order
216+ dispatcher . next ( divide ( { by : DIVIDE_BY } ) ) ;
217+ dispatcher . next ( divide ( { by : MULTYPLY_BY } ) ) ;
218+ dispatcher . complete ( ) ;
219+ } ) ;
220+
221+ it ( 'should filter out actions by action creator and type string' , ( ) => {
222+ const expected = [ ...actions . filter ( type => type === ADD ) , square . type ] ;
223+
224+ actions$
225+ . pipe (
226+ ofType ( ADD , square ) ,
227+ map ( update => update . type ) ,
228+ toArray ( )
229+ )
230+ . subscribe ( {
231+ next ( actual ) {
232+ expect ( actual ) . toEqual ( expected ) ;
233+ } ,
234+ } ) ;
235+
236+ [ ...actions , square . type ] . forEach ( action =>
237+ dispatcher . next ( { type : action } )
238+ ) ;
239+
240+ dispatcher . complete ( ) ;
241+ } ) ;
242+
243+ it ( 'should filter out actions by action creator and type string, with explicit type argument' , ( ) => {
244+ const expected = [ ...actions . filter ( type => type === ADD ) , square . type ] ;
245+
246+ actions$
247+ . pipe (
248+ // Provided type overrides any inference from arguments
249+ ofType < AddAction | ReturnType < typeof square > > ( ADD , square ) ,
250+ map ( update => update . type ) ,
251+ toArray ( )
252+ )
253+ . subscribe ( {
254+ next ( actual ) {
255+ expect ( actual ) . toEqual ( expected ) ;
256+ } ,
257+ } ) ;
258+
259+ [ ...actions , square . type ] . forEach ( action =>
260+ dispatcher . next ( { type : action } )
261+ ) ;
262+
263+ dispatcher . complete ( ) ;
264+ } ) ;
265+
266+ it ( 'should filter out up to 5 actions with type inference' , ( ) => {
267+ // Mixing all of them, up to 5
268+ const expected = [ divide . type , ADD , square . type , SUBTRACT , multiply . type ] ;
269+
270+ actions$
271+ . pipe (
272+ ofType ( divide , ADD , square , SUBTRACT , multiply ) ,
273+ map ( update => update . type ) ,
274+ toArray ( )
275+ )
276+ . subscribe ( {
277+ next ( actual ) {
278+ expect ( actual ) . toEqual ( expected ) ;
279+ } ,
280+ } ) ;
281+
282+ // Actions under test, in specific order
283+ dispatcher . next ( divide ( { by : 1 } ) ) ;
284+ dispatcher . next ( { type : ADD } ) ;
285+ dispatcher . next ( square ( ) ) ;
286+ dispatcher . next ( { type : SUBTRACT } ) ;
287+ dispatcher . next ( multiply ( { by : 2 } ) ) ;
108288 dispatcher . complete ( ) ;
109289 } ) ;
110290} ) ;
0 commit comments