Skip to content

Commit

Permalink
feat(testHook): modify testHook to return unmount function (#290)
Browse files Browse the repository at this point in the history
* Returns unmount function on testHook

* Adds test for unmount function; Adds example of useEffect

* Add Andrewmat as contributor

* Adds rerender on testHook return
  • Loading branch information
Andrewmat authored and Kent C. Dodds committed Feb 11, 2019
1 parent ac58967 commit 9c606da
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 43 deletions.
11 changes: 11 additions & 0 deletions .all-contributorsrc
Expand Up @@ -657,6 +657,17 @@
"bug",
"code"
]
},
{
"login": "Andrewmat",
"name": "Andr茅 Matulionis dos Santos",
"avatar_url": "https://avatars0.githubusercontent.com/u/5133846?v=4",
"profile": "https://twitter.com/Andrewmat",
"contributions": [
"code",
"example",
"test"
]
}
]
}
3 changes: 2 additions & 1 deletion .github/ISSUE_TEMPLATE.md
Expand Up @@ -59,7 +59,8 @@ What happened:

<!-- Please provide the full error message/screenshots/anything -->

Reproduction repository: https://github.com/alexkrolick/dom-testing-library-template
Reproduction repository:
https://github.com/alexkrolick/dom-testing-library-template

<!--
If possible, please create a repository that reproduces the issue with the
Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -26,7 +26,7 @@ practices.</p>
[![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends]
[![MIT License][license-badge]][license]

[![All Contributors](https://img.shields.io/badge/all_contributors-67-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-68-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc]
[![Join the community on Spectrum][spectrum-badge]][spectrum]

Expand Down Expand Up @@ -216,7 +216,7 @@ Thanks goes to these people ([emoji key][emojis]):
| [<img src="https://avatars3.githubusercontent.com/u/881986?v=4" width="100px;" alt="dadamssg"/><br /><sub><b>dadamssg</b></sub>](https://github.com/dadamssg)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=dadamssg "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/8734097?v=4" width="100px;" alt="Yazan Aabed"/><br /><sub><b>Yazan Aabed</b></sub>](https://www.yaabed.com/)<br />[馃摑](#blog-YazanAabeed "Blogposts") | [<img src="https://avatars0.githubusercontent.com/u/556258?v=4" width="100px;" alt="Tim"/><br /><sub><b>Tim</b></sub>](https://github.com/timbonicus)<br />[馃悰](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Atimbonicus "Bug reports") [馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Code") [馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Documentation") [鈿狅笍](https://github.com/kentcdodds/react-testing-library/commits?author=timbonicus "Tests") | [<img src="https://avatars3.githubusercontent.com/u/6682655?v=4" width="100px;" alt="Divyanshu Maithani"/><br /><sub><b>Divyanshu Maithani</b></sub>](http://divyanshu.xyz)<br />[鉁匽(#tutorial-divyanshu013 "Tutorials") [馃摴](#video-divyanshu013 "Videos") | [<img src="https://avatars2.githubusercontent.com/u/9116042?v=4" width="100px;" alt="Deepak Grover"/><br /><sub><b>Deepak Grover</b></sub>](https://www.linkedin.com/in/metagrover)<br />[鉁匽(#tutorial-metagrover "Tutorials") [馃摴](#video-metagrover "Videos") | [<img src="https://avatars0.githubusercontent.com/u/16276358?v=4" width="100px;" alt="Eyal Cohen"/><br /><sub><b>Eyal Cohen</b></sub>](https://github.com/eyalcohen4)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=eyalcohen4 "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/7452681?v=4" width="100px;" alt="Peter Makowski"/><br /><sub><b>Peter Makowski</b></sub>](https://github.com/petermakowski)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=petermakowski "Documentation") |
| [<img src="https://avatars2.githubusercontent.com/u/20361668?v=4" width="100px;" alt="Michiel Nuyts"/><br /><sub><b>Michiel Nuyts</b></sub>](https://github.com/Michielnuyts)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=Michielnuyts "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1195863?v=4" width="100px;" alt="Joe Ng'ethe"/><br /><sub><b>Joe Ng'ethe</b></sub>](https://github.com/joeynimu)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Code") [馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=joeynimu "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/19998290?v=4" width="100px;" alt="Kate"/><br /><sub><b>Kate</b></sub>](https://github.com/Enikol)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=Enikol "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/11980217?v=4" width="100px;" alt="Sean"/><br /><sub><b>Sean</b></sub>](http://www.seanrparker.com)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=SeanRParker "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/17031?v=4" width="100px;" alt="James Long"/><br /><sub><b>James Long</b></sub>](http://jlongster.com)<br />[馃](#ideas-jlongster "Ideas, Planning, & Feedback") [馃摝](#platform-jlongster "Packaging/porting to new platform") | [<img src="https://avatars1.githubusercontent.com/u/10118777?v=4" width="100px;" alt="Herb Hagely"/><br /><sub><b>Herb Hagely</b></sub>](https://github.com/hhagely)<br />[馃挕](#example-hhagely "Examples") | [<img src="https://avatars2.githubusercontent.com/u/5779538?v=4" width="100px;" alt="Alex Wendte"/><br /><sub><b>Alex Wendte</b></sub>](http://www.wendtedesigns.com/)<br />[馃挕](#example-themostcolm "Examples") |
| [<img src="https://avatars0.githubusercontent.com/u/6998954?v=4" width="100px;" alt="Monica Powell"/><br /><sub><b>Monica Powell</b></sub>](http://www.aboutmonica.com)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=M0nica "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/2699953?v=4" width="100px;" alt="Vitaly Sivkov"/><br /><sub><b>Vitaly Sivkov</b></sub>](http://sivkoff.com)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=sivkoff "Code") | [<img src="https://avatars3.githubusercontent.com/u/7049?v=4" width="100px;" alt="Weyert de Boer"/><br /><sub><b>Weyert de Boer</b></sub>](https://github.com/weyert)<br />[馃](#ideas-weyert "Ideas, Planning, & Feedback") [馃憖](#review-weyert "Reviewed Pull Requests") | [<img src="https://avatars3.githubusercontent.com/u/13613037?v=4" width="100px;" alt="EstebanMarin"/><br /><sub><b>EstebanMarin</b></sub>](https://github.com/EstebanMarin)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=EstebanMarin "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/13953703?v=4" width="100px;" alt="Victor Martins"/><br /><sub><b>Victor Martins</b></sub>](https://github.com/vctormb)<br />[馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=vctormb "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/19773?v=4" width="100px;" alt="Royston Shufflebotham"/><br /><sub><b>Royston Shufflebotham</b></sub>](https://github.com/RoystonS)<br />[馃悰](https://github.com/kentcdodds/react-testing-library/issues?q=author%3ARoystonS "Bug reports") [馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=RoystonS "Documentation") [馃挕](#example-RoystonS "Examples") | [<img src="https://avatars0.githubusercontent.com/u/6834804?v=4" width="100px;" alt="chrbala"/><br /><sub><b>chrbala</b></sub>](https://github.com/chrbala)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=chrbala "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/887639?v=4" width="100px;" alt="Donavon West"/><br /><sub><b>Donavon West</b></sub>](http://donavon.com)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Code") [馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Documentation") [馃](#ideas-donavon "Ideas, Planning, & Feedback") [鈿狅笍](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Tests") | [<img src="https://avatars2.githubusercontent.com/u/689081?v=4" width="100px;" alt="Richard Maisano"/><br /><sub><b>Richard Maisano</b></sub>](https://github.com/maisano)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=maisano "Code") | [<img src="https://avatars0.githubusercontent.com/u/5244986?v=4" width="100px;" alt="Marco Biedermann"/><br /><sub><b>Marco Biedermann</b></sub>](https://www.marcobiedermann.com)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Code") [馃毀](#maintenance-marcobiedermann "Maintenance") [鈿狅笍](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Tests") | [<img src="https://avatars3.githubusercontent.com/u/93752?v=4" width="100px;" alt="Alex Zherdev"/><br /><sub><b>Alex Zherdev</b></sub>](https://github.com/alexzherdev)<br />[馃悰](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aalexzherdev "Bug reports") [馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=alexzherdev "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/887639?v=4" width="100px;" alt="Donavon West"/><br /><sub><b>Donavon West</b></sub>](http://donavon.com)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Code") [馃摉](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Documentation") [馃](#ideas-donavon "Ideas, Planning, & Feedback") [鈿狅笍](https://github.com/kentcdodds/react-testing-library/commits?author=donavon "Tests") | [<img src="https://avatars2.githubusercontent.com/u/689081?v=4" width="100px;" alt="Richard Maisano"/><br /><sub><b>Richard Maisano</b></sub>](https://github.com/maisano)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=maisano "Code") | [<img src="https://avatars0.githubusercontent.com/u/5244986?v=4" width="100px;" alt="Marco Biedermann"/><br /><sub><b>Marco Biedermann</b></sub>](https://www.marcobiedermann.com)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Code") [馃毀](#maintenance-marcobiedermann "Maintenance") [鈿狅笍](https://github.com/kentcdodds/react-testing-library/commits?author=marcobiedermann "Tests") | [<img src="https://avatars3.githubusercontent.com/u/93752?v=4" width="100px;" alt="Alex Zherdev"/><br /><sub><b>Alex Zherdev</b></sub>](https://github.com/alexzherdev)<br />[馃悰](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Aalexzherdev "Bug reports") [馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=alexzherdev "Code") | [<img src="https://avatars0.githubusercontent.com/u/5133846?v=4" width="100px;" alt="Andr茅 Matulionis dos Santos"/><br /><sub><b>Andr茅 Matulionis dos Santos</b></sub>](https://twitter.com/Andrewmat)<br />[馃捇](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Code") [馃挕](#example-Andrewmat "Examples") [鈿狅笍](https://github.com/kentcdodds/react-testing-library/commits?author=Andrewmat "Tests") |

<!-- ALL-CONTRIBUTORS-LIST:END -->

Expand Down
5 changes: 2 additions & 3 deletions examples/__tests__/mock.react-transition-group.js
Expand Up @@ -31,9 +31,8 @@ afterEach(cleanup)

jest.mock('react-transition-group', () => {
const FakeTransition = jest.fn(({children}) => children)
const FakeCSSTransition = jest.fn(
props =>
props.in ? <FakeTransition>{props.children}</FakeTransition> : null,
const FakeCSSTransition = jest.fn(props =>
props.in ? <FakeTransition>{props.children}</FakeTransition> : null,
)
return {CSSTransition: FakeCSSTransition, Transition: FakeTransition}
})
Expand Down
125 changes: 93 additions & 32 deletions examples/__tests__/react-hooks.js
Expand Up @@ -6,53 +6,114 @@
*/
import {testHook, act, cleanup} from 'react-testing-library'

import useCounter from '../react-hooks'
import {useCounter, useDocumentTitle, useCall} from '../react-hooks'

afterEach(cleanup)

test('accepts default initial values', () => {
let count
testHook(() => ({count} = useCounter()))
describe('useCounter', () => {
test('accepts default initial values', () => {
let count
testHook(() => ({count} = useCounter()))

expect(count).toBe(0)
})
expect(count).toBe(0)
})

test('accepts a default initial value for `count`', () => {
let count
testHook(() => ({count} = useCounter({})))
test('accepts a default initial value for `count`', () => {
let count
testHook(() => ({count} = useCounter({})))

expect(count).toBe(0)
})
expect(count).toBe(0)
})

test('provides an `increment` function', () => {
let count, increment
testHook(() => ({count, increment} = useCounter({step: 2})))

expect(count).toBe(0)
act(() => {
increment()
})
expect(count).toBe(2)
})

test('provides an `decrement` function', () => {
let count, decrement
testHook(() => ({count, decrement} = useCounter({step: 2})))

expect(count).toBe(0)
act(() => {
decrement()
})
expect(count).toBe(-2)
})

test('provides an `increment` function', () => {
let count, increment
testHook(() => ({count, increment} = useCounter({step: 2})))
test('accepts a default initial value for `step`', () => {
let count, increment
testHook(() => ({count, increment} = useCounter({})))

expect(count).toBe(0)
act(() => {
increment()
expect(count).toBe(0)
act(() => {
increment()
})
expect(count).toBe(1)
})
expect(count).toBe(2)
})

test('provides an `decrement` function', () => {
let count, decrement
testHook(() => ({count, decrement} = useCounter({step: 2})))
// using unmount function to check useEffect behavior when unmounting
describe('useDocumentTitle', () => {
test('sets a title', () => {
document.title = 'original title'
testHook(() => {
useDocumentTitle('modified title')
})

expect(count).toBe(0)
act(() => {
decrement()
expect(document.title).toBe('modified title')
})

test('returns to original title when component is unmounted', () => {
document.title = 'original title'
const {unmount} = testHook(() => {
useDocumentTitle('modified title')
})

unmount()
expect(document.title).toBe('original title')
})
expect(count).toBe(-2)
})

test('accepts a default initial value for `step`', () => {
let count, increment
testHook(() => ({count, increment} = useCounter({})))
// using rerender function to test calling useEffect multiple times
describe('useCall', () => {
test('calls once on render', () => {
const spy = jest.fn()
testHook(() => {
useCall(spy, [])
})
expect(spy).toHaveBeenCalledTimes(1)
})

test('calls again if deps change', () => {
let deps = [false]
const spy = jest.fn()
const {rerender} = testHook(() => {
useCall(spy, deps)
})
expect(spy).toHaveBeenCalledTimes(1)

deps = [true]
rerender()
expect(spy).toHaveBeenCalledTimes(2)
})

test('does not call again if deps are the same', () => {
let deps = [false]
const spy = jest.fn()
const {rerender} = testHook(() => {
useCall(spy, deps)
})
expect(spy).toHaveBeenCalledTimes(1)

expect(count).toBe(0)
act(() => {
increment()
deps = [false]
rerender()
expect(spy).toHaveBeenCalledTimes(1)
})
expect(count).toBe(1)
})
21 changes: 18 additions & 3 deletions examples/react-hooks.js
@@ -1,10 +1,25 @@
import {useState} from 'react'
import {useState, useEffect} from 'react'

function useCounter({initialCount = 0, step = 1} = {}) {
export function useCounter({initialCount = 0, step = 1} = {}) {
const [count, setCount] = useState(initialCount)
const increment = () => setCount(c => c + step)
const decrement = () => setCount(c => c - step)
return {count, increment, decrement}
}

export default useCounter
export function useDocumentTitle(title) {
const [originalTitle, setOriginalTitle] = useState(document.title)
useEffect(() => {
setOriginalTitle(document.title)
document.title = title
return () => {
document.title = originalTitle
}
}, [title])
}

export function useCall(callback, deps) {
useEffect(() => {
callback()
}, deps)
}
28 changes: 27 additions & 1 deletion src/__tests__/test-hook.js
@@ -1,4 +1,4 @@
import {useState} from 'react'
import {useState, useEffect} from 'react'
import 'jest-dom/extend-expect'
import {testHook, cleanup} from '../'

Expand All @@ -12,3 +12,29 @@ test('testHook calls the callback', () => {
test('confirm we can safely call a React Hook from within the callback', () => {
testHook(() => useState())
})
test('returns a function to unmount component', () => {
let isMounted
const {unmount} = testHook(() => {
useEffect(() => {
isMounted = true
return () => {
isMounted = false
}
})
})
expect(isMounted).toBe(true)
unmount()
expect(isMounted).toBe(false)
})
test('returns a function to rerender component', () => {
let renderCount = 0
const {rerender} = testHook(() => {
useEffect(() => {
renderCount++
})
})

expect(renderCount).toBe(1)
rerender()
expect(renderCount).toBe(2)
})
10 changes: 9 additions & 1 deletion src/index.js
Expand Up @@ -67,7 +67,15 @@ function TestHook({callback}) {
}

function testHook(callback) {
render(<TestHook callback={callback} />)
const {unmount, rerender: rerenderComponent} = render(
<TestHook callback={callback} />,
)
return {
unmount,
rerender: () => {
rerenderComponent(<TestHook callback={callback} />)
},
}
}

function cleanup() {
Expand Down

0 comments on commit 9c606da

Please sign in to comment.