@@ -28,13 +28,19 @@ import type { FunctionComponent, DispatchWithoutAction, ReactNode } from 'react'
2828import type { Store , AnyAction } from 'redux'
2929import { UseSelectorOptions } from '../../src/hooks/useSelector'
3030
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
3332function ProviderMock < A extends Action < any > = AnyAction , S = unknown > ( {
3433 stabilityCheck = 'never' ,
34+ noopCheck = 'never' ,
3535 ...props
3636} : ProviderProps < A , S > ) {
37- return < Provider { ...props } stabilityCheck = { stabilityCheck } />
37+ return (
38+ < Provider
39+ { ...props }
40+ stabilityCheck = { stabilityCheck }
41+ noopCheck = { noopCheck }
42+ />
43+ )
3844}
3945
4046const IS_REACT_18 = React . version . startsWith ( '18' )
@@ -739,36 +745,38 @@ describe('React', () => {
739745 } )
740746
741747 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+ }
742768 describe ( 'selector result stability check' , ( ) => {
743769 const selector = jest . fn ( ( state : NormalStateType ) => state . count )
744770
745- const consoleSpy = jest
746- . spyOn ( console , 'warn' )
747- . mockImplementation ( ( ) => { } )
748771 afterEach ( ( ) => {
749- consoleSpy . mockClear ( )
750772 selector . mockClear ( )
751773 } )
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- }
766774
767775 it ( 'calls a selector twice, and warns in console if it returns a different result' , ( ) => {
768776 rtl . render (
769- < Provider store = { normalStore } >
777+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
770778 < RenderSelector selector = { selector } />
771- </ Provider >
779+ </ ProviderMock >
772780 )
773781
774782 expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -780,9 +788,9 @@ describe('React', () => {
780788 const unstableSelector = jest . fn ( ( ) => Math . random ( ) )
781789
782790 rtl . render (
783- < Provider store = { normalStore } >
791+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
784792 < RenderSelector selector = { unstableSelector } />
785- </ Provider >
793+ </ ProviderMock >
786794 )
787795
788796 expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -806,22 +814,22 @@ describe('React', () => {
806814 } ) )
807815
808816 rtl . render (
809- < Provider store = { normalStore } >
817+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
810818 < RenderSelector
811819 selector = { unstableSelector }
812820 options = { { equalityFn : shallowEqual } }
813821 />
814- </ Provider >
822+ </ ProviderMock >
815823 )
816824
817825 expect ( unstableSelector ) . toHaveBeenCalledTimes ( 2 )
818826 expect ( consoleSpy ) . not . toHaveBeenCalled ( )
819827 } )
820828 it ( 'by default will only check on first selector call' , ( ) => {
821829 rtl . render (
822- < Provider store = { normalStore } >
830+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
823831 < RenderSelector selector = { selector } />
824- </ Provider >
832+ </ ProviderMock >
825833 )
826834
827835 expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -834,9 +842,9 @@ describe('React', () => {
834842 } )
835843 it ( 'disables check if context or hook specifies' , ( ) => {
836844 rtl . render (
837- < Provider store = { normalStore } stabilityCheck = "never" >
845+ < ProviderMock store = { normalStore } stabilityCheck = "never" >
838846 < RenderSelector selector = { selector } />
839- </ Provider >
847+ </ ProviderMock >
840848 )
841849
842850 expect ( selector ) . toHaveBeenCalledTimes ( 1 )
@@ -846,21 +854,21 @@ describe('React', () => {
846854 selector . mockClear ( )
847855
848856 rtl . render (
849- < Provider store = { normalStore } >
857+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
850858 < RenderSelector
851859 selector = { selector }
852860 options = { { stabilityCheck : 'never' } }
853861 />
854- </ Provider >
862+ </ ProviderMock >
855863 )
856864
857865 expect ( selector ) . toHaveBeenCalledTimes ( 1 )
858866 } )
859867 it ( 'always runs check if context or hook specifies' , ( ) => {
860868 rtl . render (
861- < Provider store = { normalStore } stabilityCheck = "always" >
869+ < ProviderMock store = { normalStore } stabilityCheck = "always" >
862870 < RenderSelector selector = { selector } />
863- </ Provider >
871+ </ ProviderMock >
864872 )
865873
866874 expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -876,12 +884,12 @@ describe('React', () => {
876884 selector . mockClear ( )
877885
878886 rtl . render (
879- < Provider store = { normalStore } >
887+ < ProviderMock stabilityCheck = "once" store = { normalStore } >
880888 < RenderSelector
881889 selector = { selector }
882890 options = { { stabilityCheck : 'always' } }
883891 />
884- </ Provider >
892+ </ ProviderMock >
885893 )
886894
887895 expect ( selector ) . toHaveBeenCalledTimes ( 2 )
@@ -893,6 +901,29 @@ describe('React', () => {
893901 expect ( selector ) . toHaveBeenCalledTimes ( 4 )
894902 } )
895903 } )
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+ } )
896927 } )
897928 } )
898929
0 commit comments