jest-react-hooks-shallow
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -6,2 +6,5 @@ interface Jest { | ||
declare const enableHooks: (jestInstance: Jest) => void; | ||
declare const disableHooks: () => void; | ||
declare const reenableHooks: () => void; | ||
export default enableHooks; | ||
export { disableHooks, reenableHooks }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const mock_use_effect_1 = require("./mock-use-effect/mock-use-effect"); | ||
let originalUseEffect; | ||
let originalUseLayoutEffect; | ||
const useEffectMock = jest.fn().mockImplementation(mock_use_effect_1.default()); | ||
const useLayoutEffectMock = jest.fn().mockImplementation(mock_use_effect_1.default()); | ||
const enableHooks = (jestInstance) => { | ||
const react = jestInstance.requireActual('react'); | ||
jestInstance.mock('react', () => (Object.assign(Object.assign({}, react), { useEffect: mock_use_effect_1.default(), useLayoutEffect: mock_use_effect_1.default() }))); | ||
originalUseEffect = react.useEffect; | ||
originalUseLayoutEffect = react.useLayoutEffect; | ||
jestInstance.mock('react', () => (Object.assign(Object.assign({}, react), { useEffect: useEffectMock, useLayoutEffect: useLayoutEffectMock }))); | ||
}; | ||
const disableHooks = () => { | ||
if (!originalUseEffect) { | ||
throw new Error('Cannot call `disableHooks()` if `enableHooks()` has not been invoked'); | ||
} | ||
useEffectMock.mockImplementation(originalUseEffect); | ||
useLayoutEffectMock.mockImplementation(originalUseLayoutEffect); | ||
}; | ||
exports.disableHooks = disableHooks; | ||
const reenableHooks = () => { | ||
useEffectMock.mockImplementation(mock_use_effect_1.default()); | ||
useLayoutEffectMock.mockImplementation(mock_use_effect_1.default()); | ||
}; | ||
exports.reenableHooks = reenableHooks; | ||
exports.default = enableHooks; | ||
//# sourceMappingURL=enable-hooks.js.map |
@@ -9,6 +9,6 @@ "use strict"; | ||
const previousCalls = new Map(); | ||
let cleanupFunctions = []; | ||
const cleanupFunctions = new Map(); | ||
beforeEach(() => { | ||
previousCalls.clear(); | ||
cleanupFunctions = []; | ||
cleanupFunctions.clear(); | ||
}); | ||
@@ -22,6 +22,8 @@ return (effect, dependencies) => { | ||
previousCalls.set(effectBody, dependencies); | ||
cleanupFunctions.forEach(cleanupFunction => cleanupFunction()); | ||
if (cleanupFunctions.has(effectBody)) { | ||
cleanupFunctions.get(effectBody)(); | ||
} | ||
const cleanupFunction = effect(); | ||
if (typeof cleanupFunction === 'function') { | ||
cleanupFunctions.push(cleanupFunction); | ||
cleanupFunctions.set(effectBody, cleanupFunction); | ||
} | ||
@@ -28,0 +30,0 @@ } |
{ | ||
"name": "jest-react-hooks-shallow", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "React Hooks for shallow rendering", | ||
@@ -36,3 +36,3 @@ "homepage": "https://github.com/mikeborozdin/jest-react-hooks-shallow", | ||
"jest": "^25.1.0", | ||
"ts-jest": "^25.2.1", | ||
"ts-jest": "^25.4.0", | ||
"typescript": "^3.8.3" | ||
@@ -39,0 +39,0 @@ }, |
@@ -105,2 +105,56 @@ jest-react-hooks-shallow | ||
Usage with `mount()` | ||
==== | ||
There have been a few issues reporting problems when using the library on the tests that rely on `mount()`. | ||
You don't need this library to trigger `useEffect()` and `useLayoutEffect()` when doing full rendering with `mount()`. However, you may have a mix of tests that rely both rely on `shallow()` and `mount()`. In those cases, you may run into issues with the tests that call `mount()`. | ||
Version `1.3.0` of this library provides a solution for that. | ||
If you have a test that uses `mount()` simply call `disableHooks()` before mounting a component: | ||
```js | ||
import { disableHooks } from 'jest-react-hooks-shallow'; | ||
test('Full rendering with `mount()`', () => { | ||
disableHooks(); | ||
const component = mount(<App />); | ||
// your test code | ||
}); | ||
``` | ||
Now, that will disable hooks for the test in the same suite which rely on `shallow()`. So you need to re-enable them by calling `reenableHooks()`. | ||
```js | ||
import { disableHooks, reenableHooks } from 'jest-react-hooks-shallow'; | ||
test('Full rendering with `mount()`', () => { | ||
disableHooks(); | ||
const component = mount(<App />); | ||
// your test code | ||
}); | ||
test('Back to shallow rendering with', () => { | ||
reenableHooks(); | ||
const component = shallow(<App />); | ||
// your test code | ||
}); | ||
``` | ||
Examples | ||
---- | ||
Please, see [use-effect-component.test.jsx](sample-tests-and-e2e-tests/src/use-effect/use-effect-component.test.jsx) for the examples of that. Namely, have a look at the test called `effects mockable when used with mount() and disableHooks()` and the one that comes after it. | ||
How does that work? | ||
---- | ||
You enable `useEffect()`/`useLayoutEffect()` by calling `enableHooks()` in a file specified by `setupFilesAfterEnv` in the Jest configuration. The code in that code will be called before each test suite. | ||
So if in our test suite you call `disableHooks()` it will not affect the other ones. But it will disable hooks in shallow rendering for the tests that come after the one with `disableHooks()`. So if any the tests defined after need shallow rendering and hooks, just call `reenableHooks()`. | ||
``` | ||
Dependencies | ||
@@ -107,0 +161,0 @@ ==== |
@@ -31,2 +31,4 @@ { | ||
"dependencies": { | ||
"@material-ui/core": "^4.9.12", | ||
"material-ui": "^0.20.2", | ||
"react": "^16.8.6", | ||
@@ -33,0 +35,0 @@ "react-dom": "^16.8.6" |
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
import { act } from "react-dom/test-utils"; | ||
import { shallow, mount } from 'enzyme'; | ||
import UseEffectComponent from './use-effect-component'; | ||
import callback from './callback'; | ||
import cleanup from './cleanup'; | ||
import { disableHooks, reenableHooks } from 'jest-react-hooks-shallow'; | ||
@@ -35,3 +37,20 @@ jest.mock('./callback', () => jest.fn()); | ||
test('effects mockable when used with mount() and disableHooks()', () => { | ||
disableHooks(); | ||
const component = mount(<UseEffectComponent />); | ||
expect(component.text()).toContain('false'); | ||
expect(callback).toHaveBeenCalledTimes(1); | ||
component.find('button').simulate('click'); | ||
expect(callback).toHaveBeenCalledTimes(2); | ||
}); | ||
test('cleanup function', () => { | ||
reenableHooks(); | ||
expect(cleanup).toHaveBeenCalledTimes(0); | ||
@@ -44,3 +63,3 @@ | ||
expect(cleanup).toHaveBeenCalledTimes(1); | ||
}) | ||
}); | ||
}); |
@@ -8,12 +8,42 @@ import mockUseEffect from "./mock-use-effect/mock-use-effect"; | ||
interface React { | ||
useEffect: (...args: unknown[]) => unknown; | ||
useLayoutEffect: (...args: unknown[]) => unknown; | ||
} | ||
let originalUseEffect: (...args: unknown[]) => unknown; | ||
let originalUseLayoutEffect: (...args: unknown[]) => unknown; | ||
const useEffectMock = jest.fn().mockImplementation(mockUseEffect()); | ||
const useLayoutEffectMock = jest.fn().mockImplementation(mockUseEffect()); | ||
const enableHooks = (jestInstance: Jest): void => { | ||
const react = jestInstance.requireActual('react'); | ||
const react = jestInstance.requireActual('react') as React; | ||
originalUseEffect = react.useEffect; | ||
originalUseLayoutEffect = react.useLayoutEffect; | ||
jestInstance.mock('react', () => ({ | ||
...react, | ||
useEffect: mockUseEffect(), | ||
useLayoutEffect: mockUseEffect(), | ||
useEffect: useEffectMock, | ||
useLayoutEffect: useLayoutEffectMock, | ||
})); | ||
}; | ||
const disableHooks = (): void => { | ||
if (!originalUseEffect) { | ||
throw new Error('Cannot call `disableHooks()` if `enableHooks()` has not been invoked') | ||
} | ||
useEffectMock.mockImplementation(originalUseEffect); | ||
useLayoutEffectMock.mockImplementation(originalUseLayoutEffect); | ||
}; | ||
const reenableHooks = (): void => { | ||
useEffectMock.mockImplementation(mockUseEffect()); | ||
useLayoutEffectMock.mockImplementation(mockUseEffect()); | ||
}; | ||
export default enableHooks; | ||
export { disableHooks, reenableHooks }; |
@@ -12,3 +12,2 @@ type UseEffectSignature = (fn: () => void, triggers?: unknown[]) => void; | ||
const previousCalls = new Map<FunctionBody, unknown[]>(); | ||
// let cleanupFunctions: CleanupFunction[] = []; | ||
const cleanupFunctions = new Map<string, CleanupFunction>(); | ||
@@ -18,3 +17,2 @@ | ||
previousCalls.clear(); | ||
// cleanupFunctions = []; | ||
cleanupFunctions.clear(); | ||
@@ -21,0 +19,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
635678
33
15897
208