Skip to content

Commit

Permalink
handle deep mounted memo components properly
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanmarks committed Sep 25, 2020
1 parent a4f83d3 commit a149fb0
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 3 deletions.
11 changes: 9 additions & 2 deletions src/mount.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import omitBy from 'lodash/omitBy';
import isNil from 'lodash/isNil';
import {ForwardRef} from 'react-is';
import {ForwardRef, Memo} from 'react-is';

import {typeName} from 'enzyme/build/Debug';
import {childrenOfNode, propsOfNode} from 'enzyme/build/RSTTraversal';
Expand Down Expand Up @@ -46,12 +46,19 @@ function internalNodeToJson(node, options) {
}

if (Array.isArray(node)) {
// enzyme does some funny stuff with memo function components turning the children
// into an array resulting in undesirable snapshots
if (node.length === 1) {
return internalNodeToJson(node[0], options);
}
return node.map(child => internalNodeToJson(child, options));
}

if (
options.mode === 'deep' &&
(typeof node.type === 'function' || node.type.$$typeof === ForwardRef)
(typeof node.type === 'function' ||
node.type.$$typeof === ForwardRef ||
node.type.$$typeof === Memo)
) {
return internalNodeToJson(node.rendered, options);
}
Expand Down
39 changes: 39 additions & 0 deletions tests/__snapshots__/mount-deep.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,45 @@ exports[`excludes forwardRef node but renders wrapped component 1`] = `
</div>
`;

exports[`excludes memo node but renders wrapped component 1`] = `
<div
className="basic-memo foo"
onClick={[Function]}
>
<div
className="group"
id="group-id"
>
<span
className="empty"
/>
</div>
</div>
`;

exports[`excludes memo node but renders wrapped top level array properly 1`] = `
Array [
<div
className="test"
key="test"
>
Test
</div>,
<div
className="test2"
key="test2"
>
Test 2
</div>,
<div
className="foo"
key="test3"
>
Test 3
</div>,
]
`;

exports[`handles a component which returns null 1`] = `""`;

exports[`includes undefined props 1`] = `
Expand Down
32 changes: 32 additions & 0 deletions tests/fixtures/memo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';

function BasicComponent(props) {
return (
<div
className={`basic-memo ${props.className}`}
onClick={function handleOnClick() {}}
>
<div id="group-id" className="group">
<span className="empty" />
</div>
</div>
);
}

export const BasicMemo = React.memo(BasicComponent);

function ArrayRender(props) {
return [
<div className="test" key="test">
Test
</div>,
<div className="test2" key="test2">
Test 2
</div>,
<div className={props.className} key="test3">
Test 3
</div>,
];
}

export const ArrayMemo = React.memo(ArrayRender);
13 changes: 13 additions & 0 deletions tests/mount-deep.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
ClassArrayRender,
} from './fixtures/class';
import {ForwardRefWithDefaultProps} from './fixtures/forwardRef';
import {BasicMemo, ArrayMemo} from './fixtures/memo';

Enzyme.configure({adapter: new Adapter()});
const deepOptions = {mode: 'deep'};
Expand Down Expand Up @@ -135,3 +136,15 @@ it('excludes forwardRef node but renders wrapped component', () => {

expect(mountToJson(mounted, deepOptions)).toMatchSnapshot();
});

it.only('excludes memo node but renders wrapped component', () => {
const mounted = mount(<BasicMemo className="foo" />);

expect(mountToJson(mounted, deepOptions)).toMatchSnapshot();
});

it.only('excludes memo node but renders wrapped top level array properly', () => {
const mounted = mount(<ArrayMemo className="foo" />);

expect(mountToJson(mounted, deepOptions)).toMatchSnapshot();
});
Loading

0 comments on commit a149fb0

Please sign in to comment.