Skip to content
This repository was archived by the owner on Mar 5, 2022. It is now read-only.

Commit fd8242d

Browse files
committed
feat: add wrapper option to mountHook
1 parent 010441e commit fd8242d

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed

cypress/component/advanced/hooks/README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,18 @@
33
- [counter-with-hooks.spec.js](counter-with-hooks.spec.js) and [counter2-with-hooks.spec.js](counter2-with-hooks.spec.js) test React components that uses hooks
44
- [use-counter.spec.js](use-counter.spec.js) shows how to test a React hook using `mountHook` function
55
- [custom-hook.mount-spec.js](custom-hook.mount-spec.js) manually creates a wrapper component around a custom hook that uses Redux provider
6-
- [custom-hook.mount-hook-spec.js](custom-hook.mount-hook-spec.js) is skipped for now
6+
- [custom-hook.mount-hook-spec.js](custom-hook.mount-hook-spec.js) shows how `mountHook` can be surrounded with `wrapper` element
77

88
![Hook test](images/hook.png)
99

1010
Note: hooks are mounted inside a test component following the approach shown in [react-hooks-testing-library](https://github.com/testing-library/react-hooks-testing-library/blob/master/src/pure.js)
11+
12+
Example:
13+
14+
```js
15+
import { mountHook } from 'cypress-react-unit-test'
16+
// wrapper is optional, only if your hook requires
17+
// something like a context provider
18+
const wrapper = ({ children }) => <Provider store={store}>{children}</Provider>
19+
mountHook(() => useCustomHook(), { wrapper })
20+
```

cypress/component/advanced/hooks/custom-hook.mount-hook-spec.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ import { Provider } from 'react-redux'
66
import store from './store'
77

88
describe('custom hook that needs redux provider', () => {
9-
it.skip('mounted with wrapper', () => {
10-
mountHook(() => useCustomHook()).then(result => {
11-
console.log(result)
12-
})
9+
it('mounted with wrapper', () => {
10+
const wrapper = ({ children }) => (
11+
<Provider store={store}>{children}</Provider>
12+
)
13+
14+
cy.spy(console, 'log').as('log')
15+
mountHook(() => useCustomHook(), { wrapper })
16+
17+
// make sure the custom hook calls "useEffect"
18+
cy.get('@log').should('have.been.calledWith', 'hello world!')
1319
})
1420
})

lib/mountHook.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,39 @@ function TestHook({ callback, onError, children }: TestHookProps) {
6060
return null
6161
}
6262

63+
type MountHookOptions = {
64+
wrapper?: React.ReactElement
65+
}
66+
6367
/**
6468
* Mounts a React hook function in a test component for testing.
6569
*
6670
* @see https://github.com/bahmutov/cypress-react-unit-test#advanced-examples
6771
*/
68-
export const mountHook = (hookFn: (...args: any[]) => any) => {
72+
export const mountHook = (
73+
hookFn: (...args: any[]) => any,
74+
options: MountHookOptions = {},
75+
) => {
6976
const { result, setValue, setError } = resultContainer()
7077

71-
return mount(
72-
React.createElement(TestHook, {
73-
callback: hookFn,
74-
onError: setError,
75-
children: setValue,
76-
}),
77-
).then(() => {
78+
const testElement = React.createElement(TestHook, {
79+
callback: hookFn,
80+
onError: setError,
81+
children: setValue,
82+
key: Math.random().toString(),
83+
})
84+
85+
let mountElement: any = testElement
86+
if (options.wrapper) {
87+
// what's the proper type? I don't even care anymore
88+
// because types for React seem to be a mess
89+
// @ts-ignore
90+
mountElement = React.createElement(options.wrapper, {
91+
children: [testElement],
92+
})
93+
}
94+
95+
return mount(mountElement).then(() => {
7896
cy.wrap(result)
7997
})
8098
}

0 commit comments

Comments
 (0)