Skip to content

Commit

Permalink
[enzyme-adapter-react-16] [fix] Fix detect component used Suspense
Browse files Browse the repository at this point in the history
  • Loading branch information
lh0x00 authored and ljharb committed Feb 8, 2020
1 parent 8c254a1 commit 04cce43
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 16 deletions.
54 changes: 40 additions & 14 deletions packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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(),
Expand All @@ -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)
Expand All @@ -612,37 +644,31 @@ 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);

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,
));
Expand Down Expand Up @@ -672,7 +698,7 @@ class ReactSixteenAdapter extends EnzymeAdapter {
});
}
}
return withSetStateAllowed(() => renderer.render(renderedEl, context));
return withSetStateAllowed(() => renderElement(renderedEl, context));
}
},
unmount() {
Expand Down
8 changes: 6 additions & 2 deletions packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1816,7 +1816,9 @@ describe('shallow', () => {
</Suspense>
));

expect(wrapper.debug()).to.equal('<lazy />');
expect(wrapper.debug()).to.equal(`<Suspense fallback={{...}}>
<lazy />
</Suspense>`);
});

it('replaces LazyComponent with Fallback when render Suspense if options.suspenseFallback=true', () => {
Expand All @@ -1841,7 +1843,9 @@ describe('shallow', () => {
</Suspense>
), { suspenseFallback: true });

expect(wrapper.debug()).to.equal('<Fallback />');
expect(wrapper.debug()).to.equal(`<Suspense fallback={{...}}>
<Fallback />
</Suspense>`);
});

it('throws if options.suspenseFallback is not boolean or undefined', () => {
Expand Down

0 comments on commit 04cce43

Please sign in to comment.