import { render, screen, fireEvent } from '@testing-library/react'
import { RouteErrorBoundary } from '../error/RouteErrorBoundary'
import { NotFound } from '../error/NotFound'

describe('RouteErrorBoundary', () => {
  const makeError = () => Object.assign(new Error('boom'), { digest: 'abc123' })

  it('renders default title and description', () => {
    render(<RouteErrorBoundary error={makeError()} reset={jest.fn()} />)
    expect(screen.getByText('Something went wrong')).toBeInTheDocument()
    expect(screen.getByRole('alert')).toHaveAttribute('aria-live', 'assertive')
  })

  it('calls reset when the retry button is clicked', () => {
    const reset = jest.fn()
    render(<RouteErrorBoundary error={makeError()} reset={reset} />)
    fireEvent.click(screen.getByText('Try again'))
    expect(reset).toHaveBeenCalledTimes(1)
  })

  it('invokes onError once on mount', () => {
    const onError = jest.fn()
    const error = makeError()
    render(<RouteErrorBoundary error={error} reset={jest.fn()} onError={onError} />)
    expect(onError).toHaveBeenCalledTimes(1)
    expect(onError).toHaveBeenCalledWith(error)
  })

  it('hides the home button when homeHref is null', () => {
    render(
      <RouteErrorBoundary error={makeError()} reset={jest.fn()} homeHref={null} />
    )
    expect(screen.queryByText('Go home')).not.toBeInTheDocument()
  })

  it('supports a render-prop override via children', () => {
    render(
      <RouteErrorBoundary error={makeError()} reset={jest.fn()}>
        {({ error }) => <div>custom: {error.message}</div>}
      </RouteErrorBoundary>
    )
    expect(screen.getByText('custom: boom')).toBeInTheDocument()
    expect(screen.queryByText('Something went wrong')).not.toBeInTheDocument()
  })
})

describe('NotFound', () => {
  it('renders code, title, and description', () => {
    render(<NotFound />)
    expect(screen.getByText('404')).toBeInTheDocument()
    expect(screen.getByText('Page not found')).toBeInTheDocument()
  })

  it('renders a default home anchor when no action is given', () => {
    render(<NotFound />)
    const link = screen.getByText('Go home')
    expect(link).toHaveAttribute('href', '/')
  })

  it('renders a custom action node', () => {
    render(<NotFound action={<a href="/browse">Browse</a>} />)
    expect(screen.getByText('Browse')).toBeInTheDocument()
    expect(screen.queryByText('Go home')).not.toBeInTheDocument()
  })

  it('hides the code when set to null', () => {
    render(<NotFound code={null} />)
    expect(screen.queryByText('404')).not.toBeInTheDocument()
  })
})
