@@ -28,13 +28,19 @@ import type { FunctionComponent, DispatchWithoutAction, ReactNode } from 'react'
28
28
import type { Store , AnyAction } from 'redux'
29
29
import { UseSelectorOptions } from '../../src/hooks/useSelector'
30
30
31
- // most of these tests depend on selectors being run once, which stabilityCheck doesn't do
32
- // rather than specify it every time, let's make a new "default" here
31
+ // disable checks by default
33
32
function ProviderMock < A extends Action < any > = AnyAction , S = unknown > ( {
34
33
stabilityCheck = 'never' ,
34
+ noopCheck = 'never' ,
35
35
...props
36
36
} : ProviderProps < A , S > ) {
37
- return < Provider { ...props } stabilityCheck = { stabilityCheck } />
37
+ return (
38
+ < Provider
39
+ { ...props }
40
+ stabilityCheck = { stabilityCheck }
41
+ noopCheck = { noopCheck }
42
+ />
43
+ )
38
44
}
39
45
40
46
const IS_REACT_18 = React . version . startsWith ( '18' )
@@ -739,36 +745,38 @@ describe('React', () => {
739
745
} )
740
746
741
747
describe ( 'Development mode checks' , ( ) => {
748
+ const consoleSpy = jest
749
+ . spyOn ( console , 'warn' )
750
+ . mockImplementation ( ( ) => { } )
751
+ afterEach ( ( ) => {
752
+ consoleSpy . mockClear ( )
753
+ } )
754
+ afterAll ( ( ) => {
755
+ consoleSpy . mockRestore ( )
756
+ } )
757
+
758
+ const RenderSelector = ( {
759
+ selector,
760
+ options,
761
+ } : {
762
+ selector : ( state : NormalStateType ) => unknown
763
+ options ?: UseSelectorOptions < unknown >
764
+ } ) => {
765
+ useSelector ( selector , options )
766
+ return null
767
+ }
742
768
describe ( 'selector result stability check' , ( ) => {
743
769
const selector = jest . fn ( ( state : NormalStateType ) => state . count )
744
770
745
- const consoleSpy = jest
746
- . spyOn ( console , 'warn' )
747
- . mockImplementation ( ( ) => { } )
748
771
afterEach ( ( ) => {
749
- consoleSpy . mockClear ( )
750
772
selector . mockClear ( )
751
773
} )
752
- afterAll ( ( ) => {
753
- consoleSpy . mockRestore ( )
754
- } )
755
-
756
- const RenderSelector = ( {
757
- selector,
758
- options,
759
- } : {
760
- selector : ( state : NormalStateType ) => unknown
761
- options ?: UseSelectorOptions < unknown >
762
- } ) => {
763
- useSelector ( selector , options )
764
- return null
765
- }
766
774
767
775
it ( 'calls a selector twice, and warns in console if it returns a different result' , ( ) => {
768
776
rtl . render (
769
- < Provider store = { normalStore } >
777
+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
770
778
< RenderSelector selector = { selector } />
771
- </ Provider >
779
+ </ ProviderMock >
772
780
)
773
781
774
782
expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -780,9 +788,9 @@ describe('React', () => {
780
788
const unstableSelector = jest . fn ( ( ) => Math . random ( ) )
781
789
782
790
rtl . render (
783
- < Provider store = { normalStore } >
791
+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
784
792
< RenderSelector selector = { unstableSelector } />
785
- </ Provider >
793
+ </ ProviderMock >
786
794
)
787
795
788
796
expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -806,22 +814,22 @@ describe('React', () => {
806
814
} ) )
807
815
808
816
rtl . render (
809
- < Provider store = { normalStore } >
817
+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
810
818
< RenderSelector
811
819
selector = { unstableSelector }
812
820
options = { { equalityFn : shallowEqual } }
813
821
/>
814
- </ Provider >
822
+ </ ProviderMock >
815
823
)
816
824
817
825
expect ( unstableSelector ) . toHaveBeenCalledTimes ( 2 )
818
826
expect ( consoleSpy ) . not . toHaveBeenCalled ( )
819
827
} )
820
828
it ( 'by default will only check on first selector call' , ( ) => {
821
829
rtl . render (
822
- < Provider store = { normalStore } >
830
+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
823
831
< RenderSelector selector = { selector } />
824
- </ Provider >
832
+ </ ProviderMock >
825
833
)
826
834
827
835
expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -834,9 +842,9 @@ describe('React', () => {
834
842
} )
835
843
it ( 'disables check if context or hook specifies' , ( ) => {
836
844
rtl . render (
837
- < Provider store = { normalStore } stabilityCheck = "never" >
845
+ < ProviderMock store = { normalStore } stabilityCheck = "never" >
838
846
< RenderSelector selector = { selector } />
839
- </ Provider >
847
+ </ ProviderMock >
840
848
)
841
849
842
850
expect ( selector ) . toHaveBeenCalledTimes ( 1 )
@@ -846,21 +854,21 @@ describe('React', () => {
846
854
selector . mockClear ( )
847
855
848
856
rtl . render (
849
- < Provider store = { normalStore } >
857
+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
850
858
< RenderSelector
851
859
selector = { selector }
852
860
options = { { stabilityCheck : 'never' } }
853
861
/>
854
- </ Provider >
862
+ </ ProviderMock >
855
863
)
856
864
857
865
expect ( selector ) . toHaveBeenCalledTimes ( 1 )
858
866
} )
859
867
it ( 'always runs check if context or hook specifies' , ( ) => {
860
868
rtl . render (
861
- < Provider store = { normalStore } stabilityCheck = "always" >
869
+ < ProviderMock store = { normalStore } stabilityCheck = "always" >
862
870
< RenderSelector selector = { selector } />
863
- </ Provider >
871
+ </ ProviderMock >
864
872
)
865
873
866
874
expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -876,12 +884,12 @@ describe('React', () => {
876
884
selector . mockClear ( )
877
885
878
886
rtl . render (
879
- < Provider store = { normalStore } >
887
+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
880
888
< RenderSelector
881
889
selector = { selector }
882
890
options = { { stabilityCheck : 'always' } }
883
891
/>
884
- </ Provider >
892
+ </ ProviderMock >
885
893
)
886
894
887
895
expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -893,6 +901,29 @@ describe('React', () => {
893
901
expect ( selector ) . toHaveBeenCalledTimes ( 4 )
894
902
} )
895
903
} )
904
+ describe ( 'no-op selector check' , ( ) => {
905
+ it ( 'warns for selectors that return the entire root state' , ( ) => {
906
+ rtl . render (
907
+ < ProviderMock noopCheck = "once" store = { normalStore } >
908
+ < RenderSelector selector = { ( state ) => state . count } />
909
+ </ ProviderMock >
910
+ )
911
+
912
+ expect ( consoleSpy ) . not . toHaveBeenCalled ( )
913
+
914
+ rtl . cleanup ( )
915
+
916
+ rtl . render (
917
+ < ProviderMock noopCheck = "once" store = { normalStore } >
918
+ < RenderSelector selector = { ( state ) => state } />
919
+ </ ProviderMock >
920
+ )
921
+
922
+ expect ( consoleSpy ) . toHaveBeenCalledWith (
923
+ expect . stringContaining ( 'returned the root state when called.' )
924
+ )
925
+ } )
926
+ } )
896
927
} )
897
928
} )
898
929
0 commit comments