Search code examples
reactjstypescriptunit-testingjestjs

Typescript error when mocking React functional component with jest fn


I created a fake component inside my test to track if it’s getting called correctly, the test is running ok. But my Visual Studio Code keeps returning the following error for the code above:

MockedComponent' cannot be used as a JSX component. Its instance type 'Element' is not a valid JSX element.ts(2786)

Anyone knows why VSCode is giving me this error?

my-test.test.tsx
test('should do something', () => {
    const MockedComponent = jest.fn((props: SomeProps) => {
      return <div>{props.foo}</div>
    })

    render(
      <div>
        <MockedComponent foo="bar" />
      </div>
    )

    expect(MockedComponent).toHaveBeenCalled()
  })
VSCode error

MockedComponent' cannot be used as a JSX component. Its instance type 'Element' is not a valid JSX element.ts(2786)


Solution

  • The only way this test would make sense, is if you passed this component to another component to make sure it got rendered.

    And when you do that, there is no problem. This test works fine.

    function MyComp({
      C,
      cProps
    }: {
      C: (props: { foo: string }) => JSX.Element
      cProps: { foo: string }
    }) {
      return (
        <div>
          <C foo={cProps.foo} />
        </div>
      )
    }
    
    const MockedComponent = jest.fn((props: { foo: string }) => {
      return <div>{props.foo}</div>
    })
    
    render(<MyComp C={MockedComponent} cProps={{ foo: 'bar' }} />)
    
    expect(MockedComponent).toHaveBeenCalledWith({ foo: 'bar' })
    

    I'm not sure what it is about jest.fn() that makes Typescript unhappy, but when you actually use it any way that makes sense, the error dissappears.

    So just don't directly a render a mocked component like that (because, A: it doesn't work, and B: it doesn't make any sense to do so anyway), and you should be fine.