Enzyme: mount Suspense and throw promise - Enzyme Internal Error: unknown node with tag 2

Created on 30 Jul 2019  ·  13Comments  ·  Source: enzymejs/enzyme

Current behavior

Getting error Enzyme Internal Error: unknown node with tag 2

from mounting Suspense component with child component that throws promise:

import React, { Suspense } from "react";

const Message = props => <div>Hello Enzyme!</div>
const Loading = props => <div>loading...</div>
const Thrower = props => {
  throw new Promise(resolve => {
    setTimeout(resolve, 1000);
  });
};
describe("integration with Suspense component", () => {
  test("should render Message component", () => {
    const wrapper = mount(
      <Suspense fallback={<Loading />}>
        <Message />
      </Suspense>
    );

    expect(wrapper.find(Message)).toExist(); // ✅ passes
  });

  test("should render Loading component", () => {
    const wrapper = mount(
      <Suspense fallback={<Loading />}>
        <Thrower />
      </Suspense>
    );

    expect(wrapper.find(Loading)).toExist(); // ❌ Enzyme Internal Error: unknown node with tag 2
  });
})

trace:

    Enzyme Internal Error: unknown node with tag 2

      20 | 
      21 |   test("should render Loading component", () => {
    > 22 |     const wrapper = mount(
         |                     ^
      23 |       <Suspense fallback={<Loading />}>
      24 |         <Thrower />
      25 |       </Suspense>

      at _toTree (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:254:13)
      at toTree (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:267:12)
      at childrenToTree (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:227:14)
          at Array.map (<anonymous>)
      at map (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:269:27)
      at childrenToTree (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:248:19)
      at toTree (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:267:12)
      at childrenToTree (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:169:19)
      at Object.toTree [as getNode] (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:448:11)
      at new getNode (node_modules/enzyme/src/ReactWrapper.js:117:44)
      at mount (node_modules/enzyme/src/mount.js:10:10)
      at Object.mount (__tests__/Suspense.spec.js:22:21)

Expected behavior

No error

Your environment

API

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

Version

| library | version
| ------------------- | -------
| enzyme | 3.10.0
| _jest-enzyme_ | _7.0.2_
| 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 ( )
mount shallow bug help wanted package 16

Most helpful comment

Hi there, is there any update on the issue? Looking forward for it to be fixed!

All 13 comments

1917 #1975

Looks related to #2125.

Does this only occur when you throw a promise, as opposed to another kind of exception?

Yep, throw new Error() instead of a promise doesn't yield this kind of message

So you're not using any React.lazy components - which have to be a promise for an object with a default property that's a React component - but I'm not sure you're supposed to be able to throw a promise directly inside Suspense.

Can you link me to the React docs that talk about this? https://reactjs.org/docs/code-splitting.html doesn't seem to.

Throwing a promise inside Suspense should be the way to implement an async component - afaik.

here's a pretty recent article that talks about it:
https://blog.logrocket.com/the-future-of-react-unfolding-with-suspense/

The part about React.lazy you're referencing from the React docs talks about the import returning a promise that resolves to a module with an export default that's a React component.

hmm, in that case perhaps the "thrown promise" case isn't something we're handling properly.

Throwing promise inside render is supported by React Suspense.
See pull request in React repo Accept promise as element type

Hi there, is there any update on the issue? Looking forward for it to be fixed!

Still broken?

react-lazy-ssr triggers this error because it throws a promise.

While there is a workaround, it would be nice if Enzyme supported it without the workaround.

I also ran into this issue testing recoil with enzyme and using a value that returns a promise.

It would be nice to be able to use suspense with enzyme.

I'm working on fixing this, but the "detect fiber tags" code we use is having trouble figuring out the 17 (it has to be done dynamically so it doesn't break over time).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

timhonders picture timhonders  ·  3Comments

ivanbtrujillo picture ivanbtrujillo  ·  3Comments

aweary picture aweary  ·  3Comments

blainekasten picture blainekasten  ·  3Comments

blainekasten picture blainekasten  ·  3Comments