UNPKG

@testing-library/react-hooks

Version:

Simple and complete React hooks testing utilities that encourage good testing practices.

259 lines (188 loc) 7.27 kB
import { useState, useRef, useEffect } from 'react' describe('async hook tests', () => { const useSequence = (values: string[], intervalMs = 50) => { const [first, ...otherValues] = values const [value, setValue] = useState(() => first) const index = useRef(0) useEffect(() => { const interval = setInterval(() => { setValue(otherValues[index.current++]) if (index.current >= otherValues.length) { clearInterval(interval) } }, intervalMs) return () => { clearInterval(interval) } // eslint-disable-next-line react-hooks/exhaustive-deps }, otherValues) return value } runForRenderers(['default', 'dom', 'native', 'server/hydrated'], ({ renderHook }) => { test('should wait for next update', async () => { const { result, waitForNextUpdate } = renderHook(() => useSequence(['first', 'second'])) expect(result.current).toBe('first') await waitForNextUpdate() expect(result.current).toBe('second') }) test('should wait for multiple updates', async () => { const { result, waitForNextUpdate } = renderHook(() => useSequence(['first', 'second', 'third']) ) expect(result.current).toBe('first') await waitForNextUpdate() expect(result.current).toBe('second') await waitForNextUpdate() expect(result.current).toBe('third') }) test('should reject if timeout exceeded when waiting for next update', async () => { const { result, waitForNextUpdate } = renderHook(() => useSequence(['first', 'second'])) expect(result.current).toBe('first') await expect(waitForNextUpdate({ timeout: 10 })).rejects.toThrow( Error('Timed out in waitForNextUpdate after 10ms.') ) }) test('should not reject when waiting for next update if timeout has been disabled', async () => { const { result, waitForNextUpdate } = renderHook(() => useSequence(['first', 'second'], 1100)) expect(result.current).toBe('first') await waitForNextUpdate({ timeout: false }) expect(result.current).toBe('second') }) test('should wait for expectation to pass', async () => { const { result, waitFor } = renderHook(() => useSequence(['first', 'second', 'third'])) expect(result.current).toBe('first') let complete = false await waitFor(() => { expect(result.current).toBe('third') complete = true }) expect(complete).toBe(true) }) test('should wait for arbitrary expectation to pass', async () => { const { waitFor } = renderHook(() => null) let actual = 0 const expected = 1 setTimeout(() => { actual = expected }, 200) let complete = false await waitFor(() => { expect(actual).toBe(expected) complete = true }) expect(complete).toBe(true) }) test('should not hang if expectation is already passing', async () => { const { result, waitFor } = renderHook(() => useSequence(['first', 'second'])) expect(result.current).toBe('first') let complete = false await waitFor(() => { expect(result.current).toBe('first') complete = true }) expect(complete).toBe(true) }) test('should wait for truthy value', async () => { const { result, waitFor } = renderHook(() => useSequence(['first', 'second', 'third'])) expect(result.current).toBe('first') await waitFor(() => result.current === 'third') expect(result.current).toBe('third') }) test('should wait for arbitrary truthy value', async () => { const { waitFor } = renderHook(() => null) let actual = 0 const expected = 1 setTimeout(() => { actual = expected }, 200) await waitFor(() => actual === 1) expect(actual).toBe(expected) }) test('should reject if timeout exceeded when waiting for expectation to pass', async () => { const { result, waitFor } = renderHook(() => useSequence(['first', 'second', 'third'])) expect(result.current).toBe('first') await expect( waitFor( () => { expect(result.current).toBe('third') }, { timeout: 75 } ) ).rejects.toThrow(Error('Timed out in waitFor after 75ms.')) }) test('should not reject when waiting for expectation to pass if timeout has been disabled', async () => { const { result, waitFor } = renderHook(() => useSequence(['first', 'second', 'third'], 550)) expect(result.current).toBe('first') await waitFor( () => { expect(result.current).toBe('third') }, { timeout: false } ) expect(result.current).toBe('third') }) test('should check on interval when waiting for expectation to pass', async () => { const { result, waitFor } = renderHook(() => useSequence(['first', 'second', 'third'])) let checks = 0 await waitFor( () => { checks++ return result.current === 'third' }, { interval: 100 } ) expect(checks).toBe(3) }) test('should wait for value to change', async () => { const { result, waitForValueToChange } = renderHook(() => useSequence(['first', 'second', 'third']) ) expect(result.current).toBe('first') await waitForValueToChange(() => result.current === 'third') expect(result.current).toBe('third') }) test('should wait for arbitrary value to change', async () => { const { waitForValueToChange } = renderHook(() => null) let actual = 0 const expected = 1 setTimeout(() => { actual = expected }, 200) await waitForValueToChange(() => actual) expect(actual).toBe(expected) }) test('should reject if timeout exceeded when waiting for value to change', async () => { const { result, waitForValueToChange } = renderHook(() => useSequence(['first', 'second', 'third']) ) expect(result.current).toBe('first') await expect( waitForValueToChange(() => result.current === 'third', { timeout: 75 }) ).rejects.toThrow(Error('Timed out in waitForValueToChange after 75ms.')) }) test('should not reject when waiting for value to change if timeout is disabled', async () => { const { result, waitForValueToChange } = renderHook(() => useSequence(['first', 'second', 'third'], 550) ) expect(result.current).toBe('first') await waitForValueToChange(() => result.current === 'third', { timeout: false }) expect(result.current).toBe('third') }) test('should reject if selector throws error', async () => { const { result, waitForValueToChange } = renderHook(() => useSequence(['first', 'second'])) expect(result.current).toBe('first') await expect( waitForValueToChange(() => { if (result.current === 'second') { throw new Error('Something Unexpected') } return result.current }) ).rejects.toThrow(Error('Something Unexpected')) }) }) })