首页 > 其他 > 详细

[React Testing] Ensure Error Boundaries Can Successfully Recover from Errors

时间:2020-05-01 22:14:42      阅读:61      评论:0      收藏:0      [点我收藏+]

Our error boundary has some other use cases that it supports and we should try to make sure our tests cover all those use cases, so let’s add a test to make sure the recovery feature of our error boundary works properly.

 

Error bundary:

import React from react
import {reportError} from ./api

class ErrorBoundary extends React.Component {
  state = {hasError: false}
  componentDidCatch(error, info) {
    this.setState({hasError: true})
    reportError(error, info)
  }
  tryAgain = () => this.setState({hasError: false})
  render() {
    return this.state.hasError ? (
      <div>
        <div role="alert">There was a problem.</div>{ }
        <button onClick={this.tryAgain}>Try again?</button>
      </div>
    ) : (
      this.props.children
    )
  }
}

export {ErrorBoundary}

 

Test:

import React from react
import { render, fireEvent } from @testing-library/react
import { ErrorBoundary } from ./error-boundary
import { reportError as mockReportError } from ./components/extra/api

function Bomb(shouldThrow) {
  if (shouldThrow) {
    throw new Error(Bomb)
  } else {
    return null
  }
}

jest.mock(./components/extra/api)

beforeAll(() => {
  // do log out any error message
  jest.spyOn(console, error).mockImplementation(() => {})
})

afterAll(() => {
  console.error.mockRestore()
})

test(calls reportError and renders that there was a problem, () => {
  mockReportError.mockResolvedValueOnce({ success: true })
  const { rerender, getByRole, getByText, queryByText, queryByRole } = render(
    <ErrorBoundary>
      <Bomb />
    </ErrorBoundary>,
  )

  rerender(
    <ErrorBoundary>
      <Bomb shouldThrow={true} />
    </ErrorBoundary>,
  )

  const error = expect.any(Error)
  const errorInfo = { componentStack: expect.stringContaining(Bomb) }
  expect(mockReportError).toHaveBeenCalledWith(error, errorInfo)
  expect(mockReportError).toHaveBeenCalledTimes(1)

  expect(console.error).toHaveBeenCalledTimes(2)

  expect(queryByRole(alert)).toBeInTheDocument()
  expect(getByRole(alert).textContent).toMatchInlineSnapshot(
    Something went wrong.,
  )

  rerender(
    <ErrorBoundary>
      <Bomb shouldThrow={false} />
    </ErrorBoundary>,
  )

  const button = getByText(/try again/i)
  fireEvent.click(button)
  // reset the mock state
  mockReportError.mockClear()
  console.error.mockClear()

  expect(mockReportError).not.toHaveBeenCalled()
  expect(console.error).not.toHaveBeenCalled()
  expect(queryByRole(alert)).not.toBeInTheDocument()
  expect(queryByText(/try again/i)).not.toBeInTheDocument()
})

afterEach(() => {
  jest.clearAllMocks()
})

 

Notice:

After sucessfully rerender the DOM, we want to make sure, ‘reportError‘ and ‘console.error‘ haven‘t been called, but previously we have called once, so we have to clear the mock state by doing:

  // reset the mock state
  mockReportError.mockClear()
  console.error.mockClear()

 

[React Testing] Ensure Error Boundaries Can Successfully Recover from Errors

原文:https://www.cnblogs.com/Answer1215/p/12814652.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!