Jest/Enzyme Class Component testing with React Suspense and React.lazy child component
Asked Answered
D

2

18

So I converted an import used in a class component to React.lazy import api and wrapped it in a Suspense tag. When I test that class component, enzyme throws an error "Enzyme Internal Error: unknown node with tag 13". Is there a way to render and test the mount of the lazy loaded component rather than using shallow render?

I've already tried async await to wait until the promise of the lazy load resolved but that didn't work neither, like so:

it('async await mount', () async () => {
  const wrapper = await mount(<Component />)
}

here's example code:

Component.js

import React, { PureComponent, Suspense } from 'react'

const ChildComponent = React.lazy(() => import('../ChildComponent'))

export default class Component extends PureComponent {
  constructor() {
      super()
      this.state = {
          example: null
      }
  }

  doSomething = () => this.setState({
      example: 'example'
  })

  render() {
    return (
      <div>
        <p>Example</p>
        <Suspense fallback={<div>...loading</div>}>
            <ChildComponent 
               example={this.state.example}
               doSomething={this.doSomething}
            />
        </Suspense>
      </div>
    )
  }
}

Component.test.js

import React from 'react'
import renderer from 'react-test-renderer'
import { mount } from 'enzyme'
import Component from '../../Component'

describe('Component', () => {
    // snapshot renders loading and not children
    it('example snapshot of tree', () => {
        const tree = renderer.create(<Component />).toJSON()
        expect(tree).toMatchSnapshot()
    })

    it('example mount test', () => {
        // this test fails and throws error I state above
        const wrapper = mount(<Component />)
        wrapper.setState({ example: 'example' })
        expect(wrapper.state.example).toBe('example')
    })
})

I read that Enzyme does not support React 16.6 Suspense API yet but I wanted to know if there was still a way to test the mounted so I can use things like simulate and find API from Enzyme.

Disabuse answered 13/12, 2018 at 19:32 Comment(1)
This issue is being discussed on Github github.com/airbnb/enzyme/pull/1975Fluctuant
W
1

Solution

The GitHub issue linked by ChuckJHardy has been resolved merged and released. You are now able to use the mount API in enzyme as of 1.14.0.

References

https://github.com/airbnb/enzyme/pull/1975

Windtight answered 6/7, 2020 at 23:38 Comment(0)
R
0

I needed to test my lazy component using Enzyme. Following approach worked for me to test on component loading completion:

const myComponent = React.lazy(() => 
      import('@material-ui/icons')
      .then(module => ({ 
         default: module.KeyboardArrowRight 
      })
   )
);

Test Code ->

//mock actual component inside suspense
jest.mock("@material-ui/icons", () => { 
    return {
        KeyboardArrowRight: () => "KeyboardArrowRight",
}
});

const lazyComponent = mount(<Suspense fallback={<div>Loading...</div>}>
           {<myComponent>}
       </Suspense>);
    
const componentToTestLoaded  = await componentToTest.type._result; // to get actual component in suspense
    
expect(componentToTestLoaded.text())`.toEqual("KeyboardArrowRight");

This is hacky but working well for Enzyme library.

Romanov answered 9/12, 2021 at 19:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.