Skip to content

Commit 80d0f5d

Browse files
committed
Added initial docs site with proposed table of contents and some content pages
1 parent 7d4d3d2 commit 80d0f5d

24 files changed

+9102
-1852
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
coverage
33
lib
4+
.docz

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
site

README.md

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1+
---
2+
name: Getting Started
3+
route: '/'
4+
---
5+
16
<div align="center">
2-
<h1>react-hooks-testing-library</h1>
7+
<h1>react-hooks-testing-library</h1>
38

4-
<a href="https://www.emojione.com/emoji/1f40f">
5-
<img
6-
height="80"
7-
width="80"
8-
alt="ram"
9-
src="https://raw.githubusercontent.com/mpeyper/react-hooks-testing-library/master/other/ram.png"
10-
/>
11-
</a>
9+
<a href="https://www.emojione.com/emoji/1f40f">
10+
<img
11+
height="80"
12+
width="80"
13+
alt="ram"
14+
src="https://raw.githubusercontent.com/mpeyper/react-hooks-testing-library/master/other/ram.png"
15+
/>
16+
</a>
1217

13-
<p>Simple component wrapper and utilities for testing React hooks.</p>
18+
<p>
19+
Simple component wrapper and utilities for testing React hooks.
20+
</p>
1421

1522
</div>
1623

@@ -106,33 +113,7 @@ npm install --save-dev react-hooks-testing-library
106113

107114
## API
108115

