Skip to content

Commit a250738

Browse files
committed
refactor: transform describe: HMR handling
1 parent 545f6f9 commit a250738

File tree

1 file changed

+148
-92
lines changed

1 file changed

+148
-92
lines changed

test/components/connect.spec.tsx

Lines changed: 148 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
/*eslint-disable react/prop-types*/
22

3-
import React, { Component, MouseEvent, useEffect } from 'react'
3+
import React, {
4+
Component,
5+
MouseEvent,
6+
useEffect,
7+
ComponentClass,
8+
ComponentType,
9+
} from 'react'
410
// import createClass from 'create-react-class'
511
import PropTypes from 'prop-types'
612
import ReactDOM from 'react-dom'
@@ -75,18 +81,22 @@ describe('React', () => {
7581
return action.type === 'APPEND' ? prev + action.body : prev
7682
}
7783

78-
// function imitateHotReloading(TargetClass, SourceClass, container) {
79-
// // Crude imitation of hot reloading that does the job
80-
// Object.getOwnPropertyNames(SourceClass.prototype)
81-
// .filter((key) => typeof SourceClass.prototype[key] === 'function')
82-
// .forEach((key) => {
83-
// if (key !== 'render' && key !== 'constructor') {
84-
// TargetClass.prototype[key] = SourceClass.prototype[key]
85-
// }
86-
// })
84+
function imitateHotReloading(
85+
TargetClass: ComponentType,
86+
SourceClass: ComponentType,
87+
container: Component
88+
) {
89+
// Crude imitation of hot reloading that does the job
90+
Object.getOwnPropertyNames(SourceClass.prototype)
91+
.filter((key) => typeof SourceClass.prototype[key] === 'function')
92+
.forEach((key) => {
93+
if (key !== 'render' && key !== 'constructor') {
94+
TargetClass.prototype[key] = SourceClass.prototype[key]
95+
}
96+
})
8797

88-
// container.forceUpdate()
89-
// }
98+
container.forceUpdate()
99+
}
90100

91101
afterEach(() => rtl.cleanup())
92102

@@ -1751,94 +1761,140 @@ describe('React', () => {
17511761
})
17521762
})
17531763

