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 { update = () => { this.props.update(1, 'one') } render() { return ( ) return this.props.a + this.props.b } } function FunctionalComponent(props: IProps) { const update = useCallback(() => props.update(1, 'one'), []) return ( ) } type LocalState = Omit 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( getLocalState: TStateSelector, ) { return pack( getLocalState, (localState: LocalState) => localState, { update(a: number, b: string) { return { payload: {a, b}, type: 'CHANGE', } }, }, PureComponent, ) } function configureFunctionalComponent( getLocalState: TStateSelector, ) { return pack( getLocalState, (localState: LocalState) => localState, { update(a: number, b: string) { return { payload: {a, b}, type: 'CHANGE', } }, }, FunctionalComponent, ) } const PackedPureComponent = configurePureComponent( state => state.localState) const PackedFunctionalComponent = configureFunctionalComponent( state => state.localState) it('creates a connected component', () => { const store = createStore(reduce) const element = document.createElement('div')! ReactDOM.render( , 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( , element, ) expect(element.textContent).toBe('0') TestUtils.Simulate.click(element.querySelector('button')!) expect(element.textContent).toBe('1one') }) })