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
|
* 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
|
* easy to mock it during tests, or swap out different dependencies for
|
||||||
* different applications.
|
* different applications.
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
export abstract class Connector<LocalState> {
|
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 { 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 { Dispatch } from 'redux'
|
||||||
import { TStateSelector } from './TStateSelector'
|
import { TStateSelector } from './TStateSelector'
|
||||||
|
|
||||||
@ -29,22 +29,21 @@ export function pack<
|
|||||||
LocalState,
|
LocalState,
|
||||||
State,
|
State,
|
||||||
Props,
|
Props,
|
||||||
StateProps extends Partial<Props>,
|
StateProps,
|
||||||
DispatchProps extends Partial<Props>,
|
DispatchProps,
|
||||||
|
C extends React.ComponentType<
|
||||||
|
Matching<StateProps & ResolveThunks<DispatchProps>, GetProps<C>>>
|
||||||
>(
|
>(
|
||||||
getLocalState: TStateSelector<State, LocalState>,
|
getLocalState: TStateSelector<State, LocalState>,
|
||||||
mapStateToProps: (state: LocalState) => StateProps,
|
mapStateToProps: (state: LocalState) => StateProps,
|
||||||
mapDispatchToProps: MapDispatchToPropsParam<DispatchProps, Props>,
|
mapDispatchToProps: MapDispatchToPropsParam<DispatchProps, Props>,
|
||||||
Component: React.ComponentType<Props>,
|
Component: C,
|
||||||
): ComponentType<
|
) {
|
||||||
Omit<Props, keyof Props & (keyof StateProps | keyof DispatchProps)>
|
|
||||||
> {
|
|
||||||
|
|
||||||
return connect(
|
return connect(
|
||||||
(state: State) => {
|
(state: State) => {
|
||||||
const l = getLocalState(state)
|
const l = getLocalState(state)
|
||||||
return mapStateToProps(l)
|
return mapStateToProps(l)
|
||||||
},
|
},
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
)(Component as any) as any
|
)(Component)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user