11// TODO: Add test for React Redux connect function
22
3- import { createSelectorCreator , lruMemoize } from 'reselect'
4- import { vi } from 'vitest'
5-
6- const createSelector = createSelectorCreator ( {
3+ import { shallowEqual } from 'react-redux'
4+ import {
5+ createSelectorCreator ,
6+ lruMemoize ,
7+ referenceEqualityCheck
8+ } from 'reselect'
9+ import type { RootState } from './testUtils'
10+ import { localTest , toggleCompleted } from './testUtils'
11+
12+ const createSelectorLru = createSelectorCreator ( {
713 memoize : lruMemoize ,
814 argsMemoize : lruMemoize
915} )
@@ -268,7 +274,7 @@ describe(lruMemoize, () => {
268274
269275 const fooChangeSpy = vi . fn ( )
270276
271- const fooChangeHandler = createSelector (
277+ const fooChangeHandler = createSelectorLru (
272278 ( state : any ) => state . foo ,
273279 fooChangeSpy
274280 )
@@ -284,7 +290,7 @@ describe(lruMemoize, () => {
284290 const state2 = { a : 1 }
285291 let count = 0
286292
287- const selector = createSelector ( [ ( state : any ) => state . a ] , ( ) => {
293+ const selector = createSelectorLru ( [ ( state : any ) => state . a ] , ( ) => {
288294 count ++
289295 return undefined
290296 } )
@@ -361,7 +367,7 @@ describe(lruMemoize, () => {
361367 funcCalls = 0
362368
363369 // Test out maxSize of 3 + exposure via createSelector
364- const selector = createSelector (
370+ const selector = createSelectorLru (
365371 ( state : string ) => state ,
366372 state => {
367373 funcCalls ++
@@ -415,3 +421,134 @@ describe(lruMemoize, () => {
415421 expect ( selector . resultFunc . clearCache ) . toBeUndefined ( )
416422 } )
417423} )
424+
425+ describe ( 'lruMemoize integration with resultEqualityCheck' , ( ) => {
426+ const createAppSelector = createSelectorLru . withTypes < RootState > ( )
427+
428+ const resultEqualityCheck = vi
429+ . fn ( shallowEqual )
430+ . mockName ( 'resultEqualityCheck' )
431+
432+ afterEach ( ( ) => {
433+ resultEqualityCheck . mockClear ( )
434+ } )
435+
436+ localTest (
437+ 'resultEqualityCheck works when set to shallowEqual' ,
438+ ( { store } ) => {
439+ const selectTodoIds = lruMemoize (
440+ ( state : RootState ) => state . todos . map ( ( { id } ) => id ) ,
441+ { resultEqualityCheck }
442+ )
443+
444+ const firstResult = selectTodoIds ( store . getState ( ) )
445+
446+ store . dispatch ( toggleCompleted ( 0 ) )
447+
448+ const secondResult = selectTodoIds ( store . getState ( ) )
449+
450+ expect ( firstResult ) . toBe ( secondResult )
451+
452+ expect ( selectTodoIds . resultsCount ( ) ) . toBe ( 1 )
453+ }
454+ )
455+
456+ localTest (
457+ 'resultEqualityCheck should not be called on the first output selector call' ,
458+ ( { store } ) => {
459+ const selectTodoIds = createAppSelector (
460+ [ state => state . todos ] ,
461+ todos => todos . map ( ( { id } ) => id ) ,
462+ {
463+ memoizeOptions : { resultEqualityCheck } ,
464+ devModeChecks : { inputStabilityCheck : 'once' }
465+ }
466+ )
467+
468+ expect ( selectTodoIds ( store . getState ( ) ) ) . to . be . an ( 'array' ) . that . is . not
469+ . empty
470+
471+ expect ( resultEqualityCheck ) . not . toHaveBeenCalled ( )
472+
473+ store . dispatch ( toggleCompleted ( 0 ) )
474+
475+ expect ( selectTodoIds . lastResult ( ) ) . toBe ( selectTodoIds ( store . getState ( ) ) )
476+
477+ expect ( resultEqualityCheck ) . toHaveBeenCalledOnce ( )
478+
479+ expect ( selectTodoIds . memoizedResultFunc . resultsCount ( ) ) . toBe ( 1 )
480+
481+ expect ( selectTodoIds . recomputations ( ) ) . toBe ( 2 )
482+
483+ expect ( selectTodoIds . resultsCount ( ) ) . toBe ( 2 )
484+
485+ expect ( selectTodoIds . dependencyRecomputations ( ) ) . toBe ( 2 )
486+
487+ store . dispatch ( toggleCompleted ( 0 ) )
488+
489+ expect ( selectTodoIds . lastResult ( ) ) . toBe ( selectTodoIds ( store . getState ( ) ) )
490+
491+ expect ( resultEqualityCheck ) . toHaveBeenCalledTimes ( 2 )
492+
493+ expect ( selectTodoIds . memoizedResultFunc . resultsCount ( ) ) . toBe ( 1 )
494+
495+ expect ( selectTodoIds . recomputations ( ) ) . toBe ( 3 )
496+
497+ expect ( selectTodoIds . resultsCount ( ) ) . toBe ( 3 )
498+
499+ expect ( selectTodoIds . dependencyRecomputations ( ) ) . toBe ( 3 )
500+ }
501+ )
502+
503+ localTest (
504+ 'lruMemoize with resultEqualityCheck set to referenceEqualityCheck works the same as lruMemoize without resultEqualityCheck' ,
505+ ( { store } ) => {
506+ const resultEqualityCheck = vi
507+ . fn ( referenceEqualityCheck )
508+ . mockName ( 'resultEqualityCheck' )
509+
510+ const selectTodoIdsWithResultEqualityCheck = lruMemoize (
511+ ( state : RootState ) => state . todos . map ( ( { id } ) => id ) ,
512+ { resultEqualityCheck }
513+ )
514+
515+ const firstResultWithResultEqualityCheck =
516+ selectTodoIdsWithResultEqualityCheck ( store . getState ( ) )
517+
518+ expect ( resultEqualityCheck ) . not . toHaveBeenCalled ( )
519+
520+ store . dispatch ( toggleCompleted ( 0 ) )
521+
522+ const secondResultWithResultEqualityCheck =
523+ selectTodoIdsWithResultEqualityCheck ( store . getState ( ) )
524+
525+ expect ( firstResultWithResultEqualityCheck ) . not . toBe (
526+ secondResultWithResultEqualityCheck
527+ )
528+
529+ expect ( firstResultWithResultEqualityCheck ) . toStrictEqual (
530+ secondResultWithResultEqualityCheck
531+ )
532+
533+ expect ( selectTodoIdsWithResultEqualityCheck . resultsCount ( ) ) . toBe ( 2 )
534+
535+ const selectTodoIds = lruMemoize ( ( state : RootState ) =>
536+ state . todos . map ( ( { id } ) => id )
537+ )
538+
539+ const firstResult = selectTodoIds ( store . getState ( ) )
540+
541+ store . dispatch ( toggleCompleted ( 0 ) )
542+
543+ const secondResult = selectTodoIds ( store . getState ( ) )
544+
545+ expect ( firstResult ) . not . toBe ( secondResult )
546+
547+ expect ( firstResult ) . toStrictEqual ( secondResult )
548+
549+ expect ( selectTodoIds . resultsCount ( ) ) . toBe ( 2 )
550+
551+ resultEqualityCheck . mockClear ( )
552+ }
553+ )
554+ } )
0 commit comments