Skip to content

Commit 43c75e2

Browse files
EskiMojo14markerikson
authored andcommitted
add test
1 parent a5e9a43 commit 43c75e2

File tree

2 files changed

+68
-39
lines changed

2 files changed

+68
-39
lines changed

src/hooks/useSelector.ts

-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ export function createSelectorHook(context = ReactReduxContext): UseSelector {
9090
const selected = selector(state)
9191
if (process.env.NODE_ENV !== 'production') {
9292
const finalStabilityCheck =
93-
// are we safe to use ?? here?
9493
typeof stabilityCheck === 'undefined'
9594
? globalStabilityCheck
9695
: stabilityCheck
@@ -114,7 +113,6 @@ export function createSelectorHook(context = ReactReduxContext): UseSelector {
114113
}
115114
}
116115
const finalNoopCheck =
117-
// are we safe to use ?? here?
118116
typeof noopCheck === 'undefined' ? globalNoopCheck : noopCheck
119117
if (
120118
finalNoopCheck === 'always' ||

test/hooks/useSelector.spec.tsx

+68-37
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,19 @@ import type { FunctionComponent, DispatchWithoutAction, ReactNode } from 'react'
2828
import type { Store, AnyAction } from 'redux'
2929
import { 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
3332
function 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

4046
const 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

Comments
 (0)