1
+ import * as ngCore from '@angular/core' ;
1
2
import { cold } from 'jasmine-marbles' ;
2
3
import {
3
4
createSelector ,
@@ -40,17 +41,23 @@ describe('Selectors', () => {
40
41
it ( 'should deliver the value of selectors to the projection function' , ( ) => {
41
42
const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
42
43
43
- const selector = createSelector ( incrementOne , incrementTwo , projectFn ) (
44
- { }
45
- ) ;
44
+ const selector = createSelector (
45
+ incrementOne ,
46
+ incrementTwo ,
47
+ projectFn
48
+ ) ( { } ) ;
46
49
47
50
expect ( projectFn ) . toHaveBeenCalledWith ( countOne , countTwo ) ;
48
51
} ) ;
49
52
50
53
it ( 'should allow an override of the selector return' , ( ) => {
51
54
const projectFn = jasmine . createSpy ( 'projectionFn' ) . and . returnValue ( 2 ) ;
52
55
53
- const selector = createSelector ( incrementOne , incrementTwo , projectFn ) ;
56
+ const selector = createSelector (
57
+ incrementOne ,
58
+ incrementTwo ,
59
+ projectFn
60
+ ) ;
54
61
55
62
expect ( selector . projector ( ) ) . toBe ( 2 ) ;
56
63
@@ -63,7 +70,11 @@ describe('Selectors', () => {
63
70
64
71
it ( 'should be possible to test a projector fn independent from the selectors it is composed of' , ( ) => {
65
72
const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
66
- const selector = createSelector ( incrementOne , incrementTwo , projectFn ) ;
73
+ const selector = createSelector (
74
+ incrementOne ,
75
+ incrementTwo ,
76
+ projectFn
77
+ ) ;
67
78
68
79
selector . projector ( '' , '' ) ;
69
80
@@ -81,7 +92,10 @@ describe('Selectors', () => {
81
92
return state . unchanged ;
82
93
} ) ;
83
94
const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
84
- const selector = createSelector ( neverChangingSelector , projectFn ) ;
95
+ const selector = createSelector (
96
+ neverChangingSelector ,
97
+ projectFn
98
+ ) ;
85
99
86
100
selector ( firstState ) ;
87
101
selector ( secondState ) ;
@@ -115,7 +129,10 @@ describe('Selectors', () => {
115
129
it ( 'should allow you to release memoized arguments' , ( ) => {
116
130
const state = { first : 'state' } ;
117
131
const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
118
- const selector = createSelector ( incrementOne , projectFn ) ;
132
+ const selector = createSelector (
133
+ incrementOne ,
134
+ projectFn
135
+ ) ;
119
136
120
137
selector ( state ) ;
121
138
selector ( state ) ;
@@ -127,9 +144,18 @@ describe('Selectors', () => {
127
144
} ) ;
128
145
129
146
it ( 'should recursively release ancestor selectors' , ( ) => {
130
- const grandparent = createSelector ( incrementOne , a => a ) ;
131
- const parent = createSelector ( grandparent , a => a ) ;
132
- const child = createSelector ( parent , a => a ) ;
147
+ const grandparent = createSelector (
148
+ incrementOne ,
149
+ a => a
150
+ ) ;
151
+ const parent = createSelector (
152
+ grandparent ,
153
+ a => a
154
+ ) ;
155
+ const child = createSelector (
156
+ parent ,
157
+ a => a
158
+ ) ;
133
159
spyOn ( grandparent , 'release' ) . and . callThrough ( ) ;
134
160
spyOn ( parent , 'release' ) . and . callThrough ( ) ;
135
161
@@ -245,16 +271,20 @@ describe('Selectors', () => {
245
271
describe ( 'createSelector with arrays' , ( ) => {
246
272
it ( 'should deliver the value of selectors to the projection function' , ( ) => {
247
273
const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
248
- const selector = createSelector ( [ incrementOne , incrementTwo ] , projectFn ) (
249
- { }
250
- ) ;
274
+ const selector = createSelector (
275
+ [ incrementOne , incrementTwo ] ,
276
+ projectFn
277
+ ) ( { } ) ;
251
278
252
279
expect ( projectFn ) . toHaveBeenCalledWith ( countOne , countTwo ) ;
253
280
} ) ;
254
281
255
282
it ( 'should be possible to test a projector fn independent from the selectors it is composed of' , ( ) => {
256
283
const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
257
- const selector = createSelector ( [ incrementOne , incrementTwo ] , projectFn ) ;
284
+ const selector = createSelector (
285
+ [ incrementOne , incrementTwo ] ,
286
+ projectFn
287
+ ) ;
258
288
259
289
selector . projector ( '' , '' ) ;
260
290
@@ -272,7 +302,10 @@ describe('Selectors', () => {
272
302
return state . unchanged ;
273
303
} ) ;
274
304
const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
275
- const selector = createSelector ( [ neverChangingSelector ] , projectFn ) ;
305
+ const selector = createSelector (
306
+ [ neverChangingSelector ] ,
307
+ projectFn
308
+ ) ;
276
309
277
310
selector ( firstState ) ;
278
311
selector ( secondState ) ;
@@ -304,7 +337,10 @@ describe('Selectors', () => {
304
337
it ( 'should allow you to release memoized arguments' , ( ) => {
305
338
const state = { first : 'state' } ;
306
339
const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
307
- const selector = createSelector ( [ incrementOne ] , projectFn ) ;
340
+ const selector = createSelector (
341
+ [ incrementOne ] ,
342
+ projectFn
343
+ ) ;
308
344
309
345
selector ( state ) ;
310
346
selector ( state ) ;
@@ -316,9 +352,18 @@ describe('Selectors', () => {
316
352
} ) ;
317
353
318
354
it ( 'should recursively release ancestor selectors' , ( ) => {
319
- const grandparent = createSelector ( [ incrementOne ] , a => a ) ;
320
- const parent = createSelector ( [ grandparent ] , a => a ) ;
321
- const child = createSelector ( [ parent ] , a => a ) ;
355
+ const grandparent = createSelector (
356
+ [ incrementOne ] ,
357
+ a => a
358
+ ) ;
359
+ const parent = createSelector (
360
+ [ grandparent ] ,
361
+ a => a
362
+ ) ;
363
+ const child = createSelector (
364
+ [ parent ] ,
365
+ a => a
366
+ ) ;
322
367
spyOn ( grandparent , 'release' ) . and . callThrough ( ) ;
323
368
spyOn ( parent , 'release' ) . and . callThrough ( ) ;
324
369
@@ -433,9 +478,11 @@ describe('Selectors', () => {
433
478
describe ( 'createFeatureSelector' , ( ) => {
434
479
let featureName = '@ngrx/router-store' ;
435
480
let featureSelector : ( state : any ) => number ;
481
+ let warnSpy : jasmine . Spy ;
436
482
437
483
beforeEach ( ( ) => {
438
484
featureSelector = createFeatureSelector < number > ( featureName ) ;
485
+ warnSpy = spyOn ( console , 'warn' ) ;
439
486
} ) ;
440
487
441
488
it ( 'should memoize the result' , ( ) => {
@@ -455,6 +502,50 @@ describe('Selectors', () => {
455
502
) ;
456
503
457
504
expect ( featureState$ ) . toBeObservable ( expected$ ) ;
505
+ expect ( warnSpy ) . not . toHaveBeenCalled ( ) ;
506
+ } ) ;
507
+
508
+ it ( 'should warn if the feature does not exist in the state' , ( ) => {
509
+ spyOn ( ngCore , 'isDevMode' ) . and . returnValue ( true ) ;
510
+
511
+ const state = { otherState : '' } ;
512
+
513
+ const state$ = cold ( 'a' , { a : state } ) ;
514
+ const expected$ = cold ( 'a' , { a : undefined } ) ;
515
+
516
+ const featureState$ = state$ . pipe (
517
+ map ( featureSelector ) ,
518
+ distinctUntilChanged ( )
519
+ ) ;
520
+
521
+ expect ( featureState$ ) . toBeObservable ( expected$ ) ;
522
+ expect ( warnSpy ) . toHaveBeenCalledWith (
523
+ 'The feature name "@ngrx/router-store" does not exist ' +
524
+ 'in the state, therefore createFeatureSelector cannot ' +
525
+ 'access it. Be sure it is imported in a loaded module using ' +
526
+ "StoreModule.forRoot('@ngrx/router-store', ...) or " +
527
+ "StoreModule.forFeature('@ngrx/router-store', ...). If the " +
528
+ 'default state is intended to be undefined, as is the case ' +
529
+ 'with router state, this development-only warning message can ' +
530
+ 'be ignored.'
531
+ ) ;
532
+ } ) ;
533
+
534
+ it ( 'should not warn if not in development mode' , ( ) => {
535
+ spyOn ( ngCore , 'isDevMode' ) . and . returnValue ( false ) ;
536
+
537
+ const state = { otherState : '' } ;
538
+
539
+ const state$ = cold ( 'a' , { a : state } ) ;
540
+ const expected$ = cold ( 'a' , { a : undefined } ) ;
541
+
542
+ const featureState$ = state$ . pipe (
543
+ map ( featureSelector ) ,
544
+ distinctUntilChanged ( )
545
+ ) ;
546
+
547
+ expect ( featureState$ ) . toBeObservable ( expected$ ) ;
548
+ expect ( warnSpy ) . not . toHaveBeenCalled ( ) ;
458
549
} ) ;
459
550
} ) ;
460
551
0 commit comments