diff --git a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js index 5ba368da6..d6a946673 100644 --- a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js +++ b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js @@ -218,6 +218,7 @@ function toTree(vnode) { }; } case FiberTags.ClassComponent: + case FiberTags.ClassComponentLazy: return { nodeType: 'class', type: node.type, @@ -228,6 +229,7 @@ function toTree(vnode) { rendered: childrenToTree(node.child), }; case FiberTags.FunctionalComponent: + case FiberTags.FunctionalComponentLazy: return { nodeType: 'function', type: node.type, diff --git a/packages/enzyme-adapter-react-16/src/detectFiberTags.js b/packages/enzyme-adapter-react-16/src/detectFiberTags.js index b59f79c41..955ee2c0d 100644 --- a/packages/enzyme-adapter-react-16/src/detectFiberTags.js +++ b/packages/enzyme-adapter-react-16/src/detectFiberTags.js @@ -51,12 +51,22 @@ module.exports = function detectFiberTags() { function Fn() { return null; } + function LazyFn() { + throw Promise.resolve(); + } // eslint-disable-next-line react/prefer-stateless-function class Cls extends React.Component { render() { return null; } } + // eslint-disable-next-line react/prefer-stateless-function + class LazyCls extends React.Component { + // eslint-disable-next-line react/require-render-return + render() { + throw Promise.resolve(); + } + } let Ctx = null; let FwdRef = null; let LazyComponent = null; @@ -75,8 +85,10 @@ module.exports = function detectFiberTags() { return { HostRoot: getFiber('test').return.return.tag, // Go two levels above to find the root ClassComponent: getFiber(React.createElement(Cls)).tag, + ClassComponentLazy: supportsSuspense ? getLazyFiber(LazyCls).tag : -1, Fragment: getFiber([['nested']]).tag, FunctionalComponent: getFiber(React.createElement(Fn)).tag, + FunctionalComponentLazy: supportsSuspense ? getLazyFiber(LazyFn).tag : -1, MemoSFC: supportsMemo ? getFiber(React.createElement(React.memo(Fn))).tag : -1, diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index 901db788e..251d1d060 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -1285,6 +1285,55 @@ describeWithDOM('mount', () => { }); }); + describeIf(is('>= 16.6'), 'Suspense & lazy component', () => { + class Fallback extends React.Component { + render() { + return ( +
Fallback
+ ); + } + } + + it('finds fallback when given lazy class component', () => { + class Component extends React.Component { + // eslint-disable-next-line react/require-render-return + render() { + throw Promise.resolve(); + } + } + + const SuspenseComponent = () => ( + + + + ); + + const wrapper = mount(); + + expect(wrapper.is(SuspenseComponent)).to.equal(true); + expect(wrapper.find(Component)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(1); + }); + + it('finds fallback when given lazy functional component', () => { + function Component() { + throw Promise.resolve(); + } + + const SuspenseComponent = () => ( + + + + ); + + const wrapper = mount(); + + expect(wrapper.is(SuspenseComponent)).to.equal(true); + expect(wrapper.find(Component)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(1); + }); + }); + describe('.mount()', () => { it('calls componentWillUnmount()', () => { const willMount = sinon.spy(); diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index a46c62b56..f1f8901a2 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -2077,6 +2077,55 @@ describe('shallow', () => { }); }); + describeIf(is('>= 16.6'), 'Suspense & lazy component', () => { + class Fallback extends React.Component { + render() { + return ( +
Fallback
+ ); + } + } + + it('finds fallback when given lazy class component', () => { + class Component extends React.Component { + // eslint-disable-next-line react/require-render-return + render() { + throw Promise.resolve(); + } + } + + const SuspenseComponent = () => ( + + + + ); + + const wrapper = shallow(, { suspenseFallback: true }); + + expect(wrapper.is(Suspense)).to.equal(true); + expect(wrapper.find(Component)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(1); + }); + + it('finds fallback when given lazy functional component', () => { + function Component() { + throw Promise.resolve(); + } + + const SuspenseComponent = () => ( + + + + ); + + const wrapper = shallow(, { suspenseFallback: true }); + + expect(wrapper.is(Suspense)).to.equal(true); + expect(wrapper.find(Component)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(1); + }); + }); + describe('lifecycle methods', () => { describe('disableLifecycleMethods option', () => { describe('validation', () => {