diff --git a/.all-contributorsrc b/.all-contributorsrc index 9edfc26a..dea90e11 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -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" + ] } ] } diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 5114fdbd..724a7df6 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -59,7 +59,8 @@ What happened: -Reproduction repository: https://github.com/alexkrolick/dom-testing-library-template +Reproduction repository: +https://github.com/alexkrolick/dom-testing-library-template diff --git a/examples/__tests__/mock.react-transition-group.js b/examples/__tests__/mock.react-transition-group.js index ef22636f..83894534 100644 --- a/examples/__tests__/mock.react-transition-group.js +++ b/examples/__tests__/mock.react-transition-group.js @@ -31,9 +31,8 @@ afterEach(cleanup) jest.mock('react-transition-group', () => { const FakeTransition = jest.fn(({children}) => children) - const FakeCSSTransition = jest.fn( - props => - props.in ? {props.children} : null, + const FakeCSSTransition = jest.fn(props => + props.in ? {props.children} : null, ) return {CSSTransition: FakeCSSTransition, Transition: FakeTransition} }) diff --git a/examples/__tests__/react-hooks.js b/examples/__tests__/react-hooks.js index 5e001a37..fe616eb7 100644 --- a/examples/__tests__/react-hooks.js +++ b/examples/__tests__/react-hooks.js @@ -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) }) diff --git a/examples/react-hooks.js b/examples/react-hooks.js index fad0de4c..251644cd 100644 --- a/examples/react-hooks.js +++ b/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) +} diff --git a/src/__tests__/test-hook.js b/src/__tests__/test-hook.js index f6bce9bd..673e9497 100644 --- a/src/__tests__/test-hook.js +++ b/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 '../' @@ -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) +}) diff --git a/src/index.js b/src/index.js index 0f4c7d47..78b5ffae 100644 --- a/src/index.js +++ b/src/index.js @@ -67,7 +67,15 @@ function TestHook({callback}) { } function testHook(callback) { - render() + const {unmount, rerender: rerenderComponent} = render( + , + ) + return { + unmount, + rerender: () => { + rerenderComponent() + }, + } } function cleanup() {