@@ -13,7 +13,6 @@ import {
13
13
import { map } from 'rxjs/operators' ;
14
14
15
15
import {
16
- Effect ,
17
16
EffectSources ,
18
17
OnIdentifyEffects ,
19
18
OnInitEffects ,
@@ -76,251 +75,6 @@ describe('EffectSources', () => {
76
75
return ( effectSources as any ) [ 'toActions' ] . call ( source ) ;
77
76
}
78
77
79
- describe ( 'with @Effect()' , ( ) => {
80
- const a = { type : 'From Source A' } ;
81
- const b = { type : 'From Source B' } ;
82
- const c = { type : 'From Source C that completes' } ;
83
- const d = { not : 'a valid action' } ;
84
- const e = undefined ;
85
- const f = null ;
86
- const i = { type : 'From Source Identifier' } ;
87
- const i2 = { type : 'From Source Identifier 2' } ;
88
-
89
- const circularRef = { } as any ;
90
- circularRef . circularRef = circularRef ;
91
- const g = { circularRef } ;
92
-
93
- const error = new Error ( 'An Error' ) ;
94
-
95
- class SourceA {
96
- @Effect ( ) a$ = alwaysOf ( a ) ;
97
- }
98
-
99
- class SourceB {
100
- @Effect ( ) b$ = alwaysOf ( b ) ;
101
- }
102
-
103
- class SourceC {
104
- @Effect ( ) c$ = of ( c ) ;
105
- }
106
-
107
- class SourceD {
108
- @Effect ( ) d$ = alwaysOf ( d ) ;
109
- }
110
-
111
- class SourceE {
112
- @Effect ( ) e$ = alwaysOf ( e ) ;
113
- }
114
-
115
- class SourceF {
116
- @Effect ( ) f$ = alwaysOf ( f ) ;
117
- }
118
-
119
- class SourceG {
120
- @Effect ( ) g$ = alwaysOf ( g ) ;
121
- }
122
-
123
- class SourceError {
124
- @Effect ( ) e$ = throwError ( ( ) => error ) ;
125
- }
126
-
127
- class SourceH {
128
- @Effect ( ) empty = of ( 'value' ) ;
129
- @Effect ( )
130
- never = timer ( 50 , getTestScheduler ( ) as any ) . pipe ( map ( ( ) => 'update' ) ) ;
131
- }
132
-
133
- class SourceWithIdentifier implements OnIdentifyEffects {
134
- effectIdentifier : string ;
135
- @Effect ( ) i$ = alwaysOf ( i ) ;
136
-
137
- ngrxOnIdentifyEffects ( ) {
138
- return this . effectIdentifier ;
139
- }
140
-
141
- constructor ( identifier : string ) {
142
- this . effectIdentifier = identifier ;
143
- }
144
- }
145
-
146
- class SourceWithIdentifier2 implements OnIdentifyEffects {
147
- effectIdentifier : string ;
148
- @Effect ( ) i2$ = alwaysOf ( i2 ) ;
149
-
150
- ngrxOnIdentifyEffects ( ) {
151
- return this . effectIdentifier ;
152
- }
153
-
154
- constructor ( identifier : string ) {
155
- this . effectIdentifier = identifier ;
156
- }
157
- }
158
-
159
- it ( 'should resolve effects from instances' , ( ) => {
160
- const sources$ = cold ( '--a--' , { a : new SourceA ( ) } ) ;
161
- const expected = cold ( '--a--' , { a } ) ;
162
-
163
- const output = toActions ( sources$ ) ;
164
-
165
- expect ( output ) . toBeObservable ( expected ) ;
166
- } ) ;
167
-
168
- it ( 'should ignore duplicate sources' , ( ) => {
169
- const sources$ = cold ( '--a--a--a--' , {
170
- a : new SourceA ( ) ,
171
- } ) ;
172
- const expected = cold ( '--a--------' , { a } ) ;
173
-
174
- const output = toActions ( sources$ ) ;
175
-
176
- expect ( output ) . toBeObservable ( expected ) ;
177
- } ) ;
178
-
179
- it ( 'should resolve effects with different identifiers' , ( ) => {
180
- const sources$ = cold ( '--a--b--c--' , {
181
- a : new SourceWithIdentifier ( 'a' ) ,
182
- b : new SourceWithIdentifier ( 'b' ) ,
183
- c : new SourceWithIdentifier ( 'c' ) ,
184
- } ) ;
185
- const expected = cold ( '--i--i--i--' , { i } ) ;
186
-
187
- const output = toActions ( sources$ ) ;
188
-
189
- expect ( output ) . toBeObservable ( expected ) ;
190
- } ) ;
191
-
192
- it ( 'should ignore effects with the same identifier' , ( ) => {
193
- const sources$ = cold ( '--a--b--c--' , {
194
- a : new SourceWithIdentifier ( 'a' ) ,
195
- b : new SourceWithIdentifier ( 'a' ) ,
196
- c : new SourceWithIdentifier ( 'a' ) ,
197
- } ) ;
198
- const expected = cold ( '--i--------' , { i } ) ;
199
-
200
- const output = toActions ( sources$ ) ;
201
-
202
- expect ( output ) . toBeObservable ( expected ) ;
203
- } ) ;
204
-
205
- it ( 'should resolve effects with same identifiers but different classes' , ( ) => {
206
- const sources$ = cold ( '--a--b--c--d--' , {
207
- a : new SourceWithIdentifier ( 'a' ) ,
208
- b : new SourceWithIdentifier2 ( 'a' ) ,
209
- c : new SourceWithIdentifier ( 'b' ) ,
210
- d : new SourceWithIdentifier2 ( 'b' ) ,
211
- } ) ;
212
- const expected = cold ( '--a--b--a--b--' , { a : i , b : i2 } ) ;
213
-
214
- const output = toActions ( sources$ ) ;
215
-
216
- expect ( output ) . toBeObservable ( expected ) ;
217
- } ) ;
218
-
219
- it ( 'should report an error if an effect dispatches an invalid action' , ( ) => {
220
- const sources$ = of ( new SourceD ( ) ) ;
221
-
222
- toActions ( sources$ ) . subscribe ( ) ;
223
-
224
- expect ( mockErrorReporter . handleError ) . toHaveBeenCalledWith (
225
- new Error (
226
- 'Effect "SourceD.d$" dispatched an invalid action: {"not":"a valid action"}'
227
- )
228
- ) ;
229
- } ) ;
230
-
231
- it ( 'should report an error if an effect dispatches an `undefined`' , ( ) => {
232
- const sources$ = of ( new SourceE ( ) ) ;
233
-
234
- toActions ( sources$ ) . subscribe ( ) ;
235
-
236
- expect ( mockErrorReporter . handleError ) . toHaveBeenCalledWith (
237
- new Error (
238
- 'Effect "SourceE.e$" dispatched an invalid action: undefined'
239
- )
240
- ) ;
241
- } ) ;
242
-
243
- it ( 'should report an error if an effect dispatches a `null`' , ( ) => {
244
- const sources$ = of ( new SourceF ( ) ) ;
245
-
246
- toActions ( sources$ ) . subscribe ( ) ;
247
-
248
- expect ( mockErrorReporter . handleError ) . toHaveBeenCalledWith (
249
- new Error ( 'Effect "SourceF.f$" dispatched an invalid action: null' )
250
- ) ;
251
- } ) ;
252
-
253
- it ( 'should report an error if an effect throws one' , ( ) => {
254
- const sources$ = of ( new SourceError ( ) ) ;
255
-
256
- toActions ( sources$ ) . subscribe ( ) ;
257
-
258
- expect ( mockErrorReporter . handleError ) . toHaveBeenCalledWith (
259
- new Error ( 'An Error' )
260
- ) ;
261
- } ) ;
262
-
263
- it ( 'should resubscribe on error by default' , ( ) => {
264
- class Eff {
265
- @Effect ( )
266
- b$ = hot ( 'a--e--b--e--c--e--d' ) . pipe (
267
- map ( ( v ) => {
268
- if ( v == 'e' ) throw new Error ( 'An Error' ) ;
269
- return v ;
270
- } )
271
- ) ;
272
- }
273
-
274
- const sources$ = of ( new Eff ( ) ) ;
275
-
276
- // 👇 'e' is ignored.
277
- const expected = cold ( 'a-----b-----c-----d' ) ;
278
- expect ( toActions ( sources$ ) ) . toBeObservable ( expected ) ;
279
- } ) ;
280
-
281
- it ( 'should not resubscribe on error when useEffectsErrorHandler is false' , ( ) => {
282
- class Eff {
283
- @Effect ( { useEffectsErrorHandler : false } )
284
- b$ = hot ( 'a--b--c--d' ) . pipe (
285
- map ( ( v ) => {
286
- if ( v == 'b' ) throw new Error ( 'An Error' ) ;
287
- return v ;
288
- } )
289
- ) ;
290
- }
291
-
292
- const sources$ = of ( new Eff ( ) ) ;
293
-
294
- // 👇 completes.
295
- const expected = cold ( 'a--|' ) ;
296
-
297
- expect ( toActions ( sources$ ) ) . toBeObservable ( expected ) ;
298
- } ) ;
299
-
300
- it ( `should not break when the action in the error message can't be stringified` , ( ) => {
301
- const sources$ = of ( new SourceG ( ) ) ;
302
-
303
- toActions ( sources$ ) . subscribe ( ) ;
304
-
305
- expect ( mockErrorReporter . handleError ) . toHaveBeenCalledWith (
306
- new Error (
307
- 'Effect "SourceG.g$" dispatched an invalid action: [object Object]'
308
- )
309
- ) ;
310
- } ) ;
311
-
312
- it ( 'should not complete the group if just one effect completes' , ( ) => {
313
- const sources$ = cold ( 'g' , {
314
- g : new SourceH ( ) ,
315
- } ) ;
316
- const expected = cold ( 'a----b-----' , { a : 'value' , b : 'update' } ) ;
317
-
318
- const output = toActions ( sources$ ) ;
319
-
320
- expect ( output ) . toBeObservable ( expected ) ;
321
- } ) ;
322
- } ) ;
323
-
324
78
describe ( 'with createEffect()' , ( ) => {
325
79
const a = { type : 'From Source A' } ;
326
80
const b = { type : 'From Source B' } ;
0 commit comments