Add test for pack.ts
This commit is contained in:
parent
a6a8fd833d
commit
ee6a6741ed
@ -17,8 +17,6 @@ import {ComponentType} from 'react'
|
||||
* the Actions class might depend on the HTTPClient class, and then it becomes
|
||||
* easy to mock it during tests, or swap out different dependencies for
|
||||
* different applications.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export abstract class Connector<LocalState> {
|
||||
|
||||
|
||||
136
packages/client/src/redux/pack.test.tsx
Normal file
136
packages/client/src/redux/pack.test.tsx
Normal file
@ -0,0 +1,136 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Provider } from 'react-redux'
|
||||
import { createStore, Dispatch } from 'redux'
|
||||
import { pack } from './pack'
|
||||
import { TStateSelector } from './TStateSelector'
|
||||
import TestUtils from 'react-dom/test-utils'
|
||||
|
||||
describe('pack', () => {
|
||||
|
||||
interface IProps {
|
||||
a: number
|
||||
b: string
|
||||
update(a: number, b: string): {
|
||||
payload: {a: number, b: string},
|
||||
type: 'CHANGE',
|
||||
}
|
||||
c: string[]
|
||||
}
|
||||
|
||||
class PureComponent extends React.PureComponent<IProps> {
|
||||
update = () => {
|
||||
this.props.update(1, 'one')
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<button onClick={this.update}>
|
||||
{this.props.a + this.props.b}
|
||||
</button>
|
||||
)
|
||||
|
||||
return this.props.a + this.props.b
|
||||
}
|
||||
}
|
||||
|
||||
function FunctionalComponent(props: IProps) {
|
||||
return (
|
||||
<button onClick={() => props.update(1, 'one')}>
|
||||
{props.a + props.b}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
type LocalState = Omit<IProps, 'c' | 'update'>
|
||||
interface IState {
|
||||
localState: LocalState
|
||||
}
|
||||
|
||||
function reduce(
|
||||
state: IState = {localState: {a: 0, b: ''}},
|
||||
action: any,
|
||||
): IState {
|
||||
switch (action.type) {
|
||||
case 'CHANGE':
|
||||
return {
|
||||
...state,
|
||||
localState: {
|
||||
...action.payload,
|
||||
},
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
function configurePureComponent<State>(
|
||||
getLocalState: TStateSelector<State, LocalState>,
|
||||
) {
|
||||
return pack(
|
||||
getLocalState,
|
||||
(localState: LocalState) => localState,
|
||||
{
|
||||
update(a: number, b: string) {
|
||||
return {
|
||||
payload: {a, b},
|
||||
type: 'CHANGE',
|
||||
}
|
||||
},
|
||||
},
|
||||
PureComponent,
|
||||
)
|
||||
}
|
||||
|
||||
function configureFunctionalComponent<State>(
|
||||
getLocalState: TStateSelector<State, LocalState>,
|
||||
) {
|
||||
return pack(
|
||||
getLocalState,
|
||||
(localState: LocalState) => localState,
|
||||
{
|
||||
update(a: number, b: string) {
|
||||
return {
|
||||
payload: {a, b},
|
||||
type: 'CHANGE',
|
||||
}
|
||||
},
|
||||
},
|
||||
FunctionalComponent,
|
||||
)
|
||||
}
|
||||
|
||||
const PackedPureComponent = configurePureComponent<IState>(
|
||||
state => state.localState)
|
||||
|
||||
const PackedFunctionalComponent = configureFunctionalComponent<IState>(
|
||||
state => state.localState)
|
||||
|
||||
it('creates a connected component', () => {
|
||||
const store = createStore(reduce)
|
||||
const element = document.createElement('div')!
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<PackedPureComponent c={['test']} />
|
||||
</Provider>,
|
||||
element,
|
||||
)
|
||||
expect(element.textContent).toBe('0')
|
||||
TestUtils.Simulate.click(element.querySelector('button')!)
|
||||
expect(element.textContent).toBe('1one')
|
||||
})
|
||||
|
||||
it('should work with functional components', () => {
|
||||
const store = createStore(reduce)
|
||||
const element = document.createElement('div')!
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<PackedFunctionalComponent c={['test']} />
|
||||
</Provider>,
|
||||
element,
|
||||
)
|
||||
expect(element.textContent).toBe('0')
|
||||
TestUtils.Simulate.click(element.querySelector('button')!)
|
||||
expect(element.textContent).toBe('1one')
|
||||
})
|
||||
|
||||
})
|
||||
@ -1,5 +1,5 @@
|
||||
import { ComponentType, PureComponent } from 'react'
|
||||
import { connect, Omit, MapDispatchToPropsParam } from 'react-redux'
|
||||
import { connect, Omit, MapDispatchToPropsParam, Matching, GetProps, ResolveThunks } from 'react-redux'
|
||||
import { Dispatch } from 'redux'
|
||||
import { TStateSelector } from './TStateSelector'
|
||||
|
||||
@ -29,22 +29,21 @@ export function pack<
|
||||
LocalState,
|
||||
State,
|
||||
Props,
|
||||
StateProps extends Partial<Props>,
|
||||
DispatchProps extends Partial<Props>,
|
||||
StateProps,
|
||||
DispatchProps,
|
||||
C extends React.ComponentType<
|
||||
Matching<StateProps & ResolveThunks<DispatchProps>, GetProps<C>>>
|
||||
>(
|
||||
getLocalState: TStateSelector<State, LocalState>,
|
||||
mapStateToProps: (state: LocalState) => StateProps,
|
||||
mapDispatchToProps: MapDispatchToPropsParam<DispatchProps, Props>,
|
||||
Component: React.ComponentType<Props>,
|
||||
): ComponentType<
|
||||
Omit<Props, keyof Props & (keyof StateProps | keyof DispatchProps)>
|
||||
> {
|
||||
|
||||
Component: C,
|
||||
) {
|
||||
return connect(
|
||||
(state: State) => {
|
||||
const l = getLocalState(state)
|
||||
return mapStateToProps(l)
|
||||
},
|
||||
mapDispatchToProps,
|
||||
)(Component as any) as any
|
||||
)(Component)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user