import React from 'react'
import { Text, View } from 'react-native'
import { render, screen, fireEvent } from '@testing-library/react-native'
import moduleIndex from '../index'
import ErrorBoundary from '../ErrorBoundary'
describe('ErrorBoundary', () => {
let consoleErrorSpy: jest.SpyInstance
const ComponentWithError = () => (
{/* @ts-expect-error - We are rendering an error to trigger the ErrorBoundary component, even though it's not a valid React children. */}
{new Error('This is a test error!')}
)
beforeAll(() => {
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
})
afterAll(() => {
consoleErrorSpy.mockRestore()
})
describe('Module index', () => {
it('should default export ErrorBoundary', () => {
expect(moduleIndex).toBeInstanceOf(Function)
})
})
describe('when there are no errors', () => {
it('should render the children', () => {
const screen = render(
Hey!
,
)
expect(screen).toMatchInlineSnapshot(`
Hey!
`)
})
})
describe('when there is an error', () => {
describe('when FallbackComponent is not defined as a prop', () => {
it('should catch the error and render the default FallbackComponent', () => {
const screen = render(
,
)
expect(screen).toMatchSnapshot()
})
})
describe('when FallbackComponent is defined as a prop', () => {
it('should catch the error and render the props.FallbackComponent', () => {
const fallbackComponent = 'FallbackComponent'
render(
{fallbackComponent}}
>
,
)
expect(screen.getByText(fallbackComponent)).toBeOnTheScreen()
})
})
describe('when onError is defined as a prop', () => {
it('should catch the error and call props.onError', () => {
const onError = jest.fn()
render(
,
)
expect(onError).toHaveBeenCalledWith(
expect.any(Error),
expect.any(String),
)
})
})
describe('when FallbackComponent resetError prop is called', () => {
it('should clear the error state', () => {
const { rerender } = render(, {
wrapper: ErrorBoundary,
})
const tryAgainButton = screen.getByText('Try again')
const children = 'Children'
expect(tryAgainButton).toBeOnTheScreen()
rerender({children})
fireEvent.press(tryAgainButton)
expect(screen.getByText(children)).toBeOnTheScreen()
expect(tryAgainButton).not.toBeOnTheScreen()
})
})
})
})