1754-
// describe('HMR handling', () => {
1755-
// it.skip('should recalculate the state and rebind the actions on hot update', () => {
1756-
// const store = createStore(() => {})
1757-
// @connect(null, () => ({ scooby: 'doo' }))
1758-
// class ContainerBefore extends Component {
1759-
// render() {
1760-
// return <Passthrough {...this.props} />
1761-
// }
1762-
// }
1763-
// @connect(() => ({ foo: 'baz' }), () => ({ scooby: 'foo' }))
1764-
// class ContainerAfter extends Component {
1765-
// render() {
1766-
// return <Passthrough {...this.props} />
1767-
// }
1768-
// }
1769-
// @connect(() => ({ foo: 'bar' }), () => ({ scooby: 'boo' }))
1770-
// class ContainerNext extends Component {
1771-
// render() {
1772-
// return <Passthrough {...this.props} />
1773-
// }
1774-
// }
1775-
// let container
1776-
// const tester = rtl.render(
1777-
// <ProviderMock store={store}>
1778-
// <ContainerBefore ref={(instance) => (container = instance)} />
1779-
// </ProviderMock>
1780-
// )
1781-
// expect(tester.queryByTestId('foo')).toBe(null)
1782-
// expect(tester.getByTestId('scooby')).toHaveTextContent('doo')
1783-
// imitateHotReloading(ContainerBefore, ContainerAfter, container)
1784-
// expect(tester.getByTestId('foo')).toHaveTextContent('baz')
1785-
// expect(tester.getByTestId('scooby')).toHaveTextContent('foo')
1786-
// imitateHotReloading(ContainerBefore, ContainerNext, container)
1787-
// expect(tester.getByTestId('foo')).toHaveTextContent('bar')
1788-
// expect(tester.getByTestId('scooby')).toHaveTextContent('boo')
1789-
// })
1764+
describe('HMR handling', () => {
1765+
it.skip('should recalculate the state and rebind the actions on hot update', () => {
1766+
const store = createStore(() => {})
1767+
class ContainerBefore extends Component {
1768+
render() {
1769+
return <Passthrough {...this.props} />
1770+
}
1771+
}
1772+
const ConnectedContainerBefore = connect(null, () => ({
1773+
scooby: 'doo',
1774+
}))(ContainerBefore)
1775+
class ContainerAfter extends Component {
1776+
render() {
1777+
return <Passthrough {...this.props} />
1778+
}
1779+
}
1780+
const ConnectedContainerAfter = connect(
1781+
() => ({ foo: 'baz' }),
1782+
() => ({ scooby: 'foo' })
1783+
)(ContainerAfter)
1784+
class ContainerNext extends Component {
1785+
render() {
1786+
return <Passthrough {...this.props} />
1787+
}
1788+
}
1789+
const ConnectedContainerNext = connect(
1790+
() => ({ foo: 'bar' }),
1791+
() => ({ scooby: 'boo' })
1792+
)(ContainerNext)
17901793

1791-
// it.skip('should persist listeners through hot update', () => {
1792-
// const ACTION_TYPE = 'ACTION'
1793-
// const store = createStore((state = { actions: 0 }, action) => {
1794-
// switch (action.type) {
1795-
// case ACTION_TYPE: {
1796-
// return {
1797-
// actions: state.actions + 1,
1798-
// }
1799-
// }
1800-
// default:
1801-
// return state
1802-
// }
1803-
// })
1794+
let container = React.createRef<ContainerBefore>()
1795+
const tester = rtl.render(
1796+
<ProviderMock store={store}>
1797+
<ConnectedContainerBefore ref={container} />
1798+
</ProviderMock>
1799+
)
1800+
expect(tester.queryByTestId('foo')).toBe(null)
1801+
expect(tester.getByTestId('scooby')).toHaveTextContent('doo')
1802+
imitateHotReloading(
1803+
ConnectedContainerBefore,
1804+
ConnectedContainerAfter,
1805+
container.current!
1806+
)
1807+
expect(tester.getByTestId('foo')).toHaveTextContent('baz')
1808+
expect(tester.getByTestId('scooby')).toHaveTextContent('foo')
1809+
imitateHotReloading(
1810+
ConnectedContainerBefore,
1811+
ConnectedContainerNext,
1812+
container.current!
1813+
)
1814+
expect(tester.getByTestId('foo')).toHaveTextContent('bar')
1815+
expect(tester.getByTestId('scooby')).toHaveTextContent('boo')
1816+
})
18041817

1805-
// @connect((state) => ({ actions: state.actions }))
1806-
// class Child extends Component {
1807-
// render() {
1808-
// return <Passthrough {...this.props} />
1809-
// }
1810-
// }
1818+
it.skip('should persist listeners through hot update', () => {
1819+
const ACTION_TYPE = 'ACTION'
1820+
interface RootStateType {
1821+
actions: number
1822+
}
1823+
interface ActionType {
1824+
type: string
1825+
}
1826+
const store = createStore(
1827+
(state: RootStateType = { actions: 0 }, action: ActionType) => {
1828+
switch (action.type) {
1829+
case ACTION_TYPE: {
1830+
return {
1831+
actions: state.actions + 1,
1832+
}
1833+
}
1834+
default:
1835+
return state
1836+
}
1837+
}
1838+
)
18111839

1812-
// @connect(() => ({ scooby: 'doo' }))
1813-
// class ParentBefore extends Component {
1814-
// render() {
1815-
// return <Child />
1816-
// }
1817-
// }
1840+
class Child extends Component {
1841+
render() {
1842+
return <Passthrough {...this.props} />
1843+
}
1844+
}
1845+
interface ChildrenTStateProps {
1846+
actions: number
1847+
}
1848+
type ChildrenNoDispatch = {}
1849+
type ChildrenTOwnProps = {}
1850+
type ChildrenRootState = RootStateType
1851+
const ConnectedChild = connect<
1852+
ChildrenTStateProps,
1853+
ChildrenNoDispatch,
1854+
ChildrenTOwnProps,
1855+
ChildrenRootState
1856+
>((state) => ({
1857+
actions: state.actions,
1858+
}))(Child)
18181859

1819-
// @connect(() => ({ scooby: 'boo' }))
1820-
// class ParentAfter extends Component {
1821-
// render() {
1822-
// return <Child />
1823-
// }
1824-
// }
1860+
class ParentBefore extends Component {
1861+
render() {
1862+
return <ConnectedChild />
1863+
}
1864+
}
1865+
const ConnectedParentBefore = connect(() => ({ scooby: 'doo' }))(
1866+
ParentBefore
1867+
)
18251868

1826-
// let container
1827-
// const tester = rtl.render(
1828-
// <ProviderMock store={store}>
1829-
// <ParentBefore ref={(instance) => (container = instance)} />
1830-
// </ProviderMock>
1831-
// )
1869+
class ParentAfter extends Component {
1870+
render() {
1871+
return <Child />
1872+
}
1873+
}
1874+
const ConnectedParentAfter = connect(() => ({ scooby: 'boo' }))(
1875+
ParentAfter
1876+
)
18321877

1833-
// imitateHotReloading(ParentBefore, ParentAfter, container)
1878+
let container = React.createRef<ParentBefore>()
1879+
const tester = rtl.render(
1880+
<ProviderMock store={store}>
1881+
<ConnectedParentBefore ref={container} />
1882+
</ProviderMock>
1883+
)
18341884

1835-
// rtl.act(() => {
1836-
// store.dispatch({ type: ACTION_TYPE })
1837-
// })
1885+
imitateHotReloading(
1886+
ConnectedParentBefore,
1887+
ConnectedParentAfter,
1888+
container.current!
1889+
)
18381890

1839-
// expect(tester.getByTestId('actions')).toHaveTextContent('1')
1840-
// })
1841-
// })
1891+
rtl.act(() => {
1892+
store.dispatch({ type: ACTION_TYPE })
1893+
})
1894+
1895+
expect(tester.getByTestId('actions')).toHaveTextContent('1')
1896+
})
1897+
})
18421898

18431899
// describe('Wrapped component and HOC handling', () => {
18441900
// it('should throw an error if a component is not passed to the function returned by connect', () => {

0 commit comments

Comments
 (0)