109-
### `renderHook(callback[, options])`
110-
111-
Renders a test component that will call the provided `callback`, including any hooks it calls, every time it renders.
112-
113-
> _Note: `testHook` has been renamed to `renderHook`. `testHook` will continue work in the current version with a deprecation warning, but will be removed in a future version._
114-
>
115-
> **_You should update any usages of `testHook` to use `renderHook` instead._**
116-
117-
#### Arguments
118-
119-
- `callback` (`function()`) - function to call each render. This function should call one or more hooks for testing.
120-
- `options` (`object`) - accept the following settings:
121-
- `initialProps` (`object`) - the initial values to pass to the `callback` function
122-
- `wrapper` (`component`) - pass a React Component as the wrapper option to have it rendered around the inner element. This is most useful for creating reusable custom render functions for common data providers
123-
124-
#### Returns
125-
126-
- `result` (`object`)
127-
- `current` (`any`) - the return value of the `callback` function
128-
- `error` (`Error`) - the error that was thrown if the `callback` function threw an error during rendering
129-
- `waitForNextUpdate` (`function`) - returns a `Promise` that resolves the next time the hook renders, commonly when state is updated as the result of a asynchronous action.
130-
- `rerender` (`function([newProps])`) - function to rerender the test component including any hooks called in the `callback` function. If `newProps` are passed, the will replace the `initialProps` passed the the `callback` function for future renders.
131-
- `unmount` (`function()`) - function to unmount the test component, commonly used to trigger cleanup effects for `useEffect` hooks.
132-
133-
### `act(callback)`
134-
135-
This is the same [`act` function](https://reactjs.org/docs/hooks-faq.html#how-to-test-components-that-use-hooks) that is exported by `react-test-renderer`.
116+
See the [API documentation](/docs/reference/api.mdx)
136117

137118
## Contributors
138119

docs/reference/api.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
name: API
3+
menu: Reference
4+
route: '/reference/api'
5+
---
6+
7+
# API
8+
9+
## `renderHook(callback[, options])`
10+
11+
Renders a test component that will call the provided `callback`, including any hooks it calls, every time it renders.
12+
13+
> _Note: `testHook` has been renamed to `renderHook`. `testHook` will continue work in the current version with a deprecation warning, but will be removed in a future version._
14+
>
15+
> **_You should update any usages of `testHook` to use `renderHook` instead._**
16+
17+
### Arguments
18+
19+
- `callback` (`function([props])`) - function to call each render. This function should call one or more hooks for testing
20+
- The `props` passed into the callback will be the `initialProps` provided in the `options` until new props are provided by a `rerender` call
21+
- `options` (`object`)
22+
- `initialProps` (`object`) - the initial values to pass to the `callback` function
23+
- `wrapper` (`component`) - pass a React component to wrap the test component
24+
- This is usually used to add context providers from `React.createContext` for the hook access with `useContext`
25+
26+
### Returns
27+
28+
- `result` (`object`)
29+
- `current` (`any`) - the return value of the `callback` function
30+
- `error` (`Error`) - the error that was thrown if the `callback` function threw an error during rendering
31+
- `waitForNextUpdate` (`function`) - returns a `Promise` that resolves the next time the hook renders, commonly when state is updated as the result of a asynchronous action
32+
- `rerender` (`function([newProps])`) - function to rerender the test component including any hooks called in the `callback` function
33+
- If `newProps` are passed, the will replace the `initialProps` passed the the `callback` function for future renders
34+
- `unmount` (`function()`) - function to unmount the test component, commonly used to trigger cleanup effects for `useEffect` hooks
35+
36+
## `act(callback)`
37+
38+
This is the same [`act` function](https://testing-library.com/docs/react-testing-library/api#act) that is exported by `react-testing-library`.

docs/usage/advanced-hooks.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
---
2+
name: Advanced Hooks
3+
menu: Usage
4+
route: '/usage/advanced-hooks'
5+
---
6+
7+
# Advanced Hooks
8+
9+
## Providing Props
10+
11+
Sometimes a hook relies on the props passed to it in order to do it's thing. For example the `useCounter` hook we built in the [Basic Hooks](/usage/basic-hooks) section could easily accept the initial value of the counter:
12+
13+
```js
14+
import { useState, useCallback } from 'react'
15+
16+
export default function useCounter(initialValue = 0) {
17+
const [count, setCount] = useState(initialValue)
18+
const increment = useCallback(() => setCount(count + 1), [count])
19+
return { count, increment }
20+
}
21+
```
22+
23+
Overriding the `initialValue` prop in out test is as easy as calling the hook with the value we want to use:
24+
25+
```js
26+
import { renderHook, act } from 'react-hooks-testing-library'
27+
import useCounter from './useCounter'
28+
29+
test('should increment counter from custom initial value', () => {
30+
const { result } = renderHook(() => useCounter(9000))
31+
32+
act(() => {
33+
result.current.increment()
34+
})
35+
36+
expect(result.current.count).toBe(9001)
37+
})
38+
```
39+
40+
### Changing Props
41+
42+
Many of the hook primitives use an array of dependent values to determine when to perform specific actions, such as recalculating an expensive value or running an effect. If we update our `useCounter` hook to have a `reset` function that resets the value to the `initialValue` it might look something like this:
43+
44+
```js
45+
import { useState, useCallback } from 'react'
46+
47+
export default function useCounter(initialValue = 0) {
48+
const [count, setCount] = useState(initialValue)
49+
const increment = useCallback(() => setCount(count + 1), [count])
50+
const reset = useCallback(() => setCount(initialValue), [initialValue])
51+
return { count, increment, reset }
52+
}
53+
```
54+
55+
Now, the only time the `reset` function will be updated is if `initialValue` changes. The most basic way to handle changing the input props of our hook in a test is to simply update the value in a variable and rerender the hook:
56+
57+
```js
58+
import { renderHook, act } from 'react-hooks-testing-library'
59+
import useCounter from './useCounter'
60+
61+
test('should reset counter to updated initial value', () => {
62+
let initialValue = 0
63+
const { result, rerender } = renderHook(() => useCounter(initialValue))
64+
65+
initialValue = 10
66+
rerender()
67+
68+
act(() => {
69+
result.current.reset()
70+
})
71+
72+
expect(result.current.count).toBe(10)
73+
})
74+
```
75+
76+
This is fine, but if there are lots of props, it can become a bit difficult to have variables to keep track of them all. Another option is to use the `initialProps` option and `newProps` of `rerender`:
77+
78+
```js
79+
import { renderHook, act } from 'react-hooks-testing-library'
80+
import useCounter from './useCounter'
81+
82+
test('should reset counter to updated initial value', () => {
83+
const { result, rerender } = renderHook(({ initialValue }) => useCounter(initialValue), {
84+
initialProps: { initialValue: 0 }
85+
})
86+
87+
rerender({ initialValue: 10 })
88+
89+
act(() => {
90+
result.current.reset()
91+
})
92+
93+
expect(result.current.count).toBe(10)
94+
})
95+
```
96+
97+
Another case where this is useful is when you want limit the scope of the variables being closed over to just be inside the hook callback. The following (contrived) example fails because the `id` value changes for both the setup and cleanup of the `useEffect` call:
98+
99+
```js
100+
import { useEffect } from 'react'
101+
import { renderHook } from "react-hooks-testing-library"
102+
import sideEffect from './sideEffect
103+
104+
test("should clean up side effect", () => {
105+
let id = "first"
106+
const { rerender } = renderHook(() => {
107+
useEffect(() => {
108+
sideEffect.start(id)
109+
return () => {
110+
sideEffect.stop(id) // this id will get the new value when the effect is cleaned up
111+
}
112+
}, [id])
113+
})
114+
115+
id = "second"
116+
rerender()
117+
118+
expect(sideEffect.get("first")).toBe(false)
119+
expect(sideEffect.get("second")).toBe(true)
120+
})
121+
```
122+
123+
By using the `initialProps` and `newProps` the captured `id` value from the first render is used to clean up the effect, allowing the test to pass as expected:
124+
125+
```js
126+
import { useEffect } from 'react'
127+
import { renderHook } from "react-hooks-testing-library"
128+
import sideEffect from './sideEffect
129+
130+
test("should clean up side effect", () => {
131+
const { rerender } = renderHook(
132+
({ id }) => {
133+
useEffect(() => {
134+
sideEffect.start(id)
135+
return () => {
136+
sideEffect.stop(id) // this id will get the new value when the effect is cleaned up
137+
}
138+
}, [id])
139+
},
140+
{
141+
initialProps: { id: "first" }
142+
}
143+
)
144+
145+
rerender({ id: "second" })
146+
147+
expect(thing.get("first")).toBe(false)
148+
expect(thing.get("second")).toBe(true)
149+
})
150+
```
151+
152+
This is a fairly obscure case, so pick the method that fits best for you and your test.

docs/usage/basic-hooks.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
name: Basic Hooks
3+
menu: Usage
4+
route: '/usage/basic-hooks'
5+
---
6+
7+
# Basic Hooks
8+
9+
## Rendering
10+
11+
Imagine we have a simple hook that we want to test:
12+
13+
```js
14+
import { useState, useCallback } from 'react'
15+
16+
export default function useCounter() {
17+
const [count, setCount] = useState(0)
18+
const increment = useCallback(() => setCount(count + 1), [count])
19+
return { count, increment }
20+
}
21+
```
22+
23+
To test `useCounter` we need to render it using the `renderHook` function to provided by `react-hooks-testing-library`:
24+
25+
```js
26+
import { renderHook } from 'react-hooks-testing-library'
27+
import useCounter from './useCounter'
28+
29+
test('should use counter', () => {
30+
const { result } = renderHook(() => useCounter())
31+
32+
expect(result.current.count).toBe(0)
33+
expect(typeof result.current.increment).toBe('function')
34+
})
35+
```
36+
37+
As you can see, the result's current value matches what is returned by our hook.
38+
39+
## Updates
40+
41+
The test shown above is great and all, but it doesn't actually test what we want to use the counter for, i.e. counting. We can easily improve this test by calling the `increment` function and checking that the `count` value increases:
42+
43+
```js
44+
import { renderHook, act } from 'react-hooks-testing-library'
45+
import useCounter from './useCounter'
46+
47+
test('should increment counter', () => {
48+
const { result } = renderHook(() => useCounter())
49+
50+
act(() => {
51+
result.current.increment()
52+
})
53+
54+
expect(result.current.count).toBe(1)
55+
})
56+
```
57+
58+
After `increment` is called, the current `count` value now reflects the new value returned by our hook.
59+
60+
You may have also noticed that we also wrapped the `increment` call in `act`. This utility simulates how our hook will act in a browser, allowing us to update the values within it. For more details on `act`, please see the [React documentation](https://fb.me/react-wrap-tests-with-act).
61+
62+
So there we have it, the first test for our `useCounter` hook.

doczrc.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export default {
2+
files: '**/*.{md,mdx}',
3+
dest: 'site',
4+
public: './other',
5+
ignore: ['CODE_OF_CONDUCT.md', 'CONTRIBUTING.md', 'LICENSE.md'],
6+
htmlContext: {
7+
favicon: '/public/ram.png'
8+
},
9+
themeConfig: {
10+
mode: 'dark',
11+
logo: {
12+
src: '/public/ram.png',
13+
margin: 'auto',
14+
width: 128
15+
}
16+
},
17+
menu: [
18+
{ name: 'Getting Started' },
19+
{ name: 'Usage', menu: ['Basic Hooks', 'Advanced Hooks', 'Async Hooks'] },
20+
{ name: 'Examples' },
21+
{ name: 'Reference', menu: ['FAQ', 'Troubleshooting', 'API'] }
22+
]
23+
}

0 commit comments

Comments
 (0)