2019-09-07 07:54:53 +07:00

139 lines
3.2 KiB
TypeScript

import React, { useCallback } from 'react'
import ReactDOM from 'react-dom'
import TestUtils from 'react-dom/test-utils'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import { pack } from './pack'
import { TStateSelector } from './TStateSelector'
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) {
const update = useCallback(() => props.update(1, 'one'), [])
return (
<button onClick={update}>
{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')
})
})