Skip to content

Commit

Permalink
✅ throw an error when console.error() is called
Browse files Browse the repository at this point in the history
Throw an error when `console.error()` is called. This is especially useful in a React tests
because React uses it to show warnings and discourage you from shooting yourself in the foot.
Here are a few example warnings React throws:
- "Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded
  into the server renderer's output format. This will lead to a mismatch between the initial,
  non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in
  components that render exclusively on the client. See
  https://reactjs.org/link/uselayouteffect-ssr for common fixes."
- "Warning: Can't perform a React state update on an unmounted component. This is a no-op,
  but it indicates a memory leak in your application. To fix, cancel all subscriptions and
  asynchronous tasks in a useEffect cleanup function."
- "Warning: Cannot update a component (`Component`) while rendering a different component
  (`Component`). To locate the bad setState() call inside `Component`, follow the stack trace
  as described in https://reactjs.org/link/setstate-in-render"
  • Loading branch information
astoilkov committed Mar 25, 2022
1 parent 83dd917 commit baa4ca1
Showing 1 changed file with 21 additions and 19 deletions.
40 changes: 21 additions & 19 deletions test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
import util from 'node:util'
import storage from './src/storage'
import useLocalStorageState from '.'
import { render } from '@testing-library/react'
import React, { useEffect, useMemo } from 'react'
import { renderHook, act } from '@testing-library/react-hooks'
import { renderHook as renderHookOnServer } from '@testing-library/react-hooks/server'

beforeEach(() => {
// Throw an error when `console.error()` is called. This is especially useful in a React tests
// because React uses it to show warnings and discourage you from shooting yourself in the foot.
// Here are a few example warnings React throws:
// - "Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded
// into the server renderer's output format. This will lead to a mismatch between the initial,
// non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in
// components that render exclusively on the client. See
// https://reactjs.org/link/uselayouteffect-ssr for common fixes."
// - "Warning: Can't perform a React state update on an unmounted component. This is a no-op,
// but it indicates a memory leak in your application. To fix, cancel all subscriptions and
// asynchronous tasks in a useEffect cleanup function."
// - "Warning: Cannot update a component (`Component`) while rendering a different component
// (`Component`). To locate the bad setState() call inside `Component`, follow the stack trace
// as described in https://reactjs.org/link/setstate-in-render"
jest.spyOn(console, 'error').mockImplementation((format: string, ...args: any[]) => {
throw new Error(util.format(format, ...args))
})
})

afterEach(() => {
localStorage.clear()
storage.data.clear()
Expand Down Expand Up @@ -565,25 +586,6 @@ describe('createLocalStorageStateHook()', () => {
})
})

it(`should not call useLayoutEffect() on the server`, () => {
// When you call `useLayoutEffect()` on the server React calls `console.error` with the
// following message:
// "Warning: useLayoutEffect does nothing on the server, because its effect cannot be
// encoded into the server renderer's output format. This will lead to a mismatch between
// the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should
// only be used in components that render exclusively on the client. See
// https://reactjs.org/link/uselayouteffect-ssr for common fixes."
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})

renderHookOnServer(() =>
useLocalStorageState('number', {
defaultValue: 0,
}),
)

expect(errorSpy).not.toHaveBeenCalled()
})

it('returns default value on the server', () => {
localStorage.setItem('todos', JSON.stringify(['third', 'forth']))

Expand Down

0 comments on commit baa4ca1

Please sign in to comment.