11/*eslint-disable react/prop-types*/
22
3- import React , { Component } from 'react'
3+ import React , { Component , Dispatch } from 'react'
44import ReactDOM from 'react-dom'
55import { createStore } from 'redux'
66import { Provider , connect , ReactReduxContext } from '../../src/index'
77import * as rtl from '@testing-library/react'
8+ import type { ReactReduxContextValue } from '../../src'
9+ import type { Store } from 'redux'
10+
811import '@testing-library/jest-dom/extend-expect'
912
1013const createExampleTextReducer =
@@ -21,7 +24,8 @@ describe('React', () => {
2124 render ( ) {
2225 return (
2326 < ReactReduxContext . Consumer >
24- { ( { store } ) => {
27+ { ( props ) => {
28+ let { store } = props as ReactReduxContextValue
2529 let text = ''
2630
2731 if ( store ) {
@@ -46,10 +50,6 @@ describe('React', () => {
4650 it ( 'should not enforce a single child' , ( ) => {
4751 const store = createStore ( ( ) => ( { } ) )
4852
49- // Ignore propTypes warnings
50- const propTypes = Provider . propTypes
51- Provider . propTypes = { }
52-
5353 const spy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } )
5454
5555 expect ( ( ) =>
@@ -59,7 +59,7 @@ describe('React', () => {
5959 </ Provider >
6060 )
6161 ) . not . toThrow ( )
62-
62+ // @ts -expect-error
6363 expect ( ( ) => rtl . render ( < Provider store = { store } /> ) ) . not . toThrow (
6464 / c h i l d r e n w i t h e x a c t l y o n e c h i l d /
6565 )
@@ -73,7 +73,6 @@ describe('React', () => {
7373 )
7474 ) . not . toThrow ( / a s i n g l e R e a c t e l e m e n t c h i l d / )
7575 spy . mockRestore ( )
76- Provider . propTypes = propTypes
7776 } )
7877
7978 it ( 'should add the store to context' , ( ) => {
@@ -94,14 +93,18 @@ describe('React', () => {
9493 } )
9594
9695 it ( 'accepts new store in props' , ( ) => {
97- const store1 = createStore ( ( state = 10 ) => state + 1 )
98- const store2 = createStore ( ( state = 10 ) => state * 2 )
99- const store3 = createStore ( ( state = 10 ) => state * state + 1 )
100-
101- let externalSetState
102- class ProviderContainer extends Component {
103- constructor ( ) {
104- super ( )
96+ const store1 = createStore ( ( state : number = 10 ) => state + 1 )
97+ const store2 = createStore ( ( state : number = 10 ) => state * 2 )
98+ const store3 = createStore ( ( state : number = 10 ) => state * state + 1 )
99+
100+ interface StateType {
101+ store : Store
102+ }
103+
104+ let externalSetState : Dispatch < StateType >
105+ class ProviderContainer extends Component < unknown , StateType > {
106+ constructor ( props : { } ) {
107+ super ( props )
105108 this . state = { store : store1 }
106109 externalSetState = this . setState . bind ( this )
107110 }
@@ -156,33 +159,47 @@ describe('React', () => {
156159 } )
157160
158161 it ( 'should handle subscriptions correctly when there is nested Providers' , ( ) => {
159- const reducer = ( state = 0 , action ) =>
162+ interface ActionType {
163+ type : string
164+ }
165+ interface TStateProps {
166+ count : number
167+ }
168+ const reducer = ( state = 0 , action : ActionType ) =>
160169 action . type === 'INC' ? state + 1 : state
161170
162171 const innerStore = createStore ( reducer )
163- const innerMapStateToProps = jest . fn ( ( state ) => ( { count : state } ) )
164- @connect ( innerMapStateToProps )
165- class Inner extends Component {
166- render ( ) {
172+ const innerMapStateToProps = jest . fn < TStateProps , [ number ] > ( ( state ) => ( {
173+ count : state ,
174+ } ) )
175+ class Inner extends Component < TStateProps > {
176+ render ( ) : JSX . Element {
167177 return < div > { this . props . count } </ div >
168178 }
169179 }
170180
181+ const WrapperInner = connect < TStateProps , unknown , unknown , number > (
182+ innerMapStateToProps
183+ ) ( Inner )
184+
171185 const outerStore = createStore ( reducer )
172- @connect ( ( state ) => ( { count : state } ) )
173186 class Outer extends Component {
174187 render ( ) {
175188 return (
176189 < Provider store = { innerStore } >
177- < Inner />
190+ < WrapperInner />
178191 </ Provider >
179192 )
180193 }
181194 }
182195
196+ const WrapperOuter = connect < TStateProps , unknown , unknown , number > (
197+ ( state ) => ( { count : state } )
198+ ) ( Outer )
199+
183200 rtl . render (
184201 < Provider store = { outerStore } >
185- < Outer />
202+ < WrapperOuter />
186203 </ Provider >
187204 )
188205 expect ( innerMapStateToProps ) . toHaveBeenCalledTimes ( 1 )
@@ -195,50 +212,69 @@ describe('React', () => {
195212 } )
196213
197214 it ( 'should pass state consistently to mapState' , ( ) => {
198- function stringBuilder ( prev = '' , action ) {
215+ interface ActionType {
216+ type : string
217+ body : string
218+ }
219+ function stringBuilder ( prev = '' , action : ActionType ) {
199220 return action . type === 'APPEND' ? prev + action . body : prev
200221 }
201222
202- const store = createStore ( stringBuilder )
223+ const store : Store = createStore ( stringBuilder )
203224
204225 rtl . act ( ( ) => {
205226 store . dispatch ( { type : 'APPEND' , body : 'a' } )
206227 } )
207228
208229 let childMapStateInvokes = 0
209230
210- @connect ( ( state ) => ( { state } ) )
211- class Container extends Component {
212- emitChange ( ) {
213- store . dispatch ( { type : 'APPEND' , body : 'b' } )
214- }
231+ const childCalls : Array < Array < string > > = [ ]
215232
233+ interface ChildContainerProps {
234+ parentState : string
235+ }
236+ class ChildContainer extends Component < ChildContainerProps > {
216237 render ( ) {
217- return (
218- < div >
219- < button onClick = { this . emitChange . bind ( this ) } > change</ button >
220- < ChildContainer parentState = { this . props . state } />
221- </ div >
222- )
238+ return < div />
223239 }
224240 }
225241
226- const childCalls = [ ]
227- @connect ( ( state , parentProps ) => {
242+ const WrapperChildrenContainer = connect <
243+ { } ,
244+ unknown ,
245+ ChildContainerProps ,
246+ string
247+ > ( ( state , parentProps ) => {
228248 childMapStateInvokes ++
229249 childCalls . push ( [ state , parentProps . parentState ] )
230250 // The state from parent props should always be consistent with the current state
231251 return { }
232- } )
233- class ChildContainer extends Component {
252+ } ) ( ChildContainer )
253+
254+ interface TStateProps {
255+ state : string
256+ }
257+ class Container extends Component < TStateProps > {
258+ emitChange ( ) {
259+ store . dispatch ( { type : 'APPEND' , body : 'b' } )
260+ }
261+
234262 render ( ) {
235- return < div />
263+ return (
264+ < div >
265+ < button onClick = { this . emitChange . bind ( this ) } > change</ button >
266+ < WrapperChildrenContainer parentState = { this . props . state } />
267+ </ div >
268+ )
236269 }
237270 }
271+ const WrapperContainer = connect < TStateProps , unknown , unknown , string > (
272+ ( state ) => ( { state } )
273+ ) ( Container )
238274
239275 const tester = rtl . render (
240276 < Provider store = { store } >
241- < Container />
277+ < WrapperContainer />
242278 </ Provider >
243279 )
244280
@@ -320,37 +356,52 @@ describe('React', () => {
320356 } )
321357
322358 it ( 'should handle store and children change in a the same render' , ( ) => {
359+ interface PropsType {
360+ value : string
361+ }
362+ interface StateType {
363+ nestedA : PropsType
364+ nestedB : PropsType
365+ }
323366 const reducerA = ( state = { nestedA : { value : 'expectedA' } } ) => state
324367 const reducerB = ( state = { nestedB : { value : 'expectedB' } } ) => state
325368
326369 const storeA = createStore ( reducerA )
327370 const storeB = createStore ( reducerB )
328371
329- @connect ( ( state ) => ( { value : state . nestedA . value } ) )
330- class ComponentA extends Component {
372+ class ComponentA extends Component < PropsType > {
331373 render ( ) {
332374 return < div data-testid = "value" > { this . props . value } </ div >
333375 }
334376 }
335377
336- @connect ( ( state ) => ( { value : state . nestedB . value } ) )
337- class ComponentB extends Component {
378+ const WrapperComponentA = connect < PropsType , unknown , unknown , StateType > (
379+ ( state ) => ( {
380+ value : state . nestedA . value ,
381+ } )
382+ ) ( ComponentA )
383+
384+ class ComponentB extends Component < PropsType > {
338385 render ( ) {
339386 return < div data-testid = "value" > { this . props . value } </ div >
340387 }
341388 }
342389
390+ const WrapperComponentB = connect < PropsType , unknown , unknown , StateType > (
391+ ( state ) => ( { value : state . nestedB . value } )
392+ ) ( ComponentB )
393+
343394 const { getByTestId, rerender } = rtl . render (
344395 < Provider store = { storeA } >
345- < ComponentA />
396+ < WrapperComponentA />
346397 </ Provider >
347398 )
348399
349400 expect ( getByTestId ( 'value' ) ) . toHaveTextContent ( 'expectedA' )
350401
351402 rerender (
352403 < Provider store = { storeB } >
353- < ComponentB />
404+ < WrapperComponentB />
354405 </ Provider >
355406 )
356407
0 commit comments