diff --git a/docs/api/shallow.md b/docs/api/shallow.md index 0756bb06b..53ee3f86a 100644 --- a/docs/api/shallow.md +++ b/docs/api/shallow.md @@ -50,8 +50,9 @@ describe('', () => { - `options.disableLifecycleMethods`: (`Boolean` [optional]): If set to true, `componentDidMount` is not called on the component, and `componentDidUpdate` is not called after [`setProps`](ShallowWrapper/setProps.md) and [`setContext`](ShallowWrapper/setContext.md). Default to `false`. -- `options.wrappingComponent`: (`ComponentType` [optional]): A component that will render as a parent of the `node`. It can be used to provide context to the `node`, among other things. See the [`getWrappingComponent()` docs](ShallowWrapper/getWrappingComponent.md) for an example. **Note**: `wrappingComponent` _must_ render its children. -- `options.wrappingComponentProps`: (`Object` [optional]): Initial props to pass to the `wrappingComponent` if it is specified. + - `options.wrappingComponent`: (`ComponentType` [optional]): A component that will render as a parent of the `node`. It can be used to provide context to the `node`, among other things. See the [`getWrappingComponent()` docs](ShallowWrapper/getWrappingComponent.md) for an example. **Note**: `wrappingComponent` _must_ render its children. + - `options.wrappingComponentProps`: (`Object` [optional]): Initial props to pass to the `wrappingComponent` if it is specified. + - `options.suspenseFallback`: (`Boolean` [optional]): If set to true, when rendering `Suspense` enzyme will replace all the lazy components in children with `fallback` element prop. Otherwise it won't handle fallback of lazy component. Default to `true`. Note: not supported in React < 16.6. #### Returns diff --git a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js index 2db7317e6..5ead193ce 100644 --- a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js +++ b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js @@ -10,6 +10,7 @@ import { version as testRendererVersion } from 'react-test-renderer/package.json import TestUtils from 'react-dom/test-utils'; import semver from 'semver'; import checkPropTypes from 'prop-types/checkPropTypes'; +import has from 'has'; import { AsyncMode, ConcurrentMode, @@ -22,13 +23,17 @@ import { isContextProvider, isElement, isForwardRef, + isLazy, isMemo, isPortal, + isSuspense, isValidElementType, + Lazy, Memo, Portal, Profiler, StrictMode, + Suspense, } from 'react-is'; import { EnzymeAdapter } from 'enzyme'; import { typeOfNode } from 'enzyme/build/Utils'; @@ -228,6 +233,19 @@ function toTree(vnode) { rendered: childrenToTree(node.child), }; } + case FiberTags.Suspense: { + return { + nodeType: 'function', + type: Suspense, + props: { ...node.memoizedProps }, + key: ensureKeyOrUndefined(node.key), + ref: node.ref, + instance: null, + rendered: childrenToTree(node.child), + }; + } + case FiberTags.Lazy: + return childrenToTree(node.child); default: throw new Error(`Enzyme Internal Error: unknown node with tag ${node.tag}`); } @@ -275,6 +293,25 @@ function nodeToHostNode(_node) { return mapper(node); } +function replaceLazyWithFallback(node, fallback) { + if (!node) { + return null; + } + if (Array.isArray(node)) { + return node.map(el => replaceLazyWithFallback(el, fallback)); + } + if (isLazy(node.type)) { + return fallback; + } + return { + ...node, + props: { + ...node.props, + children: replaceLazyWithFallback(node.props.children, fallback), + }, + }; +} + const eventOptions = { animation: true, pointerEvents: is164, @@ -351,6 +388,9 @@ class ReactSixteenAdapter extends EnzymeAdapter { createMountRenderer(options) { assertDomAvailable('mount'); + if (has(options, 'suspenseFallback')) { + throw new TypeError('`suspenseFallback` is not supported by the `mount` renderer'); + } if (FiberTags === null) { // Requires DOM. FiberTags = detectFiberTags(); @@ -445,9 +485,13 @@ class ReactSixteenAdapter extends EnzymeAdapter { }; } - createShallowRenderer(/* options */) { + createShallowRenderer(options = {}) { const adapter = this; const renderer = new ShallowRenderer(); + const { suspenseFallback } = options; + if (typeof suspenseFallback !== 'undefined' && typeof suspenseFallback !== 'boolean') { + throw TypeError('`options.suspenseFallback` should be boolean or undefined'); + } let isDOM = false; let cachedNode = null; @@ -498,8 +542,20 @@ class ReactSixteenAdapter extends EnzymeAdapter { return withSetStateAllowed(() => renderer.render({ ...el, type: MockConsumer })); } else { isDOM = false; - const { type: Component } = el; - + 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); + } + const { type: Component } = renderedEl; const isStateful = Component.prototype && ( Component.prototype.isReactComponent || Array.isArray(Component.__reactAutoBindPairs) // fallback for createClass components @@ -517,7 +573,7 @@ class ReactSixteenAdapter extends EnzymeAdapter { if (!isStateful && typeof Component === 'function') { return withSetStateAllowed(() => renderer.render( - { ...el, type: wrapFunctionalComponent(Component) }, + { ...renderedEl, type: wrapFunctionalComponent(Component) }, context, )); } @@ -546,7 +602,7 @@ class ReactSixteenAdapter extends EnzymeAdapter { }); } } - return withSetStateAllowed(() => renderer.render(el, context)); + return withSetStateAllowed(() => renderer.render(renderedEl, context)); } }, unmount() { @@ -609,6 +665,9 @@ class ReactSixteenAdapter extends EnzymeAdapter { } createStringRenderer(options) { + if (has(options, 'suspenseFallback')) { + throw new TypeError('`suspenseFallback` should not be specified in options of string renderer'); + } return { render(el, context) { if (options.context && (el.type.contextTypes || options.childContextTypes)) { @@ -676,6 +735,7 @@ class ReactSixteenAdapter extends EnzymeAdapter { case StrictMode || NaN: return 'StrictMode'; case Profiler || NaN: return 'Profiler'; case Portal || NaN: return 'Portal'; + case Suspense || NaN: return 'Suspense'; default: } } @@ -693,6 +753,9 @@ class ReactSixteenAdapter extends EnzymeAdapter { const name = displayNameOfNode({ type: type.render }); return name ? `ForwardRef(${name})` : 'ForwardRef'; } + case Lazy || NaN: { + return 'lazy'; + } default: return displayNameOfNode(node); } } @@ -716,6 +779,7 @@ class ReactSixteenAdapter extends EnzymeAdapter { || isForwardRef(fakeElement) || isContextProvider(fakeElement) || isContextConsumer(fakeElement) + || isSuspense(fakeElement) ); } diff --git a/packages/enzyme-adapter-react-16/src/detectFiberTags.js b/packages/enzyme-adapter-react-16/src/detectFiberTags.js index f1368da17..92c3cce84 100644 --- a/packages/enzyme-adapter-react-16/src/detectFiberTags.js +++ b/packages/enzyme-adapter-react-16/src/detectFiberTags.js @@ -1,5 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { fakeDynamicImport } from 'enzyme-adapter-utils'; function getFiber(element) { const container = global.document.createElement('div'); @@ -14,12 +15,38 @@ function getFiber(element) { return inst._reactInternalFiber.child; } +function getLazyFiber(LazyComponent) { + const container = global.document.createElement('div'); + let inst = null; + // eslint-disable-next-line react/prefer-stateless-function + class Tester extends React.Component { + render() { + inst = this; + return React.createElement(LazyComponent); + } + } + // eslint-disable-next-line react/prefer-stateless-function + class SuspenseWrapper extends React.Component { + render() { + return React.createElement( + React.Suspense, + { fallback: false }, + React.createElement(Tester), + ); + } + } + ReactDOM.render(React.createElement(SuspenseWrapper), container); + return inst._reactInternalFiber.child; +} + module.exports = function detectFiberTags() { const supportsMode = typeof React.StrictMode !== 'undefined'; const supportsContext = typeof React.createContext !== 'undefined'; const supportsForwardRef = typeof React.forwardRef !== 'undefined'; const supportsMemo = typeof React.memo !== 'undefined'; const supportsProfiler = typeof React.unstable_Profiler !== 'undefined'; + const supportsSuspense = typeof React.Suspense !== 'undefined'; + const supportsLazy = typeof React.lazy !== 'undefined'; function Fn() { return null; @@ -32,6 +59,7 @@ module.exports = function detectFiberTags() { } let Ctx = null; let FwdRef = null; + let LazyComponent = null; if (supportsContext) { Ctx = React.createContext(); } @@ -40,6 +68,9 @@ module.exports = function detectFiberTags() { // eslint-disable-next-line no-unused-vars FwdRef = React.forwardRef((props, ref) => null); } + if (supportsLazy) { + LazyComponent = React.lazy(() => fakeDynamicImport(() => null)); + } return { HostRoot: getFiber('test').return.return.tag, // Go two levels above to find the root @@ -70,5 +101,11 @@ module.exports = function detectFiberTags() { Profiler: supportsProfiler ? getFiber(React.createElement(React.unstable_Profiler, { id: 'mock', onRender() {} })).tag : -1, + Suspense: supportsSuspense + ? getFiber(React.createElement(React.Suspense, { fallback: false })).tag + : -1, + Lazy: supportsLazy + ? getLazyFiber(LazyComponent).tag + : -1, }; }; diff --git a/packages/enzyme-adapter-utils/src/Utils.js b/packages/enzyme-adapter-utils/src/Utils.js index b9a27df87..83671c99d 100644 --- a/packages/enzyme-adapter-utils/src/Utils.js +++ b/packages/enzyme-adapter-utils/src/Utils.js @@ -363,3 +363,7 @@ export function getWrappingComponentMountRenderer({ toTree, getMountWrapperInsta }, }; } + +export function fakeDynamicImport(moduleToImport) { + return Promise.resolve({ default: moduleToImport }); +} diff --git a/packages/enzyme-test-suite/test/Adapter-spec.jsx b/packages/enzyme-test-suite/test/Adapter-spec.jsx index 8f083953a..016d2505c 100644 --- a/packages/enzyme-test-suite/test/Adapter-spec.jsx +++ b/packages/enzyme-test-suite/test/Adapter-spec.jsx @@ -9,20 +9,22 @@ import { } from 'react-is'; import PropTypes from 'prop-types'; import wrap from 'mocha-wrap'; -import { wrapWithWrappingComponent, RootFinder } from 'enzyme-adapter-utils'; +import { fakeDynamicImport, wrapWithWrappingComponent, RootFinder } from 'enzyme-adapter-utils'; import './_helpers/setupAdapters'; import Adapter from './_helpers/adapter'; import { - renderToString, + AsyncMode, + ConcurrentMode, createContext, createPortal, forwardRef, Fragment, - StrictMode, - AsyncMode, - ConcurrentMode, + lazy, Profiler, + renderToString, + StrictMode, + Suspense, } from './_helpers/react-compat'; import { is } from './_helpers/version'; import { itIf, describeWithDOM, describeIf } from './_helpers'; @@ -1063,6 +1065,20 @@ describe('Adapter', () => { itIf(is('>= 16.6'), 'supports ConcurrentMode', () => { expect(getDisplayName()).to.equal('ConcurrentMode'); }); + + itIf(is('>= 16.6'), 'supports Suspense', () => { + expect(getDisplayName()).to.equal('Suspense'); + }); + + itIf(is('>= 16.6'), 'supports lazy', () => { + class DynamicComponent extends React.Component { + render() { + return
DynamicComponent
; + } + } + const LazyComponent = lazy(() => fakeDynamicImport(DynamicComponent)); + expect(getDisplayName()).to.equal('lazy'); + }); }); describeIf(is('>= 16.2'), 'determines if node isFragment', () => { diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index f61d2e591..bddcc7988 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -15,17 +15,20 @@ import { withSetStateAllowed, } from 'enzyme/build/Utils'; import getAdapter from 'enzyme/build/getAdapter'; +import { fakeDynamicImport } from 'enzyme-adapter-utils'; import './_helpers/setupAdapters'; import { createClass, createContext, createPortal, - Fragment, forwardRef, + Fragment, + lazy, memo, Profiler, PureComponent, + Suspense, useEffect, useState, } from './_helpers/react-compat'; @@ -34,6 +37,7 @@ import { describeIf, itIf, } from './_helpers'; +import getLoadedLazyComponent from './_helpers/getLoadedLazyComponent'; import describeMethods from './_helpers/describeMethods'; import { is, @@ -1078,6 +1082,132 @@ describeWithDOM('mount', () => { 'wrap', ); + describeIf(is('>= 16.6'), 'Suspense & lazy', () => { + class DynamicComponent extends React.Component { + render() { + return ( +
Dynamic Component
+ ); + } + } + class Fallback extends React.Component { + render() { + return ( +
Fallback
+ ); + } + } + it('finds Suspense and its children when no lazy component', () => { + class Component extends React.Component { + render() { + return ( +
test
+ ); + } + } + + 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(0); + }); + + it('can mount Suspense directly', () => { + const wrapper = mount(); + expect(wrapper.is(Suspense)).to.equal(true); + }); + + it('finds fallback when given lazy component in initial mount', () => { + const LazyComponent = lazy(() => fakeDynamicImport(DynamicComponent)); + const SuspenseComponent = () => ( + }> + + + ); + + const wrapper = mount(); + + expect(wrapper.is(SuspenseComponent)).to.equal(true); + expect(wrapper.find(LazyComponent)).to.have.lengthOf(0); + expect(wrapper.find(Fallback)).to.have.lengthOf(1); + }); + + it('return fallback string when given lazy component in initial mount and call .debug()', () => { + const LazyComponent = lazy(() => fakeDynamicImport(DynamicComponent)); + const SuspenseComponent = () => ( + }> + + + ); + + const wrapper = mount(); + + expect(wrapper.debug()).to.equal(` + + +
+ Fallback +
+
+
+
`); + }); + + it('return wrapped component when given loaded lazy component in initial mount', () => { + const LazyComponent = getLoadedLazyComponent(DynamicComponent); + const SuspenseComponent = () => ( + }> + + + ); + + const wrapper = mount(); + + expect(wrapper.is(SuspenseComponent)).to.equal(true); + expect(wrapper.find(LazyComponent)).to.have.lengthOf(0); + expect(wrapper.find(DynamicComponent)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(0); + }); + + it('return wrapped component string when given loaded lazy component in initial mount and call .debug()', () => { + const LazyComponent = getLoadedLazyComponent(DynamicComponent); + const SuspenseComponent = () => ( + }> + + + ); + + const wrapper = mount(); + + expect(wrapper.debug()).to.equal(` + + +
+ Dynamic Component +
+
+
+
`); + }); + + it('throws if options.suspenseFallback is specified', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + const SuspenseComponent = () => ( + }> + + + ); + expect(() => mount(, { suspenseFallback: false })).to.throw(); + }); + }); + 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 253b11de1..7c58d2025 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -14,15 +14,18 @@ import { withSetStateAllowed, } from 'enzyme/build/Utils'; import getAdapter from 'enzyme/build/getAdapter'; +import { fakeDynamicImport } from 'enzyme-adapter-utils'; import './_helpers/setupAdapters'; import { createClass, createContext, createPortal, - Fragment, forwardRef, + Fragment, + lazy, PureComponent, + Suspense, useEffect, useState, Profiler, @@ -1591,6 +1594,209 @@ describe('shallow', () => { }); }); + describeIf(is('>= 16.6'), 'Suspense & lazy', () => { + class DynamicComponent extends React.Component { + render() { + return ( +
Dynamic Component
+ ); + } + } + + class Fallback extends React.Component { + render() { + return ( +
Fallback
+ ); + } + } + + it('finds Suspense and its children when no lazy component', () => { + class Component extends React.Component { + render() { + return ( +
test
+ ); + } + } + + const SuspenseComponent = () => ( + }> + + + ); + + const wrapper = shallow(); + + expect(wrapper.is(Suspense)).to.equal(true); + expect(wrapper.find(Component)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(0); + }); + + it('finds LazyComponent when render component wrapping lazy component', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + const SuspenseComponent = () => ( + }> + + + ); + + const wrapper = shallow(); + + expect(wrapper.is(Suspense)).to.equal(true); + expect(wrapper.find(LazyComponent)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(0); + }); + + it('returns suspense and lazy component string when debug() is called', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + const SuspenseComponent = () => ( + }> + + + ); + + const wrapper = shallow(); + + expect(wrapper.debug()).to.equal(` + +`); + }); + + it('renders lazy component when render Suspense without option', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + + const wrapper = shallow(( + }> + + + )); + + expect(wrapper.find(LazyComponent)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(0); + }); + + it('returns lazy component string when debug() is called', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + + const wrapper = shallow(( + }> + + + )); + + expect(wrapper.debug()).to.equal(''); + }); + + it('replaces LazyComponent with Fallback when render Suspense if options.suspenseFallback=true', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + + const wrapper = shallow(( + }> + + + ), { suspenseFallback: true }); + + expect(wrapper.find(LazyComponent)).to.have.lengthOf(0); + expect(wrapper.find(Fallback)).to.have.lengthOf(1); + }); + + it('returns fallback component string when debug() is called if options.suspenseFallback=true', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + + const wrapper = shallow(( + }> + + + ), { suspenseFallback: true }); + + expect(wrapper.debug()).to.equal(''); + }); + + it('throws if options.suspenseFallback is not boolean or undefined', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + const SuspenseComponent = () => ( + }> + + + ); + expect(() => shallow(, { suspenseFallback: 'true' })).to.throw(); + }); + + it('finds fallback after dive into functional component wrapping Suspense', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + const SuspenseComponent = () => ( + }> + + + ); + + const wrapper = shallow(, { suspenseFallback: true }); + const inner = wrapper.dive(); + + expect(inner.find(LazyComponent)).to.have.lengthOf(0); + expect(inner.find(Fallback)).to.have.lengthOf(1); + }); + + it('replaces nested LazyComponent with Fallback when render Suspense with options.suspenseFallback=true', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + + const wrapper = shallow(( + }> +
+ +
+ +
+
+ + ), { suspenseFallback: true }); + + expect(wrapper.find(LazyComponent)).to.have.lengthOf(0); + expect(wrapper.find(Fallback)).to.have.lengthOf(2); + expect(wrapper.find('.should-be-rendered')).to.have.lengthOf(2); + expect(wrapper.find('.should-be-rendered > .inner')).to.have.lengthOf(1); + }); + + it('does not replace LazyComponent with Fallback when render Suspense if options.suspenseFallback = false', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + + const wrapper = shallow(( + }> + + + ), { suspenseFallback: false }); + + expect(wrapper.find(LazyComponent)).to.have.lengthOf(1); + expect(wrapper.find(Fallback)).to.have.lengthOf(0); + }); + + it('does not replace nested LazyComponent with Fallback when render Suspense if option.suspenseFallback = false', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + + const wrapper = shallow(( + }> +
+ +
+ +
+
+ + ), { suspenseFallback: false }); + + expect(wrapper.find(LazyComponent)).to.have.lengthOf(2); + expect(wrapper.find(Fallback)).to.have.lengthOf(0); + expect(wrapper.find('.should-be-rendered')).to.have.lengthOf(2); + expect(wrapper.find('.should-be-rendered > .inner')).to.have.lengthOf(1); + }); + + it('throws when rendering lazy component', () => { + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + expect(() => shallow()).to.throw(); + }); + }); + describe('lifecycle methods', () => { describe('disableLifecycleMethods option', () => { describe('validation', () => { diff --git a/packages/enzyme-test-suite/test/_helpers/getLoadedLazyComponent.js b/packages/enzyme-test-suite/test/_helpers/getLoadedLazyComponent.js new file mode 100644 index 000000000..d9ca7765e --- /dev/null +++ b/packages/enzyme-test-suite/test/_helpers/getLoadedLazyComponent.js @@ -0,0 +1,31 @@ +import { fakeDynamicImport } from 'enzyme-adapter-utils'; +import { lazy } from './react-compat'; +import { is, VERSION } from './version'; + +function fakeSyncThenable(result) { + return { + then(resolve) { + return resolve({ default: result }); + }, + }; +} + +export default function getLoadedLazyComponent(wrappedComponent) { + if (is('>= 16.8')) { + return lazy(() => fakeSyncThenable(wrappedComponent)); + } + if (is('>= 16.6')) { + const LazyComponent = lazy(() => fakeDynamicImport(wrappedComponent)); + /** + * Before React v16.8 there's no public api to synchronously / await + * loaded lazy component. + * So we have to hack this by setting `_result` and `_status` implementation. + */ + /* eslint-disable no-underscore-dangle */ + LazyComponent._result = wrappedComponent; + /* eslint-disable no-underscore-dangle */ + LazyComponent._status = 1; + return LazyComponent; + } + throw Error(`Current React version ${VERSION} doesn't support \`lazy()\` api.`); +} diff --git a/packages/enzyme-test-suite/test/adapter-utils-spec.jsx b/packages/enzyme-test-suite/test/adapter-utils-spec.jsx index be23428d1..976508588 100644 --- a/packages/enzyme-test-suite/test/adapter-utils-spec.jsx +++ b/packages/enzyme-test-suite/test/adapter-utils-spec.jsx @@ -12,6 +12,7 @@ import { getNodeFromRootFinder, wrapWithWrappingComponent, getWrappingComponentMountRenderer, + fakeDynamicImport, } from 'enzyme-adapter-utils'; import './_helpers/setupAdapters'; @@ -378,4 +379,22 @@ describe('enzyme-adapter-utils', () => { }); }); }); + + describe('fakeDynamicImport', () => { + it('is a function', () => { + expect(fakeDynamicImport).to.be.a('function'); + }); + + it('returns a promise', () => { + const promise = fakeDynamicImport(); + expect(Promise.resolve(promise)).to.equal(promise); + }); + + it('returns a promise for an object containing the provided argument', () => { + const signal = {}; + return fakeDynamicImport(signal).then((actual) => { + expect(actual).to.have.property('default', signal); + }); + }); + }); }); diff --git a/packages/enzyme-test-suite/test/staticRender-spec.jsx b/packages/enzyme-test-suite/test/staticRender-spec.jsx index 7484828be..e130c1352 100644 --- a/packages/enzyme-test-suite/test/staticRender-spec.jsx +++ b/packages/enzyme-test-suite/test/staticRender-spec.jsx @@ -3,11 +3,12 @@ import PropTypes from 'prop-types'; import { expect } from 'chai'; import { render } from 'enzyme'; import renderEntry from 'enzyme/render'; +import { fakeDynamicImport } from 'enzyme-adapter-utils'; import './_helpers/setupAdapters'; import { describeWithDOM, describeIf } from './_helpers'; import { is } from './_helpers/version'; -import { createClass } from './_helpers/react-compat'; +import { createClass, lazy } from './_helpers/react-compat'; describeWithDOM('render', () => { describe('top level entry points', () => { @@ -80,4 +81,18 @@ describeWithDOM('render', () => { expect(() => render(, { context })).to.not.throw(Error); }); }); + + describeIf(is('> 16.6'), 'suspense fallback option', () => { + it('throws if options.suspenseFallback is specified', () => { + class DynamicComponent extends React.Component { + render() { + return ( +
Dynamic Component
+ ); + } + } + const LazyComponent = lazy(fakeDynamicImport(DynamicComponent)); + expect(() => render(, { suspenseFallback: false })).to.throw(); + }); + }); });