enzyme-adapter-react-17 icon indicating copy to clipboard operation
enzyme-adapter-react-17 copied to clipboard

displayName no longer appears on many React Native components

Open nabilfreeman opened this issue 2 years ago • 2 comments

Hi, I've switched over to this library as part of our React 17 upgrade. We are using React Native.

I've noticed that all our snapshots (several thousand) in the project failed due to the displayName of many components changing to a generic Component.

I think this is to do with the Object.assign forcing the display name to be Component in the methods wrapPureComponent and wrapFunctionalComponent.

https://github.com/wojtekmaj/enzyme-adapter-react-17/blob/d33c2925e402c39928dfabf2ecfd41063fb2f3a8/src/ReactSeventeenAdapter.js#L562

Is this right and can anything be done about it?

Screenshot 2021-12-09 at 20 21 10

p.s. I think it's great that you have released this despite the Enzyme maintainers refusing to release their React 17 adapter!

nabilfreeman avatar Dec 09 '21 20:12 nabilfreeman

After using the debugger and stepping through the library I located the source of the issue.

React Native attaches its displayName to ForwardRef in this way: https://github.com/facebook/react-native/blob/main/Libraries/Components/View/View.js#L37

However in the context of the React adapter it doesn't find it because it is looking for node.type.displayName. The RN name is in fact under node.type.render.displayName.

Screenshot 2021-12-09 at 21 15 52

In fact, adapter.displayNameOfNode would return this correctly, but for some reason RN components have both type.displayName = 'Component' and type.render.displayName = 'View'`. So the method returns before the more advanced name find can occur.

https://github.com/wojtekmaj/enzyme-adapter-react-17/blob/main/src/ReactSeventeenAdapter.js#L865

        case require("react-is").ForwardRef || NaN:
          {
            // vvv this check is stopping adapter.displayNameOfNode from running and all `ForwardRef` returns 'Component' as name.
            if (type.displayName) {
              return type.displayName;
            }

            // since this has `type.render` passed to it, it will return the correct displayName.
            var name = adapter.displayNameOfNode({
              type: type.render });

            return name ? "ForwardRef(".concat(name, ")") : 'ForwardRef';
          }

This could be fixed by possibly switching the order of invocation. I fixed it with a crude patch below which is suitable for our use...

diff --git a/node_modules/@wojtekmaj/enzyme-adapter-react-17/build/ReactSeventeenAdapter.js b/node_modules/@wojtekmaj/enzyme-adapter-react-17/build/ReactSeventeenAdapter.js
index e4a1837..aaf1700 100644
--- a/node_modules/@wojtekmaj/enzyme-adapter-react-17/build/ReactSeventeenAdapter.js
+++ b/node_modules/@wojtekmaj/enzyme-adapter-react-17/build/ReactSeventeenAdapter.js
@@ -1041,6 +1041,10 @@ var ReactSeventeenAdapter = /*#__PURE__*/function (_EnzymeAdapter) {
 
         case _reactIs.ForwardRef || NaN:
           {
+            if (type.render && type.render.displayName) {
+              return type.render.displayName;
+            }
+
             if (type.displayName) {
               return type.displayName;
             }

nabilfreeman avatar Dec 09 '21 21:12 nabilfreeman

@nabilfreeman Unfortunately this workaround breaks a few tests we have, so I can't add this.

wojtekmaj avatar Dec 14 '21 06:12 wojtekmaj