Enzyme: [Improved Fiber Support] Support Portals properly

Created on 26 Sep 2017  路  23Comments  路  Source: enzymejs/enzyme

I am not quite sure if these are supported yet or not. We need to add some tests. I also wonder if there are any APIs that might need to get created to assert on this or something?

Fiber Support enhancement help wanted package 16

Most helpful comment

There may well also be an issue with react-test-renderer, but the first error I get is inside the react 16 renderer adapter:

image

tag type of 4 is not recognized.

All 23 comments

I can confirm that Portals don't work with Enzyme 3.0.0 (+ adapter for React 16), React 16.0.0 and Jest 21.2.0. See related test: https://github.com/WordPress/gutenberg/pull/2813/files#diff-6cf726110898b8679af57302917acb5dR279.

I can be wrong but it looks like an issue in react-test-renderer.

I tried this via jest and CRA:

const Test = () => (
  <div>
    <h1>Hello</h1>

    <Portal>Outside message</Portal>
  </div>
)

const tree = renderer.create(<Test />).toJSON()

Where Portal returns ReactDOM.createPortal(...).

The error message is

TypeError: parentInstance.children.indexOf is not a function

      at appendChild (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7778:39)
      at commitPlacement (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:5200:13)
      at commitAllHostEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6196:13)
      at HTMLUnknownElement.callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2210:14)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:126:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)
      at Object.invokeGuardedCallbackDev (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2249:16)
      at invokeGuardedCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2106:29)
      at commitAllWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6332:9)
      at workLoop (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6643:13)
      at HTMLUnknownElement.callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2210:14)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:126:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)
      at Object.invokeGuardedCallbackDev (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2249:16)
      at invokeGuardedCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2106:29)
      at performWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6756:7)
      at scheduleUpdateImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7141:19)
      at scheduleUpdate (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7080:12)
      at scheduleTopLevelUpdate (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7351:5)
      at Object.updateContainer (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7381:7)
      at Object.create (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8186:18)
      at Object.fit (src/lib/tests/forms.js:25:48)
      at process._tickCallback (internal/process/next_tick.js:103:7)

There may well also be an issue with react-test-renderer, but the first error I get is inside the react 16 renderer adapter:

image

tag type of 4 is not recognized.

I don't know exactly if this is correct, but if I add
var Portal = 4;
and duplicate the switch case for classComponent, and match against the Portal var:

case Portal:
      return {
        nodeType: 'class',
        type: node.type,
        props: (0, _object2['default'])({}, node.memoizedProps),
        key: node.key,
        ref: node.ref,
        instance: node.stateNode,
        rendered: childrenToTree(node.child)
      };

my basic tests pass. I am not familiar at all with what should be returned from this switch block though...

I am using latest version of react-modal in my app and with the react upgrade this issue surfaced in my tests. They are indeed in 3.0.0 using the new portal component if react 16 is beiing used to render it.

Hi there,

any update?

I just switched to react 16 and my tests are failing...

Enzyme Internal Error: unknown node with tag 4

      at toTree (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:147:13)

I would appreciate any hint, how to make them work again...

@mayacode did you start using Portals as part of your switch? A react 15 codebase switched directly to 16 shouldn't be running into that error.

I ran into the issue after upgrading react-modal, which does use portals if they are available

@ljharb I upgraded react (from 15.4) and react-bootstrap (in the app is react-bootstrap's Modal in use, and I assume it uses portals, if available). In the end, I made everything else working, just tests are failing with Enzyme Internal Error: unknown node with tag 4...

thanks; if react-bootstrap uses Portals in its latest version, that would indeed trigger this code path.

@ezhlobo, did you mean to use ReactDom.createPortal instead of React.createPortal?

@Omniroot thank you for noticing this. Yeah, I meant ReactDOM, I'll update my previous message.

May one of the core contributors take a look at this PR? https://github.com/airbnb/enzyme/pull/1263

It should address this issue, but the PR owner needs help with the tests.

Any update for all waiting people? I needed to comment a lot of tests... my coverage dropped down ;(

@mayacode, you can always mock the behavior of ReactDOM.createPortal to be an identity function. At least, I ended-up mocking the internal Portal of Material-UI to migrate all the tests to react@16 without losing test coverage.

I'm confused; testing Portals with enzyme and React 16 has never been possible; how could you have working tests that use them that need commenting out?

Not exactly sure, but with react 15 and enzyme < 3, tests still worked, and when upgraded they totally fail. I wasn鈥檛 testing the portal itself per se, but a component that had one still was able to be rendered. This started happening to my project when I upgraded to latest enzyme and react 16

@kellyrmilligan right but with latest enzyme and react 15, do you still see a problem?

Enzyme doesn't yet support Portals with React 16.

I鈥檒l give it a go. But I think we鈥檙e all just wanting this to at least not fail on that node type? This is blocking my upgrade path for the time being.

correct, I branched off and just upgraded enzyme to latest, and this issue doesn't occur. again, i'm not sure here, but seems like a lot of folks would want portals to at least just not fail. there's even a PR for this issue.

1263

Of course, it should be fixed :-) just wanted to clarify that the issue only blocks upgrading to React 16, not upgrading to enzyme 3.

@ljharb I have tests which are using react-bootstrap Modals, which are using react-overlays, which is using portals (if available). In a moment of upgrading react and react-bootstrap all Modal related tests started to fail. It blocks upgrading to react 16.

gotcha; it seems like the combination of enzyme not supporting Portals, and react-overlays magically (instead of explicitly) using Portals, is the blocker.

For the moment I've been mocking portals in the top of the test file like this:

jest.mock('rc-util/lib/Portal')

Obviously the rc-util package is needed for this.

Was this page helpful?
0 / 5 - 0 ratings