Enzyme: React.Lazy always returning the Fallback value

Created on 22 Jul 2019  路  16Comments  路  Source: enzymejs/enzyme

Current behaviour

When writing a test to validate my component is rendered, I am only ever seeing the fallback value.
I am unsure as to what I am doing incorrect or if this is an issue.

import React, { Suspense } from 'react';

const LazyComponent = React.lazy(() => import('./lazy-component-file'));

const ComponentWrapper = () => {
  return (
    <Suspense fallback='...'>
      <LazyComponent />
    </Suspense>
  );
};

export default ComponentWrapper;

....

import { shallow } from 'enzyme';
import React from 'react';

import ComponentWrapper from './component-wrapper';

test('renders the suspense component', () => {
  const wrapper = shallow(<ComponentWrapper />);
  expect(wrapper.find('LazyComponent').length).toEqual(0); // Passes
});

test('renders the LazyComponent', () => {
  const wrapper = shallow(<ComponentWrapper />, { suspenseFallback: false });
  expect(wrapper.find('LazyComponent').length).toEqual(1); // Errors
});

Expected behaviour

I've tried exporting the LazyComponent and doing:
expect(wrapper.find(LazyComponent).length).toEqual(1);

But my issue is flipped on its head and wrapper.find(LazyComponent).length is always 1.

Your environment

API

  • [x] shallow
  • [ ] mount
  • [ ] render

Version

| library | version
| ------------------- | -------
| enzyme | 3.10.0
| react | 16.8.6
| react-dom | 16.8.6
| react-test-renderer | 16.8.6
| adapter (below) | 1.14.0

Adapter

  • [x] enzyme-adapter-react-16
  • [ ] enzyme-adapter-react-16.3
  • [ ] enzyme-adapter-react-16.2
  • [ ] enzyme-adapter-react-16.1
  • [ ] enzyme-adapter-react-15
  • [ ] enzyme-adapter-react-15.4
  • [ ] enzyme-adapter-react-14
  • [ ] enzyme-adapter-react-13
  • [ ] enzyme-adapter-react-helper
  • [ ] others ( )
shallow bug help wanted package 16

Most helpful comment

Yeah I was trying to use wrapper.debug() to see the output.

The suspenseFallback option seems to not be making a difference to what is output.

const wrapper = shallow(<ComponentWrapper />, { suspenseFallback: true });
console.log(wrapper.debug());

      <Suspense fallback="...">
        <lazy />
      </Suspense>
const wrapper = shallow(<ComponentWrapper />, { suspenseFallback: false });
console.log(wrapper.debug());

      <Suspense fallback="...">
        <lazy />
      </Suspense>

I would have expected in the second example to see my <LazyComponent /> in place of <lazy />

All 16 comments

By default, Lazy in shallow renders the child, but if you pass { suspenseFallback: true } as the second argument to shallow, it should render the fallback.

You can get more info by using wrapper.debug().

Yeah I was trying to use wrapper.debug() to see the output.

The suspenseFallback option seems to not be making a difference to what is output.

const wrapper = shallow(<ComponentWrapper />, { suspenseFallback: true });
console.log(wrapper.debug());

      <Suspense fallback="...">
        <lazy />
      </Suspense>
const wrapper = shallow(<ComponentWrapper />, { suspenseFallback: false });
console.log(wrapper.debug());

      <Suspense fallback="...">
        <lazy />
      </Suspense>

I would have expected in the second example to see my <LazyComponent /> in place of <lazy />

hmm, that seems like a bug then.

@philearley does it work to you with mount()? to me it returns fallback as well as shallow() does

@skyboyer when I tried to use mount I received warnings saying Mount was not supported.

Hi there, is there any update on the issue? Thanks.

Still experiencing this issue.

@webdevsyd Maybe a little late to the party but I found that I had to dive into my component and then I could find what I was looking for.

const wrapper1 = shallow(<LazyComponent />,  {suspenseFallback: true});
expect(wrapper1.dive().find('FallbackComponent').length).toBe(1);

const wrapper2 = shallow(<LazyComponent />,  {suspenseFallback: false});
expect(wrapper2.dive().find('LazyComponent').length).toBe(1);

@webdevsyd Maybe a little late to the party but I found that I had to dive into my component and then I could find what I was looking for.

const wrapper1 = shallow(<LazyComponent />,  {suspenseFallback: true});
expect(wrapper1.dive().find('FallbackComponent').length).toBe(1);

const wrapper2 = shallow(<LazyComponent />,  {suspenseFallback: false});
expect(wrapper2.dive().find('LazyComponent').length).toBe(1);

I created #2328 to resolve this issue and make a note in PR, please read it.

@lamhieu-vk Has your fix for this issue been released yet? I am on the latest versions of enzyme and enzyme-adapter-react-16 and am still seeing this issue.

@liegeandlief no, the commit that closed the PR shows it's not yet in enzyme-adapter-react-16. i'll cut a release tomorrow.

v1.15.3 of the adapter has been released.

Unfortunately this still isn't working for me. My test is as follows:

test('it renders as expected', () => {
  const wrapper = shallow(<PageSwitch pageData={{ key: 'home' }} />, { suspenseFallback: true })
  expect(wrapper.find(PageSwitchFallback)).toHaveLength(1)
  expect(wrapper.find(Home)).toHaveLength(0)

  const wrapper2 = shallow(<PageSwitch pageData={{ key: 'home' }} />, { suspenseFallback: false })
  expect(wrapper2.find(PageSwitchFallback)).toHaveLength(0)
  expect(wrapper2.find(Home)).toHaveLength(1)  / * FAILS HERE - expected 1 received 0 */
})

My PageSwitch component is as follows:

const Home = lazy(() => import('../pages/Home/'))

const PageSwitchFallback = memo(() => {
  return <div aria-live='polite' aria-busy /> 
})
PageSwitchFallback.displayName = 'PageSwitchFallback'

const PageSwitch = memo(({ pageData }) => {
  const renderPageComponent = useCallback(() => {
    if (pageData === 'NOT_FOUND') return null

    switch (pageData.key) {
      case 'home':
        return <Home />
    }
  }, [pageData])

  return (
    <Suspense fallback={<PageSwitchFallback />}>
      {renderPageComponent()}
    </Suspense>
  )
})
PageSwitch.displayName = 'PageSwitch'

export default PageSwitch

I have confirmed that it is reaching the home case in the switch block but the test does not seem to find the Home component. The Home component is also memoized and has its displayName property set to Home.

Can you see anything I'm doing wrong here?

What does wrapper2.debug() output?

It outputs:

<Suspense fallback={{...}} pageData={{...}}>
    <lazy />
</Suspense>

@liegeandlief perhaps it's fixed in latest master - your test cases pass for me. I'll add them to make sure it doesn't regress in the future.

edit: the tests fail in React v16.6 and v16.7. For now, try updating to v16.8 or newer?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ahuth picture ahuth  路  3Comments

potapovDim picture potapovDim  路  3Comments

abe903 picture abe903  路  3Comments

ivanbtrujillo picture ivanbtrujillo  路  3Comments

AdamYahid picture AdamYahid  路  3Comments