diff --git a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js index eadcf94ee..55f41f749 100644 --- a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js +++ b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js @@ -120,6 +120,22 @@ function unmemoType(type) { return isMemo(type) ? type.type : type; } +function checkIsSuspenseAndCloneElement(el, { suspenseFallback }) { + if (!isSuspense(el)) { + return el; + } + + let { children } = el.props; + + if (suspenseFallback) { + const { fallback } = el.props; + children = replaceLazyWithFallback(children, fallback); + } + + const FakeSuspenseWrapper = (props) => React.createElement(el.type, { ...el.props, ...props }, children); + return React.createElement(FakeSuspenseWrapper, null, children); +} + function elementToTree(el) { if (!isPortal(el)) { return utilElementToTree(el, elementToTree); @@ -588,6 +604,22 @@ class ReactSixteenAdapter extends EnzymeAdapter { return wrappedComponent; }; + const renderElement = (elConfig, ...rest) => { + const renderedEl = renderer.render(elConfig, ...rest); + + const typeIsExisted = !!(renderedEl && renderedEl.type); + if (is166 && typeIsExisted) { + const clonedEl = checkIsSuspenseAndCloneElement(renderedEl, { suspenseFallback }); + + const elementIsChanged = clonedEl.type !== renderedEl.type; + if (elementIsChanged) { + return renderer.render({ ...elConfig, type: clonedEl.type }, ...rest); + } + } + + return renderedEl; + }; + return { render(el, unmaskedContext, { providerValues = new Map(), @@ -602,7 +634,7 @@ class ReactSixteenAdapter extends EnzymeAdapter { (props) => props.children, el.type, ); - return withSetStateAllowed(() => renderer.render({ ...el, type: MockProvider })); + return withSetStateAllowed(() => renderElement({ ...el, type: MockProvider })); } else if (isContextConsumer(el)) { const Provider = adapter.getProviderFromConsumer(el.type); const value = providerValues.has(Provider) @@ -612,22 +644,15 @@ class ReactSixteenAdapter extends EnzymeAdapter { (props) => props.children(value), el.type, ); - return withSetStateAllowed(() => renderer.render({ ...el, type: MockConsumer })); + return withSetStateAllowed(() => renderElement({ ...el, type: MockConsumer })); } else { isDOM = false; let renderedEl = el; if (isLazy(renderedEl)) { throw TypeError('`React.lazy` is not supported by shallow rendering.'); } - if (isSuspense(renderedEl)) { - let { children } = renderedEl.props; - if (suspenseFallback) { - const { fallback } = renderedEl.props; - children = replaceLazyWithFallback(children, fallback); - } - const FakeSuspenseWrapper = () => children; - renderedEl = React.createElement(FakeSuspenseWrapper, null, children); - } + + renderedEl = checkIsSuspenseAndCloneElement(renderedEl, { suspenseFallback }); const { type: Component } = renderedEl; const context = getMaskedContext(Component.contextTypes, unmaskedContext); @@ -635,14 +660,15 @@ class ReactSixteenAdapter extends EnzymeAdapter { if (isMemo(el.type)) { const { type: InnerComp, compare } = el.type; - return withSetStateAllowed(() => renderer.render( + return withSetStateAllowed(() => renderElement( { ...el, type: wrapPureComponent(InnerComp, compare) }, context, )); } + if (!isStateful(Component) && typeof Component === 'function') { - return withSetStateAllowed(() => renderer.render( + return withSetStateAllowed(() => renderElement( { ...renderedEl, type: wrapFunctionalComponent(Component) }, context, )); @@ -672,7 +698,7 @@ class ReactSixteenAdapter extends EnzymeAdapter { }); } } - return withSetStateAllowed(() => renderer.render(renderedEl, context)); + return withSetStateAllowed(() => renderElement(renderedEl, context)); } }, unmount() { diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index 204e5653c..885ee86d1 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -1816,7 +1816,9 @@ describe('shallow', () => { )); - expect(wrapper.debug()).to.equal(''); + expect(wrapper.debug()).to.equal(` + +`); }); it('replaces LazyComponent with Fallback when render Suspense if options.suspenseFallback=true', () => { @@ -1841,7 +1843,9 @@ describe('shallow', () => { ), { suspenseFallback: true }); - expect(wrapper.debug()).to.equal(''); + expect(wrapper.debug()).to.equal(` + +`); }); it('throws if options.suspenseFallback is not boolean or undefined', () => {