@@ -125,6 +125,105 @@ describe('Selectors', () => {
125125 } ) ;
126126 } ) ;
127127
128+ describe ( 'createSelector with props' , ( ) => {
129+ it ( 'should deliver the value of selectors to the projection function' , ( ) => {
130+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
131+
132+ const selector = createSelector (
133+ incrementOne ,
134+ incrementTwo ,
135+ ( state : any , props : any ) => props . value ,
136+ projectFn
137+ ) ;
138+
139+ selector ( { } , { value : 47 } ) ;
140+ expect ( projectFn ) . toHaveBeenCalledWith ( countOne , countTwo , 47 ) ;
141+ } ) ;
142+
143+ it ( 'should be possible to test a projector fn independent from the selectors it is composed of' , ( ) => {
144+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
145+ const selector = createSelector (
146+ incrementOne ,
147+ incrementTwo ,
148+ ( state : any , props : any ) => {
149+ fail ( `Shouldn't be called` ) ;
150+ return props . value ;
151+ } ,
152+ projectFn
153+ ) ;
154+ selector . projector ( '' , '' , 47 ) ;
155+
156+ expect ( incrementOne ) . not . toHaveBeenCalled ( ) ;
157+ expect ( incrementTwo ) . not . toHaveBeenCalled ( ) ;
158+ expect ( projectFn ) . toHaveBeenCalledWith ( '' , '' , 47 ) ;
159+ } ) ;
160+
161+ it ( 'should call the projector function when the state changes' , ( ) => {
162+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
163+ const selector = createSelector (
164+ incrementOne ,
165+ ( state : any , props : any ) => props . value ,
166+ projectFn
167+ ) ;
168+
169+ const firstSate = { first : 'state' } ;
170+ const props = { foo : 'props' } ;
171+ selector ( firstSate , props ) ;
172+ selector ( firstSate , props ) ;
173+ expect ( projectFn ) . toHaveBeenCalledTimes ( 1 ) ;
174+
175+ const secondState = { second : 'state' } ;
176+ selector ( secondState , props ) ;
177+ expect ( projectFn ) . toHaveBeenCalledTimes ( 2 ) ;
178+ } ) ;
179+
180+ it ( 'should memoize the function' , ( ) => {
181+ let counter = 0 ;
182+
183+ const firstState = { first : 'state' } ;
184+ const secondState = { second : 'state' } ;
185+ const props = { foo : 'props' } ;
186+
187+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
188+ const selector = createSelector (
189+ incrementOne ,
190+ incrementTwo ,
191+ ( state : any , props : any ) => {
192+ counter ++ ;
193+ return props ;
194+ } ,
195+ projectFn
196+ ) ;
197+
198+ selector ( firstState , props ) ;
199+ selector ( firstState , props ) ;
200+ selector ( firstState , props ) ;
201+ selector ( secondState , props ) ;
202+
203+ expect ( counter ) . toBe ( 2 ) ;
204+ expect ( projectFn ) . toHaveBeenCalledTimes ( 2 ) ;
205+ } ) ;
206+
207+ it ( 'should allow you to release memoized arguments' , ( ) => {
208+ const state = { first : 'state' } ;
209+ const props = { foo : 'props' } ;
210+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
211+ const selector = createSelector (
212+ incrementOne ,
213+ ( state : any , props : any ) => props ,
214+ projectFn
215+ ) ;
216+
217+ selector ( state , props ) ;
218+ selector ( state , props ) ;
219+ selector . release ( ) ;
220+ selector ( state , props ) ;
221+ selector ( state , props ) ;
222+
223+ expect ( projectFn ) . toHaveBeenCalledTimes ( 2 ) ;
224+ } ) ;
225+ } ) ;
226+
128227 describe ( 'createSelector with arrays' , ( ) => {
129228 it ( 'should deliver the value of selectors to the projection function' , ( ) => {
130229 const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
@@ -211,6 +310,104 @@ describe('Selectors', () => {
211310 } ) ;
212311 } ) ;
213312
313+ describe ( 'createSelector with arrays and props' , ( ) => {
314+ it ( 'should deliver the value of selectors to the projection function' , ( ) => {
315+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
316+ const selector = createSelector (
317+ [ incrementOne , incrementTwo , ( state : any , props : any ) => props . value ] ,
318+ projectFn
319+ ) ( { } , { value : 47 } ) ;
320+
321+ expect ( projectFn ) . toHaveBeenCalledWith ( countOne , countTwo , 47 ) ;
322+ } ) ;
323+
324+ it ( 'should be possible to test a projector fn independent from the selectors it is composed of' , ( ) => {
325+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
326+ const selector = createSelector (
327+ [
328+ incrementOne ,
329+ incrementTwo ,
330+ ( state : any , props : any ) => {
331+ fail ( `Shouldn't be called` ) ;
332+ return props . value ;
333+ } ,
334+ ] ,
335+ projectFn
336+ ) ;
337+
338+ selector . projector ( '' , '' , 47 ) ;
339+
340+ expect ( incrementOne ) . not . toHaveBeenCalled ( ) ;
341+ expect ( incrementTwo ) . not . toHaveBeenCalled ( ) ;
342+ expect ( projectFn ) . toHaveBeenCalledWith ( '' , '' , 47 ) ;
343+ } ) ;
344+
345+ it ( 'should call the projector function when the state changes' , ( ) => {
346+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
347+ const selector = createSelector (
348+ [ incrementOne , ( state : any , props : any ) => props . value ] ,
349+ projectFn
350+ ) ;
351+
352+ const firstSate = { first : 'state' } ;
353+ const props = { foo : 'props' } ;
354+ selector ( firstSate , props ) ;
355+ selector ( firstSate , props ) ;
356+ expect ( projectFn ) . toHaveBeenCalledTimes ( 1 ) ;
357+
358+ const secondState = { second : 'state' } ;
359+ selector ( secondState , props ) ;
360+ expect ( projectFn ) . toHaveBeenCalledTimes ( 2 ) ;
361+ } ) ;
362+
363+ it ( 'should memoize the function' , ( ) => {
364+ let counter = 0 ;
365+
366+ const firstState = { first : 'state' } ;
367+ const secondState = { second : 'state' } ;
368+ const props = { foo : 'props' } ;
369+
370+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
371+ const selector = createSelector (
372+ [
373+ incrementOne ,
374+ incrementTwo ,
375+ ( state : any , props : any ) => {
376+ counter ++ ;
377+ return props ;
378+ } ,
379+ ] ,
380+ projectFn
381+ ) ;
382+
383+ selector ( firstState , props ) ;
384+ selector ( firstState , props ) ;
385+ selector ( firstState , props ) ;
386+ selector ( secondState , props ) ;
387+
388+ expect ( counter ) . toBe ( 2 ) ;
389+ expect ( projectFn ) . toHaveBeenCalledTimes ( 2 ) ;
390+ } ) ;
391+
392+ it ( 'should allow you to release memoized arguments' , ( ) => {
393+ const state = { first : 'state' } ;
394+ const props = { foo : 'props' } ;
395+ const projectFn = jasmine . createSpy ( 'projectionFn' ) ;
396+ const selector = createSelector (
397+ [ incrementOne , ( state : any , props : any ) => props ] ,
398+ projectFn
399+ ) ;
400+
401+ selector ( state , props ) ;
402+ selector ( state , props ) ;
403+ selector . release ( ) ;
404+ selector ( state , props ) ;
405+ selector ( state , props ) ;
406+
407+ expect ( projectFn ) . toHaveBeenCalledTimes ( 2 ) ;
408+ } ) ;
409+ } ) ;
410+
214411 describe ( 'createFeatureSelector' , ( ) => {
215412 let featureName = '@ngrx/router-store' ;
216413 let featureSelector : ( state : any ) => number ;
0 commit comments